此版本仍在开发中,目前尚不稳定。如需最新稳定版本,请使用 Spring Cloud Kubernetes 5.0.1spring-doc.cadn.net.cn

领导选举

Spring Cloud Kubernetes 的领导者选举机制使用 Kubernetes ConfigMap 实现了 Spring Integration 的领导者选举 API。spring-doc.cadn.net.cn

多个应用实例竞争领导权,但领导权仅授予其中一个。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

当获得领导权时,领导者应用将收到一个 OnGrantedEvent 应用事件,其中领导权为 Contextspring-doc.cadn.net.cn

应用会定期尝试获取领导权,领导权授予首个请求者。spring-doc.cadn.net.cn

领导者将保持其领导地位,直至其从集群中被移除或主动放弃领导权。spring-doc.cadn.net.cn

当领导权被移除时,前一领导者将收到 OnRevokedEvent 应用事件。spring-doc.cadn.net.cn

移除后,集群中的任何实例均可成为新的领导者,包括原领导者。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

要将其包含在您的项目中,请添加以下依赖项。<br/>Fabric8 领导者实现spring-doc.cadn.net.cn

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-kubernetes-fabric8-leader</artifactId>
</dependency>

要指定用于领导者选举的配置映射(configmap)名称,请使用以下属性。spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.config-map-name=leader

领导者选举信息贡献者

Spring Cloud Kubernetes Leader 包含一个 InfoContributor,该组件将领导者选举信息添加到 Spring Boot 的 /actuator/info 端点中。此贡献者提供当前领导者的相关信息,包括领导者 ID、角色以及当前应用实例是否为领导者。spring-doc.cadn.net.cn

Example output:spring-doc.cadn.net.cn

{
  "leaderElection": {
    "leaderId": "my-app-pod-1",
    "role": "my-role",
    "isLeader": true
  }
}

您可以将此 InfoContributor 禁用,方法是在 application.[properties | yaml] 中将 management.info.leader.enabled 设置为 falsespring-doc.cadn.net.cn

management.info.leader.enabled=false

还有一种配置领导者选举的方式,它在 fabric8 和 Kubernetes 客户端中都原生支持。从长远来看,这将成为配置领导者选举的默认方式,而之前的方式将被弃用。您可以将其视为类似于 JDK 的“预览”特性。spring-doc.cadn.net.cn

要使用它,您需要设置以下属性:spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.enabled=true

与旧实现不同,此实现将根据您的集群版本使用 LeaseConfigMap 作为锁。即使支持租约,您仍可通过以下方式强制使用 configMap:spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.use-config-map-as-lock=true

LeaseConfigMap 的名称可使用属性进行定义(默认值为 spring-k8s-leader-election-lock):spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.lockName=other-name

锁创建所在的命名空间(如果没有显式设置,则设为 default)也可以进行设置:spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.lockNamespace=other-namespace

在领导者选举流程启动之前,您可以等待直到Pod就绪(通过就绪检查)。此功能默认启用,但您可根据需要禁用它:spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.waitForPodReady=false

像以前的实现一样,我们默认情况下会发布事件,但可以将其关闭:spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.publishEvents=false

有几个参数控制选举过程。要解释它们,我们需要查看这个过程的高层实现。所有候选pod都试图成为领导者,或者它们试图获取锁。如果锁已经被占用,它们将在每spring.cloud.kubernetes.leader.election.retryPeriod(值为java.time.Duration,默认为2秒)继续重试获取它。spring-doc.cadn.net.cn

如果锁没有被占用,当前 Pod 将成为领导者。它会向锁中插入一条所谓的“记录”(LeaseConfigMap)。这条“记录”包含的内容之一是 leaseDuration(可以通过 spring.cloud.kubernetes.leader.election.leaseDuration 指定;默认为 15 秒,类型为 java.time.Duration)。这在锁上相当于TTL:除非这段时间已过期(从最后一次重新获取时间),否则其他任何候选人都不能获取锁。spring-doc.cadn.net.cn

一旦某个 Pod 成功成为领导者(通过获取锁),它将连续(每 spring.cloud.kubernetes.leader.election.retryPeriod 秒)尝试续订其租约,换句话说:它将尝试延长其领导地位。当发生续期时,存储在锁中的“记录”会被更新。例如,renewTime 会更新到记录中,用以表示上次续期发生的时间。(您可以使用 kubectl describe lease…​ 之类的命令查看这些字段的当前值)。spring-doc.cadn.net.cn

Renewal 必须在由 spring.cloud.kubernetes.leader.election.renewDeadline 指定的一定间隔内发生。默认值为 10 秒,这意味着领导者 Pod 可以有最多 10 秒的时间来重新获得领导权。如果未能完成,此 Pod 将失去领导权,并重新开始领导选举。因为其他 Pod 默认每 2 秒尝试成为领导者一次,这可能意味着刚刚失去领导权的 Pod 又会成为领导者。如果您希望其他 Pod 更有可能成为领导者,则可以设置该属性(以秒为单位,默认值为 3):spring-doc.cadn.net.cn

spring.cloud.kubernetes.leader.election.wait-after-renewal-failure=3

此操作将会导致 Pod(无法续订其租约)和失去领导权,等待此数秒后,再次尝试成为领导者。spring-doc.cadn.net.cn

让我们尝试根据一个示例来解释这些设置:有两个 pod 参与选举领导者。为了简单起见,我们称它们为podApodB。它们同时开始12:00:00,但podA确立自己成为领导者。这意味着每两秒钟retryPeriodpodB都将尝试成为新的领导者。因此,在12:00:02时,然后在12:00:04时,它基本上会询问:“我可以成为领导者吗?”在这个简化的示例中,这个问题的答案可以根据podA进行回答。活动。”spring-doc.cadn.net.cn

podA成为领导者后,每2秒它将尝试“扩展”或续订其领导权。所以在12:00:02,然后在12:00:04等等,podA去锁并更新记录,反映它仍然是领导者。最后一次成功的续订和下一个之间的间隔是10秒钟(renewalDeadline)。如果在那10秒内无法续订其领导权(例如存在连接问题或较大的GC暂停等),则停止领导,并且现在可以获取podB的领导权。当podA以优雅的方式停止作为领导者时,锁定记录被“清除”,基本上意味着podB可以立即获取领导权。spring-doc.cadn.net.cn

podA以OutOfMemory异常死亡时会发生不同的故事,无法优雅地更新锁记录,此时leaseDuration参数就很重要。最简单的解释方法是通过一个例子:spring-doc.cadn.net.cn

podA已经在其12:00:04重新获得了领导权,但在12:00:05它被OOMKiller杀死。在12:00:06podB将尝试成为新的领导者。它会检查“现在”(12:00:06)是否晚于上次续约+租约期限,本质上它会检查:spring-doc.cadn.net.cn

12:00:06 > (12:00:04 + 00:00:10)

条件不满足,因此不能成为领导者。同样,在12:00:0812:00:1012:00:16也会出现这种情况,直到TTL(leaseDuration)到期,podB才能获取它。因此,leaseDuration的值越小,其他pod获得领导权的速度就越快。spring-doc.cadn.net.cn

你可能需要给适当的RBAC权限才能使用此功能,例如:spring-doc.cadn.net.cn

 - apiGroups: [ "coordination.k8s.io" ]
   resources: [ "leases" ]
   resourceNames: [ "spring-k8s-leader-election-lock" ]
   verbs: [ "get", "update", "create" ]
 - apiGroups: [ "" ]
   resources: [ "configmaps" ]
   resourceNames: [ "spring-k8s-leader-election-lock" ]
   verbs: [ "get", "update", "create" ]