三十、K8s供应链安全1-准入控制器

一、集群环境

在这里插入图片描述
底层系统为ubuntu18.04,然后在每个node上安装k8s,并构建集群。Master node的IP地址为192.168.26.71/24,两个Worker node的IP地址为192.168.26.72/24、192.168.26.73/24。部署Calico网络插件,保证Node之间能够正常通信。

二、准入控制器

1.什么是准入控制器
在这里插入图片描述
kube-apiserver是Kubernetes集群的中心,集群中所有资源的创建和更新都是通过APIServer的Restful API实现的。 因此Kubernetes通过一系列的机制来保证APIServer的安全,包括APIServer的认证、授权以及本文中我们会使用的准入控制Admission Control。上图是APIServer被访问控制的过程,在经过认证和授权之后就进入了准备控制Admission Control。

认证的操作请查看:https://blog.csdn.net/tushanpeipei/article/details/121877797?spm=1001.2014.3001.5501
授权的操作请查看:https://blog.csdn.net/tushanpeipei/article/details/121894874?spm=1001.2014.3001.5501

准入控制器可以理解为功能开关,可以启用或者关闭。其包含的类型有很多,包括了之前笔记中提到的:

  1. Pod 安全策略(Pod Security Policy)
  2. OPA (Open Policy Agent)规则
  3. NodeRestriction

在我们环境中kube-apiserver是通过容器执行的。所以我们可以使用如下的命令查看准入控制器的相关内容:

kubectl exec -it -n kube-system kube-apiserver-vms71.rhce.cc -- kube-apiserver -h | grep enable-admission-plugins

在其显示的信息中,我们可以看到在当前版本中默认开启的准入控制分别是:

CertificateApproval, CertificateSigning, CertificateSubjectRestriction, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, LimitRanger, MutatingAdmissionWebhook, NamespaceLifecycle, PersistentVolumeClaimResize, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionWebhook

2.如何开启和关闭对应的准入控制器
kube-apiserver的 enable-admission-plugins 标志接受一个用于在集群修改对象之前 调用的(以逗号分隔的)准入控制插件顺序列表。

例如,下面的命令就启用了 NamespaceLifecycle 和 LimitRanger 准入控制插件。首先编辑kube-apiserver.yaml文件:

vim /etc/kubernetes/manifests/kube-apiserver.yaml

在command一栏下找到 --enable-admission-plugins=,添加自己想要开启的准入控制器。例如,下面的命令就启用了 NamespaceLifecycle 和 LimitRanger 准入控制插件:

--enable-admission-plugins=NamespaceLifecycle,LimitRanger

同样的,要想关闭默认启用的准入控制器插件,可以同样在command一栏下,找到–disable-admission-plugins,然后设置准备关闭的插件,例如,如下命令就跟关闭了PodNodeSelector和AlwaysDeny插件。

--disable-admission-plugins=PodNodeSelector,AlwaysDeny

3.每个准入控制器的作用是什么?

请查看官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/#每个准入控制器的作用是什么

4.整理创建pod调度的过程

  1. 用户通过可视化或者kubectl命令连接到kube-apiserver。kube-apiserver判断用户是否登录,是否有权限(认证和授权);
  2. 各种准入控制检测此创建pod请求的的合法性。如果请求符合各种准入控制器规则,则允许此请求,否则直接拒绝;
  3. 通过后准入控制器规则后,kubelet或者scheduler通过watch权限能够看到pod的状态为pending;
  4. schduler会通过主机排除、打分决定该pod运行在哪个worker node上;
  5. kubelet开始运行pause容器,创建相关的PID命名空间、网络命名空间等;
  6. pod被创建出来。

三、举例一:ResourceQuota准入控制器

ResourceQuota是默认开启的准入控制器插件,可以帮助我们限制K8s的资源配额。例如,我们使用如下yaml文件创建一个ResourceQuota准入控制器,限制只能创建2个pod:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: myrq
spec:
  hard:
    pods: "2"

查看所部署的ResourceQuota:

root@vms71:~/admission-controllers# kubectl get resourcequotas
NAME   AGE   REQUEST     LIMIT
myrq   36s   pods: 0/2

然后我们使用deployment同时部署3个pod,deployment的yaml文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web1
  name: web1
spec:
  replicas: 3
  selector:
    matchLabels:
      app1: web1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app1: web1
        app2: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}

应用后可以看到如下的结果:3个pod仅能启用两个,说明我们ResourceQuota准入控制器部署成功。

root@vms71:~/admission-controllers# kubectl get deployments.apps web1
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   2/3     2            2           10s
root@vms71:~/admission-controllers# kubectl get resourcequotas
NAME   AGE   REQUEST     LIMIT
myrq   12m   pods: 2/2

四、举例二:ImagePolicyWebhook准入控制器

ImagePolicyWebhook 准入控制器允许使用一个后端的 webhook 做出准入决策。

1.部署webhook服务器

使用集群外的另外一台Linux设备作为webhook服务,并在设备上安装好docker。下载一个已经内置规则的webhook服务器镜像:

docker pull flavio/kube-image-bouncer

这个webhook服务器所实现的规则是不允许我们我们使用最新的镜像来部署容器。然后通过此镜像生成webhook服务器容器(这里没有生成和使用对应的证书,测试环境中可能会报错,所以后续kube-apiserver直接通过http来访问webhook服务器):

docker run -dit --name=c1 --restart=always  -v `pwd`/webhook-key.pem:/certs/webhook-key.pem:ro -v `pwd`/webhook.pem:/certs/webhook.pem:ro -p 1323:1323 flavio/kube-image-bouncer

查看是否部署完成:

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED              STATUS              PORTS                    NAMES
b1b092ebd6b9   flavio/kube-image-bouncer   "./kube-image-bouncer"   About a minute ago   Up About a minute   0.0.0.0:1323->1323/tcp   c1

可以看到,已经部署成功。当我们访问这台设备(192.168.26.130)的1323端口时,也就访问到这个服务器了。

2.在K8s上启用ImagePolicyWebhook准入控制器

在master上修改/etc/kubernetes/manifests/kube-apiserver.yaml文件,启用ImagePolicyWebhook:

- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook

接下来,我们需要编辑ImagePolicyWebhook的配置文件中,ImagePolicyWebhook 使用配置文件来为后端服务器设置配置选项。该文件可以是 JSON 或 YAML,例如:

root@vms71:/etc/kubernetes/aa# cat admission_configuration.yaml
imagePolicy:
  # 指定kubeconfig的位置
  kubeConfigFile: /etc/kubernetes/aa/kubeconfig.yaml
  # 以秒计的时长,控制批准请求的缓存时间
  allowTTL: 50
  # 以毫秒计的时长,控制重试间隔
  denyTTL: 50
  # 确定 Webhook 后端失效时的行为
  retryBackoff: 500
  # 默认是允许的规则
  defaultAllow: true

ImagePolicyWebhook 的配置文件必须引用 kubeconfig 格式的文件;该文件设置了到后端的连接参数、证书等信息(本实验中没有),如:

apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/aa/webhook.pem
    server: http://192.168.26.130:1323/image_policy
  name: bouncer_webhook
contexts:
- context:
    cluster: bouncer_webhook
    user: api-server
  name: bouncer_validator
current-context: bouncer_validator
preferences: {}
users:
- name: api-server
  user:
    client-certificate: /etc/kubernetes/aa/apiserver-client.pem
    client-key:  /etc/kubernetes/aa/apiserver-client-key.pem

其中server: http://192.168.26.130:1323/image_policy指定了我们通过http连接到webhook服务器的1323端口。由于不是使用https的方式,其他的证书相关的内容,其实这里没有作用了。然后,我们还需要在kube-apiserver中指定ImagePolicyWebhook所使用的配置文件。同样在/etc/kubernetes/manifests/kube-apiserver.yaml文件中的command下,添加如下的信息即可:

- --admission-control-config-file=/etc/kubernetes/aa/admission_configuration.yaml

由于我们kube-apiserver以容器方式运行。而我们webhook相关的文件存放在宿主机上,所以要做一个挂载卷,将这些文件映射到容器中的相同目录下,同样编辑/etc/kubernetes/manifests/kube-apiserver.yaml文件,增加如下内容:

    volumeMounts:
    - mountPath: /etc/kubernetes/aa
      name: aa
      readOnly: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/aa
      type: DirectoryOrCreate
    name: aa

重启kubelet:

systemctl restart kubelet.service

3.测试能否使用latest的镜像部署pod

root@vms71:/etc/kubernetes/aa# kubectl run pod1 --image=nginx --image-pull-policy=IfNotPresent
Error from server (Forbidden): pods "pod1" is forbidden: image policy webhook backend denied one or more images: Images using latest tag are not allowed

可以看到,当我们尝试使用最新的nginx镜像创建pod时,会提示报错信息,告知我们不能够使用带有latest tag的镜像。说明webhook准入控制已经部署成功。

整理资料来源:
K8s admission-controllers: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
《老段CKS课程》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

格洛米爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值