千家信息网

kubernetes Admission Controller 原理介绍

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,Admission Controller介绍Apiserver干的最重要的三个事就是:认证 : 看是否是合法用户授权 : 看用户具备哪些权限admission controller : 一个调用链,对
千家信息网最后更新 2026年11月03日kubernetes Admission Controller 原理介绍

Admission Controller介绍

Apiserver干的最重要的三个事就是:

  1. 认证 : 看是否是合法用户
  2. 授权 : 看用户具备哪些权限
  3. admission controller : 一个调用链,对请求进行控制或修改,比如是否允许这个请求。

admission controller非常有用,也是经常会用到的k8s的一个扩展方式,今天在源码级别对其做一下介绍,以及如何自己去开发一个admission controller.

我们的应用场景是:我们希望把所有需要创建的pod都加上一个注解,因为我们早期是通过podpreset给pod注入lxcfs的配置的,但是用户在写yaml文件时很容易忘记加上,所以需要在apiserver上来个自动处理

metadata:  name: test-net  annotations:    initializer.kubernetes.io/lxcfs: "true"   # 就是在pod的metadata里加上这个配置

默认admission controller

已经有很多默认非常有用的admission插件,这里挑几个介绍一下:

名称作用
AlwaysPullImages把所有镜像策略都调整成alwaysPull, 多租户安全时比较有用
DefaultStorageClass默认存储类型
DefaultTolerationSeconds节点notready:NoExecute时的容忍时间,比如有时我们升级kubelet,希望升级时pod不要漂移就会用到
DenyEscalatingExec拒绝远程连接容器
ExtendedResourceToleration比如我有扩展资源,那么我可以通过它来玷污节点,防止不需要该资源的pod到我的机器上来,如GPU
LimitRanger在多租户配额时相当有用,如果pod没配额,那么我可以默认给个很低的配额
NamespaceAutoProvision这个也非常有用,资源的namespace不存在时就创建一个
PodPreset可以对pod进行一些预处理设置
ResourceQuota多租户配额时比较重要,看资源是否满足resource quota中的配置

alwaysPullImages 介绍

多租户时经常会开启这个,强制所有的镜像必须去拉取,因为如果不这样,那么别的租户如果知道了你的镜像名就可以写一个yaml去启动你的镜像,强制拉时犹豫需要image pull secret所以无法拉取你的镜像。

所以这个admission干的事就是把镜像拉取策略都改成alwaysPull:

代码位置:

kubernetes/plugin/pkg/admission/alwayspullimages/admission.gofunc (a *AlwaysPullImages) Admit(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) {    // 你可以在attibutes里获取到对象的一切信息,用户信息等    if shouldIgnore(attributes) { // 检查一下是不是你关注的object, 比如创建的一个configmap 那么显然可以忽视        return nil    }    pod, ok := attributes.GetObject().(*api.Pod)    // 这里把initContainer和Container的拉取策略都给改了    for i := range pod.Spec.InitContainers {        pod.Spec.InitContainers[i].ImagePullPolicy = api.PullAlways    }    for i := range pod.Spec.Containers {        pod.Spec.Containers[i].ImagePullPolicy = api.PullAlways    }    return nil}# 还提供一个校验接口,看是不是真的都已经被改了func (a *AlwaysPullImages) Validate(attributes admission.Attributes, o admission.ObjectInterfaces) (err error) {    pod, ok := attributes.GetObject().(*api.Pod)    for i := range pod.Spec.InitContainers {        if pod.Spec.InitContainers[i].ImagePullPolicy != api.PullAlways {            return admission.NewForbidden(attributes,                field.NotSupported(field.NewPath("spec", "initContainers").Index(i).Child("imagePullPolicy"),                    pod.Spec.InitContainers[i].ImagePullPolicy, []string{string(api.PullAlways)},                ),            )        }    }    ...    return nil}

然后实现一个注册函数:

func Register(plugins *admission.Plugins) {    plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {        return NewAlwaysPullImages(), nil    })}type AlwaysPullImages struct {    *admission.Handler}

最后需要在plugin里面把其注册进去:

kubernetes/pkg/kubeapiserver/options/plugins.gofunc RegisterAllAdmissionPlugins(plugins *admission.Plugins) {    imagepolicy.Register(plugins)    ...}

所以实现一个admission非常简单,主要就是实现两个接口即可。

admission control webhooks

很多情况下我们并不希望大动干戈去改apiserver代码,所以apiserver提供了一种动态扩展admission的方式,非常推荐。

有两种类型:

  1. validating admission Webhook 只作校验,比如检测到某个特殊字段就不让请求通过
  2. mutating admission webhook 可以对请求体进行修改(patch)

比较重要的是这个AdmissionReview结构体,包含一个请求一个响应

请求:有Object的详细信息,用户信息
响应: 最重要的是 1. 是否允许 2. 修改(patch)的类型 3. 修改(patch)的值, 这个符合json patch标准 (kubectl patch)

可在此 找到一个webhook server的例子

看一个具体例子,labelpatch,是给对象的元数据里加一些label的。

const (    // 特定的json patch格式    addFirstLabelPatch string = `[         { "op": "add", "path": "/metadata/labels", "value": {"added-label": "yes"}}     ]`    addAdditionalLabelPatch string = `[         { "op": "add", "path": "/metadata/labels/added-label", "value": "yes" }     ]`)// Add a label {"added-label": "yes"} to the objectfunc addLabel(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {    obj := struct {        metav1.ObjectMeta        Data map[string]string    }{}    raw := ar.Request.Object.Raw    err := json.Unmarshal(raw, &obj)    if err != nil {        klog.Error(err)        return toAdmissionResponse(err)    }    reviewResponse := v1beta1.AdmissionResponse{}    reviewResponse.Allowed = true    if len(obj.ObjectMeta.Labels) == 0 {        reviewResponse.Patch = []byte(addFirstLabelPatch) // 这里最需要注意的就是修改时是通过patch的方式    } else {        reviewResponse.Patch = []byte(addAdditionalLabelPatch)    }    pt := v1beta1.PatchTypeJSONPatch    reviewResponse.PatchType = &pt    return &reviewResponse}

把这个放到http handle里。

把这个HTTPS服务起一个service, 这样apiserver就可以自动发现它。

apiVersion: admissionregistration.k8s.io/v1beta1kind: ValidatingWebhookConfigurationmetadata:  name: webhooks:- name:   rules:                                            # 最好明确一下该hook关心哪些api,防止带来不必要的额外开销。  - apiGroups:    - ""    apiVersions:    - v1    operations:    - CREATE    resources:    - pods    scope: "Namespaced"  clientConfig:    service:      namespace:   # webhook server的namespace      name:             # service name    caBundle:  # 因为需要通过https访问,所以要给apiserver配置ca  admissionReviewVersions:  - v1beta1  timeoutSeconds: 1

总结

adminssion control 是非常重要的APIserver扩展的方式,掌握了其开发很多地方就能以比较优雅的方式解决一些实际问题。是基于k8s开发PaaS平台的利器

更多精彩: https://sealyun.com

镜像 重要 就是 方式 有用 用户 租户 信息 资源 配额 配置 策略 类型 开发 代码 例子 对象 常会 接口 节点 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司经营范围 广州百单互联网科技有限公司 厦门中拓互联网络科技有限公司 互联网 科技 上海挚品互联网科技 亿账通互联网科技 滨湖区互联网智能科技产品供应 恒生科技互联网指数分析 太原新华互联网科技学校怎么样 北京大学互联网科技怎么样 互联网企业和科技型企业 广州恒生互联网科技有限 新兴科技互联网创新大赛颁奖典礼 注册互联网科技公司经营范围大全 中国互联网十大科技股排名 元气玛特互联网科技公司是外包吗 黑科技 体验场景 互联网大会 电子商务与互联网科技的关系 互联网科技创业计划的风险分析 银川新华互联网科技学校招聘 新华互联网科技学院 互联网科技小贷 西藏七维空间互联网科技有限公司 民营互联网公司国防科技 互联网科技快讯热点 半导体是互联网高科技吗 江苏互联网科技小贷 福建互联网展示科技馆设计 中国科技和美国互联网 科技美学互联网 艺术
0