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 包含两个容器:debnginx,分别运行 debian:latestnginx: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 也会被删除


原始标题:Pod Redundancy in Kubernetes or Why Deleted Pods Get Recreated