Kubernetes 持久性系列 第3部分:控制器与弹性 — 为什么 Kubernetes 自动修复
Source: Dev.to
您将学到
- 应用控制器(NGINX Ingress、cert‑manager)在驱逐过程中的持久化方式
- 为什么控制器是无状态的,并且可以在任何地方重新启动
- 从硬件到应用的完整持久化链路
- 哪些在 Pod 驱逐后仍然存活,哪些则不会
之前
现在我们进入最后一层:你的应用控制器——以及使 Kubernetes 真正具备弹性的优雅洞见。
第 4 层:应用控制器
应用控制器如何持久化
像 NGINX Ingress、cert‑manager 和 Prometheus Operator 这样的控制器通常以 Deployments 或 StatefulSets 的形式部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
spec:
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.9.0
当该 Pod 被驱逐时:
- kubelet 停止上报该 Pod → 控制平面将其标记为 Terminated(已终止)。
- ReplicaSet 控制器 看到
currentReplicas (0)……
关键点: 控制器本身不存储状态;它从 API Server(由 etcd 支持)读取所有信息。
Helm 发布持久化
Helm 将发布信息存储在 Kubernetes Secrets 中:
kubectl get secret -n monitoring -l owner=helm -o yaml
apiVersion: v1
kind: Secret
metadata:
name: sh.helm.release.v1.prometheus.v3
labels:
owner: helm
name: prometheus
version: "3"
type: helm.sh/release.v1
data:
release: H4sIAAAAAAAAA... # Base64‑encoded release manifest
该 Secret 包含:
- 已安装的 Chart
- 使用的 Values(值)
- 所有资源的计算后 Manifest(清单)
由于该 Secret 通过 API Server 存储在 etcd 中,Helm 发布能够在任何 Pod 被驱逐后仍然保留。
完整的持久化链
┌─────────────────────────────────────────────────────────────────────┐
│ Linux Host (Physical/VM) │
├─────────────────────────────────────────────────────────────────────┤
│ systemd (PID 1) │
│ ├── Supervises all system services │
│ ├── Restarts failed services automatically │
│ └── Config: /etc/systemd/system/ │
│ │ │
│ └── kubelet.service │
│ ├── Started and supervised by systemd │
│ ├── Watches /etc/kubernetes/manifests/ for static pods │
│ ├── Watches API server for scheduled pods │
│ └── Ensures containers match pod specs │
│ │ │
│ ├── Static Pods (/etc/kubernetes/manifests/) │
│ │ ├── etcd ──────────────────┐ │
│ │ ├── kube-apiserver ◄───────┤ Persistent │
│ │ ├── kube-controller-manager│ State Store │
│ │ └── kube-scheduler │ │
│ │ │ │
│ └── Regular Pods ◄─────────────┘ │
│ │ (scheduled via API server) │
│ │ │
│ ├── kube-system namespace │
│ │ ├── CoreDNS │
│ │ ├── kube-proxy │
│ │ └── CNI plugins │
│ │ │
│ ├── ingress-nginx namespace │
│ │ └── NGINX Ingress Controller │
│ │ └── Watches Ingress resources │
│ │ │
│ └── Application namespaces │
│ ├── cert-manager │
│ ├── Prometheus Operator │
│ └── Your applications │
└─────────────────────────────────────────────────────────────────────┘
关键洞察:控制器是无状态的
这是设计的优雅核心:控制器不存储状态。
| 控制器的作用 | 工作方式 |
|---|---|
| 读取 期望状态 | 从 API 服务器(由 etcd 支持) |
| 监视 更改 | 通过 API 服务器的 watch 机制 |
| 进行更改 | 通过向 API 服务器提交更新 |
| 可以在任何地方重新启动 | 信息不丢失;API 服务器仍然是唯一的事实来源 |
API server + etcd 是 唯一的事实来源,而不是控制器本身。

监督层级 (Mermaid 图)
flowchart LR
subgraph Source["Source of Truth"]
etcd[(etcd)]
api[API Server]
end
subgraph StatelessControllers["Stateless Controllers"]
deploy[Deployment Controller]
rs[ReplicaSet Controller]
nginx[NGINX Ingress]
cert[cert-manager]
end
etcd -->> api
api -->> deploy
api -->> rs
api -->> nginx
api -->> cert
style etcd fill:#e67700,color:#fff
style api fill:#e67700,color:#fff
(如果图表未渲染,请使用上面的代码在 Mermaid Live Editor 中直接查看。)
为什么这很重要
- 删除任何控制器 Pod → 它会重新启动并赶上最新状态。
- 将控制器移动到不同节点 → 它们只需重新连接到 API Server。
- 将控制器扩展为多个副本 → 它们通过 API Server 协调工作。
- 升级控制器 → 新版本会从 etcd 读取相同的状态。
什么会保留,什么不会
在任何 Pod 驱逐情况下仍然保留
| 资源 | 为什么会保留 |
|---|---|
| etcd 中的 Kubernetes 对象 | 与 Pod 独立存储 |
| Helm 发布 | 以 Secret 形式存储在 etcd 中 |
| Operator 管理的 CRD | 由 Operator 持续调和 |
| 持久卷 | 存储位于集群外部 |
| ConfigMap / Secret | 存储在 etcd 中 |
在没有帮助的情况下不会保留
| 资源 | 为什么不会保留 |
|---|---|
Pod 本地 EmptyDir 卷 | 随 Pod 被删除 |
| 手动应用且缺少依赖的资源 | 重新创建时被验证 webhook 拒绝 |
| 内存缓存 | 进程重启后内存丢失 |
| 节点本地状态 | 除非显式持久化,否则会丢失 |
设计的优雅
Kubernetes 的架构遵循若干关键设计原则:
- 声明式优于命令式 – 描述期望的状态,而不是实现步骤。
- 调和优于事务 – 持续收敛到期望状态。
- 无状态控制器 – 状态保存在 etcd 中,而不是控制器进程。
- 层级监督 – 每一层监视其上层。
- 故障是常态 – 为恢复而设计,而不是为防止故障。
正因为这些原则,Kubernetes 集群可以:
- 节点意外失效。
- 因资源压力而驱逐 Pod。
- 发生网络分区。
- 进行滚动升级。
……并仍然保持应用可用性。
结论
从调试缺失的 Ingress 到了解完整的监督层级的过程,揭示了使 Kubernetes 具备弹性的精密机制。
systemd → kubelet → static pods → control plane → controllers → your apps
每一层都监督下一层,etcd 充当持久化内存,能够在任何组件故障后仍然存活。
关键洞见: Kubernetes 并不是阻止故障,而是通过分层监督、etcd 中的持久状态以及持续的调和循环,自动从故障中恢复。
这正是 Kubernetes 的真正力量:并非系统永不出错,而是当错误发生时,系统能够自行恢复到期望的状态。
系列回顾
- 第 1 部分:当我们的 Ingress 消失时 – 引发一切的事件。
- 第 2 部分:基础 –
systemd → kubelet → control plane。 - 第 3 部分:控制器与弹性 – 为什么 Kubernetes 能自我修复。
进一步阅读
觉得本系列有用吗?关注获取更多 Kubernetes 内部原理内容!