# Custom Stop Signals for Containers in Kubernetes v1.33
> Kubernetes v1.33 lets you configure container stop signals via PodSpec, no more rebuilding images just to change shutdown behavior.

Canonical: https://blog.abhimanyu-saharan.com/posts/custom-stop-signals-for-containers-in-kubernetes-v1-33
Published: 2025-05-20
Last updated: 2025-06-19
Authors: Abhimanyu Saharan
Categories: Kubernetes v1.33, Kubernetes

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:

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: graceful-nginx
spec:
  os:
    name: linux
  containers:
    - name: nginx
      image: nginx:latest
      lifecycle:
        stopSignal: SIGUSR1
```

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:

1. If `lifecycle.stopSignal` is defined in the container spec, that signal is used.
2. If not, it falls back to the `STOPSIGNAL` configured in the container image (if any).
3. 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.

## FAQ

### 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:

1. If `lifecycle.stopSignal` is defined in the container spec, that is used.
2. If not, it uses the STOPSIGNAL from the container image.
3. 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.
