在 TKE 中使用动态准入控制器

原理概述

动态准入控制器 Webhook 在访问鉴权过程中可以更改请求对象或完全拒绝该请求,其调用 Webhook 服务的方式使其独立于集群组件,具有非常大的灵活性,可以方便的做很多自定义准入控制,下图为动态准入控制在 API 请求调用链的位置(来源于 Kubernetes 官网):

从上图可以看出,动态准入控制过程分为两个阶段:首先执行 Mutating 阶段,可以对到达请求进行修改,然后执行 Validating 阶段来验证到达的请求是否被允许,两个阶段可以单独使用也可以组合使用,本文将在 TKE 中实现一个简单的动态准入控制调用示例。

查看验证插件

在 TKE 现有集群版本中(1.10.5 及以上)已经默认开启了 validating admission webhookmutating admission webhook API,如果是更低版本的集群,可以在 Apiserver Pod 中执行 kube-apiserver -h | grep enable-admission-plugins 验证当前集群是否开启,输出插件列表中如果有 MutatingAdmissionWebhookValidatingAdmissionWebhook 就说明当前集群开启了动态准入的控制器插件,如下图所示:

签发证书

为了确保动态准入控制器调用的是可信任的 Webhook 服务端,必须通过 HTTPS 来调用 Webhook 服务(TLS认证), 所以需要为 Webhook 服务端颁发证书,并且在注册动态准入控制 Webhook 时为 caBundle 字段( ValidatingWebhookConfigurationMutatingAdmissionWebhook 资源清单中的 caBundle 字段)绑定受信任的颁发机构证书(CA)来核验 Webhook 服务端的证书是否可信任, 这里分别介绍两种推荐的颁发证书方法:

注意:当ValidatingWebhookConfigurationMutatingAdmissionWebhook 使用 clientConfig.service 配置时(Webhook 服务在集群内),为服务器端颁发的证书域名必须为 <svc_name>.<svc_namespace>.svc

方法一: 制作自签证书

制作自签证书的方法比较独立,不依赖于 K8s 集群,类似于为一个网站做一个自签证书,有很多工具可以制作自签证书,本示例使用 Openssl 制作自签证书,操作步骤如下所示:

  1. 生成密钥位数为 2048 的 ca.key:

    openssl genrsa -out ca.key 2048
  2. 依据 ca.key 生成 ca.crt,"webserver.default.svc" 为 Webhook 服务端在集群中的域名,使用 -days 参数来设置证书有效时间:

    openssl req -x509 -new -nodes -key ca.key -subj "/CN=webserver.default.svc" -days 10000 -out ca.crt
  3. 生成密钥位数为 2048 的 server.key:

    openssl genrsa -out server.key 2048

    i. 创建用于生成证书签名请求(CSR)的配置文件 csr.conf 示例如下:

    [ req ]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
    [ dn ]
    C = cn
    ST = shaanxi
    L = xi'an
    O = default
    OU = websever
    CN = webserver.default.svc
    [ v3_ext ]
    authorityKeyIdentifier=keyid,issuer:always
    basicConstraints=CA:FALSE
    keyUsage=keyEncipherment,dataEncipherment
    extendedKeyUsage=serverAuth,clientAuth
  4. 基于配置文件 csr.conf 生成证书签名请求:

    openssl req -new -key server.key -out server.csr -config csr.conf
  5. 使用 ca.key、ca.crt 和 server.csr 颁发生成服务器证书(x509签名):

    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out server.crt -days 10000 \
    -extensions v3_ext -extfile csr.conf
  6. 查看 Webhook server 端证书:

    openssl x509  -noout -text -in ./server.crt

其中,生成的证书、密钥文件说明如下:

ca.crt 为颁发机构证书,ca.key 为颁发机构证书密钥,用于服务端证书颁发。

server.crt 为 颁发的服务端证书,server.key 为颁发的服务端证书密钥.

方法二:使用 K8S CSR API 签发

除了使用方案一加密工具制作自签证书,还可以使用 k8s 的证书颁发机构系统来下发证书,执行下面脚本可使用 K8s 集群根证书和根密钥签发一个可信任的证书用户,需要注意的是用户名应该为 Webhook 服务在集群中的域名:

USERNAME='webserver.default.svc' # 设置需要创建的用户名为 Webhook 服务在集群中的域名
# 使用 Openssl 生成自签证书 key
openssl genrsa -out ${USERNAME}.key 2048
# 使用 Openssl 生成自签证书 CSR 文件, CN 代表用户名,O 代表组名
openssl req -new -key ${USERNAME}.key -out ${USERNAME}.csr -subj "/CN=${USERNAME}/O=${USERNAME}"
# 创建 Kubernetes 证书签名请求(CSR)
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: ${USERNAME}
spec:
request: $(cat ${USERNAME}.csr | base64 | tr -d '\n')
usages:
- digital signature
- key encipherment
- server auth
EOF
# 证书审批允许信任
kubectl certificate approve ${USERNAME}
# 获取自签证书 CRT
kubectl get csr ${USERNAME} -o jsonpath={.status.certificate} > ${USERNAME}.crt

其中, ${USERNAME}.crt 为服务端证书, ${USERNAME}.key 为 Webhook 服务端证书密钥。

操作示例

下面将使用 ValidatingWebhookConfiguration 资源在 TKE 中实现一个动态准入 Webhook 调用示例,本示例代码可在 示例代码 中获取(为了确保可访问性,示例代码 Fork 自 原代码库,作者实现了一个简单的动态准入 Webhook 请求和响应的接口,具体接口格式请参考 Webhook 请求和响应 。为了方便,我将使用它作为我们的 Webhook 服务端代码。

  1. 准备 caBundle 内容

    • 若颁发证书方法是方案一, 使用 base64 编码 ca.crt 生成 caBundle 字段内容:

       cat ca.crt | base64 --wrap=0
      
      
    • 若颁发证书方法是方案二,集群的根证书即为 caBundle 字段内容,可以通过 TKE 集群控制台【基本信息】-> 【集群APIServer信息】Kubeconfig 内容中的clusters.cluster[].certificate-authority-data 字段获取,该字段已经 base64 编码过了,无需再做处理。

  2. 复制生成的 ca.crt (颁发机构证书),server.crt(HTTPS 证书)), server.key(HTTPS 密钥) 到项目主目录:

  3. 修改项目中的 Dockerfile ,添加三个证书文件到容器工作目录:

    然后使用 docker 命令构建 Webhook 服务端镜像:

    docker build -t webserver .
    
    
  4. 部署一个域名为 "weserver.default.svc" 的 Webhook 后端服务,修改适配后的 controller.yaml 如下:

  5. 注册创建类型为 ValidatingWebhookConfiguration 的资源,本示例配置的 Webhook 触发规则是当创建 pods类型,API 版本 "v1" 时触发调用,clientConfig 配置对应上述在集群中创建的的 Webhook 后端服务, caBundle 字段内容为证书颁发方法一获取的ca.crt 内容,修改适配项目中的 admission.yaml 文件如下图:

  6. 注册好后创建一个 Pod 类型, API 版本为 "v1" 的测试资源如下:

  7. 测试代码有打印请求日志, 查看 Webhook 服务端日志可以看到动态准入控制器触发了 webhook 调用,如下图:

  8. 此时查看创建的测试pod 是成功创建的,是因为测试 Webhook 服务端代码写死的 allowed: true,所以是可以创建成功的,如下图:

  9. 为了进一步验证,我们把 "allowed" 改成 "false" ,然后重复上述步骤重新打 Webserver 服务端镜像,并重新部署 controller.yaml 和 admission.yaml 资源,当再次尝试创建 "pods" 资源时请求被动态准入拦截,说明配置的动态准入策略是生效的,如下图所示:

总结

本文主要介绍了动态准入控制器 Webhook 的概念和作用、如何在 TKE 集群中签发动态准入控制器所需的证书,并使用简单示例演示如何配置和使用动态准入 Webhook 功能。

参考

Kubernetes Dynamic Admission Control by Example

Dynamic Admission Control(官网)

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

手把手教你在容器服务 TKE 中使用动态准入控制器的更多相关文章

  1. 手把手教你在容器服务 TKE 上使用 LB 直通 Pod

    什么是 LB 直通 Pod ? Kubernetes 官方提供了 NodePort 类型的 Service,即给所有节点开一个相同端口用于暴露这个 Service,大多云上 LoadBalancer ...

  2. 手把手教你使用容器服务 TKE 集群审计排查问题

    概述 有时候,集群资源莫名被删除或修改,有可能是人为误操作,也有可能是某个应用的 bug 或恶意程序调用 apiserver 接口导致,需要找出 "真凶".这时候,我们需要为集群开 ...

  3. 在腾讯云容器服务 TKE 中利用 HPA 实现业务的弹性伸缩

    在 TKE 上利用 HPA 实现业务的弹性伸缩 概述 Kubernetes Pod 水平自动扩缩(Horizontal Pod Autoscaler,以下简称 HPA)可以基于 CPU 利用率.内存利 ...

  4. 腾讯云容器服务 TKE 推出新一代零损耗容器网络

    随着容器技术的发展成熟,越来越多的组件迁移到容器,在技术迁移过程中,数据库,游戏,AI 这些组件对容器网络性能(时延,吞吐,稳定性)提出了更高的要求.为了得到更优的时延和吞吐表现,各大云厂商都在致力于 ...

  5. 容器服务 TKE 存储插件与云硬盘 CBS 最佳实践应用

    引言 随着自研上云的深入,越来越多的有状态服务对于在 TKE 集群中使用云上存储能力的需求也越来越强烈. 目前腾讯云容器服务 TKE(Tencent Kubernetes Engine已支持在 TKE ...

  6. 腾讯云容器服务 TKE 拿下新加坡 MTCS 最高级别安全认证

    近日,腾讯云容器服务 TKE 荣获新加坡 MTCS 最高级安全认证,标志着腾讯云 TKE 在为用户提供可靠.易部署.灵活扩展等基础服务上,已经全面满足了新加坡监管机构以及多个行业客户对服务安全的要求. ...

  7. 容器服务 TKE 上服务暴露的几种方式

    预备知识 1. K8S 上 Service 类型 ClusterIP 通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType. NodePort ...

  8. 手把手教你如何在Ubuntu系统中安装Pycharm

    前几天带大家一起安装了Ubuntu14.04系统,没来得及上车的伙伴可以戳这篇文章:手把手教你在VMware虚拟机中安装Ubuntu14.04系统.今天小编带大家一起在Ubuntu14.04中安装Py ...

  9. Solr专题(一)手把手教你搭建Solr服务

    一.Solr是什么,能解决什么问题? Solr是一个高性能,采用Java开发,基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对 ...

随机推荐

  1. HDFS 修改默认副本数

    描述:将HDFS副本数修改为2第一步:将HDFS上已有文件副本数修改为2 hdfs dfs -setrep 2 -R -w / 第二步:修改dfs.replication值为2(页面上操作),然后重启 ...

  2. 你知道 react-color 的实现原理吗

    一.前言 ReactColor 是一个优秀的 React 颜色选择器组件,官方给了多种布局供开发者选择. 笔者常用的主题为 Sketch,这种主题涵盖了颜色面板.推荐色块.RGB颜色输入等功能,比较完 ...

  3. linux安装ftp步骤

    1,查看是否安装了FTP:rpm -qa |grep vsftpd 2,如果没有安装,可以使用如下命令直接安装 yum -y install vsftpd 默认安装目录:/etc/vsftpd 3,添 ...

  4. C++ 简单输出当前日期时间

    根据https://www.runoob.com/cplusplus/cpp-date-time.html编写. 首先介绍2个数据类型. 一个是time_t,与时间函数相关的变量,定义的变量记录着自 ...

  5. 【JavaWeb】现代 JavaScript 教程

    js_model_tutorial !!待更新 前言 现代 JavaScript 教程的学习笔记,它是一份不错的学习资源,感谢开源. 中文链接 基础 函数 代码示例 函数的声明方式 function ...

  6. 【C++】《C++ Primer 》第十五章

    第十五章 面向对象程序设计 一.OOP:概述 面向对象程序设计(OOP)的核心思想是数据抽象.继承和动态绑定. 通过使用数据抽象,可以将类的接口和实现分离. 使用继承,可以定义相似的类型并对其相似关系 ...

  7. zabbix自定义监控nginx

    nginx配置ngx_status 1.编译安装时带上--with-http_stub_status_module参数 2.vi nginx.conf location ~* ^/ngx_status ...

  8. tomcat控制台运行窗口中文乱码

    启动tomcat时出来的运行窗口中文乱码, 如图所示:看得有点不舒服 解决方法:找到Tomcat安装路径下的 /conf/logging.properties 文件 文件末尾添加语句: java.ut ...

  9. 【数据结构与算法】Java制作一个简单数组类

    bobo老师的玩转算法系列–玩转数据结构 简单记录 文章目录 不要小瞧数组 - 制作一个数组类 1 .使用Java中的数组 数组基础 简单使用 2.二次封装属于我们自己的数组 数组基础 制作属于我们自 ...

  10. RSA共模攻击

    在安恒月赛中碰到一道密码学方向的ctf题 附上源码 from flag import flag from Crypto.Util.number import * p=getPrime(1024) q= ...