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  }