Kubernetes provides containers with lifecycle hooks that allow them to execute code when they start or before they stop. In this post we’ll detail the use of the PreStop hook to ensure that containers shutdown in a graceful manner.
Without a PreStop hook, Kubernetes terminates containers by sending their main processes a SIGTERM
signal. Relatively simple and stateless processes can safely survive this signal, stop and then restart. More complex processes may need to perform some actions before they can be safely stopped.
The hook (the name of a script or executable in your container) is defined in the container spec of a Pod and is executed immediately before the container is terminated. Apart from ensuring that your container application winds down all of its internal processes, the hook must ensure that the main process stops, often through the use of your own SIGTERM
signal.
Importantly your hook must result in stopping the container, not just draining any activities. If the container does not stop Kubernetes will kill it (more on that later).
If you have shutdown logic in your container executed via the script /home/stop.sh
you can declare it as the hook’s entry point by defining it as part of your Pod’s lifecycle definition: -
Now, when Kubernetes decides to terminate the Pod container (for whatever reason), it will run your script inside the container environment. It will then wait for the container to stop.
It isn’t obvious from the documentation but the PreStop hook is expected not only to ensure the application state reaches a point that it can stop but it must also stop the application (typically with your own SIGTERM
signal).
When you define a PreStop hook termination of the application becomes your responsibility. Kubernetes does nothing more until the Termination Grace Period has expired. The grace period is a value you set in the Pod’s spec using the property terminationGracePeriodSeconds
, which has a default value of 30 seconds. This value applies to all the containers in a Pod.
We’d advise you to always provide a value if you provide a PreStop hook, and set a value that will ensure your hook will have had sufficient time to complete its work and stop the containers (with some wiggle room).
Kubernetes starts a timer when it invokes your hook. If the timer expires and the Pod is still running Kubernetes will kill it with a SIGKILL
signal, which will terminate the application immediately. SIGKILL
cannot be caught or ignored by your application.
If your application has not stopped when this time has elapsed it will will be killed (ungracefully).