CKAD — Kubernetes Application Developer
Let the Pod Clock Out After the Response
Goal
On a personal k3s VM, you terminate a Pod while leaving an HTTP request that is already being handled, and explain it by connecting the app's shutdown handling, the EndpointSlice, and the termination grace. It uses a real process and is not a kwok state simulation.
Why it matters
A Deployment's success indication does not guarantee the completion of requests that were being handled. Here you place a small HTTP server that runs as read-only code, and the helper creates the Pod declaration the student wrote as is. You first check the Service path and the acceptance of the request and delete with the Pod watch already started, so you can connect the response, disconnection, and exit code of the same UID.
It compares a normal termination with an insufficient grace, but this is not a lab where you hit fractions of a second. You do not copy an input file or observation file to produce a success sentence; you check whether the real execution and its interpretation agree. Excluding new requests and terminating existing connections are not the same event, and this experiment does not guarantee zero downtime for a whole service including an external load balancer.
The estimate is 80 minutes. The session defaults to 60 minutes, so extend it with +time before it expires (up to 180 minutes). When the session ends, the VM and files are reclaimed. Keep the results you need separately before it ends.
Steps
- Record the personal VM's node_name, server_version, namespace_uid, and image in /root/ckad-inflight-termination/environment.json, and run run 1. The namespace is ckad-inflight-termination, and the image is the server image in the provided pod-template.json.
- Create immediate.json. The Pod name and case label are immediate, MODE is immediate, WORK_SECONDS is the string 8, terminationGracePeriodSeconds is the integer 15, and there is no lifecycle. With run 2, observe a request the server accepted during termination.
- In immediate-analysis.json, write the observed pod_uid, client_error, and exit_code and your judgments of accepted_before_delete and readiness_alone_drains_requests, and run run 3. Distinguish whether it was accepted before deletion and whether readiness alone can finish the request.
- Create graceful.json. The name and case label are graceful, MODE is graceful, WORK_SECONDS is the string 8, and the grace is the integer 15. Keep the template's preStop so that it waits 2 seconds after the /drain call, and run run 4.
- In graceful-analysis.json, write the pod_uid and, as first_terminating_conditions, the entire conditions of the first terminating endpoint. Judge hook_before_term, accepted_response_complete, and endpoint_ready_false_means_connection_closed by connecting them to the observation, and run run 5.
- Create exhausted.json. The name and case label are exhausted, MODE is graceful, WORK_SECONDS is the string 10, and the grace is the integer 5. Change only the sleep after /drain in preStop to 3 seconds, and run run 6. See whether the request result differs even when the termination mode is the same.
- Create repaired.json. The name and case label are repaired, MODE is graceful, WORK_SECONDS is the string 10, the grace is the integer 15, and preStop is 3 seconds after /drain. With run 7, confirm the actual completion response. Do not edit the existing observation files.
- In the outcomes of comparison.json, record pod_uid, client_completed, and exit_code for each of immediate, graceful, exhausted, and repaired. Judge grace_includes_prestop, api_delete_is_exact_deadline, and service_zero_downtime_proven, and run run 8.
Notes
- The working folder is /root/ckad-inflight-termination. Running every step is python3 /opt/fixtures/ckad_termination_lab.py run followed by the step number. Grading does not rerun the observation; it reads the preserved files.
- Copy pod-template.json and change only the fields you need. The image, command, security settings, and run label are the experiment's controlled conditions. Do not create the Pod in advance with kubectl apply. The run observes creation, request, and deletion in one flow from the student declaration.
- JSON is the manifest format Kubernetes accepts. The environment variable WORK_SECONDS is a string, and the termination grace is an integer. Do not overwrite the template original with sample JSON.
- The exec command of preStop is in the template. Keep the /drain call and change the number of the last time.sleep as the step requires. In the immediate termination step, remove the lifecycle itself.
- Preparing earlier steps is prepare followed by the step number. It does not produce the current step's answer, and it does not overwrite student files you have already written. If you have a wrongly written earlier-step file, fix it first.
- Rerunning an interrupted observation cannot recover the previous Pod. Preserve the error history, and if the helper asks for a new lab, do not erase the markers arbitrarily; start the environment fresh.
- Exit code 17 is a comparison marker this server chose. Do not conclude OOM or insufficient grace from 137 alone; look together at the watch's reason, the actual settings, and the hook and term.
- References: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ · https://kubernetes.io/docs/tutorials/services/pods-and-endpoint-termination-flow/
Confirm it is a real kitchen
Record the personal VM's node_name, server_version, namespace_uid, and image in /root/ckad-inflight-termination/environment.json, and run run 1. The namespace is ckad-inflight-termination, and the image is the server image in the provided pod-template.json.
Read kubectl get nodes, kubectl version -o json, the metadata.uid from kubectl get namespace, and the Pod template. Do not connect to an external cluster.
Clock out right away, leaving the guests behind
Create immediate.json. The Pod name and case label are immediate, MODE is immediate, WORK_SECONDS is the string 8, terminationGracePeriodSeconds is the integer 15, and there is no lifecycle. With run 2, observe a request the server accepted during termination.
From pod-template.json, change only the name, the case label, MODE, WORK_SECONDS, the termination grace, and preStop. The run observes the real request and deletion with that declaration.
A ready flag does not finish the order
In immediate-analysis.json, write the observed pod_uid, client_error, and exit_code and your judgments of accepted_before_delete and readiness_alone_drains_requests, and run run 3. Distinguish whether it was accepted before deletion and whether readiness alone can finish the request.
From the observation in observation-2.json, connect initial.events, delete_at, client, and pod_watch. The exit code is in the last container terminated state.
Finish the orders already taken, then clock out
Create graceful.json. The name and case label are graceful, MODE is graceful, WORK_SECONDS is the string 8, and the grace is the integer 15. Keep the template's preStop so that it waits 2 seconds after the /drain call, and run run 4.
From pod-template.json, change only the name, the case label, MODE, WORK_SECONDS, the termination grace, and preStop. The run observes the real request and deletion with that declaration.
The door is closed, but the response still arrives
In graceful-analysis.json, write the pod_uid and, as first_terminating_conditions, the entire conditions of the first terminating endpoint. Judge hook_before_term, accepted_response_complete, and endpoint_ready_false_means_connection_closed by connecting them to the observation, and run run 5.
Read the endpoints in observation-4.json in time order. Compare the hook and term in server_events with client.completed, and do not equate ready=false with a disconnection of the existing connection.
Give too short a termination grace
Create exhausted.json. The name and case label are exhausted, MODE is graceful, WORK_SECONDS is the string 10, and the grace is the integer 5. Change only the sleep after /drain in preStop to 3 seconds, and run run 6. See whether the request result differs even when the termination mode is the same.
From pod-template.json, change only the name, the case label, MODE, WORK_SECONDS, the termination grace, and preStop. The run observes the real request and deletion with that declaration.
Fix the grace and observe again
Create repaired.json. The name and case label are repaired, MODE is graceful, WORK_SECONDS is the string 10, the grace is the integer 15, and preStop is 3 seconds after /drain. With run 7, confirm the actual completion response. Do not edit the existing observation files.
From pod-template.json, change only the name, the case label, MODE, WORK_SECONDS, the termination grace, and preStop. The run observes the real request and deletion with that declaration.
Write conclusions only as far as you observed
In the outcomes of comparison.json, record pod_uid, client_completed, and exit_code for each of immediate, graceful, exhausted, and repaired. Judge grace_includes_prestop, api_delete_is_exact_deadline, and service_zero_downtime_proven, and run run 8.
Compare the observations of steps 2, 4, 6, and 7. The grace budget includes the hook, but the API deletion time does not guarantee the exact termination time, and a single request does not prove the availability of the whole service.