k8s.io/client-go@v0.31.1/tools/leaderelection/resourcelock/interface.go (about) 1 /* 2 Copyright 2016 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 resourcelock 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 v1 "k8s.io/api/coordination/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime" 27 clientset "k8s.io/client-go/kubernetes" 28 coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1" 29 corev1 "k8s.io/client-go/kubernetes/typed/core/v1" 30 restclient "k8s.io/client-go/rest" 31 ) 32 33 const ( 34 LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader" 35 endpointsResourceLock = "endpoints" 36 configMapsResourceLock = "configmaps" 37 LeasesResourceLock = "leases" 38 // When using endpointsLeasesResourceLock, you need to ensure that 39 // API Priority & Fairness is configured with non-default flow-schema 40 // that will catch the necessary operations on leader-election related 41 // endpoint objects. 42 // 43 // The example of such flow scheme could look like this: 44 // apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 45 // kind: FlowSchema 46 // metadata: 47 // name: my-leader-election 48 // spec: 49 // distinguisherMethod: 50 // type: ByUser 51 // matchingPrecedence: 200 52 // priorityLevelConfiguration: 53 // name: leader-election # reference the <leader-election> PL 54 // rules: 55 // - resourceRules: 56 // - apiGroups: 57 // - "" 58 // namespaces: 59 // - '*' 60 // resources: 61 // - endpoints 62 // verbs: 63 // - get 64 // - create 65 // - update 66 // subjects: 67 // - kind: ServiceAccount 68 // serviceAccount: 69 // name: '*' 70 // namespace: kube-system 71 endpointsLeasesResourceLock = "endpointsleases" 72 // When using configMapsLeasesResourceLock, you need to ensure that 73 // API Priority & Fairness is configured with non-default flow-schema 74 // that will catch the necessary operations on leader-election related 75 // configmap objects. 76 // 77 // The example of such flow scheme could look like this: 78 // apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 79 // kind: FlowSchema 80 // metadata: 81 // name: my-leader-election 82 // spec: 83 // distinguisherMethod: 84 // type: ByUser 85 // matchingPrecedence: 200 86 // priorityLevelConfiguration: 87 // name: leader-election # reference the <leader-election> PL 88 // rules: 89 // - resourceRules: 90 // - apiGroups: 91 // - "" 92 // namespaces: 93 // - '*' 94 // resources: 95 // - configmaps 96 // verbs: 97 // - get 98 // - create 99 // - update 100 // subjects: 101 // - kind: ServiceAccount 102 // serviceAccount: 103 // name: '*' 104 // namespace: kube-system 105 configMapsLeasesResourceLock = "configmapsleases" 106 ) 107 108 // LeaderElectionRecord is the record that is stored in the leader election annotation. 109 // This information should be used for observational purposes only and could be replaced 110 // with a random string (e.g. UUID) with only slight modification of this code. 111 // TODO(mikedanese): this should potentially be versioned 112 type LeaderElectionRecord struct { 113 // HolderIdentity is the ID that owns the lease. If empty, no one owns this lease and 114 // all callers may acquire. Versions of this library prior to Kubernetes 1.14 will not 115 // attempt to acquire leases with empty identities and will wait for the full lease 116 // interval to expire before attempting to reacquire. This value is set to empty when 117 // a client voluntarily steps down. 118 HolderIdentity string `json:"holderIdentity"` 119 LeaseDurationSeconds int `json:"leaseDurationSeconds"` 120 AcquireTime metav1.Time `json:"acquireTime"` 121 RenewTime metav1.Time `json:"renewTime"` 122 LeaderTransitions int `json:"leaderTransitions"` 123 Strategy v1.CoordinatedLeaseStrategy `json:"strategy"` 124 PreferredHolder string `json:"preferredHolder"` 125 } 126 127 // EventRecorder records a change in the ResourceLock. 128 type EventRecorder interface { 129 Eventf(obj runtime.Object, eventType, reason, message string, args ...interface{}) 130 } 131 132 // ResourceLockConfig common data that exists across different 133 // resource locks 134 type ResourceLockConfig struct { 135 // Identity is the unique string identifying a lease holder across 136 // all participants in an election. 137 Identity string 138 // EventRecorder is optional. 139 EventRecorder EventRecorder 140 } 141 142 // Interface offers a common interface for locking on arbitrary 143 // resources used in leader election. The Interface is used 144 // to hide the details on specific implementations in order to allow 145 // them to change over time. This interface is strictly for use 146 // by the leaderelection code. 147 type Interface interface { 148 // Get returns the LeaderElectionRecord 149 Get(ctx context.Context) (*LeaderElectionRecord, []byte, error) 150 151 // Create attempts to create a LeaderElectionRecord 152 Create(ctx context.Context, ler LeaderElectionRecord) error 153 154 // Update will update and existing LeaderElectionRecord 155 Update(ctx context.Context, ler LeaderElectionRecord) error 156 157 // RecordEvent is used to record events 158 RecordEvent(string) 159 160 // Identity will return the locks Identity 161 Identity() string 162 163 // Describe is used to convert details on current resource lock 164 // into a string 165 Describe() string 166 } 167 168 // Manufacture will create a lock of a given type according to the input parameters 169 func New(lockType string, ns string, name string, coreClient corev1.CoreV1Interface, coordinationClient coordinationv1.CoordinationV1Interface, rlc ResourceLockConfig) (Interface, error) { 170 leaseLock := &LeaseLock{ 171 LeaseMeta: metav1.ObjectMeta{ 172 Namespace: ns, 173 Name: name, 174 }, 175 Client: coordinationClient, 176 LockConfig: rlc, 177 } 178 switch lockType { 179 case endpointsResourceLock: 180 return nil, fmt.Errorf("endpoints lock is removed, migrate to %s (using version v0.27.x)", endpointsLeasesResourceLock) 181 case configMapsResourceLock: 182 return nil, fmt.Errorf("configmaps lock is removed, migrate to %s (using version v0.27.x)", configMapsLeasesResourceLock) 183 case LeasesResourceLock: 184 return leaseLock, nil 185 case endpointsLeasesResourceLock: 186 return nil, fmt.Errorf("endpointsleases lock is removed, migrate to %s", LeasesResourceLock) 187 case configMapsLeasesResourceLock: 188 return nil, fmt.Errorf("configmapsleases lock is removed, migrated to %s", LeasesResourceLock) 189 default: 190 return nil, fmt.Errorf("Invalid lock-type %s", lockType) 191 } 192 } 193 194 // NewFromKubeconfig will create a lock of a given type according to the input parameters. 195 // Timeout set for a client used to contact to Kubernetes should be lower than 196 // RenewDeadline to keep a single hung request from forcing a leader loss. 197 // Setting it to max(time.Second, RenewDeadline/2) as a reasonable heuristic. 198 func NewFromKubeconfig(lockType string, ns string, name string, rlc ResourceLockConfig, kubeconfig *restclient.Config, renewDeadline time.Duration) (Interface, error) { 199 // shallow copy, do not modify the kubeconfig 200 config := *kubeconfig 201 timeout := renewDeadline / 2 202 if timeout < time.Second { 203 timeout = time.Second 204 } 205 config.Timeout = timeout 206 leaderElectionClient := clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "leader-election")) 207 return New(lockType, ns, name, leaderElectionClient.CoreV1(), leaderElectionClient.CoordinationV1(), rlc) 208 }