第4章:使用Pod运行工作负载(Running Workloads with Pods)
一、导读
1.1 本章学习目标
Pod 是 Kubernetes 的基本构建块,深入理解 Pod 的内部机制对于高效使用 K8s 至关重要。本章从多容器模式开始,讲解 Pod 的高级用法:Sidecar、Ambassador、Adapter 等设计模式。然后深入 Pod 的存储、资源限制、探针配置等关键主题。
本章的核心学习目标包括:
- 掌握多容器 Pod 的设计模式:Sidecar、Ambassador、Adapter 模式的适用场景和实现方式。
- 理解 Pod 的存储机制:emptyDir、hostPath、共享存储卷的使用。
- 掌握资源限制的配置:requests 和 limits 的区别,QoS 等级的影响。
- 配置健康检查探针:Liveness、Readiness、Startup Probe 的作用和配置方法。
- 理解容器的生命周期钩子:postStart 和 preStop 的使用场景。
- 学会调试 Pod 问题:常见故障的排查方法。
1.2 为什么本章如此重要
在生产环境中,Pod 的配置直接影响应用的可用性、性能和可观测性。错误的探针配置可能导致 Pod 频繁重启,不合理的资源限制可能导致节点资源耗尽,不正确的存储配置可能导致数据丢失。
多容器 Pod 模式是 Kubernetes 的特色能力——它允许你将紧密耦合的容器组合在一起,共享网络和存储。这种模式在微服务架构中提供了更灵活的部署选择。
1.3 核心问题引导
什么时候应该在同一个 Pod 中运行多个容器?什么时候应该拆分为多个 Pod?
Liveness Probe 和 Readiness Probe 的区别是什么?配置错误会导致什么后果?
requests 和 limits 的区别是什么?如果只设置 limits 不设置 requests 会怎样?
emptyDir 和 hostPath 的区别是什么?各自的适用场景?
容器重启后,emptyDir 中的数据会丢失吗?
二、核心概念详解
2.1 多容器 Pod 设计模式
一个 Pod 中可以运行多个容器,它们共享网络命名空间(相同的 IP 和端口)和存储卷。这种设计适用于需要紧密耦合的容器组合。
2.1.1 Sidecar 模式
Sidecar 容器增强主容器的功能。常见的 Sidecar 场景:
- 日志收集:主容器写日志到共享卷,Sidecar 容器读取并转发到日志系统
- 配置同步:Sidecar 容器从配置中心拉取配置,主容器读取本地配置文件
- 代理/网关:Sidecar 容器作为主容器的本地代理
apiVersion: v1
kind: Pod
metadata:
name: app-with-log-sidecar
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
env:
- name: LOG_OUTPUT
value: "elasticsearch"
volumes:
- name: logs
emptyDir: {}2.1.2 Ambassador 模式
Ambassador 容器代理主容器与外部服务的通信。典型场景:
- 数据库代理:主容器连接 localhost 的 Ambassador,Ambassador 代理到实际的数据库
- 服务网格:Envoy/Istio sidecar 就是 Ambassador 模式
apiVersion: v1
kind: Pod
metadata:
name: app-with-db-proxy
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DB_HOST
value: "localhost"
- name: DB_PORT
value: "6379"
- name: redis-proxy
image: envoy-proxy:latest
ports:
- containerPort: 6379
env:
- name: UPSTREAM_HOST
value: "redis-cluster.production.svc"2.1.3 Adapter 模式
Adapter 容器标准化主容器的输出接口。典型场景:
- 监控标准化:不同应用暴露不同格式的指标,Adapter 统一转换为 Prometheus 格式
- 日志格式化:将非标准日志格式转换为 JSON
apiVersion: v1
kind: Pod
metadata:
name: app-with-metrics-adapter
spec:
containers:
- name: app
image: legacy-app:1.0
volumeMounts:
- name: metrics
mountPath: /var/metrics
- name: metrics-exporter
image: prometheus-exporter:latest
ports:
- containerPort: 9090
volumeMounts:
- name: metrics
mountPath: /var/metrics
readOnly: true
volumes:
- name: metrics
emptyDir: {}2.2 Pod 的存储
2.2.1 emptyDir
emptyDir 在 Pod 被调度到节点时创建,Pod 删除时数据丢失。适用于:
- 容器间共享临时数据
- 磁盘缓存
- 长时间计算中的检查点
apiVersion: v1
kind: Pod
metadata:
name: pod-with-emptydir
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: cache
mountPath: /tmp/cache
- name: worker
image: worker:1.0
volumeMounts:
- name: cache
mountPath: /data/cache
volumes:
- name: cache
emptyDir:
sizeLimit: 1Gi # 限制大小
# medium: Memory # 使用 tmpfs(内存)2.2.2 hostPath
hostPath 将节点文件系统中的文件或目录挂载到 Pod。适用于:
- 访问节点上的 Docker 引擎
- 日志收集 Agent 访问节点日志
- 监控 Agent 访问节点指标
apiVersion: v1
kind: Pod
metadata:
name: pod-with-hostpath
spec:
containers:
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
type: Directory注意:hostPath 有安全风险,因为它可以访问节点文件系统。生产环境中应谨慎使用,配合 RBAC 和 PodSecurityPolicy。
2.3 资源限制
2.3.1 requests 和 limits
- requests:调度依据,K8s 保证 Pod 能获得这么多资源
- limits:运行时上限,Pod 不能超过这个限制
resources:
requests:
cpu: 100m # 0.1 核
memory: 128Mi # 128 MB
limits:
cpu: 500m # 0.5 核
memory: 512Mi # 512 MB2.3.2 QoS 等级
K8s 根据资源配置为 Pod 分配 QoS 等级:
- Guaranteed:所有容器都设置了 requests 和 limits,且相等
- Burstable:至少一个容器设置了 requests 或 limits
- BestEffort:没有设置任何 requests 和 limits
节点资源不足时,K8s 按 QoS 等级驱逐 Pod:BestEffort → Burstable → Guaranteed。
2.4 健康检查探针
2.4.1 Liveness Probe
检测容器是否存活。失败时 K8s 重启容器。
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 32.4.2 Readiness Probe
检测 Pod 是否可以接收流量。失败时从 Service 的 Endpoints 中移除 Pod。
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 52.4.3 Startup Probe
保护慢启动容器。在 Startup Probe 成功之前,Liveness 和 Readiness 不会生效。
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
# 最多等待 300 秒启动2.4.4 探针类型
- httpGet:发送 HTTP GET 请求,2xx/3xx 为成功
- tcpSocket:TCP 连接成功
- exec:执行命令,退出码 0 为成功
- grpc:gRPC HealthCheck
三、实战案例
3.1 完整的 Pod 配置
apiVersion: v1
kind: Pod
metadata:
name: production-app
labels:
app: my-app
env: production
spec:
containers:
- name: app
image: myapp:1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo started"]
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
volumeMounts:
- name: cache
mountPath: /tmp/cache
- name: config
mountPath: /etc/config
- name: sidecar
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /var/log
readOnly: true
volumes:
- name: cache
emptyDir:
sizeLimit: 500Mi
- name: config
configMap:
name: app-config
- name: logs
emptyDir: {}3.2 调试 Pod 问题
# 查看 Pod 事件
kubectl describe pod my-pod
# 常见问题:
# - ImagePullBackOff:镜像拉取失败
# - CrashLoopBackOff:容器反复崩溃
# - Pending:无法调度(资源不足、nodeSelector 不匹配)
# 查看容器日志
kubectl logs my-pod -c app
kubectl logs my-pod --previous # 查看上一次崩溃的日志
# 进入容器调试
kubectl exec -it my-pod -c app -- /bin/bash
# 使用 ephemeral container 调试
kubectl debug -it my-pod --image=busybox --target=app
# 查看 Pod 的资源使用
kubectl top pod my-pod四、本章小结
本章深入讲解了 Pod 的高级用法:
多容器模式:Sidecar 增强功能、Ambassador 代理访问、Adapter 标准化接口。
存储:emptyDir 提供临时共享存储,hostPath 访问节点文件系统。
资源限制:requests 用于调度,limits 用于运行时限制,QoS 等级影响驱逐优先级。
健康检查:Liveness 重启容器、Readiness 控制流量、Startup 保护慢启动。
生命周期钩子:postStart 在容器启动后执行、preStop 在终止前执行。
五、思考与练习
思考题
Sidecar 模式和微服务模式的区别是什么?什么时候选择 Sidecar,什么时候选择独立服务?
如果 Liveness Probe 配置了过短的 initialDelaySeconds,会导致什么问题?
为什么 BestEffort QoS 的 Pod 在资源不足时最先被驱逐?
emptyDir 使用 Memory medium 时有什么限制?适合什么场景?
preStop 钩子中的 sleep 10 有什么作用?为什么需要优雅终止?
练习题
创建一个包含主应用和日志收集 Sidecar 的 Pod,配置共享存储卷。
为 Pod 配置 Liveness 和 Readiness 探针,模拟探针失败,观察 K8s 的行为。
设置不同的资源配置(Guaranteed、Burstable、BestEffort),观察节点压力时的驱逐行为。
使用 kubectl debug 调试一个 CrashLoopBackOff 的 Pod。