How to catch SIGTERM in a pod with Minikube

5/19/2018

I'm using the simplest docker ever:

FROM ubuntu
COPY script.sh /script.sh
CMD /script.sh

Where all the script does is:

#!/bin/bash

function sigterm() {
    echo "Got SIGTERM"
    exit
}

trap sigterm SIGTERM

i=1
while true; do
    echo "$(date +%H:%M:%S) | $((i++)) | $HOSTNAME"
    sleep 1
done

I'm running this container in Minikube, but I can't get it to catch any SIGTERM from kubernetes.

I tried deleting the pod/deployment or to scale it up and down. In no case it got SIGTERM before being deleted. It respects the terminationGracePeriodSeconds But doesn't seem to run the preStop command or send the SIGTERM before killing the pod.

Is that due to using minikube? or am I doing something else wrong?

(the deployment is not part of a service, it's just a deployment) (SSH into the pod and manually kill-ing it works as expected)

-- Amir Mehler
bash
kubernetes
minikube
termination

1 Answer

5/19/2018

Reading the Dockerfile documentation on CMD

The CMD instruction has three forms:

  • CMD ["executable","param1","param2"] (exec form, this is the preferred form)
  • CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
  • CMD command param1 param2 (shell form)

If you use the shell form of the CMD, then the will execute in /bin/sh -c

So you are using the shell form, which means your command is /bin/sh -c script.sh. Then, when kubernetes sends a SIGTERM to the container, is not the script.sh process the one receiving the signal, but the /bin/sh process. That's why you don't see the "Got SIGTERM" message.

When creating a Dockerfile, make sure you use the exec form. Otherwise the application will be started as a subcommand of /bin/sh -c, which does not pass signals. The container’s PID1 will be the shell, your application will not receive any signals.

Try changing your Dockerfile to use the exec form

FROM ubuntu
COPY script.sh /script.sh
CMD ["/script.sh"]
-- Jose Armesto
Source: StackOverflow