# 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
```