ASP.NET Core's cross-platform webserver Kestrel is the obvious choice, when running containerized .NET applications in a Kubernetes cluster.
As described in the article Graceful shutdown and zero downtime deployments in Kubernetes, Kestrel should be able to handle the SIGTERM signal from the Pod, so that incoming traffic is still processed when the application is being shut down.
Unfortunately, this is not how it works. Without further configuration, Kestrel-based applications in Kubernetes will have a small downtime when deploying a newer version in the Kubernetes cluster.
To have zero downtime deployment, the application's Pod configuration must use Kubernetes' preStop
hook in the Pod definition:
apiVersion: v1
kind: Pod
metadata:
name: my-dotnet-pod
spec:
containers:
- name: dotnet-web
image: kestrel-based-app
ports:
- name: dotnet-web
containerPort: 80
lifecycle:
preStop:
exec:
command: ["sleep", "15"]
With the preStop
hook, the container waits for 15 seconds and still operates normal. Kestrel is able to handle incoming traffic. In this time, the endpoint removal to kube-proxy, Ingress controller and other service should be propagated. The old Kestrel instance receives less and less traffic.
If 15 seconds are not enough, you can increse the value.
Please note, that the process will be forcefully killed by Kubernetes after 30 seconds.
You have to change terminationGracePeriodSeconds
setting if you need to wait longer than 30 seconds.