很多情况下我们并不希望大动干戈去改apiserver代码,所以apiserver提供了一种动态扩展admission的方式,非常推荐。
有两种类型:
- validating admission Webhook 只作校验,比如检测到某个特殊字段就不让请求通过
- mutating admission webhook 可以对请求体进行修改(patch)
比较重要的是这个AdmissionReview结构体,包含一个请求一个响应
请求:有Object的详细信息,用户信息
响应: 最重要的是 1. 是否允许 2. 修改(patch)的类型 3. 修改(patch)的值, 这个符合json patch标准 (kubectl patch)
下面是lxcfs的例子
首先lxcfs的主要作用就是提升容器资源可见性,也就是说在容器里可以看到容器自身的cpu 内存等值,但是默认情况下 看到的是宿主机的值。所有应对一些程序需要获取到容器自身的cpu内存值到需求的话 就需要使用到lxcfs。
那么lxcfs的使用的方法就是通过挂载/var/lib/lxc/lxcfs/proc/到容器的/proc下,这样如果每个容器都需要写的话会非常麻烦,所以需要在pod创建的时候自动patch相关的配置。
目前有两个方法:
1.podpreset注入
2.Admission Controller webhook注入
我们这里讲下第二种
为什么要用第二种呢,原因很简单 第二种可以进行细粒度控制。并且podpreset只能patch ,而Admission Controller webhook 还可以做校验控制
如何使用?
根据自己的需求创建不同的webhook
如果是patch pod的话就创建mutating admission webhook
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: mutate
webhooks:
- name: admission-webhook.default.xhzy
rules:
- operations:
- CREATE
apiGroups:
- ""
apiVersions:
- v1
resources:
- pods
failurePolicy: Fail
clientConfig:
#用来校验服务的证书是否正确的CA证书(https的证书域名是admission-webhook.default.svc)
caBundle: #base64的ca证书
service:
namespace: default #请求的pod所在的namespace
name: admission-webhook #请求的service name
path: /mutating-pods #请求的url
那如何创建https的证书呢?
创建证书的注意点就是cn值为svc的地址,已经证书过期时间
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=admission-webhook.default.svc" -days 10000 -out ca.crt
openssl genrsa -out server.key 2048
cat << EOF >csr.conf
> [ req ]
> default_bits = 2048
> prompt = no
> default_md = sha256
> req_extensions = req_ext
> distinguished_name = dn
>
> [ dn ]
> C = cn
> ST = cn
> L = hangzhou
> O = xxx
> OU = xxxx
> CN = admission-webhook.default.svc
>
> [ req_ext ]
> subjectAltName = @alt_names
>
> [ alt_names ]
> DNS.1 = admission-webhook.default.svc
> IP.1 = 127.0.0.1
>
> [ v3_ext ]
> authorityKeyIdentifier=keyid,issuer:always
> basicConstraints=CA:FALSE
> keyUsage=keyEncipherment,dataEncipherment
> extendedKeyUsage=serverAuth,clientAuth
> subjectAltName=@alt_names
> EOF
openssl req -new -key server.key -out server.csr -config csr.conf
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial
那么主体就是代码逻辑了
如何实现呢,其实逻辑很简单 在创建MutatingWebhookConfiguration的时候我们需要指定的clientConfig.service
所以我们只需要定义
http.HandleFunc("/mutating-pods", serveMutatePods)
在serveMutatePods下里定义相关的逻辑
最后 返回AdmissionResponse对象
return &v1beta1.AdmissionResponse{
Allowed: true, #Allowed 决定此次请求是否准入
Patch: patchBytes, #如果是patch的话,此处为patch的值
PatchType: func() *v1beta1.PatchType { #patch的类型
pt := v1beta1.PatchTypeJSONPatch
return &pt
}(),
}
如果需要返回result的信息需要定义Result值:
v1beta1.AdmissionResponse{
Result: &metav1.Status{Message: fmt.Sprintf(
"Pod %v cannot delete for %v don't has ready Pod", pod.Name, utils.GetPodAppName(pod))}
}