LabHub
学习 学习路径 课程

CKAD — Kubernetes 应用开发者

让Pod下班 — 先完成响应再退出

在 LabHub 中继续学习

目标

在个人 k3s VM 中终止 Pod,同时让已经处理中的 HTTP 请求继续完成,并把应用的终止处理、EndpointSlice 与终止宽限期联系起来进行说明。本实验使用真实进程,而不是 kwok 状态模拟。

为什么重要

Deployment 显示成功并不能保证处理中的请求已经完成。这里运行一个由只读代码构成的小型 HTTP 服务器,辅助程序会严格按照学员编写的 Pod 声明创建它。先确认 Service 路径和请求已被接受,再在启动 Pod watch 的状态下删除,因此可以把同一 UID 的响应、断连和退出代码关联起来。

本实验会比较正常终止和宽限期不足的情形,但不是要求精确匹配小数级时间。它不是通过复制输入文件或观测文件来拼出成功语句,而是检查实际运行结果是否与解释相符。拒绝新请求和终止现有连接并不是同一件事,而且本实验也不能证明包括外部负载均衡器在内的整个服务实现了零停机。

预计用时 80 分钟。会话默认持续 60 分钟,请在到期前通过+时间延长(最长 180 分钟)。会话结束后,VM 和文件都会被回收。请在结束前另行保存需要保留的结果。

步骤

  1. 将个人 VM 的 node_name、server_version、namespace_uid、image 记录到 /root/ckad-inflight-termination/environment.json,并运行 run 1。namespace 为 ckad-inflight-termination,image 为所提供 pod-template.json 中的服务器镜像。
  2. 创建 immediate.json。Pod 名称和 case 标签为 immediate,MODE 为 immediate,WORK_SECONDS 为字符串 8,terminationGracePeriodSeconds 为整数 15,并且没有 lifecycle。通过 run 2 在终止期间观测服务器已经接受的请求。
  3. 在 immediate-analysis.json 中填写观测到的 pod_uid、client_error、exit_code,以及对 accepted_before_delete、readiness_alone_drains_requests 的判断,然后运行 run 3。区分请求是否在删除前已被接受,以及仅靠 readiness 是否能结束请求。
  4. 创建 graceful.json。名称和 case 标签为 graceful,MODE 为 graceful,WORK_SECONDS 为字符串 8,宽限期为整数 15。保留模板中的 preStop,使其在调用 /drain 后等待 2 秒,然后运行 run 4。
  5. 在 graceful-analysis.json 中写入 pod_uid,并将第一个 terminating endpoint 的完整 conditions 写入 first_terminating_conditions。结合观测结果判断 hook_before_term、accepted_response_complete、endpoint_ready_false_means_connection_closed,然后运行 run 5。
  6. 创建 exhausted.json。名称和 case 标签为 exhausted,MODE 为 graceful,WORK_SECONDS 为字符串 10,宽限期为整数 5。只把 preStop 中 /drain 后的 sleep 改为 3 秒,然后运行 run 6。观察即使终止模式相同,请求结果是否也会不同。
  7. 创建 repaired.json。名称和 case 标签为 repaired,MODE 为 graceful,WORK_SECONDS 为字符串 10,宽限期为整数 15,preStop 在 /drain 后等待 3 秒。通过 run 7 确认真正完成的响应。不要修改已有观测文件。
  8. 在 comparison.json 的 outcomes 中,分别记录 immediate、graceful、exhausted、repaired 的 pod_uid、client_completed、exit_code。判断 grace_includes_prestop、api_delete_is_exact_deadline、service_zero_downtime_proven,然后运行 run 8。

参考

确认这里是真正的运行环境

将个人 VM 的 node_name、server_version、namespace_uid、image 记录到 /root/ckad-inflight-termination/environment.json,并运行 run 1。namespace 为 ckad-inflight-termination,image 为所提供 pod-template.json 中的服务器镜像。

读取 kubectl get nodes、kubectl version -o json、kubectl get namespace 的 metadata.uid 以及 Pod 模板。不要连接外部集群。

留下客人,立即下班

创建 immediate.json。Pod 名称和 case 标签为 immediate,MODE 为 immediate,WORK_SECONDS 为字符串 8,terminationGracePeriodSeconds 为整数 15,并且没有 lifecycle。通过 run 2 在终止期间观测服务器已经接受的请求。

只修改 pod-template.json 中的名称、case 标签、MODE、WORK_SECONDS、终止宽限期和 preStop。run 会根据该声明观测真实请求和删除过程。

Ready 标记不会替你完成订单

在 immediate-analysis.json 中填写观测到的 pod_uid、client_error、exit_code,以及对 accepted_before_delete、readiness_alone_drains_requests 的判断,然后运行 run 3。区分请求是否在删除前已被接受,以及仅靠 readiness 是否能结束请求。

关联 observation-2.json 的 observation 中的 initial.events、delete_at、client 和 pod_watch。退出代码位于最后一个容器的 terminated 状态中。

完成已接订单后再下班

创建 graceful.json。名称和 case 标签为 graceful,MODE 为 graceful,WORK_SECONDS 为字符串 8,宽限期为整数 15。保留模板中的 preStop,使其在调用 /drain 后等待 2 秒,然后运行 run 4。

只修改 pod-template.json 中的名称、case 标签、MODE、WORK_SECONDS、终止宽限期和 preStop。run 会根据该声明观测真实请求和删除过程。

门已关闭,但响应仍能送达

在 graceful-analysis.json 中写入 pod_uid,并将第一个 terminating endpoint 的完整 conditions 写入 first_terminating_conditions。结合观测结果判断 hook_before_term、accepted_response_complete、endpoint_ready_false_means_connection_closed,然后运行 run 5。

按时间顺序读取 observation-4.json 中的 endpoints。比较 server_events 中的 hook、term 与 client.completed,不要把 ready=false 等同于现有连接断开。

终止宽限期设置得过短

创建 exhausted.json。名称和 case 标签为 exhausted,MODE 为 graceful,WORK_SECONDS 为字符串 10,宽限期为整数 5。只把 preStop 中 /drain 后的 sleep 改为 3 秒,然后运行 run 6。观察即使终止模式相同,请求结果是否也会不同。

只修改 pod-template.json 中的名称、case 标签、MODE、WORK_SECONDS、终止宽限期和 preStop。run 会根据该声明观测真实请求和删除过程。

补足宽限期后重新观测

创建 repaired.json。名称和 case 标签为 repaired,MODE 为 graceful,WORK_SECONDS 为字符串 10,宽限期为整数 15,preStop 在 /drain 后等待 3 秒。通过 run 7 确认真正完成的响应。不要修改已有观测文件。

只修改 pod-template.json 中的名称、case 标签、MODE、WORK_SECONDS、终止宽限期和 preStop。run 会根据该声明观测真实请求和删除过程。

结论不得超出观测范围

在 comparison.json 的 outcomes 中,分别记录 immediate、graceful、exhausted、repaired 的 pod_uid、client_completed、exit_code。判断 grace_includes_prestop、api_delete_is_exact_deadline、service_zero_downtime_proven,然后运行 run 8。

比较第 2、4、6、7 步的观测。宽限期预算包含 hook,但 API 删除时刻并不保证就是精确终止时刻,单次请求也不能证明整个服务的可用性。