一、集群环境
底层系统为ubuntu18.04,然后在每个node上安装k8s,并构建集群。Master node的IP地址为192.168.26.71/24,两个Worker node的IP地址为192.168.26.72/24、192.168.26.73/24。部署Calico网络插件,保证Node之间能够正常通信。
二、准入控制器
1.什么是准入控制器
kube-apiserver是Kubernetes集群的中心,集群中所有资源的创建和更新都是通过APIServer的Restful API实现的。 因此Kubernetes通过一系列的机制来保证APIServer的安全,包括APIServer的认证、授权以及本文中我们会使用的准入控制Admission Control。上图是APIServer被访问控制的过程,在经过认证和授权之后就进入了准备控制Admission Control。
认证的操作请查看:https://blog.csdn.net/tushanpeipei/article/details/121877797?spm=1001.2014.3001.5501
授权的操作请查看:https://blog.csdn.net/tushanpeipei/article/details/121894874?spm=1001.2014.3001.5501
准入控制器可以理解为功能开关,可以启用或者关闭。其包含的类型有很多,包括了之前笔记中提到的:
- Pod 安全策略(Pod Security Policy)
- OPA (Open Policy Agent)规则
- NodeRestriction
在我们环境中kube-apiserver是通过容器执行的。所以我们可以使用如下的命令查看准入控制器的相关内容:
kubectl exec -it -n kube-system kube-apiserver-vms71.rhce.cc -- kube-apiserver -h | grep enable-admission-plugins
在其显示的信息中,我们可以看到在当前版本中默认开启的准入控制分别是:
CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, LimitRanger, MutatingAdmissionWebhook, NamespaceLifecycle, PersistentVolumeClaimResize, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook
2.如何开启和关闭对应的准入控制器
kube-apiserver的 enable-admission-plugins 标志接受一个用于在集群修改对象之前 调用的(以逗号分隔的)准入控制插件顺序列表。
例如,下面的命令就启用了 NamespaceLifecycle 和 LimitRanger 准入控制插件。首先编辑kube-apiserver.yaml文件:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
在command一栏下找到 --enable-admission-plugins=,添加自己想要开启的准入控制器。例如,下面的命令就启用了 NamespaceLifecycle 和 LimitRanger 准入控制插件:
--enable-admission-plugins=NamespaceLifecycle,LimitRanger
同样的,要想关闭默认启用的准入控制器插件,可以同样在command一栏下,找到–disable-admission-plugins,然后设置准备关闭的插件,例如,如下命令就跟关闭了PodNodeSelector和AlwaysDeny插件。
--disable-admission-plugins=PodNodeSelector,AlwaysDeny
3.每个准入控制器的作用是什么?
请查看官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/#每个准入控制器的作用是什么
4.整理创建pod调度的过程
- 用户通过可视化或者kubectl命令连接到kube-apiserver。kube-apiserver判断用户是否登录,是否有权限(认证和授权);
- 各种准入控制检测此创建pod请求的的合法性。如果请求符合各种准入控制器规则,则允许此请求,否则直接拒绝;
- 通过后准入控制器规则后,kubelet或者scheduler通过watch权限能够看到pod的状态为pending;
- schduler会通过主机排除、打分决定该pod运行在哪个worker node上;
- kubelet开始运行pause容器,创建相关的PID命名空间、网络命名空间等;
- pod被创建出来。
三、举例一:ResourceQuota准入控制器
ResourceQuota是默认开启的准入控制器插件,可以帮助我们限制K8s的资源配额。例如,我们使用如下yaml文件创建一个ResourceQuota准入控制器,限制只能创建2个pod:
apiVersion: v1
kind: ResourceQuota
metadata:
name: myrq
spec:
hard:
pods: "2"
查看所部署的ResourceQuota:
root@vms71:~/admission-controllers# kubectl get resourcequotas
NAME AGE REQUEST LIMIT
myrq 36s pods: 0/2
然后我们使用deployment同时部署3个pod,deployment的yaml文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app1: web1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app1: web1
app2: web1
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
resources: {}
应用后可以看到如下的结果:3个pod仅能启用两个,说明我们ResourceQuota准入控制器部署成功。
root@vms71:~/admission-controllers# kubectl get deployments.apps web1
NAME READY UP-TO-DATE AVAILABLE AGE
web1 2/3 2 2 10s
root@vms71:~/admission-controllers# kubectl get resourcequotas
NAME AGE REQUEST LIMIT
myrq 12m pods: 2/2
四、举例二:ImagePolicyWebhook准入控制器
ImagePolicyWebhook 准入控制器允许使用一个后端的 webhook 做出准入决策。
1.部署webhook服务器
使用集群外的另外一台Linux设备作为webhook服务,并在设备上安装好docker。下载一个已经内置规则的webhook服务器镜像:
docker pull flavio/kube-image-bouncer
这个webhook服务器所实现的规则是不允许我们我们使用最新的镜像来部署容器。然后通过此镜像生成webhook服务器容器(这里没有生成和使用对应的证书,测试环境中可能会报错,所以后续kube-apiserver直接通过http来访问webhook服务器):
docker run -dit --name=c1 --restart=always -v `pwd`/webhook-key.pem:/certs/webhook-key.pem:ro -v `pwd`/webhook.pem:/certs/webhook.pem:ro -p 1323:1323 flavio/kube-image-bouncer
查看是否部署完成:
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b1b092ebd6b9 flavio/kube-image-bouncer "./kube-image-bouncer" About a minute ago Up About a minute 0.0.0.0:1323->1323/tcp c1
可以看到,已经部署成功。当我们访问这台设备(192.168.26.130)的1323端口时,也就访问到这个服务器了。
2.在K8s上启用ImagePolicyWebhook准入控制器
在master上修改/etc/kubernetes/manifests/kube-apiserver.yaml文件,启用ImagePolicyWebhook:
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
接下来,我们需要编辑ImagePolicyWebhook的配置文件中,ImagePolicyWebhook 使用配置文件来为后端服务器设置配置选项。该文件可以是 JSON 或 YAML,例如:
root@vms71:/etc/kubernetes/aa# cat admission_configuration.yaml
imagePolicy:
# 指定kubeconfig的位置
kubeConfigFile: /etc/kubernetes/aa/kubeconfig.yaml
# 以秒计的时长,控制批准请求的缓存时间
allowTTL: 50
# 以毫秒计的时长,控制重试间隔
denyTTL: 50
# 确定 Webhook 后端失效时的行为
retryBackoff: 500
# 默认是允许的规则
defaultAllow: true
ImagePolicyWebhook 的配置文件必须引用 kubeconfig 格式的文件;该文件设置了到后端的连接参数、证书等信息(本实验中没有),如:
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/aa/webhook.pem
server: http://192.168.26.130:1323/image_policy
name: bouncer_webhook
contexts:
- context:
cluster: bouncer_webhook
user: api-server
name: bouncer_validator
current-context: bouncer_validator
preferences: {}
users:
- name: api-server
user:
client-certificate: /etc/kubernetes/aa/apiserver-client.pem
client-key: /etc/kubernetes/aa/apiserver-client-key.pem
其中server: http://192.168.26.130:1323/image_policy指定了我们通过http连接到webhook服务器的1323端口。由于不是使用https的方式,其他的证书相关的内容,其实这里没有作用了。然后,我们还需要在kube-apiserver中指定ImagePolicyWebhook所使用的配置文件。同样在/etc/kubernetes/manifests/kube-apiserver.yaml文件中的command下,添加如下的信息即可:
- --admission-control-config-file=/etc/kubernetes/aa/admission_configuration.yaml
由于我们kube-apiserver以容器方式运行。而我们webhook相关的文件存放在宿主机上,所以要做一个挂载卷,将这些文件映射到容器中的相同目录下,同样编辑/etc/kubernetes/manifests/kube-apiserver.yaml文件,增加如下内容:
volumeMounts:
- mountPath: /etc/kubernetes/aa
name: aa
readOnly: true
volumes:
- hostPath:
path: /etc/kubernetes/aa
type: DirectoryOrCreate
name: aa
重启kubelet:
systemctl restart kubelet.service
3.测试能否使用latest的镜像部署pod
root@vms71:/etc/kubernetes/aa# kubectl run pod1 --image=nginx --image-pull-policy=IfNotPresent
Error from server (Forbidden): pods "pod1" is forbidden: image policy webhook backend denied one or more images: Images using latest tag are not allowed
可以看到,当我们尝试使用最新的nginx镜像创建pod时,会提示报错信息,告知我们不能够使用带有latest tag的镜像。说明webhook准入控制已经部署成功。
整理资料来源:
K8s admission-controllers: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
《老段CKS课程》