写在前面
本文是 K8s 学习笔记系列的第二篇,深入 Pod 的生命周期、多容器模式、健康检查和资源限制。前置知识:集群搭建和基本操作(第一篇)。
一、Pod 基础
1.1 什么是 Pod
Pod 是 K8s 最小的调度单元,包含一个或多个容器,共享网络和存储。
1
2
3
4
5
6
|
Pod
├── 容器1(应用容器)
├── 容器2(Sidecar)
├── 共享网络(同一个 IP,localhost 互通)
├── 共享存储(Volume)
└── 共享配置(环境变量、ConfigMap)
|
为什么不直接调度容器?因为有些容器需要紧密协作(如应用 + 日志收集),把它们放在一个 Pod 里共享网络和存储。
1.2 Pod YAML 详解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
env: prod
spec:
containers:
- name: app
image: my-app:1.0
ports:
- containerPort: 8080
env:
- name: APP_ENV
value: "production"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
restartPolicy: Always
|
1.3 Pod 生命周期
1
2
3
4
5
|
创建 Pod → 调度到节点 → 拉取镜像 → 启动容器 → 运行中
↓
崩溃/健康检查失败
↓
重启容器
|
Pod 的 phase(阶段):
1
2
3
4
5
|
Pending — 等待调度或拉取镜像
Running — 至少一个容器在运行
Succeeded — 所有容器正常退出(不会重启)
Failed — 至少一个容器异常退出
Unknown — 无法获取状态
|
1.4 容器重启策略
1
2
3
4
|
spec:
restartPolicy: Always # 总是重启(默认,适合长期运行的服务)
restartPolicy: OnFailure # 只在失败时重启(适合 Job)
restartPolicy: Never # 从不重启
|
二、多容器模式
2.1 Sidecar(边车模式)
主容器 + 辅助容器,最常用的模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app # 主容器:业务应用
image: my-app:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-collector # Sidecar:日志收集
image: busybox
command: ["sh", "-c", "tail -f /var/log/app/*.log"]
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {} # 共享的临时目录
|
2.2 常见多容器场景
1
2
3
4
|
Sidecar — 日志收集、代理(如 Envoy/Istio)
Ambassador — 代理外部服务连接
Adapter — 标准化输出(如监控指标转换)
Init 容器 — 启动前执行初始化任务
|
2.3 Init 容器
在主容器启动前执行,完成后退出:
1
2
3
4
5
6
7
8
9
10
|
spec:
initContainers:
- name: init-db
image: busybox
command: ["sh", "-c", "until nslookup mysql-service; do echo waiting; sleep 2; done"]
# 等待数据库服务可用后再启动主容器
containers:
- name: app
image: my-app:1.0
|
Init 容器按顺序执行,全部成功后才开始主容器。任何一个失败,Pod 都会重启。
三、健康检查
K8s 通过探针(Probe)检查容器健康状态。
3.1 三种探针
1
2
3
|
livenessProbe — 存活检查:失败则重启容器
readinessProbe — 就绪检查:失败则从 Service 摘除流量
startupProbe — 启动检查:先等这个通过,再执行上面两个
|
3.2 探针配置方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
spec:
containers:
- name: app
image: my-app:1.0
# 存活检查:挂了就重启
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10 # 容器启动后等10秒开始检查
periodSeconds: 10 # 每10秒检查一次
failureThreshold: 3 # 连续失败3次才判定不健康
# 就绪检查:没准备好就不接收流量
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
# 启动检查:慢启动应用用这个(避免被 liveness 杀掉)
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 允许失败30次
periodSeconds: 10 # 最长等 30*10=300秒
|
3.3 探针类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# HTTP GET(最常用)
httpGet:
path: /health
port: 8080
# TCP 检查(适合非 HTTP 服务)
tcpSocket:
port: 3306
# 执行命令(适合自定义检查)
exec:
command:
- cat
- /tmp/healthy
|
3.4 探针配置建议
1
2
3
4
|
Web 服务 → httpGet + liveness + readiness
数据库 → tcpSocket + readiness
慢启动应用 → startupProbe + liveness + readiness
健康检查接口 → 返回 200 表示健康,返回 500 或超时表示不健康
|
四、资源限制
4.1 requests 和 limits
1
2
3
4
5
6
7
|
resources:
requests: # 调度依据:保证最少有这么多资源
memory: "128Mi"
cpu: "100m" # 100m = 0.1 核
limits: # 上限:最多用这么多,超过会被限制或杀掉
memory: "256Mi"
cpu: "500m" # 500m = 0.5 核
|
1
2
3
4
5
|
requests — 调度器用来决定 Pod 放在哪个节点
limits — 运行时的硬上限
CPU 超限 → 被限流(throttled),不会杀容器
内存超限 → 被杀掉(OOMKilled)
|
4.2 CPU 单位
1
2
3
|
1 = 1 核 CPU
500m = 0.5 核(500 millicores)
100m = 0.1 核
|
4.3 内存单位
1
2
3
|
Mi = Mebibytes(1024 KiB,K8s 中常用)
Gi = Gibibytes(1024 Mi)
M = Megabytes(1000 KB,不推荐用)
|
4.4 QoS 等级
根据 requests 和 limits 的设置,Pod 分为三个等级:
1
2
3
|
Guaranteed — requests = limits(最高优先级,最后被杀)
Burstable — 设置了 requests 但不等于 limits
BestEffort — 没设置 requests 和 limits(最先被杀)
|
建议生产环境所有 Pod 都设置 requests 和 limits,保证 Guaranteed 或 Burstable。
4.5 LimitRange(默认资源限制)
给命名空间设置默认值,防止忘记配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- default: # 默认 limits
cpu: "500m"
memory: "256Mi"
defaultRequest: # 默认 requests
cpu: "100m"
memory: "128Mi"
type: Container
|
五、环境变量与配置注入
5.1 直接定义
1
2
3
4
5
|
env:
- name: APP_ENV
value: "production"
- name: APP_PORT
value: "8080"
|
5.2 从 ConfigMap 引用
1
2
3
4
5
6
|
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config # ConfigMap 名
key: database_host # ConfigMap 中的 key
|
5.3 从 Secret 引用
1
2
3
4
5
6
|
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret # Secret 名
key: password # Secret 中的 key
|
5.4 挂载为文件
1
2
3
4
5
6
7
8
9
10
11
12
|
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
|
六、Pod 排错
6.1 常见问题速查
1
2
3
4
5
6
|
Pending → 资源不足,kubectl describe pod 看 Events
CrashLoopBackOff → 容器启动后崩溃,kubectl logs --previous 看上次日志
ImagePullBackOff → 镜像拉取失败,检查镜像名和仓库权限
OOMKilled → 内存超限,增大 limits.memory
Completed → 容器执行完退出了,正常(Job)或命令写错
ContainerCreating → 一直在创建,检查镜像拉取和挂载
|
6.2 排查步骤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 1. 查看 Pod 状态
kubectl get pods -o wide
# 2. 查看 Pod 详情和事件
kubectl describe pod <pod-name>
# 3. 查看容器日志
kubectl logs <pod-name>
kubectl logs <pod-name> --previous # 上次崩溃的日志
kubectl logs <pod-name> -c <container> # 指定容器
# 4. 进入容器排查
kubectl exec -it <pod-name> -- sh
# 5. 查看资源使用
kubectl top pods
|
七、小结
本文学习了 Pod 的核心知识:
- Pod 的概念和生命周期
- 多容器模式(Sidecar、Init 容器)
- 健康检查(liveness、readiness、startup 探针)
- 资源限制(requests/limits、QoS)
- 环境变量与配置注入
- Pod 常见问题排查
下一篇将学习工作负载管理:Deployment 滚动更新、StatefulSet 和 DaemonSet。