networkservicemesh / deployments-k8s

Apache License 2.0
42 stars 35 forks source link

`kubectl delete` is slow in tests #9128

Closed d-uzlov closed 1 year ago

d-uzlov commented 1 year ago

Expected Behavior

kubectl delete should delete pods instantly.

Current Behavior

In many tests we use alpine container which doesn't support graceful shutdown, and makes the delete command hang for 30 seconds.

d-uzlov commented 1 year ago

By default k8s starts the main process as PID 1 which have special properties regarding signals. PID 1 in Linux is supposed to be init but the official alpine image doesn't support it (busybox init doesn't work in a container).

One of the special properties of PID 1 is that it ignores signals by default and requires the program to explicitly handle them. Sleep program doesn't do it, which causes the container to hang for 30 seconds before k8s forcefully kills it.

I see several potential types of solutions solutions:

  1. Use shareProcessNamespace: true so that containers don't use PID 1. Small change but an unsafe hack, which should not be used in examples.
  2. Modify command to stop on a signal. https://github.com/networkservicemesh/deployments-k8s/pull/9126 Requires a shell command in each yaml file but doesn't require any external changes.
  3. Use a modified container image: 3.1. Add init system to alpine. For example: tini, dumb-init 3.2. Use the modified command in the Dockerfile 3.3. Use some another custom binary that can respond to signals

Solution 1

Modify deployments in out tests/examples to use the following command:

command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]

Solution 2

Create a modified docker image that can properly shutdown.

For example:

FROM alpine:3.17
CMD ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]

Then we can use this image without any additional args in yaml files.

Solution 3

Use an image with a container-friendly init built-in. Then we can just use args: ['sleep', 'infinity'] in the yaml files.

Unfortunately, there doesn't seem to be any popular images that support this. This is the only one I was able to find which looks somewhat supported: https://registry.hub.docker.com/r/fpco/pid1 Other similar images that I found were last updated several years ago.

There is a Docker option that makes such containers obsolete, so it seems like nobody builds those anymore. Unfortunately, k8s doesn't have such option.

Solution 4

Build our own image with a container-friendly init program.

FROM alpine:3.17
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["sleep", "infinity"]
denis-tingaikin commented 1 year ago

Seems like done