目录

一、资源使用的方法

1. 命令式

2. YAML 文件方式

二、资源类型

1. node

2. namespace

三、kubectl 命令

四、Pod 应用

1. 自助式管理 pod

2. 利用控制器管理 pod

3. 利用 yaml 文件部署应用

运行单个容器

运行多个容器

理解 pod 间的网络整合

端口映射

选择运行节点

共享宿主机网络

五、pod 的生命周期

1. init 容器

2. livenessprobe (存活探针)

3. ReadinessProbe

灵魂拷问


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


一、资源使用的方法

1. 命令式

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

# 创建一个运行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

运行

# 查看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 没有设置资源限制,优先级最低

# 查看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

运行

# 生成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

# 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

运行

# 建立式创建资源
[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

运行

# 注意:建立只能建立不能更新,声明可以
[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

运行

# 查看集群节点信息
[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

运行

# 查看所有命名空间
[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

运行

# 创建新的命名空间
[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

运行

# 查看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

运行

# 补丁式更新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

运行

# 暴露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

运行

# 查看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

运行

# 交互式进入容器
[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

运行

# 扩容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

运行

# 查看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

运行

# 创建运行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

运行

# 创建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

运行

# 暴露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

运行

# 更新应用版本
[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

运行

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

yaml

# 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. 存活探针和就绪探针的本质区别是什么?在什么情况下应该使用哪一个?
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐