A Notes About Graceful Shutdown on Container World

Well, Graceful shutdown it’s one of method for turning off safely some system or may your computer also it can be applied on some service application. Previously I thought this is like an unimportant method but after gaining more practice and experience this one can be very useful when you have a more complex system build as well you can’t ignore to used this method.

Before I write more about how to use it in the container world, Graceful Shutdown is so closely related with IPC (Interprocess Communication) mechanisms that mean every process or activity that goes top of Kernel has a signal process communicating with one or more processes. A signals can be generated by keyboard interrupt or some error condition like virtual memory exhausted. Every signals had their defined number code and total signals that defined on Kernel is 30 signals CMIIW but as long as i know for common signals that used in Graceful shutdown are

CodeSignals Name
2SIGINT
3SIGQUIT
9SIGKILL
15SIGTERM

A short explanation:

Dive in container

Like the title above, here is my note or some cases method dealing with Graceful shutdown.

Define it on Dockerfile

You can defined what signals what you want to triggering or trapping on Dockerfile

# STOPSIGNAL <signalID|signalName>
# Example
STOPSIGNAL SIGTERM

Sending Signals with docker command

# docker stop
# this may combine with your code like giving it timeout to trigger.
➜ docker stop --time=30 <container-name>

# docker kill
➜ docker kill --signal=SIGINT <container-name>

# docker rm --force | -f
➜ docker rm --force <container-name>

Avoid run on PID 1

When you added CMD [ "blah", "blah" ] be careful to make it run as PID 1 also commonly its happen on node.js stuff’s and can break your graceful shutdown at the code side because it cannot send or handle signals process properly because its run as PID 1.

The one of solution is using method called init-process so it will act like a mask your node process with init and below is example

RUN apk add dumb-init
# Your logic apps here
CMD ["dumb-init", "npm", "start"]

Without change on your Dockerfile it also can be used with docker run --init <your-container>.

➜ docker run --init --rm -t -i ubuntu:latest bash
root@bd1b24f6d44f:/# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  2.3  0.0   1076     4 pts/0    Ss   17:44   0:00 /sbin/docker-init -- bash
root           7  0.0  0.0   4116  3312 pts/0    S    17:44   0:00 bash
root          10  0.0  0.0   5904  2828 pts/0    R+   17:44   0:00 ps aux
root@bd1b24f6d44f:/#

Dive in kubernetes

Last things it’s doing graceful shutdown at kubernetes level, when you do kubectl delete its same way like a docker stop that act to sending signals SIGTERM and this signal can be interrupt, so you can carry out something to your apps (i call it a fun way) with preStop.

# Example
lifecycle:
  preStop:
    exec:
      command: ["/bin/bash","-c","/bin/sleep 30; kill -s SIGQUIT 1"]
# Or
lifecycle:
   preStop:
    httpGet:
    port: 8080
    path: /shutdown

preStop command can be tricky depending on how your code works, the behavior of your apps and may add or change terminationGracePeriodSeconds time which has a default time 30 seconds. For more explaining you can read about Container Lifecycle Hooks .

Conclusion

Graceful shutdown it’s fun and tricky method to handle gracefully kill on your system or may your computer also it can be applied on some service application. Some real cases are like handling connections close or you want to gracefully shutdown your apps when it goes scale down. The pattern behavior IPC signals depends on how you run and what you want to be done with your code.

As well dealing graceful shutdown can be fun and tricky way when applied on container world and may a lot of glue script (read: bash script).

Thanks