...

Source file src/k8s.io/client-go/tools/leaderelection/resourcelock/interface.go

Documentation: k8s.io/client-go/tools/leaderelection/resourcelock

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

View as plain text