02 下 | Kubernetes Pod 实战实验完全解析

目录

一、资源使用的方法

[1. 命令式](#1. 命令式)

[2. YAML 文件方式](#2. YAML 文件方式)

二、资源类型

[1. node](#1. node)

[2. namespace](#2. namespace)

[三、kubectl 命令](#三、kubectl 命令)

[四、Pod 应用](#四、Pod 应用)

[1. 自助式管理 pod](#1. 自助式管理 pod)

[2. 利用控制器管理 pod](#2. 利用控制器管理 pod)

[3. 利用 yaml 文件部署应用](#3. 利用 yaml 文件部署应用)

运行单个容器

运行多个容器

[理解 pod 间的网络整合](#理解 pod 间的网络整合)

端口映射

选择运行节点

共享宿主机网络

[五、pod 的生命周期](#五、pod 的生命周期)

[1. init 容器](#1. init 容器)

[2. livenessprobe (存活探针)](#2. livenessprobe (存活探针))

[3. ReadinessProbe](#3. ReadinessProbe)

灵魂拷问


生活总类比:Kubernetes 就像一个大型现代化机场。Pod 是机场里的 "航班",Node 是 "停机坪",Namespace 是 "航站楼",控制器是 "塔台调度系统"。你作为 "机场运营总监",通过 kubectl 命令向塔台发送指令,调度航班起降、分配停机位、管理航站楼资源。


一、资源使用的方法

1. 命令式

生活类比:就像你直接打电话给机场塔台说:"给我安排一架波音 737 航班,停靠 8 号登机口,立即起飞"。塔台收到指令后直接执行,没有中间文件。

bash 复制代码
# 创建一个运行nginx镜像的Pod,暴露80端口
[root@master ~]# kubectl run webpod --image nginx:latest --port 80

核心代码逐行解析

  • kubectl run:向 API Server 发送 POST 请求,创建一个 Pod 资源对象
  • webpod:设置 Pod 的元数据名称,底层会生成唯一的 UID
  • --image nginx:latest:指定容器镜像,kubelet 会调用 container runtime 执行docker pull nginx:latest
  • --port 80:在 Pod 的网络命名空间中打开 80 端口,底层会更新 iptables 规则允许流量通过

坑点(Gotchas)

  • --port只是声明端口,不会自动暴露到集群外部
  • latest标签会导致每次重启都拉取最新镜像,生产环境必须使用固定版本
  • ❌ 命令式创建的 Pod 没有控制器管理,Pod 崩溃后不会自动重建

bash

运行

bash 复制代码
# 查看Pod基本信息
[root@master ~]# kubectl get pods
webpod 1/1 Running 0 33s

# 查看Pod详细信息
[root@master ~]# kubectl describe pods webpod
Name: webpod
Namespace: default
Priority: 0
Service Account: default
Node: node2/172.25.254.20
Start Time: Sun, 29 Mar 2026 10:18:15 +0800
Labels: run=webpod
Annotations: <none>
Status: Running
IP: 10.244.2.2
IPs:
  IP: 10.244.2.2
Containers:
  webpod:
    Container ID: docker://688436b733ca8843f6946814f78bf59f865877081820ca43dda1c33f409ac10d
    Image: nginx:latest
    Image ID: docker-pullable://nginx@sha256:127262f8c4c716652d0e7863bba3b8c45bc9214a57d13786c854272102f7c945
    Port: 80/TCP
    Host Port: 0/TCP
    State: Running
    Started: Sun, 29 Mar 2026 10:18:30 +0800
    Ready: True
    Restart Count: 0
    Environment: <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nt87d (ro)
Conditions:
  Type Status
  PodReadyToStartContainers True
  Initialized True
  Ready True
  ContainersReady True
  PodScheduled True
Volumes:
  kube-api-access-nt87d:
    Type: Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds: 3607
    ConfigMapName: kube-root-ca.crt
    Optional: false
    DownwardAPI: true
Qos Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type Reason Age From Message
  Normal Scheduled 24s default-scheduler Successfully assigned default/webpod to node2
  Normal Pulling 24s kubelet spec.containers{webpod}: Pulling image "nginx:latest"
  Normal Pulled 20s kubelet spec.containers{webpod}: Successfully pulled image "nginx:latest" in 3.7s (3.7s including waiting). Image size: 187694648 bytes.
  Normal Created 9s kubelet spec.containers{webpod}: Container created
  Normal Started 9s kubelet spec.containers{webpod}: Container started

代码解释

  • kubectl describe:从 API Server 获取 Pod 的完整状态信息,包括调度过程、容器状态、事件日志
  • Events 部分是排障的核心:显示了从调度到启动的完整流程
  • Qos Class: BestEffort 表示该 Pod 没有设置资源限制,优先级最低
bash 复制代码
# 查看Pod的IP和所在节点
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
webpod 1/1 Running 0 2m46s 10.244.2.2 node2 <none> <none>

# 删除Pod
[root@master ~]# kubectl delete pods webpod
pod "webpod" deleted from default namespace

企业级生产应用

  • 命令式操作仅用于紧急排障和临时测试,生产环境绝对禁止使用
  • 千万级并发场景下,所有资源必须通过声明式 YAML 文件管理,纳入 Git 版本控制
  • 生产环境会使用 RBAC 限制普通用户的kubectl run权限,防止未经授权的 Pod 创建

故障排查指南

  1. 错误ErrImagePull
    • 排查思路:
      • 检查镜像名称和标签是否正确
      • 检查节点是否能访问镜像仓库
      • 检查私有仓库的 Secret 是否正确配置
  2. 错误Pending状态
    • 排查思路:
      • 执行kubectl describe pod webpod查看 Events
      • 常见原因:节点资源不足、调度器无法找到合适节点、镜像拉取失败

2. YAML 文件方式

生活类比:就像你先写一份详细的 "航班运营计划书",然后提交给塔台。塔台会根据计划书的内容来安排航班,并且会持续监控,确保实际状态与计划书一致。

bash

运行

bash 复制代码
# 生成Deployment的YAML模板(不实际创建资源)
[root@master ~]# kubectl create deployment test --image nginx --replicas 1 --dry-run=client -o yaml > test.yml

核心代码逐行解析

  • kubectl create deployment:创建 Deployment 控制器资源
  • --dry-run=client:仅在客户端验证命令,不向 API Server 发送请求
  • -o yaml:将资源对象序列化为 YAML 格式输出
  • > test.yml:将输出重定向到文件,这是生成标准 YAML 模板的最佳实践

yaml

bash 复制代码
# test.yml内容
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test
  name: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - image: nginx
        name: nginx

核心代码逐行解析

  • apiVersion: apps/v1:指定使用 apps API 组的 v1 版本,底层会路由到对应的控制器处理
  • kind: Deployment:声明资源类型为 Deployment,Deployment 控制器会监听该资源
  • metadata.name: test:资源的唯一名称,在同一个 Namespace 中不能重复
  • spec.replicas: 1:期望的 Pod 副本数,Deployment 控制器会持续比较实际副本数与期望副本数
  • spec.selector.matchLabels:控制器用来选择要管理的 Pod 的标签,必须与 Pod 模板中的标签完全一致
  • spec.template:Pod 的模板,控制器会根据这个模板创建 Pod

坑点(Gotchas)

  • spec.selector.matchLabelsspec.template.metadata.labels不一致会导致控制器无法管理 Pod
  • ❌ Deployment 不能直接管理 Pod,只能通过 ReplicaSet 间接管理
  • ❌ 修改 Pod 模板后,Deployment 会触发滚动更新

bash

运行

bash 复制代码
# 建立式创建资源
[root@master ~]# kubectl create -f test.yml
deployment.apps/test created

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-h2sct 1/1 Running 0 8s

[root@master ~]# kubectl delete -f test.yml
deployment.apps "test" deleted from default namespace

[root@master ~]# kubectl get pods
No resources found in default namespace

bash

运行

复制代码
# 声明式创建/更新资源
[root@master ~]# kubectl apply -f test.yml
deployment.apps/test created

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-cxtnp 1/1 Running 0 1s

关键区别

  • kubectl create:只能创建新资源,如果资源已存在会报错
  • kubectl apply:如果资源不存在则创建,如果已存在则更新,生产环境标准用法

bash

运行

bash 复制代码
# 注意:建立只能建立不能更新,声明可以
[root@master ~]# vim test.yml
# 修改replicas为2
spec:
  replicas: 2

[root@master ~]# kubectl create -f test.yml
Error from server (AlreadyExists): error when creating "test.yml": deployments.apps "test" already exists

[root@master ~]# kubectl apply -f test.yml
deployment.apps/test configured

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 8s
test-56848fd9dc-cxtnp 1/1 Running 0 2m42s

企业级生产应用

  • 所有生产环境资源必须使用kubectl apply管理
  • YAML 文件必须纳入 Git 版本控制,通过 CI/CD 流水线自动部署
  • 千万级并发场景下,会使用 Helm Chart 来管理复杂应用的 YAML 文件
  • 生产环境会设置resources.limitsresources.requests来保证资源隔离

故障排查指南

  1. 错误selector does not match template labels
    • 排查思路:
      • 检查spec.selector.matchLabelsspec.template.metadata.labels是否完全一致
      • Deployment 的 selector 一旦创建就不能修改,必须删除重建
  2. 错误deployment does not have minimum availability
    • 排查思路:
      • 检查节点资源是否足够
      • 检查 Pod 是否能正常启动
      • 检查滚动更新策略是否合理

二、资源类型

1. node

生活类比:Node 就是机场的停机坪,每个停机坪有不同的大小和承载能力。飞机(Pod)必须停靠在停机坪上才能运行。

bash

运行

bash 复制代码
# 查看集群节点信息
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 18h v1.35.3
node1 Ready <none> 17h v1.35.3
node2 Ready <none> 17h v1.35.3

# 生成节点加入集群的命令
[root@master ~]# kubeadm token create --print-join-command

代码解释

  • kubectl get nodes:获取集群中所有节点的状态信息
  • STATUS: Ready表示节点正常,可以接收 Pod 调度
  • ROLES: control-plane表示这是控制平面节点,默认不会调度普通 Pod

企业级生产应用

  • 生产环境会将节点分为不同的节点池(如计算节点、存储节点、GPU 节点)
  • 使用污点(Taints)和容忍度(Tolerations)来控制 Pod 的调度
  • 千万级并发场景下,会使用集群自动伸缩(Cluster Autoscaler)根据负载自动增减节点

故障排查指南

  1. 错误 :节点状态为NotReady
    • 排查思路:
      • 登录节点检查 kubelet 服务状态:systemctl status kubelet
      • 检查节点网络是否正常
      • 检查节点磁盘是否满了

2. namespace

生活类比:Namespace 就是机场的航站楼,不同的航站楼相互隔离,有自己的登机口、安检和服务设施。不同航空公司的航班会安排在不同的航站楼。

bash

运行

bash 复制代码
# 查看所有命名空间
[root@master ~]# kubectl get namespaces
NAME STATUS AGE
default Active 18h
kube-flannel Active 17h
kube-node-lease Active 18h
kube-public Active 18h
kube-system Active 18h

# 查看default命名空间的Pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 25m
test-56848fd9dc-cxtnp 1/1 Running 0 27m

# 查看kube-flannel命名空间的Pod
[root@master ~]# kubectl -n kube-flannel get pods
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-hc8gt 1/1 Running 1 (17h ago) 17h
kube-flannel-ds-rvzng 1/1 Running 1 (17h ago) 17h
kube-flannel-ds-s29g5 1/1 Running 1 (17h ago) 17h

代码解释

  • -n <namespace>:指定要操作的命名空间
  • 不指定命名空间时,默认操作default命名空间
  • kube-system命名空间存放 Kubernetes 系统组件

bash

运行

bash 复制代码
# 创建新的命名空间
[root@master ~]# kubectl create namespace timinglee
namespace/timinglee created

[root@master ~]# kubectl get namespaces
NAME STATUS AGE
default Active 18h
kube-flannel Active 17h
kube-node-lease Active 18h
kube-public Active 18h
kube-system Active 18h
timinglee Active 6s

# 在timinglee命名空间创建Pod
[root@master ~]# kubectl -n timinglee run testpod --image nginx:latest
pod/testpod created

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 28m
test-56848fd9dc-cxtnp 1/1 Running 0 30m

[root@master ~]# kubectl -n timinglee get pods
NAME READY STATUS RESTARTS AGE
testpod 1/1 Running 0 17s

# 不同命名空间可以有同名的Pod
[root@master ~]# kubectl -n timinglee run testpod --image nginx:latest
Error from server (AlreadyExists): pods "testpod" already exists

[root@master ~]# kubectl run testpod --image nginx:latest
pod/testpod created

坑点(Gotchas)

  • ❌ 命名空间名称只能包含小写字母、数字和连字符
  • ❌ 删除命名空间会删除该命名空间下的所有资源,且无法恢复
  • ❌ 不同命名空间的 Service 默认不能直接访问,需要通过 Service 的 FQDN 访问

企业级生产应用

  • 生产环境会按环境(dev、test、prod)和团队划分命名空间
  • 使用 ResourceQuota 限制每个命名空间的资源使用
  • 使用 NetworkPolicy 控制不同命名空间之间的网络访问
  • 千万级并发场景下,会将不同的微服务部署在不同的命名空间

故障排查指南

  1. 错误namespaces "xxx" not found
    • 排查思路:
      • 检查命名空间名称是否拼写正确
      • 检查是否在正确的命名空间操作
      • 执行kubectl get namespaces查看所有命名空间

三、kubectl 命令

生活类比:kubectl 就是你与机场塔台通信的对讲机。通过不同的指令,你可以查询航班状态、调整航班数量、更改航班信息、与机上人员通信等。

bash

运行

bash 复制代码
# 查看Deployment
[root@master ~]# kubectl get deployments.apps

# 查看Pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 37m
test-56848fd9dc-cxtnp 1/1 Running 0 40m

# 编辑Deployment
[root@master ~]# kubectl edit deployments.apps test
# 将replicas修改为4
replicas: 4

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 39m
test-56848fd9dc-cxtnp 1/1 Running 0 41m
test-56848fd9dc-kdm4h 1/1 Running 0 28s
test-56848fd9dc-lmpdt 1/1 Running 0 28s

代码解释

  • kubectl edit:打开默认编辑器编辑资源的 YAML 配置,保存后自动生效
  • 这是一种临时修改方式,生产环境不推荐使用

bash

运行

bash 复制代码
# 补丁式更新Deployment
[root@master ~]# kubectl patch deployments.apps test -p '{"spec":{"replicas":1}}'
deployment.apps/test patched

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-56848fd9dc-9sw95 1/1 Running 0 42m

核心代码逐行解析

  • kubectl patch:对资源进行部分更新,不需要提供完整的 YAML
  • -p:指定要更新的 JSON 补丁
  • 底层会发送 PATCH 请求到 API Server,只更新指定的字段

bash

运行

bash 复制代码
# 暴露Deployment为Service
[root@master ~]# kubectl expose deployment test --port 80 --target-port 80
service/test exposed

# 查看Service详细信息
[root@master ~]# kubectl describe service test
Name: test
Namespace: default
Labels: app=test
Annotations: <none>
Selector: app=test
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.104.29.36
IPs:
  IP: 10.104.29.36
Port: 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.2:80,10.244.2.11:80,10.244.1.5:80 + 1 more...
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>

# 访问Service
[root@master ~]# curl 10.104.29.36

代码解释

  • kubectl expose:创建一个 Service 资源,将 Pod 的端口暴露出来
  • --port 80:Service 监听的端口
  • --target-port 80:Pod 上的端口
  • Service 会自动维护 Endpoints 列表,包含所有匹配标签的 Pod 的 IP 和端口

bash

运行

bash 复制代码
# 查看Pod日志
[root@master ~]# kubectl logs pods/test-68d8574cb-8xjdv
10.244.0.0 - - [29/Mar/2026:03:32:36 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.76.1" "-"
10.244.0.0 - - [29/Mar/2026:03:32:42 +0000] "GET /hostname.html HTTP/1.1" 200 21 "-" "curl/7.76.1" "-"

代码解释

  • kubectl logs:获取容器的标准输出和标准错误输出
  • 这是排查应用问题的最常用命令

bash

运行

bash 复制代码
# 交互式进入容器
[root@master ~]# kubectl run testpod -it --image busybox
All commands and output from this session will be recorded in container logs,
including credentials and sensitive information passed through the command
prompt.
If you don't see a command prompt, try pressing enter.
/ # 
# 按ctrl+pq退出容器(不终止容器)
/ # Session ended, resume using 'kubectl attach testpod -c testpod -i -t' command when the pod is running

# 重新附加到容器
[root@master ~]# kubectl attach pods/testpod -it

# 在容器中执行命令
[root@master ~]# kubectl exec -it pods/testpod -c testpod -- /bin/sh

# 复制文件到容器
[root@master ~]# kubectl cp testpod.yml testpod:/ -c testpod

# 验证文件已复制
[root@master ~]# kubectl exec -it pods/testpod -c testpod -- /bin/sh
/ # ls
bin etc lib proc sys tmp var
dev home lib64 root testpod.yml usr

坑点(Gotchas)

  • kubectl exec只能在运行中的容器中执行命令
  • kubectl cp不支持复制符号链接
  • ❌ 生产环境应限制kubectl exec权限,防止未经授权的容器访问

bash

运行

bash 复制代码
# 扩容Deployment
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-68d8574cb-8xjdv 1/1 Running 0 14m
test-68d8574cb-b9p9x 1/1 Running 0 14m
test-68d8574cb-lb9gq 1/1 Running 0 14m
test-68d8574cb-xkd56 1/1 Running 0 14m

[root@master ~]# kubectl scale deployment test --replicas 6
deployment.apps/test scaled

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-68d8574cb-5kbgs 1/1 Running 0 2s
test-68d8574cb-7nnmn 1/1 Running 0 2s
test-68d8574cb-8xjdv 1/1 Running 0 15m
test-68d8574cb-b9p9x 1/1 Running 0 15m
test-68d8574cb-lb9gq 1/1 Running 0 15m
test-68d8574cb-xkd56 1/1 Running 0 15m

# 缩容Deployment
[root@master ~]# kubectl scale deployment test --replicas 1
deployment.apps/test scaled

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-68d8574cb-5kbgs 0/1 Completed 0 26s
test-68d8574cb-8xjdv 0/1 Completed 0 15m
test-68d8574cb-lb9gq 1/1 Running 0 15m
test-68d8574cb-xkd56 0/1 Completed 0 15m
testpod 1/1 Running 1 (6m54s ago) 8m12s

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-68d8574cb-lb9gq 1/1 Running 0 15m
testpod 1/1 Running 1 (6m56s ago) 8m14s

代码解释

  • kubectl scale:快速调整 Deployment 的副本数
  • 缩容时,Kubernetes 会优先删除较新的 Pod

bash

运行

bash 复制代码
# 查看Pod标签
[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
test-68d8574cb-lb9gq 1/1 Running 0 16m app=test,pod-template-hash=68d8574cb
testpod 1/1 Running 1 (7m54s ago) 9m12s run=testpod

# 为Pod添加标签
[root@master ~]# kubectl label pods testpod name=lee
pod/testpod labeled

[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
test-68d8574cb-lb9gq 1/1 Running 0 17m app=test,pod-template-hash=68d8574cb
testpod 1/1 Running 1 (8m23s ago) 9m41s name=lee,run=testpod

# 删除Pod标签
[root@master ~]# kubectl label pods testpod name-
pod/testpod unlabeled

[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
test-68d8574cb-lb9gq 1/1 Running 0 18m app=test,pod-template-hash=68d8574cb
testpod 1/1 Running 1 (9m10s ago) 10m run=testpod

企业级生产应用

  • 生产环境会使用标签来组织和选择资源
  • 使用kubectl apply来管理所有资源变更
  • 千万级并发场景下,会使用 HPA(Horizontal Pod Autoscaler)根据 CPU 和内存使用率自动扩缩容
  • 生产环境会使用 ELK 或 Loki 来集中收集和管理日志

故障排查指南

  1. 错误error: unable to upgrade connection: container not found
    • 排查思路:
      • 检查 Pod 是否处于 Running 状态
      • 检查容器是否已经启动
      • 执行kubectl describe pod查看容器状态

四、Pod 应用

1. 自助式管理 pod

生活类比:就像你自己驾驶一架私人飞机,你需要自己负责起飞、飞行和降落。如果飞机出了问题,没有人会帮你重新起飞。

bash

运行

bash 复制代码
# 创建运行myapp:v2镜像的Pod
[root@master pod]# kubectl run myappv2 --image myapp:v2 --port 80
pod/myappv2 created

# 查看Pod状态
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myappv2 0/1 ContainerCreating 0 8s

# 镜像拉取失败
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myappv2 0/1 ErrImagePull 0 20s

# 尝试重新拉取镜像
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myappv2 0/1 ImagePullBackOff 0 3m48s

# 镜像拉取成功,Pod运行
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myappv2 1/1 Running 0 4m20s

# 删除Pod
[root@master pod]# kubectl delete pods myappv2
pod "myappv2" deleted from default namespace

[root@master pod]# kubectl get pods
No resources found in default namespace

代码解释

  • ContainerCreating:Pod 正在创建中,kubelet 正在拉取镜像和创建容器
  • ErrImagePull:镜像拉取失败
  • ImagePullBackOff:kubelet 会等待一段时间后重新尝试拉取镜像

坑点(Gotchas)

  • ❌ 自助式 Pod 没有控制器管理,Pod 崩溃后不会自动重建
  • ❌ 节点故障时,自助式 Pod 不会被调度到其他节点
  • ❌ 生产环境绝对禁止使用自助式 Pod

企业级生产应用

  • 生产环境所有 Pod 必须由控制器(Deployment、StatefulSet、DaemonSet 等)管理
  • 千万级并发场景下,会使用 Deployment 管理无状态应用,StatefulSet 管理有状态应用

故障排查指南

  1. 错误ImagePullBackOff
    • 排查思路:
      • 检查镜像名称和标签是否正确
      • 检查节点是否能访问镜像仓库
      • 执行docker pull myapp:v2在节点上手动拉取镜像测试

2. 利用控制器管理 pod

生活类比:就像航空公司的航班调度系统。你告诉调度系统你需要每天有多少个航班,调度系统会自动安排飞机、飞行员和机组人员。如果有飞机故障,调度系统会自动安排备用飞机。

bash

运行

bash 复制代码
# 创建Deployment控制器
[root@master pod]# kubectl create deployment webcluster --image myapp:v2 --replicas 1
deployment.apps/webcluster created

# 查看Deployment详细信息
[root@master pod]# kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
webcluster 1/1 1 1 14s myapp myapp:v2 app=webcluster

# 扩容到2个副本
[root@master pod]# kubectl scale deployment webcluster --replicas 2
deployment.apps/webcluster scaled

# 缩容到1个副本
[root@master pod]# kubectl scale deployment webcluster --replicas 1

# 修改Pod标签
[root@master pod]# kubectl label pods webcluster-6c8b4bb9d7-jsjws app-
pod/webcluster-6c8b4bb9d7-jsjws unlabeled

[root@master pod]# kubectl label pods webcluster-6c8b4bb9d7-jsjws app=webcluster
pod/webcluster-6c8b4bb9d7-jsjws labeled

代码解释

  • Deployment 会创建一个 ReplicaSet,ReplicaSet 负责管理 Pod 的副本数
  • 修改 Pod 的标签会导致 Pod 脱离控制器的管理,控制器会创建一个新的 Pod 来替代它

bash

运行

bash 复制代码
# 暴露Deployment为Service
[root@master pod]# kubectl expose deployment webcluster --port 80 --target-port 80

# 查看Service详细信息
[root@master pod]# kubectl describe svc webcluster | tail -n 10
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.98.36.168
IPs:
  IP: 10.98.36.168
Port: 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.12:80
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>

# 访问Service
[root@master pod]# curl 10.98.36.168
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

bash

运行

bash 复制代码
# 更新应用版本
[root@master pod]# kubectl set image deployments webcluster myapp=myapp:v1
deployment.apps/webcluster image updated

# 验证更新
[root@master pod]# curl 10.98.36.168
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

# 查看更新历史
[root@master pod]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION CHANGE-CAUSE
1 <none>
2 <none>

# 回滚到上一个版本
[root@master pod]# kubectl rollout undo deployment webcluster --to-revision 1
deployment.apps/webcluster rolled back

# 验证回滚
[root@master pod]# curl 10.98.36.168
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

核心代码逐行解析

  • kubectl set image:更新 Deployment 的容器镜像,触发滚动更新
  • 滚动更新会先创建新的 Pod,等新 Pod 就绪后再删除旧的 Pod
  • kubectl rollout history:查看 Deployment 的更新历史
  • kubectl rollout undo:回滚到指定的版本

坑点(Gotchas)

  • ❌ 滚动更新时,如果新镜像有问题,会导致服务不可用
  • ❌ 没有设置maxSurgemaxUnavailable时,默认会同时创建 25% 的新 Pod 和删除 25% 的旧 Pod
  • ❌ 回滚只能回滚到之前保存的版本,版本会随着更新次数增加而增加

企业级生产应用

  • 生产环境会配置滚动更新策略,设置maxSurgemaxUnavailable
  • 使用蓝绿部署或金丝雀发布来降低更新风险
  • 千万级并发场景下,会使用 Istio 等服务网格来实现更精细的流量控制
  • 生产环境会设置revisionHistoryLimit来限制保存的历史版本数量

故障排查指南

  1. 错误 :滚动更新卡住
    • 排查思路:
      • 执行kubectl rollout status deployment webcluster查看更新状态
      • 检查新 Pod 是否能正常启动
      • 检查镜像是否正确
      • 检查资源是否足够

3. 利用 yaml 文件部署应用

运行单个容器

bash

运行

bash 复制代码
# 生成Pod的YAML模板
[root@master pod]# kubectl run lee1 --image myapp:v1 --dry-run=client -o yaml > 1test.yml

yaml

bash 复制代码
# 1test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  containers:
  - image: myapp:v1
    name: myappv1

核心代码逐行解析

  • apiVersion: v1:Pod 属于 core API 组的 v1 版本
  • kind: Pod:声明资源类型为 Pod
  • spec.containers:定义 Pod 中的容器列表
  • name: myappv1:容器的名称,在同一个 Pod 中必须唯一

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 1test.yml
pod/lee1 created

[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
lee1 1/1 Running 0 2s

# 查看Pod详细信息
[root@master pod]# kubectl describe pods lee1
Name: lee1
Namespace: default
Priority: 0
Service Account: default
Node: node2/172.25.254.20
Start Time: Sun, 29 Mar 2026 15:15:50 +0800
Labels: run=lee1
Annotations: <none>
Status: Running
IP: 10.244.2.23
IPs:
  IP: 10.244.2.23
Containers:
  myappv1:
    Container ID: docker://3b8b569e18a5d8dcfa55fe7fb6b3abecde985e38ea1eaf72e5c5f160e638ca42
    Image: myapp:v1
    Image ID: docker-pullable://myapp@sha256:9eeca44ba2d410e54fccc54cbe9c021802aa8b9836a0bcf3d3229354e4c8870e
    Port: <none>
    Host Port: <none>
    State: Running
    Started: Sun, 29 Mar 2026 15:15:50 +0800
    Ready: True
    Restart Count: 0
    Environment: <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-x26c2 (ro)
Conditions:
  Type Status
  PodReadyToStartContainers True
  Initialized True
  Ready True
  ContainersReady True
  PodScheduled True
Volumes:
  kube-api-access-x26c2:
    Type: Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds: 3607
    ConfigMapName: kube-root-ca.crt
    Optional: false
    DownwardAPI: true
Qos Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type Reason Age From Message
  Normal Scheduled 16s default-scheduler Successfully assigned default/lee1 to node2
  Normal Pulled 16s kubelet spec.containers{myappv1}: Container image "myapp:v1" already present on machine and can be accessed by the pod
  Normal Created 16s kubelet spec.containers{myappv1}: Container created
  Normal Started 16s kubelet spec.containers{myappv1}: Container started

# 查看Pod的IP和所在节点
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lee1 1/1 Running 0 82s 10.244.2.23 node2 <none> <none>

# 删除Pod
[root@master pod]# kubectl delete -f 1test.yml
pod "lee1" deleted from default namespace
运行多个容器

bash

运行

复制代码
# 复制YAML文件并修改
[root@master pod]# cp 1test.yml 2test.yml
[root@master pod]# vim 2test.yml

yaml

复制代码
# 2test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  containers:
  - image: myapp:v1
    name: myappv1
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 20000

核心代码逐行解析

  • 一个 Pod 中可以运行多个容器,这些容器共享同一个网络命名空间和存储卷
  • command:覆盖容器的默认启动命令
  • 多个容器之间可以通过localhost相互通信

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 2test.yml
pod/lee1 created

[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
lee1 2/2 Running 0 45s

# 强制删除Pod
[root@master pod]# kubectl delete -f 2test.yml --force

坑点(Gotchas)

  • ❌ 一个 Pod 中的多个容器会同时启动和停止
  • ❌ 如果一个容器崩溃,整个 Pod 会被重启
  • ❌ 不要在一个 Pod 中运行多个不相关的应用
理解 pod 间的网络整合

bash

运行

复制代码
[root@master pod]# cp 2test.yml 3test.yml
[root@master pod]# vim 3test.yml

yaml

复制代码
# 3test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  containers:
  - image: myapp:v1
    name: myappv1
  - image: busyboxplus:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 20000

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 3test.yml
pod/lee1 created

[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
lee1 2/2 Running 0 17s

# 进入busybox容器,访问myappv1容器
[root@master pod]# kubectl exec -it pods/lee1 -c busybox -- /bin/sh
[ root@lee1:/ ]$ curl localhost
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

代码解释

  • 同一个 Pod 中的容器共享同一个网络命名空间,所以可以通过localhost相互访问
  • 这是 Pod 设计的核心原则之一:"一个 Pod 一个 IP"
端口映射

bash

运行

复制代码
[root@master pod]# cp 1test.yml 4test.yml
[root@master pod]# vim 4test.yml

yaml

复制代码
# 4test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  containers:
  - image: myapp:v1
    name: myappv1
    ports:
    - name: webport
      containerPort: 80
      hostPort: 80
      protocol: TCP

核心代码逐行解析

  • containerPort: 80:容器监听的端口
  • hostPort: 80:将容器的 80 端口映射到宿主机的 80 端口
  • 底层会在宿主机上创建一个 iptables 规则,将宿主机 80 端口的流量转发到容器的 80 端口

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 4test.yml
pod/lee1 created

[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lee1 1/1 Running 0 7s 10.244.2.31 node2 <none> <none>

# 通过宿主机IP访问Pod
[root@master pod]# curl 172.25.254.20
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

坑点(Gotchas)

  • hostPort会占用宿主机的端口,同一个宿主机上不能有多个 Pod 使用同一个 hostPort
  • ❌ 生产环境不推荐使用 hostPort,应该使用 Service 来暴露端口
选择运行节点

bash

运行

复制代码
[root@master pod]# cp 4test.yml 5test.yml
[root@master pod]# vim 5test.yml

yaml

复制代码
# 5test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  nodeSelector:
    kubernetes.io/hostname: node1
  containers:
  - image: myapp:v1
    name: myappv1
    ports:
    - name: webport
      containerPort: 80
      hostPort: 80
      protocol: TCP

核心代码逐行解析

  • nodeSelector:指定 Pod 只能运行在具有特定标签的节点上
  • kubernetes.io/hostname是 Kubernetes 自动为每个节点添加的标签,值为节点的主机名
  • 调度器只会将 Pod 调度到满足 nodeSelector 条件的节点上

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 5test.yml
pod/lee1 created

[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lee1 1/1 Running 0 5s 10.244.1.10 node1 <none> <none>
共享宿主机网络

bash

运行

复制代码
[root@master pod]# cp 5test.yml 6test.yml
[root@master pod]# vim 6test.yml

yaml

复制代码
# 6test.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  hostNetwork: true
  nodeSelector:
    kubernetes.io/hostname: node1
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 1000

核心代码逐行解析

  • hostNetwork: true:让 Pod 使用宿主机的网络命名空间,而不是创建自己的网络命名空间
  • 此时 Pod 的 IP 就是宿主机的 IP
  • 容器可以直接访问宿主机的所有网络接口

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f 6test.yml
pod/lee1 created

# 进入容器查看网络接口
[root@master pod]# kubectl exec -it pods/lee1 -c busybox -- /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether 00:0c:29:67:23:76 brd ff:ff:ff:ff:ff:ff
    inet 172.25.254.10/24 brd 172.25.254.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::7a35:2bf3:8ff4:9419/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
    link/ether 3a:0c:33:9f:d9:36 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue
    link/ether 06:c7:70:fe:6f:e6 brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::4c7:70ff:fefe:6fe6/64 scope link
       valid_lft forever preferred_lft forever
5: cni0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
    link/ether 7a:22:fc:84:3f:e2 brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.1/24 brd 10.244.1.255 scope global cni0
       valid_lft forever preferred_lft forever
    inet6 fe80::7822:fcff:fe84:3fe2/64 scope link
       valid_lft forever preferred_lft forever

坑点(Gotchas)

  • ❌ 使用 hostNetwork 的 Pod 会绕过 Kubernetes 的网络模型
  • ❌ 容器可以直接访问宿主机的所有网络资源,存在安全风险
  • ❌ 生产环境只有在特殊情况下才使用 hostNetwork,如网络插件、监控代理等

企业级生产应用

  • 生产环境会使用 nodeSelector 和亲和性来控制 Pod 的调度
  • 千万级并发场景下,会使用拓扑分布约束(Topology Spread Constraints)来保证 Pod 在不同节点、可用区均匀分布
  • 生产环境会使用 NetworkPolicy 来控制 Pod 之间的网络访问

故障排查指南

  1. 错误 :Pod 一直处于 Pending 状态
    • 排查思路:
      • 执行kubectl describe pod lee1查看 Events
      • 检查是否有满足 nodeSelector 条件的节点
      • 检查节点资源是否足够

五、pod 的生命周期

1. init 容器

生活类比:就像飞机起飞前的准备工作。在乘客登机前,地勤人员需要完成加油、检查飞机、装载行李等工作。只有所有准备工作完成后,乘客才能登机,飞机才能起飞。

bash

运行

复制代码
[root@master pod]# cp 1test.yml init.yml
[root@master pod]# vim init.yml

yaml

复制代码
# init.yml内容
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: lee1
  name: lee1
spec:
  initContainers:
  - name: init-myservice
    image: busybox
    command: ["sh","-c","until test -e /testfile;do echo waiting for myservice; sleep 2;done"]
  containers:
  - image: myapp:v1
    name: myappv1

核心代码逐行解析

  • initContainers:定义初始化容器,这些容器会在主容器启动之前运行
  • 初始化容器会按顺序运行,只有前一个初始化容器成功完成后,才会运行下一个
  • 所有初始化容器都成功完成后,才会启动主容器
  • 本例中,初始化容器会一直等待/testfile文件出现,然后才会退出

bash

运行

复制代码
# 创建Pod
[root@master pod]# kubectl apply -f init.yml
pod/lee1 created

# 监控Pod状态
[root@master pod]# watch -n 1 kubectl get pods
NAME READY STATUS RESTARTS AGE
lee1 0/1 Init:0/1 0 3s

代码解释

  • Init:0/1表示有 1 个初始化容器,0 个已经完成
  • 此时主容器还没有启动

bash

运行

复制代码
# 进入初始化容器,创建testfile文件
[root@master pod]# kubectl exec -it pods/lee1 -c init-myservice -- /bin/sh
/ # touch /testfile
/ # command terminated with exit code 137

# 查看Pod状态
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
lee1 1/1 Running 0 2m32s

代码解释

  • 创建/testfile文件后,初始化容器成功退出
  • 主容器开始启动,最终 Pod 状态变为 Running

坑点(Gotchas)

  • ❌ 初始化容器失败会导致 Pod 重启,除非设置了restartPolicy: Never
  • ❌ 初始化容器不能使用 livenessProbe 和 readinessProbe
  • ❌ 初始化容器的资源请求会被计算在 Pod 的总资源请求中

企业级生产应用

  • 初始化容器常用于:等待依赖服务启动、初始化配置、下载数据等
  • 千万级并发场景下,会使用初始化容器来预热应用缓存,提高启动速度
  • 生产环境会设置初始化容器的超时时间,防止初始化过程无限等待

故障排查指南

  1. 错误 :Pod 一直处于 Init 状态
    • 排查思路:
      • 执行kubectl logs lee1 -c init-myservice查看初始化容器的日志
      • 检查初始化容器的命令是否正确
      • 检查依赖服务是否正常

2. livenessprobe (存活探针)

生活类比:就像飞机上的黑匣子和飞行监控系统。它会持续监控飞机的飞行状态,如果发现飞机出现严重故障,会自动触发紧急程序,甚至让飞机自动降落。

bash

运行

复制代码
# 生成Deployment和Service的YAML模板
[root@master pod]# kubectl create deployment webcluster --image myapp:v1 --replicas 1 --dry-run=client -o yaml > liveness.yml
[root@master pod]# kubectl expose deployment webcluster --port 80 --target-port 80 --dry-run=client -o yaml >> liveness.yml

# 删除已存在的资源(如果有)
[root@master pod]# kubectl delete -f liveness.yml
deployment.apps "webcluster" deleted from default namespace
Error from server (NotFound): error when deleting "liveness.yml": services "webcluster" not found

# 创建资源
[root@master pod]# kubectl apply -f liveness.yml
deployment.apps/webcluster created
service/webcluster created

yaml

复制代码
# liveness.yml内容(添加livenessProbe)
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webcluster
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 1
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: webcluster

核心代码逐行解析

  • livenessProbe:定义存活探针,用于检测容器是否正常运行
  • httpGet:通过 HTTP GET 请求来检测容器健康状态
  • initialDelaySeconds: 10:容器启动后等待 10 秒再开始检测
  • periodSeconds: 5:每隔 5 秒检测一次
  • timeoutSeconds: 1:检测超时时间为 1 秒
  • failureThreshold: 3:连续 3 次检测失败后,kubelet 会重启容器

bash

运行

复制代码
# 监控Pod状态
[root@master pod]# watch -n 1 "kubectl get pods ;kubectl describe svc webcluster | tail -n 10"
NAME READY STATUS RESTARTS AGE
webcluster-584fddd575-4ttz9 1/1 Running 3 (2s ago) 92s
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.105.47.234
IPs:
  IP: 10.105.47.234
Port: 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.36:80
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>

代码解释

  • RESTARTS 列显示为 3,表示容器已经被重启了 3 次
  • 这说明存活探针检测失败,kubelet 重启了容器

bash

运行

复制代码
# 手动停止nginx服务,模拟应用故障
[root@master pod]# kubectl exec -it pods/webcluster-7fd94cc55b-pgdx6 -c myapp -- /bin/sh
/ # nginx -s stop
2026/03/29 08:50:02 [notice] 59#59: signal process started
/ # command terminated with exit code 137

代码解释

  • 停止 nginx 服务后,存活探针的 HTTP GET 请求会失败
  • 连续 3 次失败后,kubelet 会重启容器

坑点(Gotchas)

  • ❌ 存活探针配置不当会导致容器频繁重启
  • ❌ 不要将存活探针的检测路径指向需要数据库连接的页面,否则数据库故障会导致所有 Pod 重启
  • initialDelaySeconds设置过短会导致应用还没启动完成就被重启

企业级生产应用

  • 生产环境必须为所有容器配置存活探针
  • 存活探针应该检测应用的核心功能,而不是简单的 TCP 连接
  • 千万级并发场景下,会根据应用的启动时间和响应时间来调整探针参数
  • 生产环境会结合 Prometheus 和 Grafana 来监控应用的健康状态

故障排查指南

  1. 错误 :容器频繁重启
    • 排查思路:
      • 执行kubectl describe pod查看容器重启的原因
      • 执行kubectl logs查看应用日志
      • 检查存活探针的配置是否正确
      • 手动访问探针路径,检查是否正常响应

3. ReadinessProbe

生活类比:就像机场的登机口显示屏。只有当飞机准备好接受乘客登机时,显示屏才会显示 "正在登机"。如果飞机还在准备中或者出现故障,显示屏会显示 "延误" 或 "取消",乘客就不会被引导到这个登机口。

bash

运行

复制代码
[root@master pod]# cp liveness.yml ReadinessProbe.yml
[root@master pod]# vim ReadinessProbe.yml

yaml

复制代码
# ReadinessProbe.yml内容
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webcluster
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp
        readinessProbe:
          httpGet:
            path: /test.html
            port: 80
          initialDelaySeconds: 1
          periodSeconds: 3
          timeoutSeconds: 1
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: webcluster

核心代码逐行解析

  • readinessProbe:定义就绪探针,用于检测容器是否准备好接收流量
  • 就绪探针检测成功后,Pod 会被添加到 Service 的 Endpoints 列表中
  • 就绪探针检测失败后,Pod 会从 Service 的 Endpoints 列表中移除
  • 本例中,就绪探针会检测/test.html路径是否存在

bash

运行

复制代码
# 创建资源
[root@master pod]# kubectl apply -f ReadinessProbe.yml
deployment.apps/webcluster configured
service/webcluster unchanged

# 监控Pod和Service状态
[root@master pod]# watch -n 1 "kubectl get pods ;kubectl describe svc webcluster | tail -n 10"
NAME READY STATUS RESTARTS AGE
webcluster-6bc85dfc84-zk4mn 0/1 Running 0 7s
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.107.142.60
IPs:
  IP: 10.107.142.60
Port: 80/TCP
TargetPort: 80/TCP
Endpoints:
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>

代码解释

  • READY: 0/1表示 Pod 还没有准备好接收流量
  • Service 的 Endpoints 列表为空,说明没有 Pod 可以接收流量

bash

运行

复制代码
# 进入容器,创建test.html文件
[root@master pod]# kubectl exec -it pods/webcluster-6bc85dfc84-zk4mn -c myapp -- /bin/sh
/ # echo timinglee > /usr/share/nginx/html/test.html

代码解释

  • 创建test.html文件后,就绪探针检测成功
  • Pod 的 READY 状态会变为 1/1
  • Service 的 Endpoints 列表会添加该 Pod 的 IP 和端口

bash

运行

复制代码
# 删除test.html文件
/ # rm -fr /usr/share/nginx/html/test.html

代码解释

  • 删除test.html文件后,就绪探针检测失败
  • Pod 的 READY 状态会变为 0/1
  • Service 的 Endpoints 列表会移除该 Pod 的 IP 和端口

坑点(Gotchas)

  • ❌ 就绪探针失败不会重启容器,只会将 Pod 从 Service 的 Endpoints 列表中移除
  • ❌ 不要将就绪探针和存活探针配置为相同的检测路径
  • ❌ 就绪探针检测失败会导致 Pod 无法接收流量,但 Pod 仍然在运行

企业级生产应用

  • 生产环境必须为所有容器配置就绪探针
  • 就绪探针应该检测应用是否准备好接收流量,如数据库连接是否建立、缓存是否预热等
  • 千万级并发场景下,就绪探针是实现滚动更新和自动扩缩容的关键
  • 生产环境会结合就绪探针和 PodDisruptionBudget 来保证服务的可用性

故障排查指南

  1. 错误 :Service 的 Endpoints 列表为空
    • 排查思路:
      • 执行kubectl get pods查看 Pod 的 READY 状态
      • 执行kubectl describe pod查看就绪探针的状态
      • 手动访问探针路径,检查是否正常响应
      • 检查 Service 的 selector 是否与 Pod 的标签匹配

灵魂拷问

  1. 为什么 Kubernetes 要设计 Pod 这个概念,而不是直接管理容器?
  2. 同一个 Pod 中的多个容器共享哪些资源,又有哪些资源是隔离的?
  3. 存活探针和就绪探针的本质区别是什么?在什么情况下应该使用哪一个?
相关推荐
切糕师学AI4 小时前
Envoy 详解:云原生时代的高性能网络代理
网络·云原生·istio·网络代理·envoy·sidecar·网格服务
H Journey4 小时前
VMware + Linux(Ubuntu) + 桥接网络知识梳理
linux·网络·ubuntu
少年攻城狮4 小时前
阿里云系列---【申请域名并绑定到主机ip】
linux·服务器·tcp/ip·阿里云·云计算
古城小栈4 小时前
K8s 存储组件 通俗精讲
云原生·容器·kubernetes
BIG_PEI4 小时前
如何判断Linux服务器上是否安装了rabbitmq
linux·服务器·rabbitmq
陳10304 小时前
Linux:System V 消息队列与信号量
linux·运维·服务器
云飞云共享云桌面4 小时前
SolidWorks 服务器通过云飞云共享云桌面10人研发共享方案
运维·服务器·3d·设计模式·电脑
日取其半万世不竭4 小时前
auditd:Linux 系统审计日志,记录谁动了你的服务器
linux·服务器·github
千匠网络4 小时前
千匠网络制造行业渠道分销B2B解决方案:AI驱动,重构产业分销模式
网络·云原生·架构·制造业·b2b·电商解决方案