1. 引言
Kubernetes 作为容器编排平台,其基础功能其实可以通过脚本和容器运行时配置手动实现。但 Kubernetes 的价值在于它将这些操作自动化并提供了统一的管理界面。例如,Kubernetes 提供了多种机制来实现服务的高可用和容错能力。
本文将重点探讨一个常见现象:为什么在 Kubernetes 中删除一个 Pod 后,它会被自动重建?我们将从 Pod 的基本概念讲起,逐步介绍重启策略、控制器机制,以及 Pod 被删除后的恢复逻辑。最后,我们还会讨论如何降低或禁用这种自动恢复机制。
2. Kubernetes 中的 Pod
Pod 是 Kubernetes 中最小的部署单元,一个 Pod 可以包含一个或多个共享网络、存储等资源的容器。
下面是一个包含两个容器的 Pod 示例:
$ kubectl apply --filename=- <<< '
apiVersion: v1
kind: Pod
metadata:
name: compod
spec:
containers:
- name: deb
image: debian:latest
command: ["sh", "-c"]
args: ["echo Initialized... && sleep 666"]
tty: true
- name: nginx
image: nginx:latest
command: ["sh", "-c"]
args: ["echo Initialized... && nginx -g \"daemon off;\""]
tty: true
'
这个 Pod 包含两个容器:deb
和 nginx
,分别运行 debian:latest
和 nginx:latest
镜像。
我们可以通过以下命令查看 Pod 状态:
$ kubectl get pod compod
NAME READY STATUS RESTARTS AGE
compod 2/2 Running 0 12s
✅ 注意:Pod 是运行任务的基本单位,通常承载一个或多个服务,因此我们期望它保持运行状态。
3. Pod 的重启策略
为了确保容器持续运行,Kubernetes 提供了三种重启策略:
策略 | 行为描述 |
---|---|
Always |
容器退出后总是重启(默认) |
OnFailure |
仅在容器因错误退出时重启 |
Never |
从不自动重启 |
这些策略由 Kubernetes 的监控机制执行。如果容器退出,Kubernetes 会根据策略决定是否重启。
我们来看一个示例:
$ kubectl apply --filename=- <<< '
apiVersion: v1
kind: Pod
metadata:
name: compod
spec:
containers:
- name: deb
image: debian:latest
command: ["sh", "-c"]
args: ["echo Initialized... && sleep 5"]
tty: true
- name: nginx
image: nginx:latest
command: ["sh", "-c"]
args: ["echo Initialized... && sleep 5"]
tty: true
'
这两个容器执行完命令后就会退出。由于默认策略是 Always
,Kubernetes 会不断重启它们:
$ kubectl get pod/compod
NAME READY STATUS RESTARTS AGE
compod 2/2 Running 4 (5s ago) 36m
⚠️ 注意:重启策略只适用于容器退出的情况,删除 Pod 本身不会触发重启策略。
4. Pod 与控制器
虽然 Pod 是最小部署单元,但在实际应用中,我们很少直接管理 Pod。为了实现高可用性,通常会将 Pod 与控制器(如 ReplicaSet、Deployment 等)结合使用,这类组合被称为“工作负载(Workload)”。
控制器的作用是确保指定数量的 Pod 副本始终运行。例如,ReplicaSet 可以通过 replicas
字段指定 Pod 副本数,并通过 selector
匹配对应的 Pod 标签。
以下是一个简单的 ReplicaSet 示例:
$ kubectl apply --filename=- <<< '
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: compod-rs
labels:
name: compod
spec:
replicas: 3
selector:
matchLabels:
name: compod
template:
metadata:
labels:
name: compod
spec:
containers:
- name: deb
image: debian:latest
command: ["sh", "-c"]
args: ["echo Initialized... && sleep 666"]
tty: true
- name: nginx
image: nginx:latest
command: ["sh", "-c"]
args: ["echo Initialized... && nginx -g \"daemon off;\""]
tty: true
'
查看 ReplicaSet 和 Pod 的状态:
$ kubectl get rs compod-rs
NAME DESIRED CURRENT READY AGE
compod-rs 3 3 3 30s
$ kubectl get pods --selector=name=compod
NAME READY STATUS RESTARTS AGE
compod-rs-dlh4d 2/2 Running 0 31s
compod-rs-m7r5b 2/2 Running 0 31s
compod-rs-vrmff 2/2 Running 0 31s
✅ 总结:控制器会持续监控 Pod 的状态,一旦 Pod 被删除或异常退出,控制器会自动创建新的 Pod 来维持副本数。
5. 删除 Pod 的行为分析
既然控制器会监控 Pod,那如果我们手动删除一个 Pod,会发生什么?
我们来测试一下前面创建的 ReplicaSet:
$ kubectl get pods --selector=name=compod
NAME READY STATUS RESTARTS AGE
compod-rs-dlh4d 2/2 Running 0 51s
compod-rs-m7r5b 2/2 Running 0 51s
compod-rs-vrmff 2/2 Running 0 51s
我们删除其中一个 Pod:
$ kubectl delete pod compod-rs-dlh4d
pod "compod-rs-dlh4d" deleted
稍等片刻后查看:
$ kubectl get pods --selector=name=compod
NAME READY STATUS RESTARTS AGE
compod-rs-m7r5b 2/2 Running 0 1m
compod-rs-ntskj 2/2 Running 0 5s
compod-rs-vrmff 2/2 Running 0 1m
✅ 结果:控制器检测到 Pod 被删除后,自动创建了一个新的 Pod(compod-rs-ntskj
)来替代被删除的 Pod。
⚠️ 关键点:Pod 的自动重建是由控制器触发的,而不是 Pod 本身的机制。
6. 如何降低或禁用 Pod 的自动重建
有时候我们不希望 Pod 被自动重建,比如在调试或维护期间。下面介绍几种方法。
6.1 修改重启策略
每个 Pod 都有一个 restartPolicy
字段,默认为 Always
。
查看当前策略:
$ kubectl get pod/compod --output=jsonpath='{..restartPolicy}'
Always
⚠️ 注意:Pod 的重启策略不可修改,只能重建 Pod 或将其绑定到控制器中。
控制器的重启策略也不可修改,只能重建控制器。
6.2 修改控制器副本数
我们可以使用 kubectl scale
命令修改控制器的副本数:
$ kubectl scale replicaset compod-rs --replicas=1
replicaset.apps/compod-rs scaled
查看结果:
$ kubectl get pods --selector=name=compod
NAME READY STATUS RESTARTS AGE
compod-rs-m7r5b 2/2 Running 0 12h
✅ 说明:设置副本数为 1
后,只保留了一个 Pod。如果设置为 0
,则 Pod 会被全部删除,但控制器定义仍然保留。
⚠️ 限制:控制器的 selector
字段在创建后不可修改。
6.3 删除控制器或 Pod 脱离控制器
如果我们不希望 Pod 被控制器管理,可以:
- 删除控制器,Pod 也会被删除
- 将 Pod 从控制器中“剥离”(不推荐)
一旦 Pod 不再受控制器管理,它将遵循全局的 restartPolicy
。
7. 总结
在 Kubernetes 中,Pod 被删除后自动重建的现象,是由控制器(如 ReplicaSet、Deployment)监控机制触发的。控制器确保指定数量的 Pod 副本始终运行,从而实现高可用性和容错能力。
如果你不希望 Pod 被自动重建,可以:
- 修改控制器的副本数为
0
- 删除控制器
- 手动管理 Pod(不推荐)
✅ 总结要点:
操作 | 是否触发重建 | 控制器影响 |
---|---|---|
删除 Pod | ✅ 是 | 控制器会重建 |
修改重启策略 | ❌ 否 | Pod 无法修改,需重建 |
缩容副本数 | ✅ 是 | 控制器控制 |
删除控制器 | ✅ 是 | Pod 也会被删除 |