k8s 基于MutatingWebhookConfiguration实现node超卖和sidecar注入
源码在:https://github.com/Seaiii/MutatingWebhook我写了几个脚本,可以直接运行。
一、MutatingWebhookConfiguration原理
MutatingWebhookConfiguration 是 Kubernetes 中的一种资源对象,用于配置 Mutating Admission Webhook。Mutating Admission Webhook 是一种 Kubernetes 的扩展机制,用于在对象被持久化到 etcd 存储之前,对其进行动态修改或补充。
MutatingWebhookConfiguration 定义了一个或多个 Mutating Admission Webhook 的配置信息,包括 Webhook 的 URL、服务名称、路径等。当 Kubernetes API Server 接收到创建、更新或删除对象的请求时,它将触发适用于该对象类型的 Mutating Admission Webhook。
Mutating Admission Webhook 在对象持久化之前,对对象进行拦截并进行修改或补充。它可以在不改变原始请求的情况下,通过返回修改后的对象副本来实现动态的对象转换。这使得用户能够通过自定义的逻辑对 Kubernetes 对象进行自动化的修改,例如自动注入额外的标签、注解、容器、卷等。
MutatingWebhookConfiguration 的工作原理如下:
创建 MutatingWebhookConfiguration 对象并将其提交到 Kubernetes 集群。这个对象定义了一个或多个 Mutating Admission Webhook 的配置。
Kubernetes API Server 在接收到创建、更新或删除对象的请求时,会检查适用于该对象类型的 Mutating Admission Webhook 配置。
Kubernetes API Server 将请求发送到 Mutating Admission Webhook 的 Webhook URL。
Mutating Admission Webhook 接收到请求后,根据预定义的逻辑对请求中的对象进行修改或补充,并生成修改后的对象副本。
Mutating Admission Webhook 将修改后的对象副本作为响应返回给 Kubernetes API Server。
Kubernetes API Server 使用修改后的对象副本进行后续的持久化操作。
MutatingWebhookConfiguration 和 Mutating Admission Webhook 提供了一种可扩展的方式,允许用户根据自定义的业务需求对 Kubernetes 对象进行自动化修改。这在实践中被广泛应用于诸如自动注入 sidecar、自动配置密钥等场景中。
二、超卖/sidecar思路
1.场景
超卖的场景可以很容易避免。只要设置了resource最低和适当的limits,就可以避免超卖。但是有种场景就是用户不知道这个值,本来1M内存使用量,但是设置了resource为3M。这样就导致pod占用了3M的内存,然而有2M是闲置状态。这时候就可以使用动态超卖来把那浪费的2M内存使用出来
2.思路
节点Node的Status种有两个字段,分别是Allocatable(可分配)和Capacity(总量)结构体。实现资源超卖的关键在于动态修改节点Node对象的allocatable字段值。如果使用clinet-go动态的修改这个字段,是无法实现的。因为修改后只是短暂的,Node资源对象比较特殊,计算节点会不断给ApiServer发送心跳(默认每隔10s发一次),将带有Status字段的真实信息发送给ApiServer,并更新到etcd中。也就是无论你怎么通过patch/put方法去修改Node的Status字段,计算节点都会定时通过发送心跳将真实的Status数据覆盖你修改的数据,也就是说我们无法通过直接调用RESTful API修改Node对象中的Status数据。所以这时候需要引入MutatingWebhookConfiguration资源对象,在apiserver发送给etcd之前,会先发送给MutatingWebhookConfiguration。然后通过我们注册的回调函数,来修改status,在发送给etcd,骗过etcd。
三、实现MutatingWebhookConfiguration
可以简单介绍下MutatingWebhookConfiguration流程步骤
流程步骤介绍:我们需要创建service、MutatingWebhookConfiguration、deployment来实现流程。当apiserver发起心跳后,在MutatingWebhookConfiguration中rule注册的规则中会触发。然后通过MutatingWebhookConfiguration中的service触发到我们的service,通过service转发到deployment的pod,然后实现回调。
这三个yaml在github中都有存在。
1.需要修改api-server的配置。如果是kubeadm安装的,可以如下修改
vi /etc/kubernetes/manifests/kube-apiserver.yaml
修改以下配置开启MutatingAdmissionWebhook。
- --enable-admission-plugins=NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
2.配置签名证书
github中的cfssl.sh已经帮助生产证书(要修改以下你的apiserver的ca位置)
#生成key,用k8s的ca证书进行签名,注意:-ca和-ca-key=的目录是你k8s的master主机存放CA文件的位置
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -hostname=webhook.default.svc -profile=server server-csr.json | cfssljson -bare server
生成证书后需要生成secret资源,后续deployment需要挂载这个secret
kubectl create secret tls admission-registry-tls --key=server-key.pem --cert=server.pem
3.生成必要的三个yaml
github中的statr.sh脚本中可以快速运行pod并触发node更新操作。(要修改以下你本机的deployment位置)
MutatingWebhookConfiguration.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: demo-webhook
webhooks:
- sideEffects: None
admissionReviewVersions:
- v1
- v1beta1
name: webhook.default.svc
clientConfig:
service:
name: webhook#你的server服务的名字
namespace: default
path: "/webhook"
caBundle: #这个是你的k8s集群的的ca证书base64加密后的值。可以使用“kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}'”获取
rules:
- operations: [ "UPDATE" ]
apiGroups: [ "*" ]
apiVersions: [ "v1" ]
resources: [ "nodes/status"]
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-example-deployment
labels:
app: webhook-example
spec:
replicas: 1
selector:
matchLabels:
app: webhook-example
template:
metadata:
labels:
app: webhook-example
spec:
nodeName: k8s-master
containers:
- name: webhook-example
image: webhook-example:20230517-144113
command: [ "/node" ]
ports:
- containerPort: 8443
name: webhook-api
args:
- -v=4
- -log_dir=log -alsologtostderr
volumeMounts:
- name: webhook-certs
mountPath: /etc/webhook/certs
readOnly: true
- name: kubeconfig
mountPath: /etc/
volumes:
- name: webhook-certs #这个是上面生成的secret
secret:
secretName: admission-registry-tls
- name: kubeconfig
hostPath:
path: /root/.kube/ #这个要改成你本地的kubeconfig的位置,用于client-go的客户端连接
type: Directory
service.yaml
apiVersion: v1
kind: Service
metadata:
name: webhook
labels:
app: admission-webhook-example
spec:
ports:
- port: 443
targetPort: webhook-api
selector:
app: webhook-example
执行github中的start.sh可以一步生成,或者你可以根据里面的步骤手动生成,我都做了注释。
**注:**我们需要获得node的实际使用量,所以需要Metrics,需要跑起来这个pod,后续的代码中才可以使用这个Metrics客户端。百度下载components.yaml执行即可了(可以百度获取很多)。
四、代码实现
1.代码的逻辑很简单,创建server接受https请求,需要tls校验证书。
cert, err := tls.LoadX509KeyPair("/etc/webhook/certs/tls.crt", "/etc/webhook/certs/tls.key")
if err != nil {
glog.Errorf("get cert fail.err is :", err)
panic(err)
}
// Creating a TLS Configuration
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
}
// Create an HTTP server
server := &http.Server{
Addr: ":8443",
TLSConfig: tlsConfig,
}
// start services
http.Handle("/webhook", New(&applyNode{}))
client.NewClientK8s()
if err := server.ListenAndServeTLS("", ""); err != nil {
glog.Errorf("server start fail,err is:", err)
panic(err)
}
2.证书校验成功后,将收到apiserver发过来的消息,对接受消息进行校验,并拿到Node.Status.Capacity的值和MetricsApi的值
//...省略
node := corev1.Node{}
obj, _, err := Codecs.UniversalDecoder().Decode(admissionReviewReq.Request.Object.Raw, nil, &node)
//...省略
if _, ok := obj.(*corev1.Node); ok {
bytes, err = nodePatch(admissionReviewReq, node)
}
3.拿到我们该有的数据后,做校验和自己的业务就可以了。
全部代码在github中。感兴趣的可以给个stat文章来源:https://www.toymoban.com/news/detail-660774.html
五、sidecar注入pod
代码中并没有介绍sidecar模式,其实看到这里相信也都明白原理了,只要在MutatingWebhookConfiguration.yaml中的resources中加入“pods”,operations加入“CREATE”即可。这样当pod有创建时候,就会调用MutatingWebhookConfiguration的回调。文章来源地址https://www.toymoban.com/news/detail-660774.html
到了这里,关于k8s 基于MutatingWebhookConfiguration实现node超卖和sidecar注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!