1984 字
10 分钟
Kubernetes 容器云学习手册
1. 容器云组件速查表
| 组件 | 说明 |
|---|---|
| Kubernetes | 容器编排平台,自动化部署、扩展和管理容器化应用 |
| KubeVirt | 为 K8S 提供虚拟机管理能力,实现 VM 与容器无缝集成 |
| Istio | 服务网格,连接、管理和保护微服务 |
| Grafana | 数据可视化和监控平台 |
| Prometheus | 系统监控和警报工具,多维数据收集 |
| Jaeger UI | 分布式追踪系统,监控微服务调用链 |
| Kiali | Istio 服务网格可视化平台 |
| Harbor | 企业级容器镜像仓库,镜像存储、签名和扫描 |
| Docker | 应用容器引擎 |
| Docker Compose | 多容器 Docker 应用定义和运行工具 |
| Django | Python Web 框架 |
| Jenkins | CI/CD 自动化工具 |
| GitLab | Git 仓库管理和 CI/CD 平台 |
2. Kubernetes 平台部署
2.1 环境准备
mount -o loop chinaskills_cloud_paas_v2.0.1.iso /mnt/mv /opt/kubeeasy /usr/bin/kubeeasy
# 安装依赖kubeeasy install depend \ --host 10.24.2.10,10.24.2.11 \ --user root --password Abc@1234 \ --offline-file /opt/dependencies/base-rpms.tar.gz
# 检查 SSHkubeeasy check ssh \ --host 10.24.2.10,10.24.2.11 \ --user root --password Abc@1234
# 创建 SSH 密钥kubeeasy create ssh-keygen \ --master 10.24.2.10 --worker 10.24.2.11 \ --user root --password Abc@12342.2 部署集群
kubeeasy install kubernetes \ --master 10.24.2.10 --worker 10.24.2.11 \ --user root --password Abc@1234 \ --version 1.22.1 \ --offline-file /opt/kubernetes.tar.gz
kubectl cluster-infokubectl top nodes --use-protocol-buffersDashboard:http://master_IP:30080(admin/Abc@1234)
2.3 部署示例 Pod
apiVersion: v1kind: Podmetadata: name: examspec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent env: - name: "exam" value: "2022"kubectl apply -f pod.yamlkubectl exec exam -- printenv2.4 KubeVirt 虚拟机管理
kubeeasy add --virt kubevirtkubectl -n kubevirt get pods
# VMI 操作kubectl create -f vmi.yamlkubectl get vmiskubectl delete vmis <vmi-name>
# VM 操作virtctl start <vmi-name>virtctl stop <vmi-name>virtctl restart <vmi-name>2.5 Istio 服务网格
kubeeasy add --istio istiokubectl -n istio-system get podsistioctl version访问地址:
- Grafana:
http://master_IP:33000 - Prometheus:
http://master_IP:30090 - Jaeger:
http://master_IP:30686 - Kiali:
http://master_IP:20001
istioctl profile lististioctl profile dump demoistioctl proxy-status
# 启用命名空间注入kubectl create namespace examkubectl label namespace exam istio-injection=enabled2.6 Harbor 镜像仓库
kubeeasy add --registry harbor# 访问 http://master_ip(admin/Harbor12345)2.7 集群运维
# 重置集群kubeeasy reset
# 添加 Worker 节点kubeeasy install depend --host 10.24.2.12 --user root --password Abc@1234 \ --offline-file /opt/dependencies/base-rpms.tar.gzkubeeasy add --worker 10.24.2.12 --user root --password Abc@1234 \ --offline-file /opt/kubernetes.tar.gz3. Helm 包管理
3.1 Helm 简介
Helm 是 Kubernetes 的包管理器,类似于 Linux 的 yum/apt。通过 Chart(包)来定义、安装和升级复杂的 K8S 应用。
| 概念 | 说明 |
|---|---|
| Chart | Helm 包,包含一组 K8S 资源定义的文件集合 |
| Repository | Chart 仓库,用于存储和分发 Chart |
| Release | Chart 的运行实例,一个 Chart 可多次安装产生不同 Release |
| values.yaml | Chart 的默认配置值,安装时可覆盖 |
3.2 Chart 目录结构
mychart/├── Chart.yaml # Chart 元数据(名称、版本等)├── values.yaml # 默认配置值├── charts/ # 依赖的子 Chart├── templates/ # K8S 资源模板│ ├── deployment.yaml│ ├── service.yaml│ ├── ingress.yaml│ └── _helpers.tpl # 模板辅助函数└── templates/tests/ # 测试模板3.3 常用命令
# 创建 Charthelm create mychartrm -rf mychart/templates/*# 编写 templates/deployment.yaml
# 安装和查看helm install web mycharthelm status web
# 常用命令helm version # 查看版本helm list # 查看已安装 Releasehelm search repo <chart-name> # 搜索仓库中的 Charthelm search hub <keyword> # 搜索 ArtifactHubhelm status redis # 查看 Release 状态helm uninstall web # 卸载 Releasehelm delete --purge <chart-name> # 删除(Helm 2)
# Chart 开发helm create helm_charts # 创建 Chart 骨架helm lint # 语法检查helm template helm_charts # 渲染模板查看生成的 YAMLhelm package ./ # 打包 Charthelm install web ./mychart -f custom-values.yaml # 使用自定义配置安装helm install web ./mychart --set replicaCount=3 # 命令行覆盖配置3.4 values.yaml 示例
replicaCount: 2image: repository: nginx tag: "1.21" pullPolicy: IfNotPresentservice: type: ClusterIP port: 80resources: limits: cpu: 500m memory: 128Mi requests: cpu: 250m memory: 64Mi4. Docker Compose + DjangoBlog 部署
4.1 构建四个镜像
Memcached:
FROM centos:centos7.9.2009RUN rm -rf /etc/yum.repos.d/*COPY local.repo /etc/yum.repos.d/COPY yum /root/yumRUN yum install libevent libevent-devel -y && yum install memcached -yEXPOSE 11211ENTRYPOINT /usr/bin/memcached -u rootMariaDB:
FROM centos:centos7.9.2009RUN rm -rf /etc/yum.repos.d/*COPY local.repo /etc/yum.repos.d/COPY yum /root/yumENV LC_ALL en_US.UTF-8RUN yum -y install mariadb-serverCOPY mysql_init.sh /opt/COPY sqlfile.sql /optRUN bash /opt/mysql_init.shEXPOSE 3306CMD ["mysqld_safe","--user=root"]Nginx:
FROM centos:centos7.9.2009RUN rm -rf /etc/yum.repos.d/*COPY local.repo /etc/yum.repos.d/COPY yum /root/yumRUN yum -y install nginxADD nginx.conf /etc/nginx/nginx.confEXPOSE 80CMD ["nginx","-g","daemon off;"]DjangoBlog:
FROM centos:centos7.9.2009RUN rm -rfv /etc/yum.repos.d/*COPY local.repo /etc/yum.repos.d/COPY yum /root/yumRUN yum install -y make openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel gcc gcc-devel python-devel mysql-develCOPY Python-3.6.5.tgz /optRUN tar -zxvf /opt/Python-3.6.5.tgz && mv Python-3.6.5 /usr/localRUN cd /usr/local/Python-3.6.5/ && ./configure && make && make installRUN ln -s /usr/local/python3/bin/python3 /usr/bin/python3RUN ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3ADD requirements.txt requirements.txtRUN pip3 install --upgrade pip --no-index --find-links=/optRUN pip3 install -r requirements.txt --no-index --find-links=/optRUN pip3 install gunicorn[gevent] --no-index --find-links=/optRUN mkdir -p /code/djangoBlogADD . /code/djangoBlog/RUN chmod +x /code/djangoBlog/bin/docker_start.shENTRYPOINT ["/code/djangoBlog/bin/docker_start.sh"]4.2 Compose 编排
version: '3'services: memcached: restart: always image: blog-memcached:v1.0 container_name: blog-memcached ports: ["11211:11211"] db: image: blog-mysql:v1.0 restart: always environment: [MYSQL_DATABASE=djangoblog, MYSQL_ROOT_PASSWORD=root] ports: ["3306:3306"] depends_on: [memcached] container_name: blog-mysql djangoblog: image: blog-service:v1.0 restart: always ports: ["8000:8000"] environment: - DJANGO_MYSQL_HOST=db - DJANGO_MEMCACHED_LOCATION=memcached:11211 links: [db, memcached] depends_on: [db] container_name: blog-service nginx: restart: always image: blog-nginx:v1.0 ports: ["8888:80", "443:443"] links: [djangoblog:djangoblog] container_name: blog-nginxdocker-compose up -d# 访问 http://IP:8888(admin/123456)5. 基于 K8S 构建 CI/CD
5.1 部署 Harbor 和导入镜像
tar -zxf BlueOcean.tar.gzcp BlueOcean/tools/docker-compose-Linux-x86_64 /usr/bin/docker-composetar -zxf BlueOcean/harbor-offline-installer.tar.gz -C /opt/sh /opt/harbor/install.sh# 新建 springcloud 项目(公开)
docker load -i BlueOcean/images/maven_latest.tardocker tag maven 10.26.15.244/library/mavendocker push 10.26.15.244/library/maven5.2 部署 Jenkins
kubectl create ns devopskubectl -n devops apply -f jenkins-deploy.yaml# 访问 http://master:30880kubectl -n devops exec deploy/jenkins -- cat /var/jenkins_home/secrets/initialAdminPasswordkubectl -n devops cp BlueOcean/plugins/ <pod>:/var/jenkins_homekubectl -n devops rollout restart deployment jenkins5.3 部署 GitLab
kubectl -n devops apply -f gitlab-deploy.yaml# 访问 http://master:30888(root/admin@123)5.4 Jenkinsfile 流水线
pipeline{ agent none stages{ stage('mvn-build'){ agent { docker { image '10.26.15.244/library/maven' } } steps{ sh 'mvn package -DskipTests' archiveArtifacts artifacts: '**/target/*.jar' } } stage('image-build'){ agent any steps{ sh 'docker build -t 10.26.15.244/springcloud/gateway -f Dockerfile .' sh 'docker login 10.26.15.244 -u=admin -p=Harbor12345' sh 'docker push 10.26.15.244/springcloud/gateway' } } stage('cloud-deploy'){ agent any steps{ sh 'kubectl apply -f yaml/deployment/gateway-deployment.yaml' sh 'kubectl apply -f yaml/svc/gateway-svc.yaml' } } }}5.5 Webhook 触发
- GitLab:Settings → Network → 允许本地网络请求
- GitLab:创建 Access Token
- Jenkins:系统配置 → 添加 GitLab 连接
- Jenkins:全局安全配置 → 任何用户可以做任何事
- GitLab:Settings → Webhooks → 添加 Jenkins URL
- 测试 Push events → HTTP 200 表示成功
6. GitLab 构建持续集成
6.1 部署 GitLab 到 K8S
kubectl create ns gitlab-ci# 编写 gitlab-deploy.yaml 和 gitlab-svc.yamlkubectl apply -f gitlab-deploy.yamlkubectl apply -f gitlab-svc.yaml6.2 配置 CoreDNS
kubectl edit configmap coredns -n kube-system# 添加 hosts 配置,删除 forward 相关行kubectl -n kube-system rollout restart deploy coredns6.3 部署 GitLab Runner
# 创建 ServiceAccount 和 RBACkubectl apply -f runner-sa.yaml runner-role.yaml runner-rb.yaml default.yaml
# Helm 安装 Runnerhelm -n gitlab-ci install gitlab-runner gitlab-runner6.4 编写 .gitlab-ci.yml
stages: [build, release, review]
maven_build: image: maven:3.6-jdk-8 stage: build script: - mvn clean install -DskipTests=true
image_build: image: docker:18.09.7 stage: release script: - docker build -t demo:latest . - docker push 172.129.20.38/demo/demo:latest
deploy_review: image: kubectl:1.22 stage: review script: - kubectl apply -f template/7. 容器云竞赛真题精选
7.1 容器化部署监控系统
Dockerfile 模板(Node Exporter):
FROM centos:centos7.9.2009WORKDIR /rootCOPY node_exporter-0.18.1.linux-amd64.tar.gz /root/RUN tar -zxvf node_exporter-0.18.1.linux-amd64.tar.gz && \ mv node_exporter-0.18.1.linux-amd64/* /usr/local/bin/EXPOSE 9100CMD ["/usr/local/bin/node_exporter"]Docker Compose 编排:
version: '3'services: monitor-node: container_name: monitor-node image: monitor-exporter:v1.0 ports: ["9100:9100"] monitor-alertmanager: container_name: monitor-alertmanager image: monitor-alert:v1.0 ports: ["9093:9093", "9094:9094"] monitor-grafana: container_name: monitor-grafana image: monitor-grafana:v1.0 ports: ["3000:3000"] monitor-prometheus: container_name: monitor-prometheus image: monitor-prometheus:v1.0 ports: ["9090:9090"]7.2 Istio Ingress Gateway
apiVersion: networking.istio.io/v1beta1kind: Gatewaymetadata: name: bookinfo-gatewayspec: selector: istio: ingressgateway servers: - hosts: ["*"] port: number: 80 name: http protocol: HTTP---apiVersion: networking.istio.io/v1beta1kind: VirtualServicemetadata: name: bookinfospec: hosts: ["*"] gateways: [bookinfo-gateway] http: - match: - uri: {exact: /productpage} route: - destination: host: productpage port: {number: 9080}7.3 KubeVirt 创建 VM
apiVersion: kubevirt.io/v1kind: VirtualMachinemetadata: name: vm-fedoraspec: running: true template: spec: domain: devices: disks: - disk: {bus: virtio} name: containerdisk resources: requests: memory: 1Gi volumes: - name: containerdisk containerDisk: image: fedora-virt:v1.07.4 QoS Guaranteed Pod
apiVersion: v1kind: Podmetadata: name: qos-demospec: containers: - name: nginx image: nginx:latest resources: limits: {memory: "100Mi", cpu: "500m"} requests: {memory: "100Mi", cpu: "500m"} restartPolicy: Always7.5 Pod 安全上下文
apiVersion: v1kind: Podmetadata: name: context-demospec: containers: - name: context-demo image: busybox:latest command: ["sh", "-c", "sleep 1h"] securityContext: runAsUser: 1000 runAsGroup: 30007.6 CRD 自定义资源
apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: name: students.stable.example.comspec: group: stable.example.com versions: - name: v1 served: true storage: true scope: Namespaced names: plural: students singular: student shortNames: [stu] kind: Student7.7 HPA 自动扩缩容
apiVersion: autoscaling/v2beta2kind: HorizontalPodAutoscalermetadata: name: webspec: maxReplicas: 1000 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: web behavior: scaleUp: policies: - periodSeconds: 5 type: Percent value: 900 metrics: - type: Pods pods: metric: {name: cpu} target: {averageValue: 80, type: AverageValue}7.8 HostAliases
apiVersion: v1kind: Podmetadata: name: nginxspec: containers: - name: nginx image: nginx:latest hostAliases: - ip: "127.0.0.1" hostnames: [chinaskill]7.9 Python K8S SDK — Job 管理
import time, yamlfrom kubernetes.client import BatchV1Apifrom kubernetes.config import load_kube_config
load_kube_config()api = BatchV1Api()
try: api.delete_namespaced_job(name='pi', namespace='default')except: pass
time.sleep(15)with open("spec-pi-job.yaml") as f: data = yaml.safe_load(f) api.create_namespaced_job(body=data, namespace="default")
get = api.read_namespaced_job(name="pi", namespace="default")print(get)7.10 Python 自定义调度器
from kubernetes import clientimport kubernetes as k8simport random, json
def getUseNode(api): nodes = api.list_node() return [n.metadata.name for n in nodes.items if n.status.conditions[-1].status == "True"]
def getScheduledPod(api, ns): pods = api.list_namespaced_pod(ns) return [p.metadata.name for p in pods.items if p.status.phase == 'Pending' and p.spec.node_name is None]
def podBinding(api, pod, node, ns): target = client.V1ObjectReference(kind="Node", api_version="v1", name=node) meta = client.V1ObjectMeta(name=pod) body = client.V1Binding(target=target, metadata=meta) api.create_namespaced_binding(ns, body)
k8s.config.load_kube_config()api = client.CoreV1Api()nodes = getUseNode(api)pods = getScheduledPod(api, "default")node = random.choice(nodes)for pod in pods: podBinding(api, pod, node, "default")7.11 Python REST API 封装 Pod 管理
from http.server import HTTPServer, BaseHTTPRequestHandlerimport requests, json, yaml
headers = {"Content-Type": "application/json", "Authorization": "bearer token"}url = "https://master_IP:6443/api/v1/namespaces/default/pods"
class MyHandler(BaseHTTPRequestHandler): def do_GET(self): if self.path.startswith('/pod/'): name = self.path.split('/')[-1] r = requests.get(f"{url}/{name}", headers=headers, verify=False) self.send_response(200) self.send_header("Content-type", "application/json") self.end_headers() self.wfile.write(json.dumps(r.json()).encode())
def do_POST(self): if self.path.startswith('/pod/'): filename = self.path.split('/')[-1] with open(filename) as f: data = yaml.safe_load(f) r = requests.post(url, headers=headers, data=json.dumps(data), verify=False) self.send_response(200) self.send_header("Content-type", "application/json") self.end_headers() self.wfile.write(json.dumps(r.json()).encode())
HTTPServer(("localhost", 8889), MyHandler).serve_forever() Kubernetes 容器云学习手册
https://blog.xeu.asia/posts/kubernetes-guide/