Kubernetes控制平面组件:APIServer 准入控制机制详解
云原生学习路线导航页(持续更新中)
- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes架构原则和对象设计(三)
- Kubernetes控制平面组件:etcd(一)
- Kubernetes控制平面组件:etcd(二)
- Kubernetes控制平面组件:etcd常用配置参数
- Kubernetes控制平面组件:etcd高可用集群搭建
- Kubernetes控制平面组件:etcd高可用解决方案
- Kubernetes控制平面组件:Kubernetes如何使用etcd
- Kubernetes控制平面组件:API Server详解(一)
本文主要对kubernetes的控制面组件API Server 的准入控制进行详细介绍,涵盖准入控制的基础概念、与认证授权的辨析、常见插件、自定义插件开发流程、mutatingwebhookconfigurations实操案例等
- 希望大家多多 点赞 关注 评论 收藏,作者会更有动力编写技术文章
1.什么是准入控制
2.认证、鉴权、准入 辨析
- 认证
- 认证是知道是哪个用户/group,判断请求身份
- 鉴权
- 鉴权是判断该用户是否有权限进行该操作,判断操作权限
- 准入
- 准入是对请求的具体内容进行处理,判断请求内容的合法性,还可以对请求内容进行变形、校验
3.准入控制插件
-
使用apiserver启动参数:
--enable-admission-plugins
指定开启插件
-
AlwaysPullImages:强制所有新创建的 Pod 始终拉取最新版本的容器镜像,覆盖用户显式设置的
spec.imagePullPolicy
策略,统一设置为 Always。imagePullPolicy有3种值:- Always:总是尝试拉取最新的镜像,即使集群中已经存在该image。拖慢效率,但能保证每次使用的都是最新镜像
- IfNotPresent:如果集群中已经存在该image,就直接使用。效率高,但是如果本地image被人改过只是tag保持一致,就会出现误用。
- Never:从不远程拉取,本地有就用,本地没有就起不来
-
ImagePolicyWebhook:可以用webhook对image进行更多的控制,比如安全层面控制,判断下image是否通过了安全扫描,是否出具了安全报告等等
4.怎么查看有哪些准入插件被开启?
- 查看默认开启的插件
- 在 apiserver pod中执行命令:kube-apiserver --help,即可查看默认值
- 其中
--enable-admission-plugins
的default enabled ones
就是默认开启的插件
kubectl exec -it kube-apiserver-vm-226-235-tencentos -n kube-system -- kube-apiserver -h | grep enable-admission-plugins --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only validating admission plugins run. The names in the below list may represent a validating plugin, a mutating plugin, or both. The order of plugins in which they are passed to this flag does not matter. Comma-delimited list of: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyEscalatingExec, DenyExecOnPrivileged, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodPreset, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. (DEPRECATED: Use --enable-admission-plugins or --disable-admission-plugins instead. Will be removed in a future version.) --enable-admission-plugins strings admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyEscalatingExec, DenyExecOnPrivileged, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodPreset, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.
- 查看有哪些被主动开启
ps -ef | grep apiserver,查看--enable-admission-plugins
即可
5.准入控制插件开发
- 自定义准入控制插件,生效流程:
- 首先使用 MutatingWebhookConfiguration/ValidatingWebhookConguration 声明第三方准入服务的url、caBundle、rules等信息
- 其次,apiserver在处理请求时,通过webhook的rules判断是否需要调用某一个webhook指定的第三方准入服务。
- 如果需要调用,apiserver就会封装请求为AdmissionReview结构发给 第三方准入服务AdmissionController
- AdmissionController处理之后,返回响应给apiserver
- apiserver根据响应判断是否通过 准入验证
- Apiserver 的配置文件参数:
--admission-control-config-file
- 在开启ImagePolicyWebhook或EventRateLimit时,通过该参数指定webhook的配置
- 该配置与MutatingWebhookConfiguration/ValidatingWebhookConguration并无直接合作关系
注:apiserver只会以https的方式请求webhook,所以每一个MutatingWebhookConfiguration/ValidatingWebhookConguration都要配置caBundle
6.准入控制实践案例
6.1.多租户下控制ns只能被指定用户访问
- 在多租户系统设计中,我们可通过准入控制,在ns create阶段自动为ns绑定用户权限,实现:只有指定用户才可以访问某个ns。具体实现如下:
- 在ns创建时,通过一个mutatingwebhookconfigurations变形webhook插件,将用户信息写入ns的annotation
- 在访问ns下资源时,判断请求用户信息是否存在于ns的annotation,即可判断当前用户是否有权限访问该ns
- mutatingwebhookconfigurations编写如下
6.2.namespace的自动配额管理
- 比如:限制一个ns下configmap数量为1,那么当尝试在该ns下创建第2个cm时就会报错
7.mutatingwebhookconfigurations实操案例
参考:https://github.com/cncamp/101/blob/master/module6/mutatingwebhook/readme.MD
7.1.克隆mutatingwebhook demo项目
- 该项目会对 非kube-system、非kube-public ns下的所有pod做变形操作。变形操作如下。
- 项目地址:https://github.com/cncamp/admission-controller-webhook-demo
git clone https://github.com/cncamp/admission-controller-webhook-demo.git
7.2.Deploy webhook
- deploy.sh脚本,会先生成ca证书,将之写入secret中。然后创建deploy、secret、mutatingwebhookconfigurations等资源
- mutatingwebhookconfigurations 会读取到创建好的ca,写入自己的caBundle
cd admission-controller-webhook-demo/ ./deploy.sh
注:由于我们的mutatingwebhookconfigurations会拦截所有非kube ns下的pod创建行为,所以要在webhook deployment创建成功后再让mutatingwebhookconfigurations创建,否则可能会被拦截导致webhook的pod建不出来。这是一个时序问题
7.3.Check webhook status
- 检查webhook是否已经启动成功
k get deployment.apps/webhook-server -n webhook-demo k get po -n webhook-demo
7.4.Create demo pod and verify
- 创建一个默认的pod,nsdefault,没有配置SecurityContext,则说明 runAsNotRootnil、runAsUser==nil
- 该pod会被变形为 SecurityContext.runAsNotRoottrue、runAsUser1234
kubectl create -f examples/pod-with-defaults.yaml
kubectl get po pod-with-defaults -oyaml
kubectl logs -f pod-with-defaults
# A pod with no securityContext specified.
# Without the webhook, it would run as user root (0). The webhook mutates it
# to run as the non-root user with uid 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内部有 mkdir等需要root权限才能进行的行为,pod就会执行失败。比如:
7.5.More details
https://github.com/cncamp/admission-controller-webhook-demo/blob/main/README.md
常见问题解析
多个webhook如何执行?
参考:Webhook 的执行顺序
- 多个不同类型webhook:按照 mutatingwebhook -->validatingwebhook 顺序执行
- 多个相同类型webhook:会按照name字典排序顺序执行
- 一个mutatingwebhook/validatingwebhook内部指定列表:会按照列表给定顺序执行
- 设计理念
- 确定性:通过固定排序规则(如字典序),确保执行顺序在不同环境中一致,避免随机性导致行为不可预测。
- 无优先级干扰:Kubernetes 未提供显式的优先级配置字段,避免因复杂优先级规则引入运维复杂度。
- 原子性操作:每个 Webhook 的修改操作是独立的,后执行的 Webhook 可以看到前序 Webhook 的修改结果,因此顺序可能影响最终资源状态。
mutating/validating Webhook挂了是否会影响集群?
- 会的,如果mutating/validating Webhook本身挂了,所有依赖的请求准入都会超时,都会卡在这一步
- 因此mutating/validating Webhook本身也是需要高可用的
webhook编写有没有固定框架?
- 暂无固定框架,可以参考项目来写:https://github.com/cncamp/admission-controller-webhook-demo