Pod 是 Kubernetes 中最小的调度单元,也是应用运行的最小载体。理解 Pod 的生命周期、调度机制、健康检查和资源管理,是每个 K8s 使用者的必修课。本文将深入探讨 Pod 管理的关键技术与最佳实践。

Pod 的核心概念

Pod 由一个或多个容器组成,这些容器共享:

  • 网络命名空间:共享 IP 和端口空间

  • 存储卷(Volume):共享数据

  • IPC 命名空间:进程间通信

  • 生命周期:同生共死

Pod 的调度机制
Pod 创建 → Scheduler 调度 → 节点绑定 → Kubelet 拉取镜像 → 容器启动 → Pod Running

调度器考虑的维度:

  • 资源需求(CPU/内存)

  • 节点亲和性/反亲和性

  • 污点与容忍

  • 拓扑分布约束

Pod 生命周期的五大阶段

阶段说明
PendingPod 已被创建,但尚未调度或镜像未拉取完成
Running至少一个容器处于运行状态
Succeeded所有容器成功退出(Job 场景)
Failed至少一个容器以非零状态退出
Unknown节点失联,状态未知

容器状态与重启策略

容器状态
  • Waiting:等待拉取镜像或启动

  • Running:运行中

  • Terminated:已终止,包含退出码

重启策略
Always始终重启常驻服务(Deployment)
OnFailure失败时重启批处理任务(Job)
Never从不重启一次性任务

kubectl 命令总览与分类

资源创建:create

# 从 YAML/JSON 文件创建
kubectl create -f deployment.yaml
kubectl create -f https://example.com/remote-config.yaml

# 从目录创建(递归处理)
kubectl create -f ./manifests/

# 从多个文件创建
kubectl create -f pod.yaml -f service.yaml -f configmap.yaml

kubectl apply(声明式管理)

# 创建或更新(幂等操作)
kubectl apply -f deployment.yaml

# 首次创建:效果同 create
# 再次执行:对比差异,更新变更部分

kubectl edit

# 编辑 Deployment
kubectl edit deployment nginx

# 指定编辑器
KUBE_EDITOR="nano" kubectl edit pod my-pod

# 编辑所有匹配的资源
kubectl edit deployment -l app=web

kubectl patch(部分更新)

# 修改镜像
kubectl patch deployment nginx -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","image":"nginx:1.25"}]}}}}'

# 添加标签
kubectl patch deployment nginx -p '{"metadata":{"labels":{"version":"v2"}}}'

kubectl replace

# 用新文件完全替换
kubectl replace -f updated-deployment.yaml

# 替换并强制(即使有冲突)
kubectl replace -f updated-deployment.yaml --force

# 从 stdin 替换
cat new-config.yaml | kubectl replace -f -

kubectl expose

# 为 Deployment 创建 Service(ClusterIP)
kubectl expose deployment nginx --port=80 --target-port=80

# 指定 Service 类型为 NodePort
kubectl expose deployment nginx \
  --type=NodePort \
  --port=80 \
  --target-port=8080 \
  --name=nginx-nodeport

# 创建 LoadBalancer
kubectl expose deployment web-app \
  --type=LoadBalancer \
  --port=443 \
  --target-port=8443 \
  --name=web-lb

# 指定 NodePort 端口号
kubectl expose deployment nginx \
  --type=NodePort \
  --port=80 \
  --node-port=30080

容器重启规则

Always 无论什么原因都会从新运行pod

# API 版本,Pod 属于核心 v1 组
apiVersion: v1

# 资源类型为 Pod
kind: Pod

# 元数据,用于描述资源的基本信息
metadata:
  # 标签,用于标识和筛选此 Pod
  labels:
    run: testpod        # 标签键值对:run=testpod
  # Pod 的名称,在命名空间内唯一
  name: testpod

# Pod 的规格定义,描述期望状态
spec:
  # 使用宿主机网络(关键配置)
  hostNetwork: true     # true 表示 Pod 直接使用宿主机的网络命名空间
                        # 效果:Pod 内的容器共享宿主机的 IP 和端口
                        # 无需端口映射,容器监听的端口直接在宿主机上生效

  # 重启策略
  restartPolicy: Always # 容器退出后总是自动重启
                        # 其他选项:OnFailure(失败时重启)、Never(从不重启)

  # 容器列表
  containers:
  
  # ========== 容器:busybox ==========
  - image: busybox:latest    # 使用 busybox 最新版镜像(轻量级工具容器)
    name: busybox            # 容器名称
    command:                 # 容器启动时执行的命令(覆盖镜像默认命令)
    - /bin/sh                # 使用 shell 解释器
    - -c                     # 从后面的字符串参数中读取命令
    - sleep 60               # 睡眠 60 秒
    # 作用:容器启动后执行 sleep 60,保持运行 60 秒
    # 60 秒后容器退出,由于 restartPolicy: Always,会自动重启
    # 因此这个 Pod 会不断循环:运行 60 秒 → 退出 → 重启

OnFailure 非正常管关闭会从其pod

# API 版本,Pod 属于核心 v1 组
apiVersion: v1

# 资源类型为 Pod
kind: Pod

# 元数据,用于描述资源的基本信息
metadata:
  # 标签,用于标识和筛选此 Pod
  labels:
    run: testpod        # 标签键值对:run=testpod
  # Pod 的名称,在命名空间内唯一
  name: testpod

# Pod 的规格定义,描述期望状态
spec:
  # 使用宿主机网络(关键配置)
  hostNetwork: true     # true 表示 Pod 直接使用宿主机的网络命名空间
                        # 效果:Pod 内的容器共享宿主机的 IP 和端口
                        # 无需端口映射,容器监听的端口直接在宿主机上生效

  # 重启策略(与上一个配置的差异)
  restartPolicy: OnFailure   # 仅当容器失败退出(退出码非 0)时才重启
                             # 如果容器正常退出(退出码 0),不会重启
                             # 其他选项:Always(总是重启)、Never(从不重启)

  # 容器列表
  containers:
  
  # ========== 容器:busybox ==========
  - image: busybox:latest    # 使用 busybox 最新版镜像(轻量级工具容器)
    name: busybox            # 容器名称
    command:                 # 容器启动时执行的命令(覆盖镜像默认命令)
    - /bin/sh                # 使用 shell 解释器
    - -c                     # 从后面的字符串参数中读取命令
    - sleep 30               # 睡眠 30 秒
    # 作用:容器启动后执行 sleep 30,保持运行 30 秒
    # 30 秒后容器正常退出(退出码 0)
    # 由于 restartPolicy: OnFailure,正常退出不会触发重启
    # 因此这个 Pod 运行 30 秒后就会变为 Completed 状态

Never pod关闭后不重启

# API 版本,Pod 属于核心 v1 组
apiVersion: v1

# 资源类型为 Pod
kind: Pod

# 元数据
metadata:
  # 标签:run=testpod
  labels:
    run: testpod
  # Pod 名称
  name: testpod

# Pod 规格定义
spec:
  # 使用宿主机网络(关键配置)
  hostNetwork: true     # true 表示 Pod 直接使用宿主机的网络命名空间
                        # 效果:Pod 内的容器共享宿主机的 IP 地址和端口
                        # 无需端口映射,容器监听的端口直接在宿主机上生效
                        # 容器可以直接访问宿主机的网络接口

  # 重启策略
  restartPolicy: Never  # 从不重启
                        # 容器退出后(无论成功或失败)都不会重启
                        # 其他选项:
                        #   Always    - 总是重启(默认)
                        #   OnFailure - 失败时重启(退出码非 0)

  # 容器列表
  containers:
  - image: busybox:latest    # 使用 busybox 最新版镜像(轻量级工具容器)
    name: busybox            # 容器名称
    command:                 # 容器启动时执行的命令
    - /bin/sh                # 使用 shell 解释器
    - -c                     # 从后面的字符串参数中读取命令
    - sleep 30               # 睡眠 30 秒
    # 作用:容器启动后执行 sleep 30,保持运行 30 秒
    # 30 秒后容器正常退出(退出码 0)
    # 由于 restartPolicy: Never,容器不会重启
    # Pod 最终状态为 Succeeded(Completed)

init容器

什么是 Init 容器

Init 容器是 Pod 中在应用容器启动之前运行的特殊容器,用于完成初始化工作。一个 Pod 可以包含多个 Init 容器,它们按顺序依次执行,全部成功完成后,应用容器才会启动。

# API 版本,Pod 属于核心 v1 组
apiVersion: v1

# 资源类型为 Pod
kind: Pod

# 元数据,用于描述资源的基本信息
metadata:
  # 标签,用于标识和筛选此 Pod
  labels:
    run: webserver      # 标签键值对:run=webserver
  # Pod 的名称,在命名空间内唯一
  name: webserver

# Pod 的规格定义,描述期望状态
spec:
  # ========== Init 容器列表 ==========
  initContainers:
  - name: busybox                    # Init 容器名称
    image: busybox:latest            # 使用 busybox 最新版镜像
    command:                         # 容器启动时执行的命令
    - /bin/sh                        # 使用 shell 解释器
    - -c                             # 从后面的字符串参数中读取命令
    - "until test -e /testfile;do echo wating for myservice; sleep 2;done"
    # 命令含义:
    # until test -e /testfile:循环检查 /testfile 文件是否存在
    # do echo wating for myservice:文件不存在时输出提示信息
    # sleep 2:每 2 秒检查一次
    # done:结束循环
    # 作用:等待 /testfile 文件出现,文件存在后循环结束,Init 容器成功退出

  # ========== 应用容器列表 ==========
  containers:
  - image: myapp:v1                  # 使用 myapp:v1 镜像
    name: webserver                  # 容器名称
    # 注意:未定义 command,使用镜像默认启动命令
    # 注意:未定义端口,未定义资源限制

  # 重启策略
  restartPolicy: Always              # 容器退出后总是重启
                                     # 其他选项:OnFailure(失败时重启)、Never(从不重启)

注意事项

  • Init 容器会一直等待,直到 /testfile 文件出现

  • 如果文件一直不出现,Pod 会一直处于 Init:0/1 状态

  • Init 容器成功退出后,应用容器才会启动

  • restartPolicy: Always 对 Init 容器同样生效,失败后会重启

Kubernetes Liveness 存活探针

什么是 Liveness 探针

Liveness 探针(存活探针)用于检测容器是否还活着。如果探针检测到容器已经"死亡"(应用崩溃、死锁等),Kubernetes 会自动重启该容器,尝试恢复服务。

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
    command: ["/bin/sh", "-c"]
    args:
    - |
      nginx -g "daemon off;"
      sleep 10000
    
    # 添加 Liveness 探针
    livenessProbe:
      httpGet:                    # HTTP 方式检查
        path: /                   # 检查根路径
        port: 80                  # 检查 80 端口
      initialDelaySeconds: 10     # 启动后 10 秒开始检查
      periodSeconds: 5            # 每 5 秒检查一次
      timeoutSeconds: 3           # 超时时间 3 秒
      failureThreshold: 3         # 连续失败 3 次后重启
  
  restartPolicy: Always

Kubernetes Readiness 就绪探针

什么是 Readiness 探针

Readiness 探针(就绪探针)用于检测容器是否准备好接收流量。如果探针失败,Kubernetes 会将该 Pod 从 Service 的负载均衡中摘除,但不会重启容器。

# ========== 第一部分:Pod 定义 ==========

# API 版本,Pod 属于核心 v1 组
apiVersion: v1

# 资源类型为 Pod
kind: Pod

# 元数据,用于描述资源的基本信息
metadata:
  # 标签,用于标识和筛选此 Pod
  labels:
    run: webserver      # 标签键值对:run=webserver(关键,Service 通过此标签关联)
  # Pod 的名称,在命名空间内唯一
  name: webserver

# Pod 的规格定义,描述期望状态
spec:
  # 容器列表
  containers:
  - image: myapp:v1                  # 使用 myapp:v1 镜像
    name: webserver                  # 容器名称
    # 注意:未定义 ports,容器需自行监听端口
    # 注意:未定义 readinessProbe,Pod 启动后立即就绪

  # 重启策略
  restartPolicy: Always              # 容器退出后总是重启

---
# ========== 第二部分:Service 定义 ==========
# 分隔符,表示两个独立的 Kubernetes 资源

# API 版本,Service 属于核心 v1 组
apiVersion: v1

# 资源类型为 Service
kind: Service

# 元数据,用于描述资源的基本信息
metadata:
  # 标签,用于标识此 Service
  labels:
    run: webserver      # Service 自身的标签
  # Service 的名称,在命名空间内唯一
  name: webserver

# Service 的规格定义
spec:
  # 端口配置列表
  ports:
  - port: 80            # Service 对外暴露的端口(集群内部访问用)
    protocol: TCP       # 使用 TCP 协议
    targetPort: 80      # 转发到 Pod 的端口(Pod 内容器监听的端口)

  # 选择器:关联标签为 run=webserver 的 Pod
  selector:
    run: webserver      # 选中所有带有 run=webserver 标签的 Pod
  1. 注意事项

  2. 标签必须匹配

  3. 端口必须正确

  4. 缺少就绪探针

  5. Service 默认只能内部访问

  6. 节点污点可能导致调度失败

Kubernetes 控制器

ReplicaSet 控制器

ReplicaSet 是 Kubernetes 中保证 Pod 副本数量的基础控制器,它确保在任何时刻都有指定数量的 Pod 副本在运行

创建 ReplicaSet

通过 kubectl create deployment 生成配置模板,再修改为 ReplicaSet 类型

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  replicas: 2
  selector:
    matchLabels:
      app: webcluster
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp

动态伸缩

# 扩容到 4 个副本
kubectl scale replicaset webcluster --replicas 4

# 缩容到 2 个副本
kubectl scale replicaset webcluster --replicas 2

# 缩容到 0
kubectl scale replicaset webcluster --replicas 0

核心价值:当 Pod 因故障退出时,ReplicaSet 会自动创建新的 Pod 进行替换,实现了自愈能力。

Deployment 控制器

Deployment 是 ReplicaSet 的上层封装,提供了声明式更新、版本回滚、更新策略控制等高级功能,是生产环境中最常用的控制器。

创建 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  minReadySeconds: 5
  replicas: 2
  selector:
    matchLabels:
      app: webcluster
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp

关键参数说明:

  • minReadySeconds: 新 Pod 就绪后等待多久才视为可用

  • replicas: 期望的 Pod 副本数

  • selector: 标签选择器,用于关联 Pod

版本升级与回滚

升级到 v2 版本:

# 修改镜像版本并重新 apply
vim dep.yml  # image: myapp:v2
kubectl apply -f dep.yml
curl <ClusterIP>:80  # Hello MyApp | Version: v2

回滚到 v1 版本:

vim dep.yml  # image: myapp:v1
kubectl apply -f dep.yml
curl <ClusterIP>:80  # Hello MyApp | Version: v1

DaemonSet 控制器

DaemonSet 确保在每个节点上运行一个 Pod 副本,常用于日志收集、监控代理、网络插件等需要节点级部署的场景。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: daemonset
  name: daemonset
spec:
  selector:
    matchLabels:
      app: daemonset
  template:
    metadata:
      labels:
        app: daemonset
    spec:
      containers:
      - image: myapp:v1
        name: myapp

节点自动扩展

当新节点加入集群时,DaemonSet 会自动在新节点上创建 Pod:

# 生成新节点加入 Token
kubeadm token create --print-join-command

# 新节点加入后,DaemonSet Pod 自动运行
kubectl get pods -o wide  # 查看 Pod 分布

Job 控制器

创建 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: job
spec:
  completions: 6      # 总任务数
  parallelism: 2      # 并行执行数
  backoffLimit: 4     # 失败重试次数
  template:
    spec:
      containers:
      - image: perl:5.34.0
        name: job
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  • completions: 总共需要成功完成的 Pod 数量

  • parallelism: 同时运行的 Pod 数量

  • backoffLimit: 失败重试次数上限

CronJob 控制器

CronJob 是 Job 的定时调度版本,类似 Linux 的 cron,用于周期性执行任务。

创建 CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob
spec:
  schedule: '* * * * *'   # 每分钟执行一次
  jobTemplate:
    metadata:
      name: cronjob
    spec:
      template:
        spec:
          containers:
          - image: busybox
            name: cronjob
            command:
              - /bin/sh
              - -c
              - echo "hello timinglee"
          restartPolicy: OnFailure

CronJob 常见用途:

  • 定期数据库备份

  • 定时清理过期数据

  • 周期性报表生成

  • 定时同步数据

实践建议

  1. 生产环境优先使用 Deployment,充分利用滚动更新和回滚能力

  2. 合理设置更新策略:maxSurge: 1, maxUnavailable: 0 实现零停机更新

  3. 使用 minReadySeconds 确保新版本 Pod 稳定后再继续滚动更新

  4. DaemonSet 用于节点级服务,如日志、监控、网络组件

  5. Job/CronJob 设置合理的 backoffLimit,避免无限重试浪费资源

  6. 结合 kubectl rollout 命令实现优雅的版本管理和发布控制

更多推荐