istio
170 строк · 6.0 Кб
1/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package k8sresourcelock
18
19import (
20"context"
21"fmt"
22"time"
23
24metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25"k8s.io/apimachinery/pkg/runtime"
26clientset "k8s.io/client-go/kubernetes"
27coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
28corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
29restclient "k8s.io/client-go/rest"
30)
31
32const (
33LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader"
34EndpointsResourceLock = "endpoints"
35ConfigMapsResourceLock = "configmaps"
36LeasesResourceLock = "leases"
37EndpointsLeasesResourceLock = "endpointsleases"
38ConfigMapsLeasesResourceLock = "configmapsleases"
39)
40
41// LeaderElectionRecord is the record that is stored in the leader election annotation.
42// This information should be used for observational purposes only and could be replaced
43// with a random string (e.g. UUID) with only slight modification of this code.
44// TODO(mikedanese): this should potentially be versioned
45type LeaderElectionRecord struct {
46// HolderIdentity is the ID that owns the lease. If empty, no one owns this lease and
47// all callers may acquire. Versions of this library prior to Kubernetes 1.14 will not
48// attempt to acquire leases with empty identities and will wait for the full lease
49// interval to expire before attempting to reacquire. This value is set to empty when
50// a client voluntarily steps down.
51HolderIdentity string `json:"holderIdentity"`
52// HolderKey is the Key of the lease owner. This may be empty if a key is not set.
53HolderKey string `json:"holderKey"`
54LeaseDurationSeconds int `json:"leaseDurationSeconds"`
55AcquireTime metav1.Time `json:"acquireTime"`
56RenewTime metav1.Time `json:"renewTime"`
57LeaderTransitions int `json:"leaderTransitions"`
58}
59
60// EventRecorder records a change in the ResourceLock.
61type EventRecorder interface {
62Eventf(obj runtime.Object, eventType, reason, message string, args ...any)
63}
64
65// ResourceLockConfig common data that exists across different
66// resource locks
67type ResourceLockConfig struct {
68// Identity is the unique string identifying a lease holder across
69// all participants in an election.
70Identity string
71// Key is a user-defined value used to indicate how high priority this lock
72// have. Other locks may steal the lock from us if they believe their key
73// has a higher priority.
74Key string
75// EventRecorder is optional.
76EventRecorder EventRecorder
77}
78
79// Interface offers a common interface for locking on arbitrary
80// resources used in leader election. The Interface is used
81// to hide the details on specific implementations in order to allow
82// them to change over time. This interface is strictly for use
83// by the leaderelection code.
84type Interface interface {
85// Get returns the LeaderElectionRecord
86Get(ctx context.Context) (*LeaderElectionRecord, []byte, error)
87
88// Create attempts to create a LeaderElectionRecord
89Create(ctx context.Context, ler LeaderElectionRecord) error
90
91// Update will update and existing LeaderElectionRecord
92Update(ctx context.Context, ler LeaderElectionRecord) error
93
94// RecordEvent is used to record events
95RecordEvent(string)
96
97// Identity will return the locks Identity
98Identity() string
99Key() string
100
101// Describe is used to convert details on current resource lock
102// into a string
103Describe() string
104}
105
106// Manufacture will create a lock of a given type according to the input parameters
107// nolint: lll
108func New(lockType string, ns string, name string, coreClient corev1.CoreV1Interface, coordinationClient coordinationv1.CoordinationV1Interface, rlc ResourceLockConfig) (Interface, error) {
109endpointsLock := &EndpointsLock{
110EndpointsMeta: metav1.ObjectMeta{
111Namespace: ns,
112Name: name,
113},
114Client: coreClient,
115LockConfig: rlc,
116}
117configmapLock := &ConfigMapLock{
118ConfigMapMeta: metav1.ObjectMeta{
119Namespace: ns,
120Name: name,
121},
122Client: coreClient,
123LockConfig: rlc,
124}
125leaseLock := &LeaseLock{
126LeaseMeta: metav1.ObjectMeta{
127Namespace: ns,
128Name: name,
129},
130Client: coordinationClient,
131LockConfig: rlc,
132}
133switch lockType {
134case EndpointsResourceLock:
135return endpointsLock, nil
136case ConfigMapsResourceLock:
137return configmapLock, nil
138case LeasesResourceLock:
139return leaseLock, nil
140case EndpointsLeasesResourceLock:
141return &MultiLock{
142Primary: endpointsLock,
143Secondary: leaseLock,
144}, nil
145case ConfigMapsLeasesResourceLock:
146return &MultiLock{
147Primary: configmapLock,
148Secondary: leaseLock,
149}, nil
150default:
151return nil, fmt.Errorf("invalid lock-type %s", lockType)
152}
153}
154
155// NewFromKubeconfig will create a lock of a given type according to the input parameters.
156// Timeout set for a client used to contact to Kubernetes should be lower than
157// RenewDeadline to keep a single hung request from forcing a leader loss.
158// Setting it to max(time.Second, RenewDeadline/2) as a reasonable heuristic.
159// nolint: lll
160func NewFromKubeconfig(lockType string, ns string, name string, rlc ResourceLockConfig, kubeconfig *restclient.Config, renewDeadline time.Duration) (Interface, error) {
161// shallow copy, do not modify the kubeconfig
162config := *kubeconfig
163timeout := renewDeadline / 2
164if timeout < time.Second {
165timeout = time.Second
166}
167config.Timeout = timeout
168leaderElectionClient := clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "leader-election"))
169return New(lockType, ns, name, leaderElectionClient.CoreV1(), leaderElectionClient.CoordinationV1(), rlc)
170}
171