一、Pod就像小饭馆里的厨师

想象一下,Kubernetes的Pod就像一个小饭馆里的厨师团队。一个Pod可以包含一个或多个容器(厨师),他们共享厨房(网络和存储空间)。厨师从接单到关火的过程,就是Pod的生命周期——创建、运行、结束。

比如一个简单的Nginx服务Pod:

# 技术栈:Kubernetes YAML
apiVersion: v1
kind: Pod
metadata:
  name: nginx-chef
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

这个厨师(Nginx容器)会一直工作,直到有人喊停(删除Pod)。

二、Hook是厨师的闹钟

Kubernetes提供了两种特殊的"闹钟":

  1. PostStart:厨师刚系上围裙时响铃(容器启动后立即执行)
  2. PreStop:厨师收到下班通知时响铃(容器终止前执行)

看个实际例子:

# 技术栈:Kubernetes YAML
apiVersion: v1
kind: Pod
metadata:
  name: hook-demo
spec:
  containers:
  - name: main-chef
    image: busybox
    command: ["/bin/sh", "-c", "sleep 3600"]  # 主程序休眠1小时
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo '开始备菜' > /tmp/log"]  # 启动时记录
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo '收拾厨房' > /tmp/log"]  # 停止前清理

这个厨师会在上班时自动记录工作日志,下班前也会自觉打扫卫生。

三、Hook的三种触发方式

1. 命令行方式(Exec)

就像直接给厨师下口头指令:

lifecycle:
  postStart:
    exec:
      command: ["/bin/sh", "-c", "date >> /app/start.log"]

2. HTTP请求方式(HTTPGet)

相当于让厨师去查看特定菜单:

lifecycle:
  postStart:
    httpGet:
      path: /healthcheck
      port: 8080
      httpHeaders:
      - name: X-Custom-Header
        value: "WakeUp"

3. TCP探测方式(TCPSocket)

类似检查灶台是否点火成功:

lifecycle:
  preStop:
    tcpSocket:
      port: 8000

四、实战:优雅关闭数据库

假设我们有个MySQL服务,需要在关闭前完成现有操作:

# 技术栈:Kubernetes YAML
apiVersion: v1
kind: Pod
metadata:
  name: mysql-graceful
spec:
  containers:
  - name: mysql
    image: mysql:5.7
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "secret"
    lifecycle:
      preStop:
        exec:
          command: 
          - /bin/sh
          - -c
          - |
            # 停止接受新连接
            mysqladmin -uroot -p$MYSQL_ROOT_PASSWORD shutdown || true
            # 等待10秒确保完成
            sleep 10
    ports:
    - containerPort: 3306

这样关闭Pod时,MySQL会先优雅停止服务,而不是直接被"断电"。

五、什么时候该用Hook?

适用场景:

  • 服务启动时需要预热缓存(如Redis加载数据)
  • 关闭前需要通知其他服务(如微服务下线通知)
  • 执行关键初始化(如数据库迁移)

注意事项:

  1. PostStart不保证在容器入口命令前执行完成
  2. Hook执行超时会强制终止(默认30秒)
  3. 失败的PostStart不会阻止容器运行

六、Hook的替代方案

如果Hook不能满足需求,还可以考虑:

  1. Init容器:专门做初始化工作的临时工
  2. Readiness探针:控制流量进入时机
  3. Sidecar模式:雇个专门处理杂务的副厨

比如用Init容器准备配置文件:

# 技术栈:Kubernetes YAML
apiVersion: v1
kind: Pod
metadata:
  name: web-server
spec:
  initContainers:
  - name: config-loader
    image: busybox
    command: ['sh', '-c', 'echo "production=true" > /config/settings.ini']
    volumeMounts:
    - name: config
      mountPath: /config
  containers:
  - name: web
    image: nginx
    volumeMounts:
    - name: config
      mountPath: /etc/nginx/conf.d

七、经验总结

  1. 轻量原则:Hook脚本要像快餐一样快速完成
  2. 幂等设计:重复执行不会出问题
  3. 超时设置:复杂操作要显式设置timeout
  4. 日志记录:给每个Hook加日志就像给厨师装监控

记住,Kubernetes的生命周期管理就像管理一支厨师团队——既要保证他们准时开工,也要确保他们优雅收工。合理使用Hook机制,能让你的应用像米其林餐厅后厨一样井然有序。