第一点:关于“容器刚创建”与“启动命令”的关系
command(即 ENTRYPOINT/CMD)写入容器的配置中。此时,容器处于“已创建但未运行”的状态。command(主进程启动)。就在主进程被拉起的同时,Kubelet 会立刻触发 PostStart 钩子。第二点:关于“删除 Pod”还是“删除容器”
containers 子标签下的,Pod 里可能有多个容器。执行 kubectl delete pod 时,难道不应该叫“删除容器”吗?kubectl delete pod 和“删除容器”并不冲突,它们是“整体与局部”的关系。kubectl delete pod 时,你是在向 K8s 的 API Server 发出一个指令:“我要销毁这个 Pod”。API Server 接收到指令后,会将这个 Pod 标记为“Terminating(终止中)”。container 下的,所以 Kubelet 只会对配置了 PreStop 的那个特定容器触发钩子。delete pod 时,Kubelet 会先执行容器 A 的 PreStop,然后再发 SIGTERM 给 A;而容器 B 没有 PreStop,Kubelet 会直接发 SIGTERM 给 B。kubectl delete pod 时,Kubelet 会触发对应容器的 PreStop 钩子”是最严谨的docker run 确实是一个“创建并启动”的组合动作,而 Kubernetes 在底层把这两个动作严格拆分了。1. Docker 的 docker run = docker create + docker start
docker run 其实是一个“快捷指令”,它等价于:docker create:创建容器,分配资源,写入启动命令,但此时容器处于 Created 状态,进程并未运行。docker start:启动这个已经创建好的容器,主进程开始运行。2. K8s 为什么要强行拆分 Create 和 Start?
postStart 钩子。3. 为什么要这样设计?(核心目的)
总结
docker run 是 Docker 封装好的用户态快捷操作;而 Kubernetes 中的 Create 和 Start,是 Kubelet 在底层编排时为了精准控制生命周期而做出的架构拆分。apiVersion: v1 kind: Pod metadata: name: lifecycle-pod labels: app: lifecycle-pod spec: containers: - name: busybox-container image: wangyanglinux/tools:busybox command: ["/bin/sh","-c","touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep 3600"] livenessProbe: exec: command: ["test","-e","/tmp/live"] initialDelaySeconds: 1 periodSeconds: 3 lifecycle: postStart: httpGet: host: 192.168.66.11 path: index.html port: 1234 preStop: httpGet: host: 192.168.66.11 path: hostname.html port: 1234 - name: myapp-container image: wangyanglinux/myapp:v1.0 livenessProbe: httpGet: port: 80 path: /index.html initialDelaySeconds: 1 periodSeconds: 3 timeoutSeconds: 3 readinessProbe: httpGet: port: 80 path: /index1.html initialDelaySeconds: 1 periodSeconds: 3 initContainers: - name: init-myservice image: wangyanglinux/tools:busybox command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] - name: init-mydb image: wangyanglinux/tools:busybox command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']这个给我分析下到底怎么执行 这份 YAML 资源清单非常经典,它把 Kubernetes Pod 生命周期中的核心组件(Init 容器、主容器、存活探针、就绪探针、生命周期钩子)全部串联在了一起。 按照 Kubernetes 的底层运行逻辑,这个 Pod 的完整执行时间线如下: 第一阶段:Init 容器串行执行(启动前的“门卫”) Pod 创建后,不会直接启动业务容器,而是严格按照 YAML 中定义的顺序,串行执行 initContainers: 执行 init-myservice:运行 nslookup myservice。如果找不到,就会一直循环等待(每 2 秒重试一次)。只有当 DNS 解析成功(退出码为 0),它才会结束。 执行 init-mydb:在第一个 Init 容器成功后,才开始运行 nslookup mydb。同样,必须等待 DNS 解析成功才会结束。 注:如果这两个 Init 容器一直失败,Pod 会卡在 Pending 状态,主容器永远不会启动。 第二阶段:主容器并行启动(业务“员工”打卡上班) 当两个 Init 容器都顺利完成后,Kubelet 会并行启动 containers 下定义的两个主容器: 启动 busybox-container 启动 myapp-container 第三阶段:生命周期钩子触发(入职/离职手续) 在容器刚创建后,会触发 postStart 钩子: 注意:这里的 postStart 钩子是和容器的启动命令(command)并发(并行)执行的,不保证谁先完成。 在这个例子中,busybox-container 启动时,会立刻向 192.168.66.11:1234/index.html 发送一个 HTTP GET 请求。 第四阶段:探针接管(“医生”与“质检员”开始工作) 容器启动后,Kubelet 开始根据配置进行健康检查: 1. busybox-container 的存活探针(Liveness Probe): 机制:延迟 1 秒后开始,每 3 秒执行一次 test -e /tmp/live(检查 /tmp/live 文件是否存在)。 业务联动:它的启动命令是 touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep 3600。这意味着前 600 秒内,文件存在,探针成功;600 秒后文件被删除,探针将连续失败。 结果:存活探针失败会触发重启机制,因此这个容器会在运行 600 多秒后被 K8s 强制重启,重启后又重新创建文件,进入下一个 600 秒的循环。 2. myapp-container 的存活探针与就绪探针: 存活探针(Liveness):延迟 1 秒,每 3 秒请求一次 80/index.html。如果失败,容器会被重启。 就绪探针(Readiness):延迟 1 秒,每 3 秒请求一次 80/index1.html。如果这个探针成功,Pod 才会被加入 Service 的 Endpoints 列表,开始接收外部流量;如果失败,流量会被切断(但不会重启容器)。 第五阶段:Pod 终止(PreStop 钩子) 当用户执行 kubectl delete pod 删除该 Pod 时: 在容器被发送 SIGTERM 信号强制关闭之前,会触发 preStop 钩子。 busybox-container 会向 192.168.66.11:1234/hostname.html 发送 HTTP GET 请求,用于执行优雅下线前的清理或注销动作。 💡 核心总结 这个 YAML 完美演示了 K8s 的分工: Init 容器负责阻塞等待依赖(数据库/服务)就绪。 PostStart 负责启动时的外部通知。 Readiness 探针决定 Pod 什么时候能接客(接收流量)。 Liveness 探针决定 Pod 什么时候该“死而复生”(比如 busybox 的 600 秒定时自杀重启)。 PreStop 负责被杀前的优雅告别。