From c6d0afd0cbce7ee69dcb6c9d98deef60aa62b1c6 Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Tue, 7 Feb 2023 01:34:02 +0000 Subject: [PATCH] Check for existing resources before creating them Prevents errors when starting with fail-closed webhooks Also, use panic instead of Fatalf so that the CloudControllerManager rescue can handle the error Signed-off-by: Brad Davidson --- manifests/ccm.yaml | 1 + pkg/cloudprovider/cloudprovider.go | 8 ++++---- pkg/cloudprovider/servicelb.go | 24 ++++++++++++++++-------- pkg/daemons/executor/embed.go | 12 ++++++------ 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/manifests/ccm.yaml b/manifests/ccm.yaml index d72b7fded9..e8f5403605 100644 --- a/manifests/ccm.yaml +++ b/manifests/ccm.yaml @@ -54,6 +54,7 @@ rules: - serviceaccounts verbs: - create + - get - apiGroups: - "" resources: diff --git a/pkg/cloudprovider/cloudprovider.go b/pkg/cloudprovider/cloudprovider.go index 236bc97ef8..f756ee26c8 100644 --- a/pkg/cloudprovider/cloudprovider.go +++ b/pkg/cloudprovider/cloudprovider.go @@ -96,7 +96,7 @@ func (k *k3s) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, st processor, err := apply.NewForConfig(config) if err != nil { - logrus.Fatalf("Failed to create apply processor for %s: %v", controllerName, err) + logrus.Panicf("failed to create apply processor for %s: %v", controllerName, err) } k.processor = processor.WithDynamicLookup().WithCacheTypes(lbAppsFactory.Apps().V1().DaemonSet()) k.daemonsetCache = lbAppsFactory.Apps().V1().DaemonSet().Cache() @@ -105,17 +105,17 @@ func (k *k3s) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, st k.workqueue = workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) if err := k.Register(ctx, coreFactory.Core().V1().Node(), lbCoreFactory.Core().V1().Pod(), lbDiscFactory.Discovery().V1().EndpointSlice()); err != nil { - logrus.Fatalf("Failed to register %s handlers: %v", controllerName, err) + logrus.Panicf("failed to register %s handlers: %v", controllerName, err) } if err := start.All(ctx, 1, coreFactory, lbCoreFactory, lbAppsFactory, lbDiscFactory); err != nil { - logrus.Fatalf("Failed to start %s controllers: %v", controllerName, err) + logrus.Panicf("failed to start %s controllers: %v", controllerName, err) } } else { // If load-balancer functionality has not been enabled, delete managed daemonsets. // This uses the raw kubernetes client, as the controllers are not started when the load balancer controller is disabled. if err := k.deleteAllDaemonsets(ctx); err != nil { - logrus.Fatalf("Failed to clean up %s daemonsets: %v", controllerName, err) + logrus.Panicf("failed to clean up %s daemonsets: %v", controllerName, err) } } } diff --git a/pkg/cloudprovider/servicelb.go b/pkg/cloudprovider/servicelb.go index 89478f2069..6523d60fbb 100644 --- a/pkg/cloudprovider/servicelb.go +++ b/pkg/cloudprovider/servicelb.go @@ -56,11 +56,11 @@ func (k *k3s) Register(ctx context.Context, pods.OnChange(ctx, controllerName, k.onChangePod) endpointslices.OnChange(ctx, controllerName, k.onChangeEndpointSlice) - if err := k.createServiceLBNamespace(ctx); err != nil { + if err := k.ensureServiceLBNamespace(ctx); err != nil { return err } - if err := k.createServiceLBServiceAccount(ctx); err != nil { + if err := k.ensureServiceLBServiceAccount(ctx); err != nil { return err } @@ -69,9 +69,13 @@ func (k *k3s) Register(ctx context.Context, return k.removeServiceFinalizers(ctx) } -// createServiceLBNamespace ensures that the configured namespace exists. -func (k *k3s) createServiceLBNamespace(ctx context.Context) error { - _, err := k.client.CoreV1().Namespaces().Create(ctx, &core.Namespace{ +// ensureServiceLBNamespace ensures that the configured namespace exists. +func (k *k3s) ensureServiceLBNamespace(ctx context.Context) error { + ns := k.client.CoreV1().Namespaces() + if _, err := ns.Get(ctx, k.LBNamespace, meta.GetOptions{}); err == nil || !apierrors.IsNotFound(err) { + return err + } + _, err := ns.Create(ctx, &core.Namespace{ ObjectMeta: meta.ObjectMeta{ Name: k.LBNamespace, }, @@ -82,9 +86,13 @@ func (k *k3s) createServiceLBNamespace(ctx context.Context) error { return err } -// createServiceLBServiceAccount ensures that the ServiceAccount used by pods exists -func (k *k3s) createServiceLBServiceAccount(ctx context.Context) error { - _, err := k.client.CoreV1().ServiceAccounts(k.LBNamespace).Create(ctx, &core.ServiceAccount{ +// ensureServiceLBServiceAccount ensures that the ServiceAccount used by pods exists. +func (k *k3s) ensureServiceLBServiceAccount(ctx context.Context) error { + sa := k.client.CoreV1().ServiceAccounts(k.LBNamespace) + if _, err := sa.Get(ctx, "svclb", meta.GetOptions{}); err == nil || !apierrors.IsNotFound(err) { + return err + } + _, err := sa.Create(ctx, &core.ServiceAccount{ ObjectMeta: meta.ObjectMeta{ Name: "svclb", Namespace: k.LBNamespace, diff --git a/pkg/daemons/executor/embed.go b/pkg/daemons/executor/embed.go index 58430c7f8d..c09dd8277b 100644 --- a/pkg/daemons/executor/embed.go +++ b/pkg/daemons/executor/embed.go @@ -57,7 +57,7 @@ func (e *Embedded) Kubelet(ctx context.Context, args []string) error { go func() { defer func() { if err := recover(); err != nil { - logrus.Fatalf("kubelet panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("kubelet panic: %v", err) } }() // The embedded executor doesn't need the kubelet to come up to host any components, and @@ -79,7 +79,7 @@ func (*Embedded) KubeProxy(ctx context.Context, args []string) error { go func() { defer func() { if err := recover(); err != nil { - logrus.Fatalf("kube-proxy panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("kube-proxy panic: %v", err) } }() logrus.Fatalf("kube-proxy exited: %v", command.ExecuteContext(ctx)) @@ -101,7 +101,7 @@ func (*Embedded) APIServer(ctx context.Context, etcdReady <-chan struct{}, args <-etcdReady defer func() { if err := recover(); err != nil { - logrus.Fatalf("apiserver panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("apiserver panic: %v", err) } }() logrus.Fatalf("apiserver exited: %v", command.ExecuteContext(ctx)) @@ -130,7 +130,7 @@ func (e *Embedded) Scheduler(ctx context.Context, apiReady <-chan struct{}, args } defer func() { if err := recover(); err != nil { - logrus.Fatalf("scheduler panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("scheduler panic: %v", err) } }() logrus.Fatalf("scheduler exited: %v", command.ExecuteContext(ctx)) @@ -147,7 +147,7 @@ func (*Embedded) ControllerManager(ctx context.Context, apiReady <-chan struct{} <-apiReady defer func() { if err := recover(); err != nil { - logrus.Fatalf("controller-manager panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("controller-manager panic: %v", err) } }() logrus.Fatalf("controller-manager exited: %v", command.ExecuteContext(ctx)) @@ -180,7 +180,7 @@ func (*Embedded) CloudControllerManager(ctx context.Context, ccmRBACReady <-chan <-ccmRBACReady defer func() { if err := recover(); err != nil { - logrus.Fatalf("cloud-controller-manager panic: %s", debug.Stack()) + logrus.WithField("stack", debug.Stack()).Fatalf("cloud-controller-manager panic: %v", err) } }() logrus.Errorf("cloud-controller-manager exited: %v", command.ExecuteContext(ctx))