目录
[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 创建
故障排查指南:
- 错误 :
ErrImagePull- 排查思路:
- 检查镜像名称和标签是否正确
- 检查节点是否能访问镜像仓库
- 检查私有仓库的 Secret 是否正确配置
- 排查思路:
- 错误 :
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.matchLabels与spec.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.limits和resources.requests来保证资源隔离
故障排查指南:
- 错误 :
selector does not match template labels- 排查思路:
- 检查
spec.selector.matchLabels与spec.template.metadata.labels是否完全一致 - Deployment 的 selector 一旦创建就不能修改,必须删除重建
- 检查
- 排查思路:
- 错误 :
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)根据负载自动增减节点
故障排查指南:
- 错误 :节点状态为
NotReady- 排查思路:
- 登录节点检查 kubelet 服务状态:
systemctl status kubelet - 检查节点网络是否正常
- 检查节点磁盘是否满了
- 登录节点检查 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 控制不同命名空间之间的网络访问
- 千万级并发场景下,会将不同的微服务部署在不同的命名空间
故障排查指南:
- 错误 :
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 来集中收集和管理日志
故障排查指南:
- 错误 :
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 管理有状态应用
故障排查指南:
- 错误 :
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):
- ❌ 滚动更新时,如果新镜像有问题,会导致服务不可用
- ❌ 没有设置
maxSurge和maxUnavailable时,默认会同时创建 25% 的新 Pod 和删除 25% 的旧 Pod - ❌ 回滚只能回滚到之前保存的版本,版本会随着更新次数增加而增加
企业级生产应用:
- 生产环境会配置滚动更新策略,设置
maxSurge和maxUnavailable - 使用蓝绿部署或金丝雀发布来降低更新风险
- 千万级并发场景下,会使用 Istio 等服务网格来实现更精细的流量控制
- 生产环境会设置
revisionHistoryLimit来限制保存的历史版本数量
故障排查指南:
- 错误 :滚动更新卡住
- 排查思路:
- 执行
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:声明资源类型为 Podspec.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 之间的网络访问
故障排查指南:
- 错误 :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 的总资源请求中
企业级生产应用:
- 初始化容器常用于:等待依赖服务启动、初始化配置、下载数据等
- 千万级并发场景下,会使用初始化容器来预热应用缓存,提高启动速度
- 生产环境会设置初始化容器的超时时间,防止初始化过程无限等待
故障排查指南:
- 错误 :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 来监控应用的健康状态
故障排查指南:
- 错误 :容器频繁重启
- 排查思路:
- 执行
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 来保证服务的可用性
故障排查指南:
- 错误 :Service 的 Endpoints 列表为空
- 排查思路:
- 执行
kubectl get pods查看 Pod 的 READY 状态 - 执行
kubectl describe pod查看就绪探针的状态 - 手动访问探针路径,检查是否正常响应
- 检查 Service 的 selector 是否与 Pod 的标签匹配
- 执行
- 排查思路:
灵魂拷问
- 为什么 Kubernetes 要设计 Pod 这个概念,而不是直接管理容器?
- 同一个 Pod 中的多个容器共享哪些资源,又有哪些资源是隔离的?
- 存活探针和就绪探针的本质区别是什么?在什么情况下应该使用哪一个?