利用kubernetes资源锁完成自己的HA应用
Backgroud
前一章中,对kubernetes的选举原理进行了深度剖析,下面就通过一个example来实现一个,利用kubernetes提供的选举机制完成的高可用应用。
对于此章需要提前对一些概念有所了解后才可以继续看下去
- leader election mechanism
- RBCA
- Pod runtime mechanism
Implementation
代码实现
如果仅仅是使用Kubernetes中的锁,实现的代码也只有几行而已。
package main
import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/klog/v2"
)
func buildConfig(kubeconfig string) (*rest.Config, error) {
if kubeconfig != "" {
cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, err
}
return cfg, nil
}
cfg, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
return cfg, nil
}
func main() {
klog.InitFlags(nil)
var kubeconfig string
var leaseLockName string
var leaseLockNamespace string
var id string
// 初始化客户端的部分
flag.StringVar(&kubeconfig, "kubeconfig", "", "absolute path to the kubeconfig file")
flag.StringVar(&id, "id", "", "the holder identity name")
flag.StringVar(&leaseLockName, "lease-lock-name", "", "the lease lock resource name")
flag.StringVar(&leaseLockNamespace, "lease-lock-namespace", "", "the lease lock resource namespace")
flag.Parse()
if leaseLockName == "" {
klog.Fatal("unable to get lease lock resource name (missing lease-lock-name flag).")
}
if leaseLockNamespace == "" {
klog.Fatal("unable to get lease lock resource namespace (missing lease-lock-namespace flag).")
}
config, err := buildConfig(kubeconfig)
if err != nil {
klog.Fatal(err)
}
client := clientset.NewForConfigOrDie(config)
run := func(ctx context.Context) {
// 实现的业务逻辑,这里仅仅为实验,就直接打印了
klog.Info("Controller loop...")
for {
fmt.Println("I am leader, I was working.")
time.Sleep(time.Second * 5)
}
}
// use a Go context so we can tell the leaderelection code when we
// want to step down
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 监听系统中断
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
klog.Info("Received termination, signaling shutdown")
cancel()
}()
// 创建一个资源锁
lock := &resourcelock.LeaseLock{
LeaseMeta: metav1.ObjectMeta{
Name: leaseLockName,
Namespace: leaseLockNamespace,
},
Client: client.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: id,
},
}
// 开启一个选举的循环
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
ReleaseOnCancel: true,
LeaseDuration: 60 * time.Second,
RenewDeadline: 15 * time.Second,
RetryPeriod: 5 * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
// 当选举为leader后所运行的业务逻辑
run(ctx)
},
OnStoppedLeading: func() {
// we can do cleanup here
klog.Infof("leader lost: %s", id)
os.Exit(0)
},
OnNewLeader: func(identity string) { // 申请一个选举时的动作
if identity == id {
return
}
klog.Infof("new leader elected: %s", identity)
},
},
})
}
注:这种lease锁只能在in-cluster模式下运行,如果需要类似二进制部署的程序,可以选择endpoint类型的资源锁。
生成镜像
这里已经制作好了镜像并上传到dockerhub(cylonchau/leaderelection:v0.0.2
)上了,如果只要学习运行原理,则忽略此步骤
FROM golang:alpine AS builder
MAINTAINER cylon
WORKDIR /election
COPY . /election
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o elector main.go
FROM alpine AS runner
WORKDIR /go/elector
COPY --from=builder /election/elector .
VOLUME ["/election"]
ENTRYPOINT ["./elector"]
准备资源清单
默认情况下,Kubernetes运行的pod在请求Kubernetes集群内资源时,默认的账户是没有权限的,默认服务帐户无权访问协调 API,因此我们需要创建另一个serviceaccount并相应地设置 对应的RBAC权限绑定;在清单中配置上这个sa,此时所有的pod就会有协调锁的权限了
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-leaderelection
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leaderelection
rules:
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leaderelection
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: leaderelection
subjects:
- kind: ServiceAccount
name: sa-leaderelection
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: leaderelection
name: leaderelection
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: leaderelection
template:
metadata:
labels:
app: leaderelection
spec:
containers:
- image: cylonchau/leaderelection:v0.0.2
imagePullPolicy: IfNotPresent
command: ["./elector"]
args:
- "-id=$(POD_NAME)"
- "-lease-lock-name=test"
- "-lease-lock-namespace=default"
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
name: elector
serviceAccountName: sa-leaderelection
集群中运行
执行完清单后,当pod启动后,可以看到会创建出一个 lease
$ kubectl get lease
NAME HOLDER AGE
test leaderelection-5644c5f84f-frs5n 1s
$ kubectl describe lease
Name: test
Namespace: default
Labels: <none>
Annotations: <none>
API Version: coordination.k8s.io/v1
Kind: Lease
Metadata:
Creation Timestamp: 2022-06-28T16:39:45Z
Managed Fields:
API Version: coordination.k8s.io/v1
Fields Type: FieldsV1
fieldsV1:
f:spec:
f:acquireTime:
f:holderIdentity:
f:leaseDurationSeconds:
f:leaseTransitions:
f:renewTime:
Manager: elector
Operation: Update
Time: 2022-06-28T16:39:45Z
Resource Version: 131693
Self Link: /apis/coordination.k8s.io/v1/namespaces/default/leases/test
UID: bef2b164-a117-44bd-bad3-3e651c94c97b
Spec:
Acquire Time: 2022-06-28T16:39:45.931873Z
Holder Identity: leaderelection-5644c5f84f-frs5n
Lease Duration Seconds: 60
Lease Transitions: 0
Renew Time: 2022-06-28T16:39:55.963537Z
Events: <none>
通过其持有者的信息查看对应pod(因为程序中对holder Identity设置的是pod的名称),实际上是工作的pod。
如上实例所述,这是利用Kubernetes集群完成的leader选举的方案,虽然这不是最完美解决方案,但这是一种简单的方法,因为可以无需在集群上部署更多东西或者进行大量的代码工作就可以利用Kubernetes集群来完成一个高可用的HA应用。
利用kubernetes资源锁完成自己的HA应用的更多相关文章
- 深入理解Kubernetes资源限制:CPU
写在前面 在上一篇关于Kubernetes资源限制的文章我们讨论了如何通过ResourceRequirements设置Pod中容器内存限制,以及容器运行时是如何利用Linux Cgroups实现这些限 ...
- Kubernetes资源与对象简述
资料 k8s基本对象概念 背景 资源和对象 Kubernetes 中的所有内容都被抽象为"资源",如 Pod.Service.Node 等都是资源."对象" ...
- 第15章: Prometheus监控Kubernetes资源与应用
Prometheus监控Kubernetes资源与应用 目录 1 监控方案 2 2 监控指标 4 3 实现思路 4 4 在K8S中部署Prometheus 4 5 在K8S中部署Grafana与可视化 ...
- kubernetes系列06—kubernetes资源清单定义入门
本文收录在容器技术学习系列文章总目录 1.认识kubernetes资源 1.1 常用资源/对象 workload工作负载型资源:pod,ReplicaSet,Deployment,StatefulSe ...
- 使用kubesql进行kubernetes资源查询
kubesql kubesql(https://github.com/xuxinkun/kubesql)是我最近开发的一个使用sql查询kubernetes资源的工具.诸如node,pod等kuber ...
- Transaction And Lock--使用资源锁来控制并发
写过程序的朋友都知道,在多线程处理时,对于非线程安全的对象,需用使用锁定特定对象(LOCK)的方法来保证串行操作.曾经有位开发询问我,在SQL Server内部是否有类似的实现方法来控制某一操作不能并 ...
- 新手学习FFmpeg - 如何编写Kubernetes资源文件
Kubernetes API的使用方式 Kubernetes API属于声明式API编程, 它和常用的命令式编程有一些区别. 通俗的说,命令式编程是第一人称,我要做什么,我要怎么做. 操作系统最喜欢这 ...
- 深入理解 Kubernetes 资源限制:CPU
原文地址:https://www.yangcs.net/posts/understanding-resource-limits-in-kubernetes-cpu-time/ 在关于 Kubernet ...
- kubefuse 让Kubernetes 资源成为fuse 文件系统
kubefuse 是基于fuse 开发的文件系统,我们可以像访问文件系统一样访问Kubernetes 资源,使用python开发 支持以下特性: 可以使用方便的linux tools: ls. vim ...
随机推荐
- BurpSuite与Xray多级代理实现联动扫描
Xray是长亭科技推出的,最经典的莫过于代理模式下的被动扫描,它使得整个过程可控且更加精细化: 代理模式下的基本架构为,扫描器作为中间人,首先原样转发流量,并返回服务器响应给浏览器等客户端,通讯两端都 ...
- 论文阅读 Continuous-Time Dynamic Network Embeddings
1 Continuous-Time Dynamic Network Embeddings Abstract 描述一种将时间信息纳入网络嵌入的通用框架,该框架提出了从CTDG中学习时间相关嵌入 Co ...
- 我的树莓派 Raspberry Pi Zero 2W 折腾笔记,记录一些遇到的问题和解决办法
0x00 前言说明 最近买了一块Raspberry Pi Zero 2W来玩,目的是想搭建一台远程运行的个人服务器,上面放个博客.点个灯啥的.于是就有了这篇文章. 树莓派官网地址:https://ww ...
- ChCore Lab4 多核处理 实验笔记
本文为上海交大 ipads 研究所陈海波老师等人所著的<现代操作系统:原理与实现>的课程实验(LAB)的学习笔记的第四篇:多核处理.所有章节的笔记可在此处查看:chcore | 康宇PL' ...
- pandas子集选取的三种方法:[]、.loc[]、.iloc[]
pandas读取Excel.csv文件中的数据时,得到的大多是表格型的二维数据,在pandas中对应的即为DataFrame数据结构.在处理这类数据时,往往要根据据需求先获取数据中的子集,如某些列.某 ...
- Linux应急响应入门——入侵排查
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 账号安全: 1.用户信息文件 /etc/passwd # ...
- python+pytest接口自动化(15)-日志管理模块loguru简介
python自带日志管理模块logging,使用时可进行模块化配置,详细可参考博文Python日志采集(详细). 但logging配置起来比较繁琐,且在多进行多线程等场景下使用时,如果不经过特殊处理, ...
- this-2
读起来使你有新认识或可以使你离更确切的定义更近时的文章不应该被忽略.thisthis既不指向函数自身,也不指向函数的词法作用域(ES6中箭头函数采用词法作用域).this实际上是函数被调用时才发生绑定 ...
- ElasticSearch7.3学习(二十四)----相关度评分机制详解
1.算法介绍 relevance score(相关性分数) 算法,简单来说,就是计算出,一个索引中的文本,与搜索文本,他们之间的关联匹配程度.Elasticsearch使用的是 term freque ...
- 《Mybatis 手撸专栏》第8章:把反射用到出神入化
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么,读不懂框架源码? 我们都知道作为一个程序员,如果想学习到更深层次的技术,就需 ...