- 一.系統環境
- 二.前言
- 三.OPA Gatekeeper簡介
- 四.在kubernetes上安裝OPA Gatekeeper
- 五.gatekeeper規則
- 5.1 使用gatekeeper禁止某些網站的映象建立pod
- 5.2 使用gatekeeper禁止建立LoadBalancer型別的Services服務
- 六.總結
一.系統環境
本文主要基於Kubernetes1.22.2和Linux作業系統Ubuntu 18.04。
伺服器版本 | docker軟體版本 | Kubernetes(k8s)叢集版本 | CPU架構 |
---|---|---|---|
Ubuntu 18.04.5 LTS | Docker version 20.10.14 | v1.22.2 | x86_64 |
Kubernetes叢集架構:k8scludes1作為master節點,k8scludes2,k8scludes3作為worker節點。
伺服器 | 作業系統版本 | CPU架構 | 程序 | 功能描述 |
---|---|---|---|---|
k8scludes1/192.168.110.128 | Ubuntu 18.04.5 LTS | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master節點 |
k8scludes2/192.168.110.129 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
k8scludes3/192.168.110.130 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
二.前言
隨著雲端計算和容器技術的普及,Kubernetes已經成為現代應用程式部署和運維的事實標準。然而,隨著叢集規模的擴大和許可權的分散,如何保證叢集的安全性和合規性成為了一個亟待解決的問題。OPA Gatekeeper作為Open Policy Agent在Kubernetes上的一個外掛,為Kubernetes叢集提供了強大的策略治理能力。
使用OPA Gatekeeper的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Ubuntu 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/17632858.html。
三.OPA Gatekeeper簡介
OPA Gatekeeper是一個開源專案,它將Open Policy Agent(開放策略代理)整合到Kubernetes中,以實現細粒度的策略控制。OPA是一個通用的策略引擎,可以評估策略並做出決策,這些策略定義了哪些資源可以被訪問以及如何訪問。透過將OPA整合到Kubernetes中,我們可以充分利用Kubernetes的資源管理能力和OPA的策略治理能力,構建一個既安全又靈活的雲原生應用環境。
請求透過認證和鑑權之後、被持久化為 Kubernetes 中的物件之前,Kubernetes 允許透過 admission controller webhooks 將策略決策與 API 伺服器分離,從而攔截這些請求。Gatekeeper 建立的目的是使使用者能夠透過配置(而不是程式碼)自定義控制許可,並使使用者瞭解叢集的狀態,而不僅僅是針對評估狀態的單個物件,在這些物件准許加入的時候。
docker也可以使用Open Policy Agent(OPA)進行訪問控制,詳細操作請檢視部落格《docker使用Open Policy Agent(OPA)進行訪問控制》。
四.在kubernetes上安裝OPA Gatekeeper
建立目錄存放檔案。
root@k8scludes1:~# mkdir gatekeeper
root@k8scludes1:~# cd gatekeeper/
OPA Gatekeeper安裝官網為:https://open-policy-agent.github.io/gatekeeper/website/docs/install/ 。
下載gatekeeper的安裝yaml檔案。
root@k8scludes1:~/gatekeeper# wget https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.8/deploy/gatekeeper.yaml
root@k8scludes1:~/gatekeeper# ls
gatekeeper.yaml
檢視部署gatekeeper所需的映象。
root@k8scludes1:~/gatekeeper# grep image gatekeeper.yaml
image: openpolicyagent/gatekeeper:v3.8.1
imagePullPolicy: Always
image: openpolicyagent/gatekeeper:v3.8.1
imagePullPolicy: Always
在k8s的worker節點提前下載好gatekeeper:v3.8.1映象。
root@k8scludes2:~# docker pull openpolicyagent/gatekeeper:v3.8.1
root@k8scludes2:~# docker images | grep gatekeeper
openpolicyagent/gatekeeper v3.8.1 b14dbfb1e27a 3 weeks ago 70.3MB
root@k8scludes3:~# docker pull openpolicyagent/gatekeeper:v3.8.1
root@k8scludes3:~# docker images | grep gatekeeper
openpolicyagent/gatekeeper v3.8.1 b14dbfb1e27a 3 weeks ago 70.3MB
修改映象下載策略為IfNotPresent。
root@k8scludes1:~/gatekeeper# vim gatekeeper.yaml
root@k8scludes1:~/gatekeeper# grep image gatekeeper.yaml
image: openpolicyagent/gatekeeper:v3.8.1
imagePullPolicy: IfNotPresent
image: openpolicyagent/gatekeeper:v3.8.1
imagePullPolicy: IfNotPresent
在Kubernetes 中一切都可視為資源,Kubernetes 1.7 之後增加了對 CRD 自定義資源二次開發能力來擴充套件 Kubernetes API,透過 CRD 我們可以向 Kubernetes API 中增加新資源型別,而不需要修改 Kubernetes 原始碼來建立自定義的 API server,該功能大大提高了 Kubernetes 的擴充套件能力。當你建立一個新的CustomResourceDefinition (CRD)時,Kubernetes API伺服器將為你指定的每個版本建立一個新的RESTful資源路徑,我們可以根據該api路徑來建立一些我們自己定義的型別資源。CRD可以是名稱空間的,也可以是叢集範圍的,由CRD的作用域(scpoe)欄位中所指定的,與現有的內建物件一樣,刪除名稱空間將刪除該名稱空間中的所有自定義物件,CRD是全域性生效的。
檢視crd。
root@k8scludes1:~/gatekeeper# kubectl get crd
NAME CREATED AT
bgpconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
bgppeers.crd.projectcalico.org 2022-04-16T18:41:13Z
......
ipreservations.crd.projectcalico.org 2022-04-16T18:41:13Z
issuers.cert-manager.io 2022-04-24T17:07:46Z
kubecontrollersconfigurations.crd.projectcalico.org 2022-04-16T18:41:13Z
networkpolicies.crd.projectcalico.org 2022-04-16T18:41:13Z
networksets.crd.projectcalico.org 2022-04-16T18:41:13Z
orders.acme.cert-manager.io 2022-04-24T17:07:46Z
現在還沒有gatekeeper的crd資源。
root@k8scludes1:~/gatekeeper# kubectl get crd | grep gatekeeper
部署gatekeeper。
root@k8scludes1:~/gatekeeper# kubectl apply -f gatekeeper.yaml
namespace/gatekeeper-system created
resourcequota/gatekeeper-critical-pods created
customresourcedefinition.apiextensions.k8s.io/assign.mutations.gatekeeper.sh created
customresourcedefinition.apiextensions.k8s.io/assignmetadata.mutations.gatekeeper.sh created
customresourcedefinition.apiextensions.k8s.io/configs.config.gatekeeper.sh created
......
Warning: policy/v1beta1 PodDisruptionBudget is deprecated in v1.21+, unavailable in v1.25+; use policy/v1 PodDisruptionBudget
poddisruptionbudget.policy/gatekeeper-controller-manager created
mutatingwebhookconfiguration.admissionregistration.k8s.io/gatekeeper-mutating-webhook-configuration created
validatingwebhookconfiguration.admissionregistration.k8s.io/gatekeeper-validating-webhook-configuration created
gatekeeper安裝好之後,會建立相關的crd資源。
root@k8scludes1:~/gatekeeper# kubectl get crd | grep gatekeeper
assign.mutations.gatekeeper.sh 2022-05-30T04:07:59Z
assignmetadata.mutations.gatekeeper.sh 2022-05-30T04:07:59Z
configs.config.gatekeeper.sh 2022-05-30T04:07:59Z
constraintpodstatuses.status.gatekeeper.sh 2022-05-30T04:07:59Z
constrainttemplatepodstatuses.status.gatekeeper.sh 2022-05-30T04:07:59Z
constrainttemplates.templates.gatekeeper.sh 2022-05-30T04:07:59Z
modifyset.mutations.gatekeeper.sh 2022-05-30T04:08:00Z
mutatorpodstatuses.status.gatekeeper.sh 2022-05-30T04:08:00Z
providers.externaldata.gatekeeper.sh 2022-05-30T04:08:00Z
五.gatekeeper規則
5.1 使用gatekeeper禁止某些網站的映象建立pod
在k8s裡安裝好gatekeeper之後,需要定義一系列的規則,gatekeeper-tmp.yaml表示建立一個名為BlacklistImages的crd模板,透過CRD自定義了一個資源型別 BlacklistImages,並定義了規則:“字首為docker-fake.io/和google-gcr-fake.com/的映象建立不了pod”。
root@k8scludes1:~/gatekeeper# vim gatekeeper-tmp.yaml
root@k8scludes1:~/gatekeeper# cat gatekeeper-tmp.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
#映象不以docker-fake.io/和google-gcr-fake.com/開頭
not startswith(image, "docker-fake.io/")
not startswith(image, "google-gcr-fake.com/")
}
#當出現以docker-fake.io/和google-gcr-fake.com/開頭的映象,則禁止並輸出"not trusted image!"
violation[{"msg": msg}] {
not images
msg := "not trusted image!"
}
target: admission.k8s.gatekeeper.sh
建立自定義資源型別BlacklistImages。
root@k8scludes1:~/gatekeeper# kubectl apply -f gatekeeper-tmp.yaml
constrainttemplate.templates.gatekeeper.sh/blacklistimages created
root@k8scludes1:~/gatekeeper# kubectl get crd | grep blacklistimages
blacklistimages.constraints.gatekeeper.sh 2022-05-30T08:18:21Z
利用自定義資源型別BlacklistImages建立一個例項,指定用於哪個資源(pod/deploy/job)。
root@k8scludes1:~/gatekeeper# vim gatekeeper-blacklist.yaml
root@k8scludes1:~/gatekeeper# cat gatekeeper-blacklist.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: BlacklistImages
metadata:
generation: 1
managedFields:
name: pod-trusted-images
resourceVersion: "14449"
spec:
match:
kinds:
- apiGroups:
- ""
#表示自定義資源型別BlacklistImages用於pod
kinds:
- Pod
建立例項,pod-trusted-images就是自定義資源型別BlacklistImages的例項。
root@k8scludes1:~/gatekeeper# kubectl get BlacklistImages
No resources found
root@k8scludes1:~/gatekeeper# kubectl apply -f gatekeeper-blacklist.yaml
blacklistimages.constraints.gatekeeper.sh/pod-trusted-images created
root@k8scludes1:~/gatekeeper# kubectl get BlacklistImages
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
pod-trusted-images
編輯pod配置檔案,表示使用hub.c.163.com/library/nginx:latest映象建立一個pod。
root@k8scludes1:~/gatekeeper# vim pod.yaml
root@k8scludes1:~/gatekeeper# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- image: hub.c.163.com/library/nginx:latest
imagePullPolicy: IfNotPresent
name: podtest
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
因為映象名符合Gatekeeper規則,pod建立成功。
root@k8scludes1:~/gatekeeper# kubectl apply -f pod.yaml
pod/podtest created
root@k8scludes1:~/gatekeeper# kubectl get pod
NAME READY STATUS RESTARTS AGE
podtest 1/1 Running 0 9s
刪除pod。
root@k8scludes1:~/gatekeeper# kubectl delete pod podtest
pod "podtest" deleted
在k8s的worker節點給hub.c.163.com/library/nginx:latest進行打標籤重新命名。
root@k8scludes2:~# docker tag hub.c.163.com/library/nginx:latest docker-fake.io/library/nginx:1.12.5
root@k8scludes2:~# docker tag hub.c.163.com/library/nginx:latest google-gcr-fake.com/library/nginx:1.12.5
root@k8scludes2:~# docker images | grep nginx
docker-fake.io/library/nginx 1.12.5 46102226f2fd 5 years ago 109MB
google-gcr-fake.com/library/nginx 1.12.5 46102226f2fd 5 years ago 109MB
hub.c.163.com/library/nginx latest 46102226f2fd 5 years ago 109MB
root@k8scludes3:~# docker tag hub.c.163.com/library/nginx:latest docker-fake.io/library/nginx:1.12.5
root@k8scludes3:~# docker tag hub.c.163.com/library/nginx:latest google-gcr-fake.com/library/nginx:1.12.5
root@k8scludes3:~# docker images | grep nginx
docker-fake.io/library/nginx 1.12.5 46102226f2fd 5 years ago 109MB
google-gcr-fake.com/library/nginx 1.12.5 46102226f2fd 5 years ago 109MB
hub.c.163.com/library/nginx latest 46102226f2fd 5 years ago 109MB
編輯pod配置檔案,表示使用docker-fake.io/library/nginx:1.12.5映象建立pod。
root@k8scludes1:~/gatekeeper# vim pod.yaml
root@k8scludes1:~/gatekeeper# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- image: docker-fake.io/library/nginx:1.12.5
imagePullPolicy: IfNotPresent
name: podtest
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
建立pod失敗,映象不符合gatekeeper規則,[pod-trusted-images] not trusted image!。
root@k8scludes1:~/gatekeeper# kubectl apply -f pod.yaml
Error from server (Forbidden): error when creating "pod.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [pod-trusted-images] not trusted image!
這次使用google-gcr-fake.com/library/nginx:1.12.5映象建立pod,可以發現,因為BlacklistImages定義了規則:“字首為docker-fake.io/和google-gcr-fake.com/的映象建立不了pod”,使用docker-fake.io/library/nginx:1.12.5映象和google-gcr-fake.com/library/nginx:1.12.5映象建立不了pod。
root@k8scludes1:~/gatekeeper# vim pod.yaml
root@k8scludes1:~/gatekeeper# grep image: pod.yaml
- image: google-gcr-fake.com/library/nginx:1.12.5
root@k8scludes1:~/gatekeeper# kubectl apply -f pod.yaml
Error from server (Forbidden): error when creating "pod.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [pod-trusted-images] not trusted image!
5.2 使用gatekeeper禁止建立LoadBalancer型別的Services服務
aa-tmp.yaml檔案表示建立一個名為LBTypeSvcNotAllowed的CRD模板,透過CRD自定義了一個資源型別LBTypeSvcNotAllowed,並定義了規則:“禁止建立LoadBalancer型別的Services服務”。
root@k8scludes1:~/gatekeeper# vim aa-tmp.yaml
root@k8scludes1:~/gatekeeper# cat aa-tmp.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: lbtypesvcnotallowed
spec:
crd:
spec:
names:
kind: LBTypeSvcNotAllowed
#listKind: LBTypeSvcNotAllowedList
#plural: lbtypesvcnotallowed
#singular: 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 := "LoadBalancer Services are not permitted"
}
建立自定義資源型別LBTypeSvcNotAllowed。
root@k8scludes1:~/gatekeeper# kubectl apply -f aa-tmp.yaml
constrainttemplate.templates.gatekeeper.sh/lbtypesvcnotallowed created
root@k8scludes1:~/gatekeeper# kubectl get LBTypeSvcNotAllowed
No resources found
root@k8scludes1:~/gatekeeper# kubectl get crd | grep lbtypesvcnotallowed
lbtypesvcnotallowed.constraints.gatekeeper.sh 2022-05-30T09:14:53Z
利用自定義資源型別LBTypeSvcNotAllowed建立一個例項,bb-contraint.yaml表示把自定義資源LBTypeSvcNotAllowed應用於bb名稱空間的Service上。
root@k8scludes1:~/gatekeeper# vim bb-contraint.yaml
root@k8scludes1:~/gatekeeper# cat bb-contraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: LBTypeSvcNotAllowed
metadata:
name: deny-lb-type-svc-dev-ns
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Service"]
namespaces:
- "bb"
建立例項,deny-lb-type-svc-dev-ns就是自定義資源型別LBTypeSvcNotAllowed的例項。
root@k8scludes1:~/gatekeeper# kubectl apply -f bb-contraint.yaml
lbtypesvcnotallowed.constraints.gatekeeper.sh/deny-lb-type-svc-dev-ns created
root@k8scludes1:~/gatekeeper# kubectl get LBTypeSvcNotAllowed
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
deny-lb-type-svc-dev-ns 0
建立bb名稱空間。
root@k8scludes1:~/gatekeeper# kubectl create ns bb
namespace/bb created
root@k8scludes1:~/gatekeeper# kubectl get pod -n bb
No resources found in bb namespace.
編輯pod配置檔案,表示使用nginx建立pod。
root@k8scludes1:~/gatekeeper# vim pod.yaml
root@k8scludes1:~/gatekeeper# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: podtest
name: podtest
spec:
terminationGracePeriodSeconds: 0
containers:
- image: hub.c.163.com/library/nginx:latest
imagePullPolicy: IfNotPresent
name: podtest
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
使用hub.c.163.com/library/nginx:latest映象在bb名稱空間建立pod。
root@k8scludes1:~/gatekeeper# kubectl apply -f pod.yaml -n bb
pod/podtest created
root@k8scludes1:~/gatekeeper# kubectl get pod -n bb
NAME READY STATUS RESTARTS AGE
podtest 1/1 Running 0 18s
ClusterIP型別的svc建立成功。關於svc的詳細操作,請檢視部落格《Kubernetes(k8s)服務service:service的發現和service的釋出》。
root@k8scludes1:~/gatekeeper# kubectl expose --name=bb-nginxsvc pod podtest -n bb --port=80
service/bb-nginxsvc exposed
root@k8scludes1:~/gatekeeper# kubectl get svc -n bb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bb-nginxsvc ClusterIP 10.109.160.157 <none> 80/TCP 7s
刪除SVC。
root@k8scludes1:~/gatekeeper# kubectl delete svc bb-nginxsvc -n bb
service "bb-nginxsvc" deleted
NodePort型別的svc建立成功。
root@k8scludes1:~/gatekeeper# kubectl expose pod podtest --name=bb-nginxsvc --port=80 -n bb --type=NodePort
service/bb-nginxsvc exposed
root@k8scludes1:~/gatekeeper# kubectl get svc -n bb
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bb-nginxsvc NodePort 10.106.79.112 <none> 80:31311/TCP 21s
刪除SVC。
root@k8scludes1:~/gatekeeper# kubectl delete svc bb-nginxsvc -n bb
service "bb-nginxsvc" deleted
因為不符合gatekeeper規則,LoadBalancer型別的svc不能建立,LoadBalancer Services are not permitted。
在bb名稱空間,LoadBalancer型別的svc不能建立,其他型別的svc可以建立,在其他名稱空間可以建立所有型別的svc。
root@k8scludes1:~/gatekeeper# kubectl expose pod podtest --name=bb-nginxsvc --port=80 -n bb --type=LoadBalancer
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [deny-lb-type-svc-dev-ns] LoadBalancer Services are not permitted
刪除pod。
root@k8scludes1:~/gatekeeper# kubectl get all -n bb
NAME READY STATUS RESTARTS AGE
pod/podtest 1/1 Running 0 11m
root@k8scludes1:~/gatekeeper# kubectl delete pod podtest -n bb
pod "podtest" deleted
六.總結
OPA Gatekeeper為Kubernetes提供了強大的策略管理能力,使您能夠實施自定義策略以控制資源訪問。透過使用OPA Gatekeeper,您可以確保Kubernetes叢集的安全性和合規性。