Pod 是 K8s 最小调度单位,理解其状态流转和容器协作模式是应用稳定性的前提。一个 Pod 中多个容器的启动/终止顺序、探针配置的细微差别直接影响线上表现。
Pod 生命周期状态机
创建 → PodScheduled(调度到节点)→ Init Containers 依次执行 → 主容器启动 → PostStart 钩子 → readiness 通过才被 service 接收流量 → liveness 失败重启 → 删除时 SIGTERM → preStop → terminationGracePeriodSeconds 超时强制杀。
apiVersion: v1
kind: Pod
metadata: { name: web-app-pod, labels: { app: web } }
spec:
terminationGracePeriodSeconds: 60
shareProcessNamespace: true
serviceAccountName: web-sa
initContainers:
- name: wait-for-db
image: bitnami/postgresql:16
command: ["/bin/sh", "-c", "until pg_isready -h postgres -p 5432 -U app; do echo wait; sleep 3; done;"]
- name: migrate-db
image: registry.example.com/app:${APP_VERSION}
command: ["alembic", "upgrade", "head"]
envFrom: [{ configMapRef: { name: web-config } }]
volumeMounts: [{ name: app-secret, mountPath: /run/secrets, readOnly: true }]
- name: fetch-assets
image: amazon/aws-cli
command: ["aws", "s3", "sync", "s3://app-assets/static/", "/var/www/static/", "--delete"]
volumeMounts: [{ name: static-assets, mountPath: /var/www/static }]
containers:
- name: app
image: registry.example.com/app:${APP_VERSION}
ports: [{ containerPort: 8000, name: http }]
lifecycle:
postStart: { exec: { command: ["/bin/sh", "-c", "echo started >> /var/log/app/boot.log"] } }
preStop:
exec: { command: ["/bin/sh", "-c", "sleep 5; kill -SIGTERM 1; while pidof app >/dev/null; do sleep 1; done;"] }
readinessProbe: { httpGet: { path: /health/ready, port: http }, initialDelaySeconds: 3, periodSeconds: 5 }
livenessProbe: { httpGet: { path: /health/live, port: http }, initialDelaySeconds: 15, periodSeconds: 20, failureThreshold: 3 }
startupProbe: { httpGet: { path: /health/started, port: http }, periodSeconds: 5, failureThreshold: 30 }
resources:
requests: { cpu: 100m, memory: 256Mi }
limits: { cpu: 1000m, memory: 1Gi }
volumeMounts:
- { name: static-assets, mountPath: /app/static, readOnly: true }
- { name: app-logs, mountPath: /var/log/app }
- name: envoy-sidecar
image: envoyproxy/envoy:v1.30
lifecycle:
preStop: { exec: { command: ["/bin/sh", "-c", "curl -X POST http://localhost:15000/healthcheck/fail; sleep 10;"] } }
- name: fluentbit-sidecar
image: fluent/fluent-bit:3.0
volumeMounts: [{ name: app-logs, mountPath: /var/log/app, readOnly: true }]
volumes:
- { name: static-assets, emptyDir: {} }
- { name: app-logs, emptyDir: {} }
- { name: app-secret, secret: { secretName: web-secret } }
Init 容器与 Sidecar 模式
Init Containers 按顺序逐一执行,成功后主容器才启动。适合做数据库等待、数据迁移、静态资源拉取。Sidecar 和主容器共享网络/卷,提供主容器无侵入的代理(istio/envoy)、日志收集(fluentbit)。
| 容器类型 | 启动时机 | 与主容器关系 | 用途示例 |
|---|---|---|---|
| Init Container | 主容器之前串行 | 成功一次即可退出 | 等待DB、数据迁移 |
| Sidecar 容器 | 与主容器并行 | 同生命周期同退 | Service Mesh代理 |
| Sidecar 容器 | 与主容器并行 | 生命周期相同 | 日志收集fluentbit |
| Main App 容器 | Init完成后 | 业务主进程 | Web服务API |
| Ephemeral 容器 | 任意时刻debug注入 | 临时 | 调试故障Pod |
最佳实践
永远配 startupProbe 给冷启动慢的应用,preStop 里睡几秒等待 service 摘掉端点再终止,避免流量进来时进程已死掉。readiness 判断数据库依赖,不要启动就 ready。