Custom Stop Signals for Containers in Kubernetes v1.33
Containers are often expected to shut down gracefully, especially when running critical workloads like stateful services, background daemons, or applications with long-running connections. Until now, Kubernetes relied entirely on the base image configuration to determine how a container should be terminated. That behavior just changed.
In Kubernetes v1.33, a new alpha feature gate, ContainerStopSignals
has been introduced. This enhancement allows platform teams to explicitly define the stop signal used to terminate a container at the Pod level, without relying on the container image to specify it via the STOPSIGNAL
Dockerfile instruction. With this, Kubernetes aligns itself more closely with real-world operational needs, where uniform behavior across containers matters more than what’s baked into upstream images.
Why Was This Needed?¶
Previously, the only way to control the termination signal for a container was by defining it at image build time. This was done using the STOPSIGNAL
instruction in a Dockerfile. If you were using third-party images or didn’t control the build process, your only options were to accept the default signal (typically SIGTERM
) or rebuild the image yourself.
This approach fell short for modern workloads. Many applications listen for signals like SIGINT
, SIGUSR1
, or SIGQUIT
for cleanup and exit handling. Being unable to define this in the Kubernetes spec meant operators had no control over shutdown semantics unless they altered the image. That’s no longer the case.
The New stopSignal
Lifecycle Field¶
With Kubernetes v1.33, the PodSpec now supports a new lifecycle.stopSignal
field inside each container definition. This field allows users to set the exact signal (like SIGTERM
, SIGUSR1
, or SIGINT
) that the kubelet should send to the container when it's terminating.
Here’s a simple example:
This configuration instructs the kubelet to send a SIGUSR1
signal to the nginx
container instead of the default SIGTERM
. The signal is only sent if it’s valid for the operating system the Pod is scheduled on. In the above case, Linux is specified via spec.os.name
, which is mandatory when using a custom stop signal. This cross-validation ensures the signal is compatible with the runtime environment.
How It Works Under the Hood¶
When a Pod is deleted or a container is terminated (e.g., due to scaling or rollout), Kubernetes determines which signal to use in the following order of precedence:
- If
lifecycle.stopSignal
is defined in the container spec, that signal is used. - If not, it falls back to the
STOPSIGNAL
configured in the container image (if any). - If neither is present, the container runtime’s default stop signal, typically
SIGTERM
is used.
This gives platform operators fine-grained control over container shutdown behavior at the orchestration level. It also reduces the need to patch or rebuild images just to change the exit behavior.
OS-Specific Constraints¶
While Linux containers can use any standard signal (like SIGUSR1
, SIGTERM
, SIGINT
, etc.), Windows containers are limited to just two: SIGTERM
and SIGKILL
. Kubernetes enforces these limits based on the spec.os.name
field in the Pod. Attempting to use unsupported signals for a given OS will result in validation errors during Pod creation.
The os.name
field itself was introduced to prepare for exactly this kind of cross-OS configuration handling and is now mandatory for stop signal validation.
Compatibility and Runtime Considerations¶
It's important to note that this feature is currently alpha in Kubernetes v1.33. That means it’s disabled by default and must be explicitly enabled using the ContainerStopSignals
feature gate in both the kube-apiserver
and kubelet
components.
Additionally, the container runtime must also support this functionality. While the Kubernetes API changes are already available, the implementation support in runtimes like containerd and CRI-O is still catching up and may be released in future versions.
If you attempt to use this feature in a setup where the runtime does not yet support custom stop signals, the behavior will gracefully fall back to using the image-defined or default signal, ensuring no disruption to existing workloads.
Real-World Impact¶
Consider a case where you’re running a Redis instance that listens to SIGINT
for graceful shutdown. Previously, if the base image didn’t define this, Kubernetes would send SIGTERM
, which Redis might ignore or mishandle, leading to unclean exits. Now, you can declare the desired shutdown signal directly in the Kubernetes spec, ensuring consistency across environments and eliminating the need to fork upstream images.
This change also benefits those using wrapper scripts in entrypoints that trap specific signals. It gives DevOps and platform teams a declarative mechanism to align container behavior with operational requirements.
Final Thoughts¶
This enhancement might appear minor at first glance, but it reflects a larger shift in Kubernetes: giving operators more control over workload behavior without requiring image-level changes.
By making container lifecycle termination signals configurable at the Pod level, Kubernetes improves the precision of workload management and paves the way for more predictable shutdown handling, critical for production-grade systems.
As the feature matures and gets broader runtime support, expect it to become a core part of how graceful shutdowns are implemented in Kubernetes-native environments.
FAQs
What is the new stopSignal field introduced in Kubernetes v1.33?
The stopSignal
field is part of the container.lifecycle
spec and allows you to define a custom termination signal (e.g., SIGINT
, SIGUSR1
) for a container. Kubernetes will use this signal instead of the default SIGTERM
when stopping the container.
Why was this feature necessary if the STOPSIGNAL instruction already existed in Dockerfiles?
The STOPSIGNAL directive only works at image build time. If you use third-party images or lack control over the image build process, you're stuck with its default stop behavior. The new stopSignal
field lets you override this behavior directly in the Pod spec, without modifying the image.
How does Kubernetes determine which stop signal to use?
Kubernetes follows this order of precedence:
- If
lifecycle.stopSignal
is defined in the container spec, that is used. - If not, it uses the STOPSIGNAL from the container image.
- If neither is set, the runtime default (typically
SIGTERM
) is used.
Are there OS-specific limitations for this feature?
Yes. Linux containers can use any valid signal (e.g., SIGINT
, SIGTERM
, SIGUSR1
), but Windows containers support only SIGTERM
and SIGKILL
. The spec.os.name
field is required when using stopSignal
to ensure the signal is valid for the container's operating system.
Is this feature enabled by default in Kubernetes v1.33?
No. The feature is alpha and must be manually enabled using the ContainerStopSignals
feature gate on both the API server and kubelet. Runtime support (e.g., in containerd or CRI-O) is still evolving, so fallback behavior may apply if unsupported.