使用gatekeeper限制kubernetes创建特定类型的资源

正常情况下用户要登录k8s创建某资源比如pod时,首先apiserver会检测
1.通过token或者证书认证此用户是否能够登录k8s
2.会检测此用户是否具备足够的权限
在k8s默认的情况下,如果用户能登录且具备权限的话,是可以正确的创建资源的。但是我们可以通过准入控制器(admission control)或者动态准入控制器(Dynamic Admission Control)定制一系列的规则,进一步限制所要创建的pod是否合规。
file
OPA(全称是Open Policy Agent )是CNCF孵化出来的一个项目,是一种开源的策略引擎,可以用于为docker、envoy、ssh、kubernetes等应用定制策略。

而gatekeeper是基于OPA为kubernetes定制的一个项目,可以实现各种策略。这些策略是通过准入控制器作用到kubernetes上的。

安装gatekeeper

先到下面的地址下载最新的manifest文件
https://github.com/open-policy-agent/gatekeeper/tree/master/deploy
然后在master上执行下面的命令安装gatekeeper。

root@vms61:~/demo4# kubectl apply -f gatekeeper.yaml 
namespace/gatekeeper-system created
...输出...
poddisruptionbudget.policy/gatekeeper-controller-manager created
validatingwebhookconfiguration.admissionregistration.k8s.io/gatekeeper-validating-webhook-configuration created
root@vms61:~/demo4#

安装之后,会自动创建一个名字为gatekeeper-system的命名空间,在此命名空间里会创建一系列的pod,确认这些pod的状态都是运行的。

root@vms61:~/demo4# kubectl get pods -n gatekeeper-system 
NAME                                                                                READY   STATUS    RESTARTS   AGE
gatekeeper-audit-7b67879df4-sm4fw               1/1    Running    0  30s
gatekeeper-controller-manager-6cb56f759f-96jmn  1/1     Running   0  30s
gatekeeper-controller-manager-6cb56f759f-hnxc4  1/1     Running   0   30s
gatekeeper-controller-manager-6cb56f759f-sv5zp  1/1     Running   0   30s
root@vms61:~/demo4#

gatekeeper会创建一系列的资源类型。

root@vms61:~/demo4# kubectl get crd | grep gatekeep
configs.config.gatekeeper.sh                          2022-05-09T11:51:01Z
constraintpodstatuses.status.gatekeeper.sh            2022-05-09T11:51:01Z
constrainttemplatepodstatuses.status.gatekeeper.sh    2022-05-09T11:51:01Z
constrainttemplates.templates.gatekeeper.sh           2022-05-09T11:51:01Z
providers.externaldata.gatekeeper.sh                  2022-05-09T11:51:01Z
root@vms61:~/demo4#

创建测试用的镜像
在所有节点把nginx镜像重新打标签为hub.c.163.com/library/nginx

root@vms6X:~# nerdctl tag nginx hub.c.163.com/library/nginx
root@vms6X:~#

现在对于使用哪个镜像是没有任何限制的,所以如果使用镜像nginx hub.c.163.com/library/nginx创建pod也是能创建出来的。
创建pod1.yaml内容如下。

root@vms61:~/demo4# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/nginx
    imagePullPolicy: IfNotPresent
    name: pod1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

root@vms61:~/demo4# 

开始创建pod。

root@vms61:~/demo4# kubectl apply -f pod1.yaml 
pod/pod1 created
root@vms61:~/demo4# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          3s
root@vms61:~/demo4# 

从这里可以看到pod能创建出来,也就是现在是可以正常使用hub.c.163.com/library/nginx这个镜像的。下面把这个pod删除。

root@vms61:~/demo4# kubectl delete  pod pod1
pod "pod1" deleted
root@vms61:~/demo4#

禁止使用特定的镜像

我们先自定义一个类型为blacklistimages的CRD资源类型,用于禁止以hub.c.163.com开头的镜像。
注:如同有了pod这种资源类型,我们才能创建pod1、pod2、pod3等这些pod资源。我们要先创建一种资源类型才能创建具体的资源。
先查看是否存在blacklistimages类型的资源。

root@vms61:~/demo4# kubectl get blacklistimages
error: the server doesn't have a resource type "blacklistimages"
root@vms61:~/demo4# 

这里提示不存在blacklistimages这种资源类型,所以先通过CRD创建出来这种类型。下面创建gatekeeper-blk-type.yaml内容如下。

root@vms61:~/demo4# cat gatekeeper-blk-type.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: blacklistimages
spec:
  crd:
    spec:
      names:
        kind: BlacklistImages
  targets:
  - rego: |
      package k8strustedimages

      images {
        image := input.review.object.spec.containers[_].image
        not startswith(image, "hub.c.163.com/")
      }

      violation[{"msg": msg}] {
        not images
        msg := "不可用的镜像!"
      }
    target: admission.k8s.gatekeeper.sh
root@vms61:~/demo4#

这里指定如果使用了hub.c.163.com开头的镜像的话,那么则提示“不可用的镜像!”。
创建此资源。

root@vms61:~/demo4# kubectl apply -f gatekeeper-blk-type.yaml 
constrainttemplate.templates.gatekeeper.sh/blacklistimages created
root@vms61:~/demo4# 
root@vms61:~/demo4# kubectl get blacklistimages
No resources found
root@vms61:~/demo4# 

这里提示"No resources found",说明已经存在资源类型blacklistimages了,只是这个类型下面还没创建任何资源。
下面创建一个名字为pod-blk-img的BlacklistImages。

root@vms61:~/demo4#  cat gatekeeper-blacklist.yaml 
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: BlacklistImages
metadata:
  generation: 1
  managedFields:
  name: pod-blk-img
  resourceVersion: "14449"
spec:
  match:
    kinds:
    - apiGroups:
      - ""
      kinds:
      - Pod
root@vms61:~/demo4#

这里定义的pod-blk-img将用于pod的创建,先把名字叫做pod-blk-img 的blacklistimages创建出来。

root@vms61:~/demo4# kubectl apply -f gatekeeper-blacklist.yaml 
blacklistimages.constraints.gatekeeper.sh/pod-blk-img  created
root@vms61:~/demo4#

root@vms61:~/demo4# kubectl get blacklistimages
NAME              AGE
pod-blk-img       74s
root@vms61:~/demo4# 

下面再次创建pod1。

root@vms61:~/demo4# kubectl apply -f pod1.yaml 
Error from server ([pod-blk-img] 不可用的镜像!): error when creating "pod1.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [pod-blk-img] 不可用的镜像!
root@vms61:~/demo4#

这里pod创建失败,说明现在已经不能使用hub.c.163.com的镜像了。

删除pod-blk-img。

root@vms61:~/demo4# kubectl delete -f gatekeeper-blacklist.yaml 
blacklistimages.constraints.gatekeeper.sh "pod-blk-img" deleted
root@vms61:~/demo4# 

删除blacklistimages这个资源类型。

root@vms61:~/demo4# kubectl delete -f gatekeeper-blk-type.yaml 
constrainttemplate.templates.gatekeeper.sh "blacklistimages" deleted
root@vms61:~/demo4#

禁止创建LB类型的svc

下面再来一个练习,用于禁止创建LoadBalancer类型的service。
先把pod1创建出来。

root@vms61:~/demo4# kubectl apply -f pod1.yaml 
pod/pod1 created
root@vms61:~/demo4# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          2s
root@vms61:~/demo4# 

在没有任何限制的情况下,先创建一个LoadBalancer类型的service。

root@vms61:~/demo4# kubectl expose --name=svc1 pod pod1 --port=80 --type=LoadBalancer
service/svc1 exposed
root@vms61:~/demo4# kubectl get svc svc1
NAME   TYPE          CLUSTER-IP       EXTERNAL-IP      PORT(S)       AGE
svc1   LoadBalancer  10.110.158.128   192.168.26.240   80:32109/TCP   5s
root@vms61:~/demo4#

可以此时是可以创建出来类型为LoadBalancer的service的,下面把此service删除。

root@vms61:~/demo4# kubectl delete svc svc1
service "svc1" deleted
root@vms61:~/demo4#

下面准备创建一个CRD的资源类型lbtypesvcnotallowed,先判断是否存在这种资源类型。

root@vms61:~/demo4# kubectl get lbtypesvcnotallowed
error: the server doesn't have a resource type "lbtypesvcnotallowed"
root@vms61:~/demo4# 

报错,说明现在还不存在 lbtypesvcnotallowed这种资源类型。

首先创建资源类型lbtypesvcnotallowed,编写aa-tmp.yaml内容如下。

root@vms61:~/demo4# cat aa-tmp.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: lbtypesvcnotallowed
spec:
  crd:
    spec:
      names:
        kind: LBTypeSvcNotAllowed
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package kubernetes.admission
        violation[{"msg": msg}] {
                    input.review.kind.kind = "Service"
                    input.review.operation = "CREATE"
                    input.review.object.spec.type = "LoadBalancer"
                    msg := "不允许创建LB类型的service!"
        }
root@vms61:~/demo4#

这里创建了一个名字为lbtypesvcnotallowed的资源类型,禁止创建LB类型的service,如果创建的话,则会有"不允许创建LB类型的service!" 报错。
下面创建资源类型。

root@vms61:~/demo4# kubectl apply -f aa-tmp.yaml 
constrainttemplate.templates.gatekeeper.sh/lbtypesvcnotallowed created
root@vms61:~/demo4# 
root@vms61:~/demo4# kubectl get lbtypesvcnotallowed
No resources found
root@vms61:~/demo4# 

现在已经存在 lbtypesvcnotallowed这种资源类型了,只是下面还没有任何的资源。
下面创建名字为deny-create-lb-type-svc的lbtypesvcnotallowed,编写bb-contraint.yaml内容如下。

root@vms61:~/demo4# cat bb-contraint.yaml 
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: LBTypeSvcNotAllowed
metadata:
  name: deny-create-lb-type-svc
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Service"]
    namespaces:
      - "default"
root@vms61:~/demo4#

创建此资源。

root@vms61:~/demo4# kubectl apply -f bb-contraint.yaml
lbtypesvcnotallowed.constraints.gatekeeper.sh/deny-create-lb-type-svc created
root@vms61:~/demo4# 
root@vms61:~/demo4# kubectl get lbtypesvcnotallowed
NAME                      AGE
deny-create-lb-type-svc   4s
root@vms61:~/demo4#

再次创建LoadBalancer的service。

root@vms61:~/demo4# kubectl expose --name=svc1 pod pod1 --port=80 --type=LoadBalancer
Error from server ([deny-create-lb-type-svc] 不允许创建LB类型的service!): admission webhook "validation.gatekeeper.sh" denied the request: [deny-create-lb-type-svc] 不允许创建LB类型的service!
root@vms61:~/demo4#

这里可以看到已经不允许创建了。
删除lbtypesvcnotallowed,则下面的资源会一起删除掉。

root@vms61:~/demo4# kubectl delete -f aa-tmp.yaml 
constrainttemplate.templates.gatekeeper.sh "lbtypesvcnotallowed" deleted
root@vms61:~/demo4#

相关新闻

发表回复

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

                                                                                                                                    RHCE9学习指南连载,点击阅读