k8s lease使用案例
下面给你一个 完整可运行的 Go 示例,演示如何使用 Kubernetes 的 Lease
实现 leader 选举机制。
这个示例使用官方 client-go
提供的 leaderelection
库,能在多个副本间自动选主、续约、切换。
🧩 示例结构
lease-demo/
├── main.go
├── go.mod
└── go.sum
📦 1. go.mod
module lease-demogo 1.20require (k8s.io/client-go v0.30.0k8s.io/apimachinery v0.30.0
)
🧠 2. main.go
package mainimport ("context""flag""fmt""os""time"v1 "k8s.io/api/coordination/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/rest""k8s.io/client-go/tools/leaderelection""k8s.io/client-go/tools/leaderelection/resourcelock"
)func main() {var leaseName, leaseNamespace stringflag.StringVar(&leaseName, "lease-name", "demo-lease", "Name of the lease resource")flag.StringVar(&leaseNamespace, "lease-namespace", "default", "Namespace of the lease resource")flag.Parse()// 1️⃣ 连接集群(使用 InCluster 或本地 kubeconfig)cfg, err := rest.InClusterConfig()if err != nil {fmt.Println("Not in cluster, try kubeconfig")cfg, err = rest.InClusterConfig()if err != nil {panic(err)}}clientset, err := kubernetes.NewForConfig(cfg)if err != nil {panic(err)}// 2️⃣ 设置租约对象(LeaseLock)id, _ := os.Hostname()lock := &resourcelock.LeaseLock{LeaseMeta: metav1.ObjectMeta{Name: leaseName,Namespace: leaseNamespace,},Client: clientset.CoordinationV1(),LockConfig: resourcelock.ResourceLockConfig{Identity: id,},}// 3️⃣ 创建上下文ctx, cancel := context.WithCancel(context.Background())defer cancel()// 4️⃣ Leader 选举配置leaderelectionCfg := leaderelection.LeaderElectionConfig{Lock: lock,LeaseDuration: 15 * time.Second, // 租约有效期RenewDeadline: 10 * time.Second, // 续约截止时间RetryPeriod: 2 * time.Second, // 重试间隔ReleaseOnCancel: true,Name: "lease-demo-election",Callbacks: leaderelection.LeaderCallbacks{OnStartedLeading: func(ctx context.Context) {fmt.Printf("[%s] ✅ 成为 leader,开始执行任务...\n", id)for {select {case <-ctx.Done():returndefault:fmt.Printf("[%s] 正在执行任务中...\n", id)time.Sleep(5 * time.Second)}}},OnStoppedLeading: func() {fmt.Printf("[%s] ❌ 失去 leader 身份\n", id)},OnNewLeader: func(identity string) {if identity == id {fmt.Printf("[%s] 🏆 我是当前 leader\n", id)} else {fmt.Printf("[%s] 当前 leader 是 %s\n", id, identity)}},},}// 5️⃣ 启动 leader 选举leaderelection.RunOrDie(ctx, leaderelectionCfg)
}
🚀 3. 构建镜像 & 部署
Dockerfile
FROM golang:1.21 as builder
WORKDIR /app
COPY . .
RUN go mod tidy && go build -o lease-demo .FROM alpine:3.18
COPY --from=builder /app/lease-demo /lease-demo
ENTRYPOINT ["/lease-demo"]
Kubernetes Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:name: lease-demo
spec:replicas: 3selector:matchLabels:app: lease-demotemplate:metadata:labels:app: lease-demospec:serviceAccountName: lease-demo-sacontainers:- name: lease-demoimage: yourrepo/lease-demo:latestargs: ["--lease-name=demo-lease", "--lease-namespace=default"]
---
apiVersion: v1
kind: ServiceAccount
metadata:name: lease-demo-sanamespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: lease-demo-rolenamespace: default
rules:
- apiGroups: ["coordination.k8s.io"]resources: ["leases"]verbs: ["get", "watch", "list", "update", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: lease-demo-rbnamespace: default
subjects:
- kind: ServiceAccountname: lease-demo-sa
roleRef:kind: Rolename: lease-demo-roleapiGroup: rbac.authorization.k8s.io
🧾 4. 运行效果
部署后:
kubectl logs -l app=lease-demo -f
输出类似:
[node1] 🏆 我是当前 leader
[node1] ✅ 成为 leader,开始执行任务...
[node2] 当前 leader 是 node1
[node3] 当前 leader 是 node1
...
(node1 被删除后)
[node2] 🏆 我是当前 leader
[node2] ✅ 成为 leader,开始执行任务...
✅ 5. 小结
功能 | 描述 |
---|---|
LeaseLock | 使用 coordination.k8s.io/v1 的 Lease 实现选举 |
LeaseDuration | leader 失效超时时间 |
RenewDeadline | leader 续租截止时间 |
RetryPeriod | 非 leader 的重试时间 |
OnStartedLeading | 成为 leader 后执行的逻辑 |
OnStoppedLeading | 失去 leader 时触发 |
OnNewLeader | 每次 leader 切换都会回调 |
是否希望我再帮你生成一个对应的 可直接运行的 YAML + Go 代码打包 zip 文件?(可以直接 kubectl apply -f
运行)