阿里云 网站建设方案书网站根据城市做二级目录
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:00
当前位置: 首页 > news >正文
阿里云 网站建设方案书,网站根据城市做二级目录,企业网站一般做哪些栏目,国外做西餐的网站简介 对于无状态的组件来说#xff0c;天然具备高可用特性#xff0c;无非就是多开几个副本而已#xff1b;而对于有状态组件来说#xff0c;实现高可用则要麻烦很多#xff0c;一般来说通过选主来达到同一时刻只能有一个组件在处理业务逻辑。 在Kubernetes中#xff0c;… 简介 对于无状态的组件来说天然具备高可用特性无非就是多开几个副本而已而对于有状态组件来说实现高可用则要麻烦很多一般来说通过选主来达到同一时刻只能有一个组件在处理业务逻辑。 在Kubernetes中为了实现组件高可用同一个组件需要部署多个副本例如多个apiserver、scheduler、controller-manager等其中apiserver是无状态的每个组件都可以工作而scheduler与controller-manager是有状态的同一时刻只能存在一个活跃的需要进行选主。 Kubernetes中是通过leaderelection来实现组件的高可用的。在Kubernetes本身的组件中kube-scheduler和kube-manager-controller两个组件是有leader选举的这个选举机制是Kubernetes对于这两个组件的高可用保障。即正常情况下kube-scheduler或kube-manager-controller组件的多个副本只有一个是处于业务逻辑运行状态其它副本则不断的尝试去获取锁去竞争leader直到自己成为leader。如果正在运行的leader因某种原因导致当前进程退出或者锁丢失则由其它副本去竞争新的leader获取leader继而执行业务逻辑。 在Kubernetes client-go包中就提供了接口供用户使用。代码路径在client-go/tools/leaderelection下。 如何使用 因为client-go帮我们封装了大部分逻辑使用起来非常简单 rl, err : resourcelock.New(resourcelock.EndpointsResourceLock,namespace,lockName,ctx.KubeClient.CoreV1(),resourcelock.ResourceLockConfig{Identity: id,EventRecorder: ctx.Recorder(namespace),}) if err ! nil {log.Fatalf(error creating lock: %v, err)panic(err) }// Try and become the leader and start cloud controller manager loops leaderelection.RunOrDie(context.Background(), leaderelection.LeaderElectionConfig{Lock: rl,LeaseDuration: ctx.LeaseDuration,RenewDeadline: ctx.RenewDeadline,RetryPeriod: ctx.RetryPeriod,Callbacks: leaderelection.LeaderCallbacks{OnStartedLeading: func(_ context.Context) {log.Infof(cmdb running in leader elect)run(ctx)},OnStoppedLeading: func() {log.Fatalf(leaderelection lost)},}, }) 首先是新建给资源锁对象开始选举同时业务会提供回调方法给leaderelection针对不同的选举结果leaderelection会回调业务相应的方法有三种回调方法 成为leader时的回调失去leader时的回调leader变更时的回调 下面就从源码来分析下它是怎么实现的 源码解析 leaderelection基本原理其实就是利用通过Kubernetes中configmap 、endpoints资源实现一个分布式锁获取到锁的进程成为leader并且定期更新租约renew。其他进程也在不断的尝试进行抢占抢占不到则继续等待下次循环。当leader节点挂掉之后租约到期其他节点就成为新的leader。 为了针对不同资源的锁机制leaderelection定义了一个接口协议 type Interface interface {// Get returns the LeaderElectionRecordGet() (*LeaderElectionRecord, error)// Create attempts to create a LeaderElectionRecordCreate(ler LeaderElectionRecord) error// Update will update and existing LeaderElectionRecordUpdate(ler LeaderElectionRecord) error// RecordEvent is used to record eventsRecordEvent(string)// Identity will return the locks IdentityIdentity() string// Describe is used to convert details on current resource lock// into a stringDescribe() string } 目前有configmap和endpoints两种资源的实现。 从上面的使用来说第一步我们首先会新建一个资源锁对应源码如下 func New(lockType string, ns string, name string, client corev1.CoreV1Interface, rlc ResourceLockConfig) (Interface, error) {switch lockType {case EndpointsResourceLock:return amp;EndpointsLock{EndpointsMeta: metav1.ObjectMeta{Namespace: ns,Name: name,},Client: client,LockConfig: rlc,}, nilcase ConfigMapsResourceLock:return amp;ConfigMapLock{ConfigMapMeta: metav1.ObjectMeta{Namespace: ns,Name: name,},Client: client,LockConfig: rlc,}, nildefault:return nil, fmt.Errorf(Invalid lock-type %s, lockType)} } 可以看到返回的是接口类型对应到configmap和endpoints两种锁的实现。 第二步开始选举对应源码如下 func RunOrDie(ctx context.Context, lec LeaderElectionConfig) {le, err : NewLeaderElector(lec)if err ! nil {panic(err)}if lec.WatchDog ! nil {lec.WatchDog.SetLeaderElection(le)}le.Run(ctx) } func (le *LeaderElector) Run(ctx context.Context) {defer func() {runtime.HandleCrash()le.config.Callbacks.OnStoppedLeading()}()if !le.acquire(ctx) {return // ctx signalled done}ctx, cancel : context.WithCancel(ctx)defer cancel()go le.config.Callbacks.OnStartedLeading(ctx)le.renew(ctx) } 上面的代码就是尝试去获取锁然后根据处理结果回调业务相应的方法下面来看下具体的选举逻辑 func (le *LeaderElector) acquire(ctx context.Context) bool {ctx, cancel : context.WithCancel(ctx)defer cancel()succeeded : falsedesc : le.config.Lock.Describe()klog.Infof(attempting to acquire leader lease %v…, desc)wait.JitterUntil(func() {succeeded le.tryAcquireOrRenew()le.maybeReportTransition()if !succeeded {klog.V(4).Infof(failed to acquire lease %v, desc)return}le.config.Lock.RecordEvent(became leader)klog.Infof(successfully acquired lease %v, desc)cancel()}, le.config.RetryPeriod, JitterFactor, true, ctx.Done())return succeeded } wait是一个周期性任务该任务主要就是如下逻辑 尝试去获取锁如果没有获取到则直接返回等待下一次周期的到来再次尝试获取如果获取到表示自己已经是leader可以处理业务逻辑了此时就通过取消context来退出wait周期性任务 下面来看下具体的获取锁代码 func (le *LeaderElector) tryAcquireOrRenew() bool {now : metav1.Now()leaderElectionRecord : rl.LeaderElectionRecord{HolderIdentity: le.config.Lock.Identity(),LeaseDurationSeconds: int(le.config.LeaseDuration / time.Second),RenewTime: now,AcquireTime: now,}// 1. obtain or create the ElectionRecordoldLeaderElectionRecord, err : le.config.Lock.Get()if err ! nil {if !errors.IsNotFound(err) {klog.Errorf(error retrieving resource lock %v: %v, le.config.Lock.Describe(), err)return false}if err le.config.Lock.Create(leaderElectionRecord); err ! nil {klog.Errorf(error initially creating leader election record: %v, err)return false}le.observedRecord leaderElectionRecordle.observedTime le.clock.Now()return true}// 2. Record obtained, check the Identity amp; Timeif !reflect.DeepEqual(le.observedRecord, *oldLeaderElectionRecord) {le.observedRecord *oldLeaderElectionRecordle.observedTime le.clock.Now()}if le.observedTime.Add(le.config.LeaseDuration).After(now.Time) amp;amp;!le.IsLeader() {klog.V(4).Infof(lock is held by %v and has not yet expired, oldLeaderElectionRecord.HolderIdentity)return false}// 3. Were going to try to update. The leaderElectionRecord is set to its default// here. Lets correct it before updating.if le.IsLeader() {leaderElectionRecord.AcquireTime oldLeaderElectionRecord.AcquireTimeleaderElectionRecord.LeaderTransitions oldLeaderElectionRecord.LeaderTransitions} else {leaderElectionRecord.LeaderTransitions oldLeaderElectionRecord.LeaderTransitions 1}// update the lock itselfif err le.config.Lock.Update(leaderElectionRecord); err ! nil {klog.Errorf(Failed to update lock: %v, err)return false}le.observedRecord leaderElectionRecordle.observedTime le.clock.Now()return true } 上面的逻辑如下 获取锁对象信息LeaderElectionRecord如果没有获取到说明此时还没有leader则去创建一个如果获取到了则说明系统中存在leader了根据id标识检查自己是否是leader如果自己不是leader检查锁是否过期如果没有过期则退出后面的逻辑等待wait的下一次调用如果过期了则更新锁对象自己成为leader续约成功或者新成为 上面对对象锁信息的处理调用了一系列的接口根据前面说的有两种实现configmap和endpoints下面以endpoints为例看看接口都是怎么处理对象锁的 func (el *EndpointsLock) Get() (*LeaderElectionRecord, error) {var record LeaderElectionRecordvar err errorel.e, err el.Client.Endpoints(el.EndpointsMeta.Namespace).Get(el.EndpointsMeta.Name, metav1.GetOptions{})if err ! nil {return nil, err}if el.e.Annotations nil {el.e.Annotations make(map[string]string)}if recordBytes, found : el.e.Annotations[LeaderElectionRecordAnnotationKey]; found {if err : json.Unmarshal([]byte(recordBytes), amp;record); err ! nil {return nil, err}}return amp;record, nil }// Create attempts to create a LeaderElectionRecord annotation func (el *EndpointsLock) Create(ler LeaderElectionRecord) error {recordBytes, err : json.Marshal(ler)if err ! nil {return err}el.e, err el.Client.Endpoints(el.EndpointsMeta.Namespace).Create(amp;v1.Endpoints{ObjectMeta: metav1.ObjectMeta{Name: el.EndpointsMeta.Name,Namespace: el.EndpointsMeta.Namespace,Annotations: map[string]string{LeaderElectionRecordAnnotationKey: string(recordBytes),},},})return err } 从上面可以看出其实所谓的提供接口无非就是提供一个锁对象信息的存储位置因为k8s中的资源都是给业务使用的k8s不想专门提供一种资源来代表组件锁而是将锁信息存储在了接口实现资源的annotations标签中。
相关文章
-
阿里云 万网 网站兰州网站建设推广报价
阿里云 万网 网站兰州网站建设推广报价
- 技术栈
- 2026年03月21日
-
阿里云 个人网站备案烟台主流网站
阿里云 个人网站备案烟台主流网站
- 技术栈
- 2026年03月21日
-
阿里云 多个网站中小型网站建设与管理设计总结
阿里云 多个网站中小型网站建设与管理设计总结
- 技术栈
- 2026年03月21日
-
阿里云esc 可以做几个网站校园网站建设的必要性论文
阿里云esc 可以做几个网站校园网站建设的必要性论文
- 技术栈
- 2026年03月21日
-
阿里云oss建站 直接上传wordpress深圳做企业网站
阿里云oss建站 直接上传wordpress深圳做企业网站
- 技术栈
- 2026年03月21日
-
阿里云备案成功怎么建设网站获客引流100种方法
阿里云备案成功怎么建设网站获客引流100种方法
- 技术栈
- 2026年03月21日






