K8s准入控制Admission Controller深入介绍

目录
  • K8s 的准入控制器是什么
    • K8s 中的请求处理流程
    • 什么是准入控制器(Admission Controller)
  • 为什么需要准入控制器 Admission Controller
  • 准入控制器
  • 动态准入控制器
    • 使用条件
    • Admission Webhook 是什么
    • 如何部署 Admission Webhook
  • 总结

在我之前发布的文章 《云原生时代下的容器镜像安全》(系列)中,我提到过 Kubernetes 集群的核心组件 -- kube-apiserver,它允许来自终端用户或集群的各组件与之进行通信(例如,查询、创建、修改或删除 Kubernetes 资源)。

K8s 的准入控制器是什么

K8s 中的请求处理流程

在聊 K8s 准入控制器是什么之前,让我们先来回顾一下 Kubernetes API 的处理具体请求的过程。

图 1 ,Kubernetes API 处理请求的过程 (从 API Handler 到 etcd 持久化的过程)

如上图所示,每个 API 的请求从开始被 kube-apiserver 接收到最终持久化到 ETCD 的过程,即为 Kubernetes API 的请求处理流程。

它主要包含了以下几个部分:

API Handler -- 主要负责提供服务,接收请求。

对于其内部实现而言,请求会先到 FullHandlerChain (它是由 DefaultBuildHandlerChain 构建出来的)是一个 director 对象

type director struct {
	name               string
	goRestfulContainer *restful.Container
	nonGoRestfulMux    *mux.PathRecorderMux
}

director根据配置进行初始化,如果 goRestfulContainer的 WebServices 的 RootPath 是 /apis,或者请求前缀与 RootPath 匹配,则进入 Restful 处理链路。

Authentication -- 认证的流程。

在TLS 连接建立后,会进行认证处理,如果请求认证失败,会拒绝该请求并返回 401 错误码;如果认证成功,将进行到鉴权的部分。目前支持的客户端认证方式有很多,例如:x509 客户端证书、Bearer Token、基于用户名密码的认证、OpenID 认证等。由于这些内容不是本篇的重点我们暂且跳过,感兴趣的小伙伴可以在评论区留言讨论。

Authorization -- 鉴权的流程。

对于 Kubernetes 而言,支持多种的鉴权模式,例如,ABAC 模式,RBAC 模式和 Webhook 模式等。我们在创建集群时,可以直接为 kube-apiserver 传递参数进行配置,这里也不赘述了。

Mutating Admission -- 指执行可用于变更操作的准入控制器,下文中会详细介绍。

Object Schema Validation -- 对资源对象的 schema 校验。

Validating Admission -- 指执行可用于验证操作的准入控制器,下文中会详细介绍。

ETCD -- ETCD 实现资源的持久化存储。

上面便是一个请求的处理流程,其中 Mutating Admission 和 Validating Admission 便是我们今天的主角。我们来详细的看一看。

什么是准入控制器(Admission Controller)

准入控制器是指在请求通过认证和授权之后,可用于对其进行变更操作或验证操作的一些代码或功能。

准入控制的过程分为两个阶段:

  • 第一阶段,运行变更准入控制器(Mutating Admission)。它可以修改被它接受的对象,这就引出了它的另一个作用,将相关资源作为请求处理的一部分进行变更;
  • 第二阶段,运行验证准入控制器(Validating Admission)。它只能进行验证,不能进行任何资源数据的修改操作;

需要注意的是,某些控制器可以既是变更准入控制器又是验证准入控制器。如果任一个阶段的准入控制器拒绝了该请求,则整个请求将立即被拒绝,并向终端用户返回错误。

为什么需要准入控制器 Admission Controller

我们主要从两个角度来理解为什么我们需要准入控制器:

从安全的角度

我们需要明确在 Kubernetes 集群中部署的镜像来源是否可信,以免遭受攻击;

一般情况下,在 Pod 内尽量不使用 root 用户,或者尽量不开启特权容器等;

从治理的角度

比如通过 label 对业务/服务进行区分,那么可以通过 admission controller 校验服务是否已经有对应的 label 存在之类的;

比如添加资源配额限制 ,以免出现资源超卖之类的情况;

准入控制器

考虑到这些需求比较有用 & 确实也比较需要,所以 Kubernetes 目前已经实现了很多内置的 Admission Controller 。 可以参考官方文档来获取详细列表: kubernetes.io/docs/refere…

这些内置的 Admission Controller 都是以插件的方式与 kube-apiserver 构建到一起的,你可以对其进行启用和关停。比如用如下参数进行控制:

➜  bin ./kube-apiserver --help |grep 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, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, 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.)
      --disable-admission-plugins strings      admission plugins that should be disabled although they are in the default enabled plugins list (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, 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, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.
      --enable-admission-plugins strings       admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, 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, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodSecurityPolicy, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.

这么多的准入控制器中有两个比较特别,分别是 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。它们并没有真正执行相应的策略,而是为 kube-apiserver 提供了一种可扩展的方式, 用户可以通过配置 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 来使用自构建的服务, 而且这种方式是无需对 kube-spiserver 执行编译或者重启,完全是动态的,非常的方便。

我们来具体看一下。

动态准入控制器

利用上文中提到的 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 进行运行时配置的,以 Webhook 形式调用的 Admission Controller 即为动态准入控制器。

它是一种用于接收准入请求并对其进行处理的 HTTP 回调机制,就是一个 Web 服务。当前的两种类型的准入 webhook:

validating admission webhook

mutating admission webhook

mutating admission webhook 会优先被调用,这个过程中可以对资源进行修改。

如果我们需要确保对象的最终状态以执行某些操作应该考虑使用 validating admission webhook *,*因为到达这个阶段的请求不会再被修改。

使用条件

确保 Kubernetes 集群版本至少为 v1.16(以便使用 admissionregistration.k8s.io/v1 API) 或者 v1.9 (以便使用 admissionregistration.k8s.io/v1beta1 API);

确保已经启用 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 准入控制器;

确保启用了 admissionregistration.k8s.io/v1beta1 或者 admissionregistration.k8s.io/v1 API;

Admission Webhook 是什么

它其实就是一个普通的 HTTP Server,需要处理的就是 AdmissionReview 类型的资源,我们来看个示例,比如说要对 Ingress资源进行准入校验:

func (ia *IngressAdmission) HandleAdmission(obj runtime.Object) (runtime.Object, error) {
	review, isV1 := obj.(*admissionv1.AdmissionReview)
	if !isV1 {
		return nil, fmt.Errorf("request is not of type AdmissionReview v1")
	}
	if !apiequality.Semantic.DeepEqual(review.Request.Kind, ingressResource) {
		return nil, fmt.Errorf("rejecting admission review because the request does not contain an Ingress resource but %s with name %s in namespace %s",
			review.Request.Kind.String(), review.Request.Name, review.Request.Namespace)
	}
	status := &admissionv1.AdmissionResponse{}
	status.UID = review.Request.UID
	ingress := networking.Ingress{}
	codec := json.NewSerializerWithOptions(json.DefaultMetaFactory, scheme, scheme, json.SerializerOptions{
		Pretty: true,
	})
	codec.Decode(review.Request.Object.Raw, nil, nil)
	_, _, err := codec.Decode(review.Request.Object.Raw, nil, &ingress)
	if err != nil {
		klog.ErrorS(err, "failed to decode ingress")
		status.Allowed = false
		status.Result = &metav1.Status{
			Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
			Message: err.Error(),
		}
		review.Response = status
		return review, nil
	}
	if err := ia.Checker.CheckIngress(&ingress); err != nil {
		klog.ErrorS(err, "invalid ingress configuration", "ingress", fmt.Sprintf("%v/%v", review.Request.Name, review.Request.Namespace))
		status.Allowed = false
		status.Result = &metav1.Status{
			Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
			Message: err.Error(),
		}
		review.Response = status
		return review, nil
	}
	klog.InfoS("successfully validated configuration, accepting", "ingress", fmt.Sprintf("%v/%v", review.Request.Name, review.Request.Namespace))
	status.Allowed = true
	review.Response = status
	return review, nil
}

核心处理逻辑其实就是处理请求 Webhook 时候发送的 AdmissionReview ,它会包含着我们待校验的资源对象。然后我们就按照实际的需要对资源对象进行校验或者修改了。

这里需要注意几个点:

Mutating Webhook 的处理是串行的,而 Validating Webhook 是并行处理的;

Mutating Webhook 虽然处理是串行的,但是并不保证顺序;

注意对 Mutating Webhook 的处理做到幂等性,以免结果不符合预期;

请求处理时,注意要处理资源对象的所有 API 版本;

如何部署 Admission Webhook

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  labels:
    app.kubernetes.io/name: ingress-nginx
  name: ingress-nginx-admission
webhooks:
  - name: validate.nginx.ingress.kubernetes.io
    matchPolicy: Equivalent
    rules:
      - apiGroups:
          - networking.k8s.io
        apiVersions:
          - v1
        operations:
          - CREATE
          - UPDATE
        resources:
          - ingresses
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions:
      - v1
    clientConfig:
      service:
        namespace: ingress-nginx
        name: ingress-nginx-controller-admission
        path: /networking/v1/ingresses

webhooks 中配置 webhook 的具体连接信息,以及触发规则。rules中可指定对哪些资源的具体行为生效。

总结

本篇主要介绍了 Kubernetes 中的 Admission Controller ,默认情况下有一些已经以插件形式与 kube-apiserver 编译到了一起,另外我们也可以通过自己编写动态准入控制器来完成相关的需求。

当然,目前在 K8s 生态中已经有很多现成的工具可以帮我们完成对应的这些事情了,很多情况下不需要再自行开发对应的服务了。后续我来为大家分享当前一些比较主流的,可用于进行 Mutating 和 Validating 准入控制的工具, 欢迎关注。

以上就是K8s准入控制Admission Controller深入介绍的详细内容,更多关于K8s准入控制Admission Controller的资料请关注我们其它相关文章!

(0)

相关推荐

  • 解决国内k8s的ingress-nginx镜像无法正常pull拉取问题

    一.问题描述 我们期望运行Ingress就必须给我们的集群创建Ingress controller 目前官方推荐的controller有:[目前支持和维护 AWS, GCE 和 nginx Ingress 控制器] https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/ 我们使用nginx控制器,其官网给出的配置方法如下:https://kubernetes.github.io/ingress

  • 关于k8s中subpath的使用详解

    目录 有两种情况: 1.做为volumes使用时,subPath代表存储卷的子路径: 2.作为configmap/secret使用时,subPath代表configmap/secret的子路径: 有两种情况: 1.做为volumes使用时,subPath代表存储卷的子路径: apiVersion: v1 kind: Pod metadata: name: testpod0 spec: containers: - name: testc image: busybox command: ["/bin

  • kubernetes k8s入门定义一个Pod

    目录 什么是Pod? 为什么要引入Pod? 定义一个Pod:pod.yaml Pod探针: Pod探针检测方式: Pod退出流程 什么是Pod? pod是kubernetes中最小的单元,由一组.一个或多个容器组成,每个pod中包含了一个pause容器. pause容器是pod的父容器,主要负责僵尸进程的回收管理,通过pause容器可以使同一个pod中多个容器共享存储.网络.PID.IPC等,同一个Pod中多容器间访问仅通过localhost就可以通信. 为什么要引入Pod? 将有强依赖性的容器

  • k8s入门-集群组件介绍

    目录 k8s是谷歌以Borg为前身,基于谷歌15年生产环境经验的基础上开源的一个项目. k8s致力于提供跨主机集群的自动部署.扩展.高可用以及运行应用程序容器的平台. k8s集群包含master节点和node节点,是一个主从架构,通常我们会用3台服务器已高可用的形式作为主节点,不进行业务部署(可以设置要不要在主节点上部署应用):从节点作为工作节点. 以下为集群组件及功能: master节点:集群的控制中枢 kube-apiserver:集群的控制中枢,各模块间信息交互需要经过kube-apise

  • k8s监控数据组件Pod自动化进行扩缩容HPA

    自动扩缩容HPA:全称是Horizontal Pod Autoscaler 我们安装k8s集群的时候,安装过一个metrics-server的组件,这是一个监控数据组件,提供HPA和基础资源监控的能力.就是这面这个Pod: [root@k8s-master01 ~]# kubectl get pod -n kube-system metrics-server-6bf7dcd649-5fhrw 1/1 Running 2 (3d5h ago) 8d 通过这个组件可以看到节点或者Pod的内存和CPU

  • K8s准入控制Admission Controller深入介绍

    目录 K8s 的准入控制器是什么 K8s 中的请求处理流程 什么是准入控制器(Admission Controller) 为什么需要准入控制器 Admission Controller 准入控制器 动态准入控制器 使用条件 Admission Webhook 是什么 如何部署 Admission Webhook 总结 在我之前发布的文章 <云原生时代下的容器镜像安全>(系列)中,我提到过 Kubernetes 集群的核心组件 -- kube-apiserver,它允许来自终端用户或集群的各组件

  • K8S中五种控制器的介绍以及使用

    目录 k8s的控制器类型 pod与控制器之间的关系 Deployment(无状态化应用) 状态与无状态化对特点 Deployment的更新 Deployment的回滚 CronJob控制器 总结 k8s的控制器类型 Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为 Deployment:适合无状态的服务部署 StatefullSet:适合有状态的服务部署 DaemonSet:一次部署,所有的node节点都会部署,例如一些典型的应

  • JavaScript+CSS控制打印格式示例介绍

    1. 用media="print"的css来控制要打印的文件testPrint.html中引用media为print的样式,表示打印时该样式才起作用 复制代码 代码如下: <link href="/style/print.css" rel="stylesheet" type="text/css" media="print"> /style/print.css文件 复制代码 代码如下: .nopr

  • python流程控制详细介绍

    目录 1. 布尔逻辑 1.1 条件控制语句-if 1.2 if/else 语句 1.3 if/elif 语句 2 循环控制语句 2.1 循环控制之for 2.2 循环控制之while 3 for vs while 3.1 对输入的数字求和 3.2 未知个数字的求和 3.3 阶乘计算 前言: 经过简单的了解python基本语法和使用后,发现其都是一些顺序执行语句,也就是依次执行,没有任何的分支,循环,也不会返回到以前的执行语句-流程控制.在实际使用中,当然不可避免使用到流程控制语句,但其都要由逻辑

  • Kubernetes(K8S)基础知识

    目录 Kubernetes 是什么 Kubernetes 集群的组成 Kubernetes 结构 组件 Master 节点 kube-apiserver etcd kube-scheduler kube-controller-manager Kubernetes 是什么 在 2008 年,LXC(Linux containers) 发布第一个版本,这是最初的容器版本:2013 年,Docker 推出了第一个版本:而 Google 则在 2014 年推出了 LMCTFY. 为了解决大集群(Clus

  • SpringBoot--- SpringSecurity进行注销权限控制的配置方法

    环境 IDEA :2020.1 Maven:3.5.6 SpringBoot: 2.0.9 (与此前整合的版本2.3.3 不同,版本适配问题,为配合使用降级) 1.注销 这里也有一个前提问题需要注意,我们登录操作都是在开启防跨域攻击的环境下进行的. 毫无疑问,注销也是在这样的情况下进行的. 登录时我们提交表单,采用 POST 方法传输,通过使用 Thymeleaf 在 form 表单添加 th:action 元素,Thymeleaf 会自动为我们添加 _csrf 元素. 同样注销操作也是要带有

  • Springboot 整合shiro实现权限控制的方法

    Author:jeffrey Date:2019-04-08 一.开发环境: 1.mysql - 5.7 2.navicat(mysql客户端管理工具) 3.idea 2017.2 4.jdk8 5.tomcat 8.5 6.springboot2.1.3 7.mybatis 3 8.shiro1.4 9.maven3.3.9 二.数据库设计 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CB46ByC1-1604249108144)(img/shiro01.pn

  • DELL R730服务器配置RAID与安装服务器系统以及域的控制详细图文教程

    最近公司采购了一台DELL R730服务器,正好找到了下面的教程,特分享一下 CPU:e5-2609 v3  内存2*8GB  硬盘:4*2TB 阵列卡:H330,忘记拍安装导轨及上架的图片了,这个已经装上机柜了. 首先开机进行RAID配置 在启动界面显示按CTRL+R的画面的时候,按CTRL+R 进行到虚拟磁盘管理器界面 这里忘记拍图了,在网上找的图片 首先进入到VG MGMT菜单(这里可以用CTRL+NT和CTRL+P切换菜单) 按F2展开虚拟磁盘创建菜单 选择create new VD创建

  • 在docker中部署k8s的方法

    K8s k8s是一个cluster集群,在cluster集群中有多个Namespace,一个namespace下又有多个pods,一个pod下有多个container. 这篇文章带你从头在docker中部署k8s. docker下载 docker安装 docker: https://docs.docker.com/docker-for-mac/install/ 在docker中使用k8s: https://docs.docker.com/desktop/kubernetes/ 在docker设置

  • SpringCloud 微服务数据权限控制的实现

    目录 一. 整体架构 二. 实现流程 三. 实现步骤 1. 注解实现 2. 注解使用 3. 实现AuthStoreSupplier 4. 实现AuthQuerySupplier 5. 开启数据权限 四. 综述 五.源代码 举个例子: 有一批业务员跟进全国的销售订单.他们被按城市进行划分,一个业务员跟进3个城市的订单,为了保护公司的业务数据不能被所有人都掌握,故每个业务员只能看到自己负责城市的订单数据.所以从系统来讲每个业务员都有访问销售订单的功能,然后再需要配置每个业务员负责的城市,以此对订单数

随机推荐