Pod 管理总结

前言

在 Kubernetes 中,Pod 是最小的可部署计算单元,也是所有工作负载的载体。无论是 Deployment、ReplicaSet 还是 Job,最终都会以 Pod 的形式运行在集群节点上。因此,掌握 Pod 的创建、管理、资源声明以及生命周期控制,是玩转 K8s 的第一步。

本文基于实战笔记整理,从命令式对象管理讲到 YAML 声明式配置,再到 Pod 的生命周期与探针机制,带你完整走一遍 Pod 管理的核心知识点。所有命令均在 kubeadm 搭建的 1.35 版本集群实测。

实验环境说明 :集群包含 k8s-masterk8s-node1k8s-node2 三个节点;私有镜像仓库地址为 reg.timinglee.org,实验镜像为 myapp:v1 / myapp:v2(基于 Nginx 的演示镜像,访问根路径会返回 Hello MyApp | Version: vX)。你可以用自己的镜像或 Docker Hub 公开镜像替换。


一、命令式对象管理

1.1 命名空间(Namespace)管理

命名空间用于在一个物理集群中隔离不同的项目或环境。默认集群自带几个系统命名空间:defaultkube-systemkube-publickube-node-lease 等。

复制代码
# 查看所有命名空间
kubectl get namespaces

# 创建命名空间
kubectl create namespace timinglee

# 删除命名空间(其内部所有资源会一并删除,谨慎操作)
kubectl delete namespace timinglee

💡 提示:大多数日常实验都在 default 命名空间中操作即可,无需频繁切换。

1.2 Pod 的创建、查看与删除

最简单的方式是使用 kubectl run 命令式地创建一个 Pod:

复制代码
# 创建一个名为 lee 的 Pod,使用 nginx:latest 镜像
kubectl run lee --image nginx:latest
pod/lee created

# 查看 Pod 运行状态及所在节点(-o wide 显示更详细信息)
kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
lee    1/1     Running   0          25s   10.244.1.10   k8s-node1   <none>           <none>

当镜像不存在或拉取失败时,Pod 会处于异常状态:

复制代码
# 使用一个不存在的镜像
kubectl run error --image lee:v1
kubectl get pods -o wide
NAME    READY   STATUS             RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
error   0/1     ImagePullBackOff   0          38s   10.244.2.3    k8s-node2   <none>           <none>

删除 Pod:

复制代码
# 删除指定 Pod
kubectl delete pods error

# 删除当前命名空间下所有 Pod(谨慎)
kubectl delete pods --all

1.3 Pod 故障排查(describe)

当 Pod 状态异常时,第一反应是查看它的详细信息,重点关注 EventsConditions

复制代码
kubectl describe pods error

输出中的关键部分:

复制代码
Events:
  Type     Reason    Age   From      Message
  ----     ------    ----  ----      -------
  Normal   Scheduled 87s   default-scheduler  Successfully assigned default/error to k8s-node2
  Warning  Failed    28s   kubelet            Failed to pull image "lee:v1": ... not found
  Warning  Failed    16s   kubelet            Error: ImagePullBackOff

通过 Events 可以快速定位是镜像拉取失败、调度失败还是资源不足等问题。

二、kubectl 核心命令实操

2.1 准备工作:镜像准备

在离线或私有仓库环境中,通常需要先把实验镜像加载并推送到私有仓库:

复制代码
docker load -i myapp.tar.gz
docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
docker push reg.timinglee.org/library/myapp:v1
docker tag timinglee/myapp:v2 reg.timinglee.org/library/myapp:v2
docker push reg.timinglee.org/library/myapp:v2

2.2 create / edit / patch

create ------ 命令式创建 Deployment:

复制代码
kubectl create deployment webcluster --replicas 2 --image myapp:v1
kubectl get deployments.apps
kubectl get pods

edit ------ 在线修改资源配置(会打开编辑器,修改后即时生效):

复制代码
kubectl create deployment webcluster --image myapp:v1
kubectl edit deployments.apps webcluster
# 将 spec.replicas 改为 2,保存后 Pod 数量自动变为 2

patch ------ 以 JSON 补丁方式局部更新(非交互式,适合脚本/CICD):

复制代码
kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":1}}'

2.3 expose / logs

expose ------ 为 Deployment 创建 Service,使其可被集群内访问:

复制代码
kubectl expose deployment webcluster --port 80 --target-port 80
kubectl get service
kubectl describe svc webcluster
# 访问 ClusterIP 验证负载均衡
curl 10.97.61.108/hostname.html

logs ------ 查看容器日志:

复制代码
kubectl logs pods/webcluster-77c87d9946-gh9v7

2.4 attach / exec / cp

attach ------ 附加到正在运行的容器(类似 docker attach):

复制代码
kubectl run -it testpod --image busybox:latest
# 在容器内执行 <ctrl+pq> 退出但不停止容器
kubectl attach pods/testpod -it

exec ------ 在容器内执行命令(最常用):

复制代码
kubectl exec -it pods/testpod -c testpod -- /bin/bash

cp ------ 在宿主机与容器之间拷贝文件:

复制代码
# 从容器拷贝到宿主机
kubectl cp testpod:/usr/share/nginx/html/index.html /mnt/test
# 从宿主机拷贝到容器
echo timinglee > /mnt/index.html
kubectl cp /mnt/index.html testpod:/usr/share/nginx/html/index.html
curl 10.244.1.12   # 返回 timinglee

2.5 rollout / scale / label

rollout ------ 管理 Deployment 的发布过程:

复制代码
kubectl rollout status deployment webcluster     # 查看滚动发布状态
kubectl rollout restart deployment webcluster    # 重启(触发一次滚动更新)

scale ------ 调整副本数:

复制代码
kubectl scale deployment webcluster --replicas 4
kubectl scale deployment webcluster --replicas 1

label ------ 管理资源标签:

复制代码
kubectl get pods --show-labels
kubectl label pods webcluster-9787d97f6-zl6q2 app-   # 删除标签
kubectl label pods webcluster-9787d97f6-zl6q2 app=webcluster  # 添加标签

三、利用控制器实现滚动更新与回滚(版本更替)

单独一个"裸 Pod"无法自愈和滚动更新,通常需要交给 Deployment 控制器管理。

3.1 创建 Deployment 并暴露服务

复制代码
kubectl create deployment webcluster --image myapp:v1 --replicas 2 --dry-run=client -o yaml > webcluster.yml

apiVersion: apps/v1
kind: Deployment
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

kubectl apply -f webcluster.yml
kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
kubectl get svc
# 通过节点 IP:NodePort 访问
curl http://172.25.254.100:30713/hostname.html

3.2 更新业务版本

复制代码
kubectl set image deployments webcluster myapp=myapp:v2
# 建议为本次更新添加变更说明
kubectl annotate deployment webcluster kubernetes.io/change-cause="myappv2" --overwrite
curl http://172.25.254.100:30713
# 返回 Hello MyApp | Version: v2 ...

3.3 版本回退

复制代码
kubectl rollout history deployment webcluster
kubectl rollout undo deployment webcluster --to-revision 3
curl http://172.25.254.100:30713
# 返回 Hello MyApp | Version: v1 ...

💡 提示:想让 rollout history 显示有意义的 change-cause,除了 annotate,在 kubectl apply 时加上 --record 也能自动记录命令。


四、用 YAML 声明 Pod 资源

4.1 多容器 Pod

一个 Pod 内可以运行多个容器,它们共享网络命名空间和存储卷(同一 Pod 内容器通过 localhost 互通):

图示:一个 Pod 由 Pause 容器提供共享网络栈,多个应用容器与 sidecar 共享同一网络命名空间与 Volume。

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
  - image: busyboxplus:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000

kubectl apply -f testpod.yaml
kubectl exec -it pods/testpod -c busybox -- /bin/sh
# 在 busybox 容器内访问本地 127.0.0.1 即可访问到 myapp1 容器

4.2 将容器端口暴露到节点(hostPort)

复制代码
spec:
  containers:
  - image: myapp:v1
    name: myapp1
    ports:
    - name: http
      containerPort: 80   # Pod 内部容器端口
      hostPort: 80         # Pod 所在节点的端口
      protocol: TCP

kubectl apply -f testpod.yaml
curl k8s-node2   # 直接通过节点主机名/IP 访问,无需经过 Service

4.3 在 Pod 中设置环境变量

常用于传递配置,例如 MySQL 密码:

复制代码
spec:
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee
  - image: phpmyadmin:latest
    name: mysqladmin
    env:
    - name: PMA_ARBITRARY
      value: "1"

4.4 选择指定节点运行(nodeSelector)

根据节点标签把 Pod 调度到特定节点:

复制代码
kubectl get nodes --show-labels

spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node2
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee

💡 更灵活的节点调度可以用 nodeName(强制指定)、affinity(亲和性)或 tolerations(污点容忍)。

4.5 共享宿主机网络(hostNetwork)

开启后,Pod 直接使用宿主机的网络命名空间(不再有独立的 Pod IP):

复制代码
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000

进入容器后执行 ifconfig,能看到宿主机的 eth0 等网卡,说明网络已共享。

4.6 资源优先级(QoS Class)

Kubernetes 根据容器的资源请求(requests)和限制(limits)自动划分服务质量等级,节点资源紧张时按优先级驱逐(OOM 或 Eviction):

QoS 等级 条件 优先级
BestEffort 完全不设置 requests/limits 最低(最先被驱逐)
Burstable 设置了 requests/limits,但不相等 居中
Guaranteed 每个容器的 requests == limits(且都设置) 最高(最后被驱逐)

图示为Qos三档质量对比

复制代码
# Guaranteed 示例:requests 与 limits 相等
spec:
  containers:
  - image: busybox:latest
    name: busybox
    command: ["/bin/sh","-c","sleep 10000"]
    resources:
      limits:
        cpu: 500m
        memory: 100M
      requests:
        cpu: 500m
        memory: 100M

kubectl describe pods testpod | grep "QoS Class:"
# QoS Class:  Guaranteed

4.7 容器重启策略(restartPolicy)

Pod 级别的 restartPolicy 决定容器退出后是否重启,可选值:

  • Always:无论以何种原因退出都重启(默认,适合长驻服务)

  • OnFailure:只有非正常退出(非 0 状态码)才重启(适合批处理)

  • Never:无论退出状态都不重启

    spec:
    restartPolicy: Always
    containers:
    - image: busybox:latest
    name: busybox
    command: ["/bin/sh","-c","sleep 60"]

注意:restartPolicy 仅针对 Pod 内容器;Job/CronJob 通常配合 OnFailure / Never 使用,避免任务被无限重启。


五、Pod 生命周期与探针

Pod 在其生命周期内会经历不同阶段(Phase)Pending(调度中/镜像拉取中)、Running(至少一个容器运行中)、Succeeded(所有容器正常退出)、Failed(至少一个容器异常退出)、Unknown(状态无法获取)。

5.1 Init 容器(Init Containers)

Init 容器在主容器启动按顺序运行,必须全部成功才会启动主容器,常用于等待依赖就绪、初始化配置等。

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  initContainers:
  - name: busybox
    image: busybox:latest
    command:
    - /bin/sh
    - -c
    - "until test -e /testfile; do echo waiting for myservice; sleep 2; done"
  containers:
  - image: myapp:v1
    name: webserver
  restartPolicy: Always

进入 init 容器创建 /testfile,等待条件满足后主容器才启动:

复制代码
kubectl exec -it pods/webserver -c busybox -- /bin/sh
/ # touch /testfile

5.2 存活探针(Liveness Probe)

存活探针用于检测容器是否"活着",检测失败时 kubelet 会杀死并重启容器。没有存活探针时,即使 Nginx 进程挂了,Pod 仍显示 Running,但访问会失败。

复制代码
spec:
  containers:
  - image: myapp:v1
    name: testpod
    command: ["/bin/sh","-c"]
    args:
    - |
      nginx -g "daemon off;"
      sleep 10000
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 3   # 容器启动后等待 3 秒再开始探测
      periodSeconds: 1          # 每 1 秒探测一次
      timeoutSeconds: 1         # 探测超时时间

在容器内执行 nginx -s stop 后,探针探测失败,kubelet 会重启容器从而恢复服务。

Kubernetes 支持三种探针类型:exec(执行命令)、httpGet(HTTP 请求)、tcpSocket(TCP 端口探测),上面用的是 tcpSocket。

5.3 就绪探针(Readiness Probe)

就绪探针用于判断容器是否"准备好接收流量"。探测失败时,Pod 会被从 Service 的 Endpoints 中摘除,不再接收请求,但容器不会被重启

复制代码
spec:
  containers:
  - image: myapp:v1
    name: webserver
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 2
      timeoutSeconds: 1

kubectl describe svc webserver
# Endpoints 中会显示当前就绪的 Pod IP
# 删除容器内的 /usr/share/nginx/html/index.html 后,该 Pod 会被自动从 Endpoints 摘除

💡 关键区别:Liveness 决定"要不要重启容器",Readiness 决定"要不要把流量打给它"。生产环境建议两者都配置,以保障服务健壮性。

图示为两者对比

相关推荐
张洛闻Eren9 小时前
云原生k8s【第六课】:K8s 访问控制
运维·docker·云原生·容器·kubernetes·k8s
张洛闻Eren2 天前
云原生k8s【第五课】:资源配额与限制
运维·数据库·云原生·kubernetes·k8s·github
.柒宇.2 天前
运维常见面试题_07_配置管理与监控(Ansible · Prometheus · Alertmanager)· 容器编排(Kubernetes)
运维·k8s·ansible·prometheus
智码看视界2 天前
Day58-K8s部署Spring Boot微服务:ConfigMap+Secret+HPA
spring boot·微服务·云原生·kubernetes·k8s·hpa
赴前尘2 天前
使用 Init Container + iptables 强制隔离 Pod 网络(Flannel 环境)
k8s
智码看视界3 天前
Day57-K8s核心概念速通:Pod、Deployment、Service与Ingress
云原生·容器·kubernetes·k8s·ingress·java后端·deployment
国医中兴4 天前
全文搜索的数据库选择:MySQL Fulltext与Elasticsearch的深度对比
微服务·云原生·容器·kubernetes·k8s
万里侯4 天前
GitOps 2026年演进趋势:从配置管理到环境即代码的范式转移及Pull vs Push模型的再思考
微服务·容器·k8s
张洛闻Eren8 天前
云原生k8s【第一课】: Docker 容器技术
运维·云原生·容器·k8s