资讯专栏INFORMATION COLUMN

kubernetes Admission Controller 原理介绍

AlphaWatch / 1554人阅读

摘要:介绍干的最重要的三个事就是认证看是否是合法用户授权看用户具备哪些权限一个调用链,对请求进行控制或修改,比如是否允许这个请求。把这个服务起一个这样就可以自动发现它。是基于开发平台的利器更多精彩

Admission Controller介绍

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

认证 : 看是否是合法用户

授权 : 看用户具备哪些权限

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.go

func (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.go

func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
    imagepolicy.Register(plugins)
    ...
}

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

admission control webhooks

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

有两种类型:

validating admission Webhook 只作校验,比如检测到某个特殊字段就不让请求通过

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 object
func 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/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
  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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/32986.html

相关文章

  • kubernetes Admission Controller 原理介绍

    摘要:介绍干的最重要的三个事就是认证看是否是合法用户授权看用户具备哪些权限一个调用链,对请求进行控制或修改,比如是否允许这个请求。把这个服务起一个这样就可以自动发现它。是基于开发平台的利器更多精彩 Admission Controller介绍 Apiserver干的最重要的三个事就是: 认证 : 看是否是合法用户 授权 : 看用户具备哪些权限 admission controller : ...

    Leo_chen 评论0 收藏0
  • Kubernetes taint & toleration

    摘要:对应的又给新增了配套属性容忍,用于表示这些可以但不强制要求被调度到具有相应的上。的默认值有几个特殊情况为空并且等于,表示匹配了所有的,和。用来指定在添加了的后,能容忍该的可停留在上的时间。目的是确保在出现或的问题时,永远不会被驱逐。 一、概述 前一篇文章讲解了 Kubernetes 亲和性调度, 所涉及的内容都是描述 pod 的属性,来声明此 pod 希望调度到哪类 nodes。而本文...

    wenzi 评论0 收藏0
  • 利用K8S技术栈打造个人私有云(连载之:K8S集群搭建)

    摘要:最近被业务折腾的死去活来,实在没时间发帖,花了好多个晚上才写好这篇帖子,后续会加油的利用技术栈打造个人私有云系列文章目录利用技术栈打造个人私有云连载之初章利用技术栈打造个人私有云连载之集群搭建利用技术栈打造个人私有云连载之环境理解和练手利用 showImg(https://segmentfault.com/img/remote/1460000013077799); 最近被业务折腾的死...

    Ryan_Li 评论0 收藏0
  • 利用K8S技术栈打造个人私有云(连载之:K8S集群搭建)

    摘要:最近被业务折腾的死去活来,实在没时间发帖,花了好多个晚上才写好这篇帖子,后续会加油的利用技术栈打造个人私有云系列文章目录利用技术栈打造个人私有云连载之初章利用技术栈打造个人私有云连载之集群搭建利用技术栈打造个人私有云连载之环境理解和练手利用 showImg(https://segmentfault.com/img/remote/1460000013077799); 最近被业务折腾的死...

    邱勇 评论0 收藏0
  • kubernetes中的Admission Controllers

    摘要:如果有一个准入控制拒绝了此次请求,那么整个请求的结果将会立即返回,并提示用户相应的信息。 这是啥 准入控制admission controller本质上一段代码,在对kubernetes api的请求过程中,顺序为 先经过 认证 & 授权,执行准入操作,在对目标对象进行操作。这个准入代码在apiserver中,而且必须被编译到二进制文件中才能被执行。 在对集群进行请求时,每个准入控...

    keithxiaoy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<