大纲 Kubernetes 核心技术 Controller 的使用 部署应用 部署无状态应用 学习目标
本节将演示在 Kubernetes 集群中,如何通过 Deployment 部署一个 Nginx 的 Pod,并通过 Service 暴露端口,以便从 Kubernetes 集群外部访问 Nginx。
Kubernetes 无状态应用(Stateless)的特点
主要特点:Pod 之间完全一致所有 Pod 完全等价,没有区别,任意一个 Pod 都可以处理请求。 没有启动顺序要求 不依赖固定 Node 节点 Pod 可以在任意 Node 节点上调度和运行,不需要绑定特定节点。 可随意扩缩容 Pod 数量可以随时增加或减少,自动水平扩容(HPA)非常适合。 无持久化存储依赖不保存本地状态,数据通常存储在外部系统中,例如:数据库、对象存储、缓存服务等。 Kubernetes 控制器通常使用 Deployment 管理,支持滚动升级和回滚。 典型代表:Nginx、Web 服务、后端接口、无状态微服务。 Kubernetes 通过 Deployment 部署无状态应用
生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx 1 kubectl create deployment nginx --image =nginx --dry -run=client -o yaml > nginx_deployment.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {}
配置信息 作用对象 核心作用 简单解释 metadata.labelsDeployment 自身 标识 Deployment 自身 给 Deployment 资源对象自己打上标签,用于被其他资源(如 Service、HPA)查询和选择,或者方便用户管理。它说:” 我是谁。” spec.selector.matchLabelsDeployment 的选择器 在 Deployment 与 Pod 之间建立管理关系 Deployment 用来寻找和管理拥有指定标签的 Pod 的规则。它说:” 哪些 Pod 归我管。” spec.template.metadata.labelsPod 模板 定义 Pod 的身份(标签) 规定了 Deployment 在创建新 Pod 时会为其打上的标签。它确保了新 Pod 都带有能被选择器识别的标签。它说:” 我创建的 Pod 长这样。”
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment) 1 kubectl apply -f nginx_deployment.yaml
1 kubectl get pods -o wide
1 2 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-6799fc88d8-jwp6g 1/1 Running 0 29m 10.244.2.18 k8s-node3 <none> <none>
Kubernetes 通过 Service 暴露无状态应用
生成 YAML 配置文件,用于为名称为 nginx 的 Deployment 创建一个 NodePort 类型的 Service,将该 Deployment 的 80 端口暴露到 Kubernetes 集群每个节点的静态端口上,以便从集群外部访问 Nginx 1 kubectl expose deployment nginx --port =80 --type =NodePort --target -port=80 --name =nginx --dry -run=client -o yaml > nginx_service.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 apiVersion: v1 kind: Service metadata: creationTimestamp: "2025-09-11T10:15:16Z" labels: app: nginx managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:labels: .: {} f:app: {} f:spec: f:externalTrafficPolicy: {} f:ports: .: {} k:{"port":80,"protocol":"TCP"}: .: {} f:port: {} f:protocol: {} f:targetPort: {} f:selector: .: {} f:app: {} f:sessionAffinity: {} f:type: {} manager: kubectl-expose operation: Update time: "2025-09-11T10:15:16Z" name: nginx namespace: default resourceVersion: "491002" selfLink: /api/v1/namespaces/default/services/nginx uid: e3729f4c-17f9-4100-86dd-2178fe1aa65f spec: clusterIP: 10.0 .0 .106 externalTrafficPolicy: Cluster ports: - nodePort: 30754 port: 80 protocol: TCP targetPort: 80 selector: app: nginx sessionAffinity: None type: NodePort status: loadBalancer: {}
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Service) 1 kubectl apply -f nginx_service.yaml
1 2 3 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 38d nginx NodePort 10.0.0.106 <none> 80:30754/TCP 30s
通过浏览器访问 http://192.168.2.112:30754,请自行更改 IP 和端口;其中 IP 可以是 Kubernetes 集群任意节点的 IP 地址,端口由 kubectl get svc 命令可得知。若 Ngninx 容器在 Kubernetes 集群中创建并启动成功,则浏览器可以正常访问 Nginx 的首页(如下图所示)。 Kubernetes 删除 Deployment 和 Service
如果需要删除上面创建的 Deployment 和 Service,可以执行以下命令: 1 2 3 4 5 kubectl delete service nginx kubectl delete deployment nginx
部署有状态应用 学习目标
本节将演示在 Kubernetes 集群中,如何通过 StatefulSet 部署一个 Nginx 的 Pod,并通过 Headless Service(无头服务)暴露应用,以便从 Kubernetes 集群内部访问。
Kubernetes 有状态应用(Stateful)的特点
主要特点:
每个 Pod 独立且不可互换每个 Pod 都有自己的身份、配置、存储,不能随意替换或重建。 需要固定的网络标识 Pod 需要固定的名称(DNS)或网络标识符,便于集群内通信,比如 mysql-0.mysql。 有启动和停止顺序 Pod 必须按照特定顺序启动或停止。 例如,先启动主节点,再启动从节点。 需要持久化存储必须使用 PersistentVolume(PV)保证数据不随 Pod 删除而丢失。 Pod 调度位置需要考虑 Pod 可能需要绑定特定的 Node 节点,确保存储卷挂载一致性或性能需求。 Kubernetes 控制器使用 StatefulSet 管理,支持:固定的 Pod 命名(如 mysql-0, mysql-1); 有序部署、有序扩容和缩容; 持久化存储与 Pod 一一对应。 典型代表:
MySQL、Kafka、ZooKeeper、ElasticSearch、Redis Cluster。 Kubernetes 通过 StatefulSet 部署有状态应用
创建 YAML 配置文件(比如 nginx_statefulset.yaml),用于通过 StatefulSet 部署一个 Nginx 的 Pod 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx-statefulset namespace: default spec: serviceName: nginx replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 StatefulSet) 1 kubectl apply -f nginx_statefulset.yaml
查看所有 Pod 的运行状态,可以看到 Pod 的名称是根据一定规则生成的(全局唯一) 1 kubectl get pods -o wide
1 2 3 4 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-statefulset-0 1/1 Running 0 77s 10.244.2.29 k8s-node3 <none> <none> nginx-statefulset-1 1/1 Running 0 65s 10.244.3.11 k8s-node2 <none> <none> nginx-statefulset-2 1/1 Running 0 37s 10.244.0.15 k8s-node1 <none> <none>
Kubernetes 通过 Service 暴露有状态应用
创建 YAML 配置文件(如 nginx_service.yaml),用于通过 Service 暴露有状态应用 1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 60 name: web clusterIP: None selector: app: nginx
无头服务(Headless Service)是什么
无头服务是没有虚拟 IP(ClusterIP)的 Service(Headless Service),是一种没有 ClusterIP 的特殊 Service 类型,详细介绍请看 这里 。 无头服务可以用于暴露 Kubernetes 集群内 Pod 的真实 IP 和 DNS 名称(域名),而不是通过一个统一的虚拟 IP(ClusterIP)进行负载均衡,即 Kubernetes 不会做流量负载均衡。 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Service) 1 kubectl apply -f nginx_service.yaml
查看 Servcie 列表,可以看到有状态应用的 ClusterIP 为 None 1 2 3 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 53d nginx ClusterIP None <none> 60/TCP 2m12s
提示
通过 Headless Service 暴露 Pod 后,每个 Pod 都有一个唯一的名称和 DNS 名称(域名),域名格式:<pod-name>.<service-name>.<namespace>.svc.cluster.local,默认的命名空间(namespace)是 default。 在 Kubernetes 集群内,可以通过 Pod 的 DNS 域名直接访问 Pod(前提是已经部署 CoreDNS ),比如:http:://nginx-statefulset-0.nginx.default.svc.cluster.local:80。 在 Kubernetes 集群内部,通过 Service 的 DNS 名称(域名)访问有状态应用
特别注意
ClusterIP 为 None 的 Service(Headless Service)只能在 Kubernetes 集群内部访问,如果在集群外部机器(比如直接在集群的 Master 节点)上,通过 Pod 的 DNS 名称直接访问 Pod(比如 http://nginx-statefulset-0.nginx.default.svc.cluster.local:80),肯定是无法访问成功的。
创建一个临时 Pod,并进入 Pod 内部的交互式 Shell 1 2 kubectl run test -pod --image =busybox:1.35 --restart =Never -it --rm -- sh
在临时 Pod 的内部,可以通过 Service 的 DNS 名称(域名)查询所有匹配 Pod 的 IP(必须保证临时 Pod 与 Service 处于同一个命名空间),域名格式:<service-name>.<namespace>.svc.cluster.local 1 nslookup nginx.default.svc.cluster.local
1 2 3 4 5 6 7 8 9 Server: 10.0.0.2 Address: 10.0.0.2:53 Name: nginx.default.svc.cluster.local Address: 10.244.3.11 Name: nginx.default.svc.cluster.local Address: 10.244.2.29 Name: nginx.default.svc.cluster.local Address: 10.244.0.15
在临时 Pod 的内部,还可以通过 Pod 的 DNS 名称(域名)直接访问指定的 Pod,域名格式:<pod-name>.<service-name>.<namespace>.svc.cluster.local 1 nslookup nginx-statefulset-0.nginx.default.svc.cluster.local
1 2 3 4 5 Server: 10.0.0.2 Address: 10.0.0.2:53 Name: nginx-statefulset-0.nginx.default.svc.cluster.local Address: 10.244.2.29
1 2 wget -qO - http://nginx-statefulset-0.nginx.default.svc.cluster.local :80
Kubernetes 删除 StatefulSet 和 Service
如果需要删除上面创建的 StatefulSet 和 Service,可以执行以下命令 1 2 3 4 5 kubectl delete service nginx kubectl delete statefulset nginx-statefulset --cascade =true
部署守护进程 note
本节将演示在 Kubernetes 集群中,如何通过 DaemonSet 在每个 Node(工作节点)上分别部署一个守护进程。 这里的守护进程是指节点级的后台服务,比如日志收集(Filebeat)、网络插件(Flannel)、监控代理(Prometheus Node Exporter)等服务,为了方便演示,下面直接使用 Nginx 来代替。 Kubernetes 中 DaemonSet 的主要功能和适用场景
主要功能:
在每个节点上运行一个指定的 Pod 自动在集群中每个符合条件的节点上部署且只运行一个指定的 Pod 实例。 节点加入自动部署当新节点加入集群时,DaemonSet 会自动在该节点上调度并启动 Pod。 节点移除自动回收节点被移除或不可用时,对应 Pod 会自动删除,保持一致性。 不支持手动扩容 / 缩容 Pod 的副本数量与节点数量直接关联,不支持手动管理 replicas。 支持滚动更新与回滚 可结合节点选择器、节点亲和性、污点 / 容忍等使用支持精确控制 DaemonSet Pod 部署在哪些节点上。 与 Deployment 区别 Deployment:通常用于无状态服务,副本数固定,由用户定义。 DaemonSet:与节点数量绑定,强调 “每个节点一个 Pod”。 删除行为可控使用 kubectl delete daemonset 删除 DaemonSet 时,可通过 --cascade=orphan 参数控制是否保留关联的 Pod。 适用场景:
日志收集部署日志收集 Agent(如 Fluentd、Logstash、Filebeat),保证每个节点日志都能被采集。 监控与指标采集例如 Prometheus Node Exporter、Datadog Agent、cAdvisor 等,采集节点和 Pod 的监控指标。 网络插件或 CNI 管理 Kubernetes CNI 插件通常以 DaemonSet 运行,例如 Calico、Flannel、Cilium 等。 存储插件或 CSI 驱动如 Ceph、Rook 等分布式存储系统的节点守护进程。 安全与合规审计如 Falco、Sysdig Secure 等安全审计或防护 Agent。 节点运维任务自动在每个节点运行健康检查、系统维护脚本或运维工具。 Kubernetes 通过 DaemonSet 部署守护进程
创建 YAML 配置文件(比如 nginx_daemonset.yaml),用于通过 DaemonSet 在每个节点上分别部署一个 Nginx 的 Pod,,并将宿主机内的 /var/log 目录挂载到容器内部的 /tmp/log 目录(可选操作) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx-daemonset labels: app: nginx spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.15 ports: - containerPort: 80 volumeMounts: - name: varlog mountPath: /tmp/log volumes: - name: varlog hostPath: path: /var/log
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 DaemonSet) 1 kubectl apply -f nginx_daemonset.yaml
1 kubectl get daemonset nginx-daemonset
1 2 NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE nginx-daemonset 4 4 4 4 4 <none> 6m17s
查看所有 Pod 的运行状态,可以发现每个 Node(工作节点)都部署了一个 Nginx 的 Pod 1 kubectl get pods -o wide
1 2 3 4 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-daemonset-mhxpg 1/1 Running 0 4s 10.244.2.35 k8s-node3 <none> <none> nginx-daemonset-nsb7r 1/1 Running 0 4s 10.244.1.16 k8s-node1 <none> <none> nginx-daemonset-p9k2d 1/1 Running 0 4s 10.244.3.17 k8s-node2 <none> <none>
1 2 3 4 5 kubectl exec -it nginx-daemonset-p9k2d bash ls /tmp/log /
Kubernetes 删除 DaemonSet
如果需要删除上面创建的 DaemonSet,可以执行以下命令 1 2 3 4 5 kubectl delete daemonset nginx-daemonset kubectl delete daemonset nginx-daemonset --cascade =orphan
部署一次性任务 提示
本节将演示在 Kubernetes 集群中,如何通过 Job 执行一次性任务。
Kubernetes 中 Job 的主要功能和适用场景
主要功能
执行一次性任务,保证任务至少成功执行一次 Job 会确保定义的 Pod 按照预期执行,直到成功完成(运行状态为 Completed)。 Pod 运行失败时,Job 会根据重试策略自动重新创建新的 Pod 继续执行任务。 支持并行或串行执行可以通过 spec.parallelism 控制同时运行的 Pod 数量; 可以通过 spec.completions 控制任务总共需要成功完成的 Pod 数量。 适合一次性任务,执行完成后不会再次运行 Job 完成后,Pod 不会被自动删除,但状态保持为 Completed; 可以通过配置 TTL 控制器自动清理已完成的 Job 及 Pod。 适用场景
Kubernetes 通过 Job 执行一次性任务
创建 YAML 配置文件(比如 pi_job.yaml),用于通过 Job 执行一次 Perl 脚本(计算圆周率) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 apiVersion: batch/v1 kind: Job metadata: name: pi-job spec: backoffLimit: 4 template: spec: containers: - name: pi image: perl command: ["perl" , "-Mbignum=bpi" , "-wle" , "print bpi(2000)" ] restartPolicy: Never
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Job) 1 kubectl apply -f pi_job.yaml
1 2 NAME COMPLETIONS DURATION AGE pi-job 1/1 25s 25s
查看所有 Pod 的运行状态,可以发现当 Job(一次性任务)执行完成后,Pod 的状态会切换为 Completed 1 kubectl get pods -o wide
1 2 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pi-ks6pn 0/1 Completed 0 41s 10.244.2.36 k8s-node3 <none> <none>
1 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
Kubernetes 删除 Job
1 2 3 4 5 kubectl delete job pi-job kubectl delete job pi-job --cascade =orphan
部署定时任务 提示
本节将演示在 Kubernetes 集群中,如何通过 CronJob 周期性(定时)执行任务。
Kubernetes 中 CronJob 的主要功能和适用场景
主要功能
周期性任务调度使用 cron 表达式定义执行计划,精确到分钟; 可在每天、每周、每月或特定时间点自动运行任务。 自动创建 JobCronJob 在到达调度时间后,会自动创建对应的 Job 资源; Job 负责任务的执行、失败重试和状态维护。 控制并发执行可通过 concurrencyPolicy 控制多次调度的 Job 是否允许并发执行:Allow:允许多个任务并发运行;Forbid:禁止并发,若上一个任务未完成,跳过新的调度;Replace:如果上一个任务未完成,先删除旧任务,再启动新任务。 支持任务历史管理可以配置保留的成功任务和失败任务历史数量,避免资源无限增长。 支持一次性定时任务通过指定一次性运行的时间点,实现一次性定时触发的 Job。 适用场景
定时数据处理每天凌晨自动跑批处理作业,生成统计报表; 定时清理临时文件或过期数据。 数据库备份 日志归档 周期性健康检查 定时通知或消息推送 一次性延时执行任务 Kubernetes 通过 CronJob 运行定时任务
创建 YAML 配置文件(比如 hello_cronjob.yaml),用于通过 CronJob 周期性地执行 Shell 脚本(打印日志信息) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 apiVersion: batch/v1beta1 kind: CronJob metadata: name: hello-cronjob spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello image: busybox args: - /bin/sh - -c - date; echo Hello from the Kubernetes cluster restartPolicy: OnFailure
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 CronJob) 1 kubectl apply -f hello_cronjob.yaml
1 2 NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE hello-cronjob */1 * * * * False 0 49s 52s
查看所有 Job 的运行状态,CronJob 不直接创建和运行 Pod,所有 Pod 都由其生成的 Job 进行管理 1 2 3 4 NAME COMPLETIONS DURATION AGE hello-cronjob-1759064520 1/1 17s 3m11s hello-cronjob-1759064580 1/1 13s 2m20s hello-cronjob-1759064640 1/1 17s 78s
查看所有 Pod 的运行状态,可以发现当 CronJob 每次执行完成后,Pod 的状态会切换为 Completed 1 kubectl get pods -o wide
1 2 3 4 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hello-cronjob-1759064340-mfppj 0/1 Completed 0 2m28s 10.244.2.38 k8s-node3 <none> <none> hello-cronjob-1759064400-djk6l 0/1 Completed 0 86s 10.244.2.39 k8s-node3 <none> <none> hello-cronjob-1759064460-5lbxj 0/1 Completed 0 25s 10.244.3.18 k8s-node2 <none> <none>
1 kubectl logs hello-cronjob-1759064460-5lbxj
1 2 Sun Sep 28 13:01:26 UTC 2025 Hello from the Kubernetes cluster
Kubernetes 删除 CronJob
如果需要删除上面创建的 CronJob,可以执行以下命令 1 2 3 4 5 kubectl delete cronjob hello-cronjob kubectl delete cronjob hello-cronjob --cascade =orphan
应用升级回滚 学习目标
本节将演示在 Kubernetes 集群中部署 Nginx 后,如何升级 Nginx 的版本,还有如何回滚 Nginx 的版本,更详细的应用升级回滚实战可以看 这里 。
部署应用 生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx,Nginx 的版本号为 1.14 1 kubectl create deployment nginx --image =nginx:1.14 --dry -run=client -o yaml > nginx_deployment.yaml
更改自动生成的 YAML 配置文件内容(如下所示),将 replicas 改为 2(表示 Pod 有两个副本) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 2 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.14 name: nginx resources: {} status: {}
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment) 1 kubectl apply -f nginx_deployment.yaml
1 kubectl get pods -o wide
1 2 3 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5658bdf5d4-6sbmg 1/1 Running 0 31m 10.244.1.2 k8s-node1 <none> <none> nginx-5658bdf5d4-ksjgm 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>
升级应用版本 当执行完上述步骤将 Nginx 部署到 Kubernetes 集群后,可以执行以下命令来升级 Nginx 的版本(比如,将 Nginx 升级到 1.15 版本) 1 kubectl set image deployment nginx nginx=nginx:1.15
1 kubectl rollout status deployment nginx
1 kubectl get pods -o wide
1 2 3 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-764b95f4c5-f744r 1/1 Running 0 31m 10.244.1.2 k8s-node3 <none> <none> nginx-764b95f4c5-w96gl 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>
若执行完应用升级版本的命令后,在查看所有 Pod 的运行状态时,新 Pod 的 STATUS 一直显示 ContainerCreating,则说明应用升级版本存在问题 1 2 3 4 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5658bdf5d4-6sbmg 1/1 Running 0 77m 10.244.1.2 k8s-node1 <none> <none> nginx-764b95f4c5-f744r 1/1 Running 0 27m 10.244.2.19 k8s-node3 <none> <none> nginx-764b95f4c5-w96gl 0/1 ContainerCreating 0 3m36s <none> k8s-node2 <none> <none>
可以执行以下命令来排查问题(比如,原因是一直卡在拉取镜像的环节上) 1 kubectl describe pod nginx-764b95f4c5-w96gl
若无法排查应用升级版本的问题,则可以删除卡住的 Pod 以触发重建 1 kubectl delete pod nginx-764b95f4c5-w96gl
若无法排查应用升级版本的问题,又急需恢复服务,最快捷的方法是回滚(回退)到上一个版本(即用旧版本的 Pod 替换掉所有新版本的 Pod),之后服务会逐渐恢复正常 1 kubectl rollout undo deployment nginx
特别注意
Kubernetes 在升级应用的版本时,是不会中断服务的(比如,升级期间 Nginx 依然可以对外提供服务),这主要归功于其精细的流量控制和渐进的替换过程。具体是通过 Deployment 控制器,先启动新版本的 Pod 并确认其就绪,然后逐步终止旧版本的 Pod,同时 Service 的负载均衡器会确保流量只路由到健康的 Pod 上,从而实现了服务的平滑升级。
回滚应用版本 当执行完上述步骤将 Nginx 的版本从 1.14 升级到 1.15 后,若希望回滚到旧的版本(即用旧版本的 Pod 替换掉所有新版本的 Pod),可以执行以下命令 1 2 kubectl rollout history deployment nginx
1 2 3 4 5 kubectl rollout undo deployment nginx kubectl rollout undo deployment nginx --to -revision=2
1 kubectl get pods -o wide
1 2 3 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5658bdf5d4-6sbmg 1/1 Running 0 31m 10.244.1.2 k8s-node1 <none> <none> nginx-5658bdf5d4-ksjgm 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>
应用弹性伸缩 学习目标
本节将演示在 Kubernetes 集群中部署 Nginx 后,如何对 Nginx 进行扩容(即增加 Pod 的副本数量),更详细的应用扩容缩容实战可以看 这里 。
部署应用 生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx 1 kubectl create deployment nginx --image =nginx --dry -run=client -o yaml > nginx_deployment.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} status: {}
创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment) 1 kubectl apply -f nginx_deployment.yaml
1 kubectl get pods -o wide
1 2 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5658bdf5d4-kt6fv 1/1 Running 0 29m 10.244.2.18 k8s-node3 <none> <none>
应用扩缩容 当执行完上述步骤将 Nginx 部署到 Kubernetes 集群后,可以执行以下命令来对 Pod 的副本数进行扩缩容 1 2 kubectl scale deployment nginx --replicas =3
1 kubectl get pods -o wide
1 2 3 4 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-5658bdf5d4-kt6fv 1/1 Running 0 29m 10.244.0.7 k8s-node3 <none> <none> nginx-5658bdf5d4-tbvzz 1/1 Running 0 2m55s 10.244.1.3 k8s-node1 <none> <none> nginx-5658bdf5d4-z48mx 1/1 Running 0 2m57s 10.244.3.6 k8s-node2 <none> <none>
参考资料