golang Kubernetes领导人选举实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang Kubernetes领导人选举实例相关的知识,希望对你有一定的参考价值。

import (
	"fmt"
	"os"
	"time"

	"k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes"
	v1core "k8s.io/client-go/kubernetes/typed/core/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/leaderelection"
	"k8s.io/client-go/tools/leaderelection/resourcelock"
)

func main() {
  config, err := rest.InClusterConfig()
	if err != nil {
		fmt.Println("Failed to get kubernetes config", err)
		os.Exit(1)
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		fmt.Println("Failed to create kubernetes client", err)
		os.Exit(1)
	}

	namespace := "default"
	name := "leader-election-example"
  lockID := rand.New(rand.UUIDEncoder()).KeyEncoded()

	rl, err := resourcelock.New(resourcelock.ConfigMapsResourceLock,
		namespace,
		name,
		clientset.CoreV1(),
		resourcelock.ResourceLockConfig{
			Identity: lockID,
		})

	le, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
		Lock:          rl,
		LeaseDuration: 6 * time.Second,
		RenewDeadline: 5 * time.Second,
		RetryPeriod:   3 * time.Second,
		Callbacks: leaderelection.LeaderCallbacks{
			OnStartedLeading: func(stop <-chan struct{}) {
				for {
					select {
					case <-stop:
						return
					default:
						fmt.Println(time.Now())
						<-time.After(10 * time.Second)
					}
				}
			},
			OnStoppedLeading: func() {
				fmt.Println("Stop leading")
			},
		},
	})
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	for {
		le.Run()
	}
}

云计算设计模式(十三)——领导人选举模式

云计算设计模式(十三)——领导人选举模式


通过协调合作。在分布式应用程序的任务实例集合运行的操作,选举一个实例作为承担管理其它实例责任的领导者这个模式能够有助于确保任务实例不互相冲突导致争用共享资源与其它的任务实例正在运行工作无意中干扰

背景和问题


一个典型的云应用包含行动协调的方式非常多任务这些任务都能够是实例执行同样的代码须要訪问同样的资源,或者它们可能是可并行工作,以执行复杂计算的各个部分

任务实例可能时间自主执行,但它也可能是必要的,以协调实例的操作,以确保它们不发生冲突导致争用共享资源无意中妨碍工作,其它的任务实例正在执行比如
?在基于云的系统,该系统实现了横向扩展同一个任务的多个实例能够每一个实例服务于不同的用户同一时候执行

假设这些实例写入到共享资源。也可能是必要的,以协调它们的操作,以防止每一个实例盲目地覆盖他人进行的更改。


?假设任务正在运行复杂的计算以并行单个元素,其结果将须要被聚合时,他们完毕了。

因为任务实例都是同行,没有天生的领导者,可以充当协调员或聚合器。

解决方式


单个任务实例应选充当领导者,这样的情况下应协调其它从属任务实例操作。假设全部的任务实例都执行同样的代码他们可能可以充当领导者因此选举过程必须慎重管理,以防止两个或多个实例接管领导者的角色在同一时间

该系统必须选择的领导者提供了一个牢固的机构

这样的机制必须可以应付诸如网络中断进程故障事件。

在很多解决方式中。下属的工作情况监控的领导者,通过某种类型的心跳机制通过轮询假设指定的领导者意外终止网络故障使得领导者不通下属的工作情况有必要为他们选出了新的领导人

有可用于选举的领导者之间的一组任务在分布式环境中。包含几个策略:
?排名最低的实例或进程ID选择任务实例
?竞速获得一个共享的分布式相互排斥第一个任务实例获取该相互排斥锁处于率先地位

然而,系统必须保证,假设领导者终止变得与系统的其余部分断开。该相互排斥被释放。以同意还有一个任务实例成为领导者。


?实施的共同领导人选举算法,如恶霸算法算法之中的一个。这些算法相对简单的但也有一些更复杂的技术提供。这些算法假定每一个候选參选具有唯一的ID而且。它们能够可靠的方式其它候选人进行通信

 

问题和注意事项


在决定怎样实现这个模式时,请考虑下面几点
?选出一个领导者的过程应该是弹性的瞬时和永久失效
?必须可以检測到当领导失败,或变成不可用(可能是因为通讯故障这是须要这样的检測速度将取决于系统。有些系统可能可以发挥作用一会儿没有一个领导者。在此期间造成领导人变得不可用瞬时故障可能已被排除其它情况下。可能有必要马上检測领袖失败并引发新的选举。
?在实现自己主动缩放水平的系统中,假设系统背面关闭一些计算资源领导者可能被终止。
?使用一个共享的分布式相互排斥引入外部服务,提供相互排斥锁的可用性依赖。该服务能够构成一个点故障。假设此服务应该以不论什么理由变得不可用时,系统将无法选出一个领导者
?使用一个专用进程的领导者是一个比較简单的方法然而,假设该过程失败,可能有显著延迟又一次启动,而且将得到的延迟可能影响其它进程的性能和响应时间。假设他们正在等待领导人来协调的动作
?实施领导人选举算法之中的一个手动调整和优化代码的最大灵活性。


何时使用这个模式


使用此模式时。在分布式应用程序任务比方云托管解决方式须要认真协调。也没有天生的领导者

注意:

避免使领导者在系统中的瓶颈。领导者的目的是协调附属任务完毕的工作,它不一定有机会參加这项工作本身虽然它应该是有能力这样做。假设任务没有当选领导人

这样的模式可能不适合
?假设有一个天生的领导者或专用的过程,能够随时充当领导者。比如有可能实现一个单进程。其协调该任务的实例。

假设这个过程失败或变得不健康,系统能够将其关闭并又一次启动它
?假设任务之间的协调。能够非常easy地通过使用更轻便的机构来实现的。

比如,假设几个任务实例须要对共享资源的訪问协调一个最好的解决的方法可能是使用乐观悲观锁来控制訪问该资源。
?假设一个第三方的解决方式是比較合适的比如。微软的Azure HDInsight服务基于Apache Hadoop的)使用所提供的ApacheZookeeper协调的map / reduce汇总任务和汇总数据服务它也能够安装并在Azure的虚拟机配置动物园管理员,并将其集成到自己的解决方式或使用可从微软开放技术动物园管理员预置的虚拟机映像欲了解很多其它信息,请參阅Apache的动物园管理员在微软的Azure微软开放技术的站点。

样例


列入可用于本指南的演示样例代码LeaderElection解决方式DistributedMutex项目展示了怎样使用租赁Azure存储BLOB提供了一种机制,实现共享的分布式相互排斥此相互排斥锁能够用来选择Azure云服务的领导者之间的一组角色的实例

第一个角色实例获得租约当选领导人并保持率先直至其租赁或直到它无法续租其它角色实例能够继续监视领导不再可用的情况下将BLOB租赁



注意:

一个BLOB租赁是一个blob排他写锁。单个BLOB能够是一整不论什么一个时间的问题。角色实例能够请求租约在指定的斑点并且将被授予租约,假设没有其它租赁在同一个斑点,是由这个或不论什么其它作用,比方举行否则将抛出一个异常


为了降低一个故障角色实例保留无限期租用的可能性指定了一辈子租约。

当此期满后。租赁变为可用然而,当一个角色实例持有租赁能够请求租约到期而且将被授予租约的时间再延长角色实例能够不断反复这一过程。假设它希望保留租约
有关怎样租用一个blob的具体信息。请參阅租赁斑点REST API在MSDN上





在该实例中BlobDistributedMutex类包括RunTaskWhenMutexAquired方法,使一个角色实例试图获得租约在指定的斑点

团块名称,容器和储存的帐户的细节传递给构造一个BlobSettings对象被创建BlobDistributedMutex对象这个对象是包括在演示样例代码的简单结构)构造函数也接受一个任务。它引用角色实例应该执行,假设它成功收购租赁BLOB和当选领导人的代码。须要注意的是处理获得租约低层次细节中的代码名为BlobLeaseManager一个单独的辅助类实现

public class BlobDistributedMutex
{
  ...
  private readonly BlobSettings blobSettings;
  private readonly Func<CancellationToken, Task> taskToRunWhenLeaseAcquired;
  ...

  public BlobDistributedMutex(BlobSettings blobSettings, 
           Func<CancellationToken, Task> taskToRunWhenLeaseAquired)
  {
    this.blobSettings = blobSettings;
    this.taskToRunWhenLeaseAquired = taskToRunWhenLeaseAquired;
  }
  
  public async Task RunTaskWhenMutexAcquired(CancellationToken token)
  {
    var leaseManager = new BlobLeaseManager(blobSettings);
    await this.RunTaskWhenBlobLeaseAcquired(leaseManager, token);    
  } 
  ...


代码演示样例中RunTaskWhenMutexAquired上述方法调用下面代码演示样例来实际获得租赁所看到的的RunTaskWhenBlobLeaseAcquired方法RunTaskWhenBlobLeaseAcquired方法异步执行

假设租赁成功获取角色实例已经当选的领导者taskToRunWhenLeaseAcquired托付的目的是为了执行协调其他角色实例的工作。

假设未取得租赁还有一个角色实例已当选为领导人和当前角色实例仍然是一个下属注意,TryAcquireLeaseOrWait方法是使用BlobLeaseManager对象获取租赁一个辅助方法

 

 ...
  private async Task RunTaskWhenBlobLeaseAcquired(
    BlobLeaseManager leaseManager, CancellationToken token)
  {
    while (!token.IsCancellationRequested)
    {
      // Try to acquire the blob lease. 
      // Otherwise wait for a short time before trying again.
      string leaseId = await this.TryAquireLeaseOrWait(leaseManager, token);

      if (!string.IsNullOrEmpty(leaseId))
      {
        // Create a new linked cancellation token source so that if either the 
        // original token is cancelled or the lease cannot be renewed, the
        // leader task can be cancelled.
        using (var leaseCts = 
          CancellationTokenSource.CreateLinkedTokenSource(new[] { token }))
        {
          // Run the leader task.
          var leaderTask = this.taskToRunWhenLeaseAquired.Invoke(leaseCts.Token);          
          ...
        }
      }
    }
  }
  ...


 

由领导開始的任务还异步执行。

尽管这个任务正在执行,以下的代码演示样例所看到的的RunTaskWhenBlobLeaseAquired方法周期性地尝试续订租约。这个动作有助于确保该角色实例保持率先。

在简单解决方式中,续订请求之间的延迟小于对租赁期限。以防止还有一角色实例当选的领导人指定的时间。

假设更新失败,以不论什么理由,任务被取消。假设租用未能被更新或任务被取消(可能为角色实例关停的结果),租赁被释放。在这一点上,这个或还有一个角色实例可能被选为领导者。以下的代码提取物显示出此过程的一部分。

...
  private async Task RunTaskWhenBlobLeaseAcquired(
    BlobLeaseManager leaseManager, CancellationToken token)
  {
    while (...)
    {
      ...
      if (...)
      {
        ...
        using (var leaseCts = ...)
        {
          ...
          // Keep renewing the lease in regular intervals. 
          // If the lease cannot be renewed, then the task completes.
          var renewLeaseTask = 
            this.KeepRenewingLease(leaseManager, leaseId, leaseCts.Token);

          // When any task completes (either the leader task itself or when it could
          // not renew the lease) then cancel the other task.
          await CancelAllWhenAnyCompletes(leaderTask, renewLeaseTask, leaseCts);
        }
      }
    }
  }
  ...
}


 

KeepRenewingLease方法是使用BlobLeaseManager对象续租还有一个helper方法

CancelAllWhenAnyCompletes方法取消指定为前两个參数的任务。

图1示出BlobDistributedMutex的功能。

技术分享

图1 - 使用BlobDistributedMutex选出一个领导者和执行协调操作的任务


以下的代码演示样例显示了怎样使用BlobDistributedMutex辅助角色此代码获取租赁一个名为MyLeaderCoordinatorTask开发仓储租赁容器中的blob并指定MyLeaderCoordinatorTask方法定义的代码应该执行,假设角色实例当选领导人

var settings = new BlobSettings(CloudStorageAccount.DevelopmentStorageAccount, 
  "leases", "MyLeaderCoordinatorTask");
var cts = new CancellationTokenSource();
var mutex = new BlobDistributedMutex(settings, MyLeaderCoordinatorTask);
mutex.RunTaskWhenMutexAcquired(this.cts.Token);
...

// Method that runs if the role instance is elected the leader
private static async Task MyLeaderCoordinatorTask(CancellationToken token)
{
  ...
}


 

请注意有关样品溶液中的下面几点
?BLOB一个潜在的单点故障。假设Blob服务不可用,的blob人迹罕至。领导者将无法续租。并没有其它的作用,比方可以获得租约这样的情况下。没有作用,比如将可以充当领导者。

然而。的blob服务被设计为弹性的。所述的blob的服务。以便彻底失败被觉得是极不可能的
?假设领导者摊位正在运行的任务,领导者可能会继续续租,防止不论什么其它角色实例获得租约,并接管领导作用,以协调任务在现实世界中,领导者健康应该频繁地进行检查。
?在选举过程具有不确定性你不能做不论什么如果哪个角色实例得到的blob租约,成为领导者。
?不应使用不论什么其它目的用作的blob租赁目标的blob假设一个角色实例尝试将数据存储在的blob,该数据不能被訪问,除非该角色实例是领导者持有的blob租约。

本文翻译自MSDN:http://msdn.microsoft.com/en-us/library/dn568104.aspx

 

 






























































以上是关于golang Kubernetes领导人选举实例的主要内容,如果未能解决你的问题,请参考以下文章

实例详解ZooKeeper ZAB协议分布式锁与领导选举

卡夫卡领导人多党选举与仲裁员/证人/观察员一起选举

图解Raft之领导者选举

Zookeeper领导选举

Raft协议之领导者选举

云原生安全系列 5:ETCD 安全加固