kube-apiserver准入
介绍k8s中的准入插件以及如何自定义mutating插件
前面介绍了认证和授权,接下来看看kube-apiserver的准入机制。准入控制过程分为两个阶段,第一阶段,运行变更准入控制器。第二阶段,运行验证准入控制器。注意,某些控制器既是变更准入控制器又是验证准入控制器。
kubenetes内置了很多准入控制器,具体如下所示
- AlwaysPullImages:此准入控制器修改每个 Pod 的时候都强制重新拉取镜像。
- DefaultStorageClass:此准入控制器观察创建PersistentVolumeClaim时不请求任何特定存储类的对象,并自动向其添加默认存储类。这样,用户就不需要关注特殊存储类而获得默认存储类。
- DefaultTolerationSeconds:此准入控制器将Pod的容忍时间notready:NoExecute和unreachable:NoExecute 默认设置为5分钟。
- DenyEscalatingExec:此准入控制器将拒绝exec 和附加命令到以允许访问宿主机的升级了权限运行的pod。
- EventRateLimit (alpha):此准入控制器缓解了 API Server 被事件请求淹没的问题,限制时间速率。
- ExtendedResourceToleration:此插件有助于创建具有扩展资源的专用节点。
- ImagePolicyWebhook:此准入控制器允许后端判断镜像拉取策略,例如配置镜像仓库的密钥。
- Initializers (alpha):Pod初始化的准入控制器,详情请参考动态准入控制。
- LimitPodHardAntiAffinityTopology:此准入控制器拒绝任何在 requiredDuringSchedulingRequiredDuringExecution 的 AntiAffinity 字段中定义除了kubernetes.io/hostname 之外的拓扑关键字的 pod 。
- LimitRanger:此准入控制器将确保所有资源请求不会超过 namespace 的 LimitRange。
- MutatingAdmissionWebhook (1.9版本中为beta):该准入控制器调用与请求匹配的任何变更 webhook。匹配的 webhook是串行调用的;如果需要,每个人都可以修改对象。
- NamespaceAutoProvision:此准入控制器检查命名空间资源上的所有传入请求,并检查引用的命名空间是否存在。如果不存在就创建一个命名空间。
- NamespaceExists:此许可控制器检查除 Namespace 其自身之外的命名空间资源上的所有请求。如果请求引用的命名空间不存在,则拒绝该请求。
- NamespaceLifecycle:此准入控制器强制执行正在终止的命令空间中不能创建新对象,并确保Namespace拒绝不存在的请求。此准入控制器还防止缺失三个系统保留的命名空间default、kube-system、kube-public。
- NodeRestriction:该准入控制器限制了 kubelet 可以修改的Node和Pod对象。
- OwnerReferencesPermissionEnforcement:此准入控制器保护对metadata.ownerReferences对象的访问,以便只有对该对象具有“删除”权限的用户才能对其进行更改。
- PodNodeSelector:此准入控制器通过读取命名空间注释和全局配置来限制可在命名空间内使用的节点选择器。
- PodPreset:此准入控制器注入一个pod,其中包含匹配的PodPreset中指定的字段,详细信息见Pod Preset。
- PodSecurityPolicy:此准入控制器用于创建和修改pod,并根据请求的安全上下文和可用的Pod安全策略确定是否应该允许它。
- PodTolerationRestriction:此准入控制器首先验证容器的容忍度与其命名空间的容忍度之间是否存在冲突,并在存在冲突时拒绝该容器请求。
- Priority:此控制器使用priorityClassName字段并填充优先级的整数值。如果未找到优先级,则拒绝Pod。
- ResourceQuota:此准入控制器将观察传入请求并确保它不违反命名空间的ResourceQuota对象中列举的任何约束。
- SecurityContextDeny:此准入控制器将拒绝任何试图设置某些升级的SecurityContext字段的pod
- ServiceAccount:此准入控制器实现serviceAccounts的自动化。
- 用中的存储对象保护:该StorageObjectInUseProtection插件将kubernetes.io/pvc-protection或kubernetes.io/pv-protection终结器添加到新创建的持久卷声明(PVC)或持久卷(PV)。在用户删除PVC或PV的情况下,PVC或PV不会被移除,直到PVC或PV保护控制器从PVC或PV中移除终结器。有关更多详细信息,请参阅使用中的存储对象保护。
- ValidatingAdmissionWebhook(1.8版本中为alpha;1.9版本中为beta):该准入控制器调用与请求匹配的任何验证webhook。匹配的webhooks是并行调用的;如果其中任何一个拒绝请求,则请求失败。
查看已经开启的准入控制器(kube-apiserver -h | grep enable-admission-plugins)
还可以通过如下命令开启或者关闭某个准入控制器
kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ...
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
除默认的控制插件外,kubernetes还支持自定义准入控制插件,用户可自定义变形插件(MutatingWebhookConfiguration)和校验插件(ValidatingWebhookConfiguration),变形插件支持对准入对象进行修改,校验插件支持对准入的对象合法性进行校验,不能修改。接下来就看看如何自定义一个MutatingWebhook,MutatingWebhook的demo代码请看这里。
以下是Webhook服务中mutating逻辑主要代码,可以看到如果创建pod时没有指定runAsNonRoot和runAsUser,那么runAsUser会被mutating成1234,如果设置runAsRoot=false,那么runAsUser会被这只为0,如果runAsNonRoot设置为true且runAsUser设置为0,那么会报错。
在上面的demo代码的examples的目录下有三个pod文件,用于验证上面的webhook mutating逻辑。pod的yaml文件如下所示:
pod-with-default yaml file
未设置runAsNonRoot和runAsUser,pod创建后,会显示I am running as user 1234
apiVersion: v1
kind: Pod
metadata:
name: pod-with-defaults
labels:
app: pod-with-defaults
spec:
restartPolicy: OnFailure
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "echo I am running as user $(id -u)"]
pod-with-override yaml file
runAsNonRoot设置为false,未设置runAsUser值,启动pod后,会显示I am running as user 0
apiVersion: v1
kind: Pod
metadata:
name: pod-with-override
labels:
app: pod-with-override
spec:
restartPolicy: OnFailure
securityContext:
runAsNonRoot: false
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "echo I am running as user $(id -u)"]
pod-with-conflict yaml file
runAsNonRoot设置为true,且runAsUser设置为0,启动pod时会报错,无法成功创建pod
apiVersion: v1
kind: Pod
metadata:
name: pod-with-conflict
labels:
app: pod-with-conflict
spec:
restartPolicy: OnFailure
securityContext:
runAsNonRoot: true
runAsUser: 0
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "echo I am running as user $(id -u)"]
接下来将演示上面的过程,看看是否如预期的一样。
1.下载代码
2.执行deploy.sh 脚本
cd admission-controller-webhook-demo/
./deploy.sh
3.查看web-hook服务是否已经启动,如果已经启动,那么通过kubectl create -f podYamlFile创建上面三种类的pod。执行部署shell脚本后,可以看到webhook服务已经成功启动
创建pod,可以看到default pod创建成功后,查看log信息,user被设置为1234,创建conflict pod,创建失败,显示错误信息。
创建override pod,user被设置为0.
以上pod创建过程的信息说明webhook按期望的逻辑执行。 接着我们看看deploy.sh文件中具体是如何完成部署的,具体内容如下所示:可以看到部署文件中将ca.crt进行base64编码后放到部署的template文件中,另外,创建了secret,里面存放了webhook的crt和key信息。
一下是generatekey.sh文件,可以看到主要是通过openssl创建了ca的key和crt,webhook server的key和crt,并存放到相应目录。通过这些配置,就可以通过https的方式访问webhook的服务了。
最后再来看看pod部署的template文件,可以看到在Deployment文件中设置了secret信息,也就是签发给webhook服务的证书信息,另外,在webhookmutatingconfiguration中设置了证书签发机构的crt信息,即ca.crt信息。
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-server
namespace: webhook-demo
labels:
app: webhook-server
spec:
replicas: 1
selector:
matchLabels:
app: webhook-server
template:
metadata:
labels:
app: webhook-server
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1234
containers:
- name: server
image: cncamp/admission-controller-webhook-demo:latest
imagePullPolicy: Always
ports:
- containerPort: 8443
name: webhook-api
volumeMounts:
- name: webhook-tls-certs
mountPath: /run/secrets/tls
readOnly: true
volumes:
- name: webhook-tls-certs
secret:
secretName: webhook-server-tls
---
apiVersion: v1
kind: Service
metadata:
name: webhook-server
namespace: webhook-demo
spec:
selector:
app: webhook-server
ports:
- port: 443
targetPort: webhook-api
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: demo-webhook
webhooks:
- name: webhook-server.webhook-demo.svc
sideEffects: None
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
service:
name: webhook-server
namespace: webhook-demo
path: "/mutate"
caBundle: ${CA_PEM_B64}
rules:
- operations: [ "CREATE" ]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
更多推荐
所有评论(0)