From 116100a62e4713f076123429e0703c2407840714 Mon Sep 17 00:00:00 2001 From: Arpit Bhagat Date: Thu, 10 Sep 2026 03:53:00 +0530 Subject: [PATCH] OCPBUGS-95087: reload client CA after kubelet-ca.crt is replaced kube-rbac-proxy-crio authenticates Prometheus with --client-ca-file /etc/kubernetes/kubelet-ca.crt. After MCO replaces that file, the process can keep a stale in-memory CA and return HTTP 401 while TLS still succeeds. Reload the client CA (and serving cert/key) on a 1m timer as well as on filesystem events so TargetDown job=crio does not stick until a process restart. Related: OCPBUGS-95087 Signed-off-by: Arpit Bhagat Co-authored-by: Cursor --- .../server/dynamiccertificates/dynamic_cafile_content.go | 7 +++++++ .../server/dynamiccertificates/dynamic_serving_content.go | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_cafile_content.go b/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_cafile_content.go index 2f2195134..5955a684c 100644 --- a/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_cafile_content.go +++ b/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_cafile_content.go @@ -164,6 +164,13 @@ func (c *DynamicFileCAContent) Run(ctx context.Context, workers int) { // doesn't matter what workers say, only start one. go wait.Until(c.runWorker, time.Second, ctx.Done()) + // Reload the client CA on a timer. MCO replaces kubelet-ca.crt with a new + // inode, so a filesystem watch on the old inode never fires and scrapes + // keep failing with HTTP 401 until the process restarts. + go wait.Until(func() { + c.queue.Add(workItemKey) + }, FileRefreshDuration, ctx.Done()) + // start the loop that watches the CA file until stopCh is closed. go wait.Until(func() { if err := c.watchCAFile(ctx.Done()); err != nil { diff --git a/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_serving_content.go b/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_serving_content.go index 268fe70b0..26985fee2 100644 --- a/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_serving_content.go +++ b/vendor/k8s.io/apiserver/pkg/server/dynamiccertificates/dynamic_serving_content.go @@ -138,6 +138,11 @@ func (c *DynamicCertKeyPairContent) Run(ctx context.Context, workers int) { // doesn't matter what workers say, only start one. go wait.Until(c.runWorker, time.Second, ctx.Done()) + // Reload cert/key files on a timer. Same inode-replace case as the client CA. + go wait.Until(func() { + c.queue.Add(workItemKey) + }, FileRefreshDuration, ctx.Done()) + // start the loop that watches the cert and key files until stopCh is closed. go wait.Until(func() { if err := c.watchCertKeyFile(ctx.Done()); err != nil {