避免自定义 Kubernetes 调度器与默认调度器的领导者选举冲突
如果你的自定义 Kubernetes 调度器与默认的 kube-scheduler
在领导者选举时发生冲突,可能会阻塞在 attempting to acquire leader lease kube-system/kube-scheduler...
。这是因为自定义调度器尝试使用相同的租约对象(kube-system/kube-scheduler
)或命名空间。以下是避免冲突的解决方案。
解决方法
1. 使用唯一的租约对象名称
默认的 kube-scheduler
使用 kube-system
命名空间中的 kube-scheduler
租约对象。为你的自定义调度器配置一个唯一的租约名称,以避免冲突。
配置示例(YAML):
leaderElection:enabled: trueresourceNamespace: kube-systemresourceName: my-custom-scheduler
代码示例(如果使用 Go 语言的 Scheduler Framework):
leaderElection: componentconfig.LeaderElectionConfiguration{LeaderElect: true,LeaseDuration: 15 * time.Second,RenewDeadline: 10 * time.Second,RetryPeriod: 2 * time.Second,ResourceNamespace: "kube-system",ResourceName: "my-custom-scheduler",
}
确保 resourceName
与默认的 kube-scheduler
不同。
2. 使用不同的命名空间(可选)
为了进一步隔离自定义调度器,可以使用独立的命名空间,而不是 kube-system
。
步骤:
- 创建新命名空间(例如
custom-scheduler-ns
):kubectl create namespace custom-scheduler-ns
- 更新配置或代码中的
resourceNamespace
:leaderElection:enabled: trueresourceNamespace: custom-scheduler-nsresourceName: my-custom-scheduler
3. 确保 RBAC 权限正确
自定义调度器需要对租约对象的操作权限。创建一个独立的 ClusterRole
和 ClusterRoleBinding
:
示例 RBAC 配置:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: custom-scheduler
rules:
- apiGroups: ["coordination.k8s.io"]resources: ["leases"]verbs: ["get", "create", "update"]resourceNames: ["my-custom-scheduler"]
- apiGroups: [""]resources: ["pods", "nodes", "services", "endpoints"]verbs: ["get", "list", "watch"]
- apiGroups: [""]resources: ["pods/binding", "pods/status"]verbs: ["create", "update"]---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: custom-scheduler-binding
subjects:
- kind: ServiceAccountname: custom-scheduler-sanamespace: custom-scheduler-ns
roleRef:kind: ClusterRolename: custom-schedulerapiGroup: rbac.authorization.k8s.io
创建 ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:name: custom-scheduler-sanamespace: custom-scheduler-ns
在调度器 Pod 的部署中指定该 ServiceAccount
:
spec:serviceAccountName: custom-scheduler-sa
4. 禁用默认 kube-scheduler(如果不需要)
如果自定义调度器完全替代默认 kube-scheduler
,可以禁用默认调度器:
- 找到
kube-scheduler
的 Pod(通常在kube-system
命名空间):kubectl get pods -n kube-system | grep scheduler
- 编辑静态 Pod 清单(通常在
/etc/kubernetes/manifests/kube-scheduler.yaml
),删除或注释掉。 - 或者,设置
replicas: 0
(如果通过 Deployment 部署)。
注意:仅在确认自定义调度器能完全接管调度职责时才禁用默认调度器。
5. 验证调度器配置
确保调度器的启动参数或配置文件正确设置了领导者选举参数:
--leader-elect=true
(启用领导者选举)--leader-election-lease-duration
(租约持续时间,建议 15s)--leader-election-renew-deadline
(续约截止时间,建议 10s)--leader-election-retry-period
(重试间隔,建议 2s)--leader-election-resource-name
(自定义租约名称,如my-custom-scheduler
)--leader-election-resource-namespace
(自定义命名空间,如custom-scheduler-ns
)
命令行启动示例:
./my-custom-scheduler --leader-elect=true --leader-election-resource-name=my-custom-scheduler --leader-election-resource-namespace=custom-scheduler-ns
6. 检查调度器名称
确保自定义调度器在 Kubernetes 中注册了一个唯一的调度器名称(通过 schedulerName
字段)。
Pod 示例:
apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:schedulerName: my-custom-schedulercontainers:- name: my-containerimage: nginx
这确保 Pod 只由自定义调度器处理,避免与默认调度器冲突。
7. 日志和调试
- 检查自定义调度器日志,确认是否仍在尝试获取默认的
kube-scheduler
租约:kubectl logs <custom-scheduler-pod> -n <namespace>
- 检查租约对象状态:
kubectl get lease my-custom-scheduler -n custom-scheduler-ns -o yaml
- 如果租约对象被意外占用,删除后重试:
kubectl delete lease my-custom-scheduler -n custom-scheduler-ns
示例:完整部署配置
以下是一个自定义调度器的部署 YAML 示例:
apiVersion: v1
kind: Namespace
metadata:name: custom-scheduler-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:name: custom-scheduler-sanamespace: custom-scheduler-ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: custom-scheduler
rules:
- apiGroups: ["coordination.k8s.io"]resources: ["leases"]verbs: ["get", "create", "update"]resourceNames: ["my-custom-scheduler"]
- apiGroups: [""]resources: ["pods", "nodes", "services", "endpoints"]verbs: ["get", "list", "watch"]
- apiGroups: [""]resources: ["pods/binding", "pods/status"]verbs: ["create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: custom-scheduler-binding
subjects:
- kind: ServiceAccountname: custom-scheduler-sanamespace: custom-scheduler-ns
roleRef:kind: ClusterRolename: custom-schedulerapiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:name: custom-schedulernamespace: custom-scheduler-ns
spec:replicas: 1selector:matchLabels:app: custom-schedulertemplate:metadata:labels:app: custom-schedulerspec:serviceAccountName: custom-scheduler-sacontainers:- name: custom-schedulerimage: my-custom-scheduler:latestargs:- --leader-elect=true- --leader-election-resource-name=my-custom-scheduler- --leader-election-resource-namespace=custom-scheduler-ns- --scheduler-name=my-custom-scheduler
关键注意事项
- 唯一性:租约名称、调度器名称和命名空间必须与默认
kube-scheduler
区分开。 - 高可用性:如果运行多个调度器实例,确保它们共享相同的租约对象以进行领导者选举。
- 测试:部署后,创建几个 Pod(指定
schedulerName: my-custom-scheduler
),验证是否由自定义调度器处理:kubectl get pods -o wide --show-labels
- 文档参考:查阅 Kubernetes 官方文档中的 Scheduler Framework 和 Leader Election 部分。
进一步排查
如果问题未解决,请提供以下信息:
- 自定义调度器的实现方式(Scheduler Framework、自定义二进制等)。
- 当前配置文件或启动参数。
- 调度器日志片段。
- 租约对象状态(
kubectl get lease -n <namespace>
)。