-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Health Probes do not gracefully shutdown traffic for externalTrafficPolicy Cluster services #3499
Comments
I think this KEP which talks about graceful draining of connections might be related, I wonder if Azure maintainers have seen this? |
The following annotation is added to change the probe port number for service. FYI |
Hi @MartinForReal thanks for the suggestion, have you confirmed that this actually works with the Azure cloud provider? I'm on PTO right now so don't have a laptop handy, but I did go through the code pretty thoroughly before submitting this issue and came to the conclusion that there was no way to override the port. I saw other annotations of a similar format, but this one didn't appear to be supported in Azure. |
I think it is added.
|
Reviewing that, looks like we need to have the port in the service for it to be used as a health check right?
So in that case, you'd expect to add a dummy port 10256 to the service, and then set |
… health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
I've tried the above today to no luck, if I specify a port annotation to redirect the health check port on my service to port 10256, it errors because there is no port within the service with port 10256. If i were to create a port, that doesn't actually help me because I can't force the nodeport to be port 10256 The service I was trying is as below:
So how can I get the load balancer health probe port to be an arbitrary port that isn't within the bounds of the service? |
… health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
Cc @alexanderConstantinescu I know you've been working on improving disruption to services, could you check out this issue and see if you agree/if there's any more you can add |
…rs from lb when unready workaround to mitigate issue: kubernetes-sigs/cloud-provider-azure#3500 bug: https://issues.redhat.com/browse/OCPBUGS-7359 UPSTREAM: <carry>: legacy-cloud-providers: azure: use kube-proxy based health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
…rs from lb when unready workaround to mitigate issue: kubernetes-sigs/cloud-provider-azure#3500 bug: https://issues.redhat.com/browse/OCPBUGS-7359 UPSTREAM: <carry>: legacy-cloud-providers: azure: use kube-proxy based health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
…rs from lb when unready workaround to mitigate issue: kubernetes-sigs/cloud-provider-azure#3500 bug: https://issues.redhat.com/browse/OCPBUGS-7359 UPSTREAM: <carry>: legacy-cloud-providers: azure: use kube-proxy based health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
…rs from lb when unready workaround to mitigate issue: kubernetes-sigs/cloud-provider-azure#3500 bug: https://issues.redhat.com/browse/OCPBUGS-7359 UPSTREAM: <carry>: legacy-cloud-providers: azure: use kube-proxy based health probes by default See issue: kubernetes-sigs/cloud-provider-azure#3499 bug: https://issues.redhat.com/browse/OCPBUGS-7359
The Kubernetes project currently lacks enough contributors to adequately respond to all issues. This bot triages un-triaged issues according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues. This bot triages un-triaged issues according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs. This bot triages issues according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /close not-planned |
@k8s-triage-robot: Closing this issue, marking it as "Not Planned". In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
What happened:
I have been investigating disruption of services behind load balancers with their
externalTrafficPolicy: Cluster
(herein ETP Cluster). Currently in Azure, for an ETP Cluster service, the health probes on Azure are configured to check the node port of the application itself, using a blind TCP check. They can be configured to use an HTTP(S) based check but this only allows the path of the check to be specified, it doesn't allow you to specify a custom port.When draining an application, for an ETP Local service, assuming you have configured graceful shutdown correctly, you can return a negative health probe while still accepting new connections, during the graceful termination period. This allows you to signal to the load balancer before you go away, that you are going away. Allowing it to route new connections to other nodes.
In an ETP Cluster service, this doesn't work. With the same backend, during the graceful shutdown period, the application will start showing a negative readiness probe within the cluster, and will be removed from the service endpoints. To the nodeport however, this is completely opaque and it has no idea that the pod has been removed from the node.
As soon as the application goes into an unready state, kube-proxy (or equivalent) on the node will start routing traffic to other endpoints within the service. The load balancer still believes that the instance is healthy, no matter how you configure the health checks. It is only once the node itself can no longer route traffic to these other endpoints, that the health probes start to fail.
Because we are health checking, effectively, another load balancer, this can only happen after the application can no longer accept new connections (typically this means kube-proxy has shut down).
What you expected to happen:
I should be able to configure a health probe that tells Azure that my instance will shortly, no longer be able to serve traffic, allowing it to remove the instance from service before the instance can no longer accept new connections.
How to reproduce it (as minimally and precisely as possible):
I've created a test that you can run which runs some disruption tests to observe how much a service is disrupted when we upgrade a cluster (we run this within CI as part of OpenShift's release process).
To run it, you will need
oc
on your PATH (download here)KUBECONFIG
var pointing to the the clustergo test ./test/e2e/upgrade/service/disruption-test -v –timeout=60m
from the checked out repo aboveNote, this test will take approximately 30 minutes to run and will fail if there is any disruption to the service. We are typically seeing between 3 and 6 seconds of disruption, where we see 0 seconds with the equivalent for an ETP local service.
The test runs through each node in the cluster, drains the instance, reboots it, then uncordons it before moving onto the next instance.
Anything else we need to know?:
I think you don't necessarily need to reproduce this as we can have a discussion logically about this.
Since the service and kube-proxy handle the load balancing within the cluster, health checking the application itself is not helpful from an azure perspective to know whether to route traffic to the instance. Instead, we need to ascertain whether the instance has an ability to route traffic to the backend. This relies on whatever is implementing the node ports, in most cases this is kube-proxy.
Based on that, we should logically be checking kube-proxy's health, and not the node port itself.
In fact, GCP came to the same conclusion and, for an ETP Cluster service, they by default check port
10256
with path/healthz
, which is exposed by kube-proxy. (internal and external).I've been testing a patch that is very much WIP right now, but moves Azure's default ETP Cluster check to match GCPs and, in some testing with the above tests, I have achieved results of 0s of disruption on Azure as well. Because the Azure LB can now see when the instance is going to go unhealthy, it can remove the instance from service earlier meaning fewer dropped connections.
I would like to propose that we make that patch a feature of the Azure CCM and make sure that, by default, when no other health probe configuration is specified, Azure ETP Cluster services health check port
10256
with path/healthz
instead of their current behaviour.Some other notes:
Environment:
kubectl version
): 1.26.2cat /etc/os-release
):uname -a
):The text was updated successfully, but these errors were encountered: