# 7. Self-healing - 使用 k8s 的 **Deployment** object 来使 app **resilient**。 ## Intro to k8s Deployments - k8s 有许多 objects 用来添加特性和能力。Deployment object 用来添加 self-healing。 - deploy.yml <img src="https://img.jonahgao.com/oss/note/2025p1/intro_k8s_deployment.jpeg" width="600" /> ### How Deployments work - Deployments 有两个主要的部分: 1. The **object**:负责定义(definition) 2. The **controller**:负责实现和正确运行。 - controller 不断地监测 cluster,留意变化。 - 例如期望是 5 个 pods,当前是 4 个,它会重新启动一个 pod,同步到 desired state。 ## Self-heal from a Pod failure - 如果 Pods 是由 Deployment 管理的,当 Pod 故障后,K8s 会自动尝试进行恢复,启动新 Pod 替换失败的 Pod。 - 部署 deployment 到 cluster : ```sh kubectl apply -f deploy.yml # 查看 Deployment kubectl get deployments ``` - pod failure ```sh # 手动删除一个 pod kubectl delete pod qsk-deploy-845b58bd85-5txzv ``` ## Self-heal from a worker node failure - 当一个 worker node 失败后,node 上的所有 Pods 都会丢失。 如果是通过 Deployment 管理的 Pods,k8s 会在存活的 nodes 上启动替换 Pods。 - 但 k8s 不会自动在 nodes 上 re-balance Pods。 ----------- # 8. Scaling the app - 使用 Horizontal Pod Autoscaler(HPA)来自动化 scaling。 ## Scale an application up - 编辑 Deployment YAML 文件,增加 replica(为 10),重新发送文件到 K8s,通知 reconciliation 处理和增加副本。 - K8s scaling 的单元是 **Pod** ,即通过增加 / 减少 Pod 来扩缩容。 - 将新的 YAML 文件重新发送后会发生: 1. desired state 会从 5 变为 10 2. Deployment controller 观察到当前副本数与期望副本数不一样 3. Deployment controller 调度 5 个新的副本 - 调度新副本过程中 K8s 会考虑 Pods 在 worker nodes 上 的 re-balance。 - 通过 YAML 文件来 scalling 使用了声明式的方式( declarative method)。 ## Scale an application down - 使用 **kubectl scale**命令来讲副本减少到 5,这种是命令式的方式(imperative method,更推荐使用声明式)。 ```sh kubectl scale --replicas 5 deployment/qsk-deploy ``` ### The role of labels - Deployment 使用 labels 来确保只管理它创建的 Pods。 - 每次 Deployment 创建一个 Pod 后,它会给这个新 Pod 一个 label。 - 通过这个 label,它可以知道哪些 Pods 是它创建的,它可以管理。 - scaling up 时,Deployment 会添加相同 label 的 Pods。scale down 时也只会删除 label 相同的 Pods。 ### Declarative vs imperative - 两种执行更新的方式: - Declaratively:通过 YAML 配置文件。 - Imperatively:使用 kubectl 命令,生产环境不建议使用。手动设置的状态容易跟配置文件冲突。 -------- # 9. Performing a rolling update - zero-downtime rolling update。 ## Deploy the rollout - 实验目标:对所有 5 个副本执行滚动更新,一次一个副本,中间停止一小段时间。 - 更新步骤: 1. 编辑 deploy.yml 文件,配置更新设置 和 执行镜像的新版本 2. 发送更改后的 YAML 文件给 k8s 3. 观察更新过程 4. 测试新版本 - 编辑 rolling-update YAML 文件: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: qsk-deploy spec: replicas: 5 selector: matchLabels: project: qsk-book minReadySeconds: 20 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 template: metadata: labels: project: qsk-book spec: containers: - name: qsk-pod imagePullPolicy: Always ports: - containerPort: 8080 # 指定新的镜像版本 image: nigelpoulton/qsk-book:1.1 ``` - K8s 不会真的去更新副本,而是**删除已有的副本**,将它们替换为新版本。 - 新增的六行告诉 k8s 如何执行更新 - **minReadySeconds**: 每次更新完一个副本后,等待多少秒 - **maxSurge=1**:更新过程中可以额外添加一个 Pod。 - **maxUnavailable=0**:当低于 5 个 Pods 停止更新。(5 个是之前 deployment 指定的)。 - 后两个选项强制 k8s 更新时添加第 6 个新版本的 Pod,然后删除一个老的。 - 执行更新: ```sh kubectl apply -f deploy.yml ``` - 观察滚动更新过程: ```sh kubectl rollout status deployment qsk-deploy ```