k8s.io/kubernetes@v1.29.3/pkg/controlplane/controller/systemnamespaces/system_namespaces_controller.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package systemnamespaces 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/errors" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 "k8s.io/apimachinery/pkg/util/wait" 29 coreinformers "k8s.io/client-go/informers/core/v1" 30 "k8s.io/client-go/kubernetes" 31 listers "k8s.io/client-go/listers/core/v1" 32 "k8s.io/client-go/tools/cache" 33 34 "k8s.io/klog/v2" 35 ) 36 37 // Controller ensure system namespaces exist. 38 type Controller struct { 39 client kubernetes.Interface 40 41 namespaceLister listers.NamespaceLister 42 namespaceSynced cache.InformerSynced 43 44 systemNamespaces []string 45 interval time.Duration 46 } 47 48 // NewController creates a new Controller to ensure system namespaces exist. 49 func NewController(clientset kubernetes.Interface, namespaceInformer coreinformers.NamespaceInformer) *Controller { 50 systemNamespaces := []string{metav1.NamespaceSystem, metav1.NamespacePublic, v1.NamespaceNodeLease, metav1.NamespaceDefault} 51 interval := 1 * time.Minute 52 53 return &Controller{ 54 client: clientset, 55 namespaceLister: namespaceInformer.Lister(), 56 namespaceSynced: namespaceInformer.Informer().HasSynced, 57 systemNamespaces: systemNamespaces, 58 interval: interval, 59 } 60 } 61 62 // Run starts one worker. 63 func (c *Controller) Run(stopCh <-chan struct{}) { 64 defer utilruntime.HandleCrash() 65 defer klog.Infof("Shutting down system namespaces controller") 66 67 klog.Infof("Starting system namespaces controller") 68 69 if !cache.WaitForCacheSync(stopCh, c.namespaceSynced) { 70 utilruntime.HandleError(fmt.Errorf("timed out waiting for caches to sync")) 71 return 72 } 73 74 go wait.Until(c.sync, c.interval, stopCh) 75 76 <-stopCh 77 } 78 79 func (c *Controller) sync() { 80 // Loop the system namespace list, and create them if they do not exist 81 for _, ns := range c.systemNamespaces { 82 if err := c.createNamespaceIfNeeded(ns); err != nil { 83 utilruntime.HandleError(fmt.Errorf("unable to create required kubernetes system Namespace %s: %v", ns, err)) 84 } 85 } 86 } 87 88 func (c *Controller) createNamespaceIfNeeded(ns string) error { 89 if _, err := c.namespaceLister.Get(ns); err == nil { 90 // the namespace already exists 91 return nil 92 } 93 newNs := &v1.Namespace{ 94 ObjectMeta: metav1.ObjectMeta{ 95 Name: ns, 96 Namespace: "", 97 }, 98 } 99 _, err := c.client.CoreV1().Namespaces().Create(context.TODO(), newNs, metav1.CreateOptions{}) 100 if err != nil && errors.IsAlreadyExists(err) { 101 err = nil 102 } 103 return err 104 }