github.phpd.cn/cilium/cilium@v1.6.12/operator/k8s_identity.go (about) 1 // Copyright 2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "time" 20 21 "github.com/cilium/cilium/pkg/controller" 22 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 23 "github.com/cilium/cilium/pkg/k8s/informer" 24 "github.com/cilium/cilium/pkg/k8s/types" 25 "github.com/cilium/cilium/pkg/logging/logfields" 26 "github.com/sirupsen/logrus" 27 28 "k8s.io/api/core/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/fields" 31 "k8s.io/apimachinery/pkg/util/wait" 32 "k8s.io/client-go/tools/cache" 33 ) 34 35 var identityStore cache.Store 36 37 // deleteIdentity deletes an identity. It includes the resource version and 38 // will error if the object has since been changed. 39 func deleteIdentity(identity *types.Identity) error { 40 err := ciliumK8sClient.CiliumV2().CiliumIdentities().Delete( 41 identity.Name, 42 &metav1.DeleteOptions{ 43 Preconditions: &metav1.Preconditions{ 44 UID: &identity.UID, 45 ResourceVersion: &identity.ResourceVersion, 46 }, 47 }) 48 if err != nil { 49 log.WithError(err).Error("Unable to delete identity") 50 } else { 51 log.WithFields(logrus.Fields{"identity": identity.GetName()}).Info("Garbage collected identity") 52 } 53 54 return err 55 } 56 57 // identityGCIteration is a single iteration of a garbage collection. It will 58 // delete identities that have node status entries that are all older than 59 // k8sIdentityHeartbeatTimeout. 60 // Note: cilium-operator deletes identities in the OnDelete handler when they 61 // have no nodes using them (status is empty). This generally means that 62 // deletes here are for longer lived identities with no active users. 63 func identityGCIteration() { 64 if identityStore == nil { 65 return 66 } 67 68 nextIdentity: 69 for _, identityObject := range identityStore.List() { 70 identity, ok := identityObject.(*types.Identity) 71 if !ok { 72 log.WithField(logfields.Object, identityObject). 73 Errorf("Saw %T object while expecting k8s/types.Identity", identityObject) 74 continue 75 } 76 77 for _, heartbeat := range identity.Status.Nodes { 78 if time.Since(heartbeat.Time) < k8sIdentityHeartbeatTimeout { 79 continue nextIdentity 80 } 81 } 82 83 log.WithFields(logrus.Fields{ 84 logfields.Identity: identity, 85 "nodes": identity.Status.Nodes, 86 }).Debug("Deleting unused identity") 87 deleteIdentity(identity) 88 } 89 } 90 91 func startCRDIdentityGC() { 92 controller.NewManager().UpdateController("crd-identity-gc", 93 controller.ControllerParams{ 94 RunInterval: identityGCInterval, 95 DoFunc: func(ctx context.Context) error { 96 identityGCIteration() 97 return nil 98 }, 99 }) 100 } 101 102 func handleIdentityUpdate(identity *types.Identity) { 103 // If no more nodes are using this identity, release the ID for reuse. 104 // If deleteIdentity fails the identity will be removed by the periodic GC. 105 if len(identity.Status.Nodes) == 0 { 106 deleteIdentity(identity) 107 } 108 } 109 110 func startManagingK8sIdentities() { 111 identityStore = cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) 112 identityInformer := informer.NewInformerWithStore( 113 cache.NewListWatchFromClient(ciliumK8sClient.CiliumV2().RESTClient(), 114 "ciliumidentities", v1.NamespaceAll, fields.Everything()), 115 &v2.CiliumIdentity{}, 116 0, 117 cache.ResourceEventHandlerFuncs{ 118 UpdateFunc: func(oldObj, newObj interface{}) { 119 if identity, ok := newObj.(*types.Identity); ok { 120 handleIdentityUpdate(identity) 121 } 122 }, 123 }, 124 types.ConvertToIdentity, 125 identityStore, 126 ) 127 128 go identityInformer.Run(wait.NeverStop) 129 }