안녕하세요. 오늘은 Kyverno라는 애드온을 이용해 특정 상황에서의 파드 생성을 제한해 보겠습니다.
Kyverno란?
Kyverno는 CNCF의 Incubating 프로젝트로서 클라우드 네이티브 정책 엔진입니다. Kyverno를 사용하면 플랫폼 엔지니어가 보안, 규정 준수, 모범 사례 검증을 자동화하고 애플리케이션 팀에 안전한 셀프서비스를 제공할 수 있습니다. Kyverno 정책을 사용하여 커스텀 리소스를 포함한 모든 Kubernetes 리소스를 검증, 변형, 생성 및 삭제할 수 있습니다. OPA와 달리 새로운 언어를 배울 필요 없이 YAML 기반 선언적 Kubernetes 리소스로 정책을 사용할 수 있습니다.
Kyverno 사이트에 접속하여 다양한 정보들을 알아보세요!
Kyverno
Kyverno is a policy engine designed for Kubernetes
kyverno.io
Policy 예제
Kyverno는 하나의 네임스페이스에만 적용되는 Policy, 클러스터 전체에 적용되는 ClusterPolicy 정책이 있습니다. 상세적인 정책 설정들은 다 설명드리기 어렵고, 정책 예시를 통해 간단하게 이해해 봅시다. 정책에 대해 더 상세히 알고 싶다면, 다음 페이지를 참고하세요.
https://kyverno.io/docs/writing-policies/
Writing Policies
Create policies which can validate, mutate, generate, and clean up resources as well as perform verification of container images.
kyverno.io
다음 정책은 prod 네임스페이스에 파드가 생성될 때, "environment: prod"라는 라벨이 없으면 파드 생성을 거부합니다.
- kind가 Policy이므로 정책이 적용될 네임스페이스인 prod를 지정했습니다.
- spec.background를 true로 설정한다면 백그라운드 스캐닝을 통해 기존 리소스의 위반 사항을 찾고, 정책 리포트를 생성합니다. 지금은 필요 없으므로 false로 설정했습니다.
- spec.rules는 쿠버네티스 내에서 어떠한 행동에 정책이 개입할지 정하는 항목입니다. 이번 정책에서는 파드가 생성될 때로 지정했습니다.
- spec.validate는 어떠한 것을 검증하고, 검증에 실패했을 때의 행동을 서술하는 항목입니다. 검증에 실패했을 때의 행동으로 요청을 거부하는 "Enforce", 요청은 허가하지만 정책 리포트에 기록되며 경고를 보내는 "Audit"이 있습니다. 이번 정책에서는 파드에 "environment: prod" 라벨이 있는지 검사하며, 이에 맞지 않은 경우 생성을 거부하고 메시지를 보냅니다.
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: prod-check
namespace: prod
spec:
background: false
rules:
- name: check-for-labels
match:
any:
- resources:
kinds:
- Pod
operations:
- CREATE
validate:
failureAction: Enforce
message: "The label `environment: prod` is required."
pattern:
metadata:
labels:
environment: prod
다음 정책은 모든 네임스페이스에 파드가 생성될 때, 파드 이미지의 태그가 없으면 생성을 거부하고 "latest"라면 경고만을 보냅니다. 간단하게 추가 설명을 약간 하겠습니다.
- kind가 ClusterPolicy이므로 모든 네임스페이스에 생성되는 파드를 검사합니다.
- operations 항목이 없다면 기본값으로 CREATE, UPDATE가 지정됩니다.
- foreach로 서로 다른 하위 요소를 처리하기 위한 여러 항목을 포함할 수 있습니다.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
background: false
rules:
- name: require-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "An image tag is required."
foreach:
- list: "request.object.spec.containers"
pattern:
image: "*:*"
- list: "request.object.spec.initContainers"
pattern:
image: "*:*"
- list: "request.object.spec.ephemeralContainers"
pattern:
image: "*:*"
- name: validate-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Audit
message: "Using a mutable image tag e.g. 'latest' is not allowed."
foreach:
- list: "request.object.spec.containers"
pattern:
image: "!*:latest"
- list: "request.object.spec.initContainers"
pattern:
image: "!*:latest"
- list: "request.object.spec.ephemeralContainers"
pattern:
image: "!*:latest"
실습
쿠버네티스 클러스터와 파드가 실행될 노드가 필요합니다. 저는 EKS를 사용했고, CloudShell을 이용해 작업 중입니다.
먼저, prod와 beta 네임스페이스를 생성하겠습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl create namespace prod
namespace/prod created
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl create namespace beta
namespace/beta created
이번 글의 주인공인 Kyverno 정책 엔진을 Helm을 통해 설치하겠습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ helm repo add kyverno https://kyverno.github.io/kyverno/
"kyverno" has been added to your repositories
[cloudshell-user@ip-10-0-2-90 ~]$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "kyverno" chart repository
Update Complete. ⎈Happy Helming!⎈
[cloudshell-user@ip-10-0-2-90 ~]$ helm install kyverno kyverno/kyverno -n kyverno --create-namespace
NAME: kyverno
LAST DEPLOYED: Wed Jan 1 05:53:17 2025
NAMESPACE: kyverno
STATUS: deployed
REVISION: 1
NOTES:
Chart version: 3.3.4
Kyverno version: v1.13.2
Thank you for installing kyverno! Your release is named kyverno.
The following components have been installed in your cluster:
- CRDs
- Admission controller
- Reports controller
- Cleanup controller
- Background controller
⚠️ WARNING: Setting the admission controller replica count below 2 means Kyverno is not running in high availability mode.
⚠️ WARNING: PolicyExceptions are disabled by default. To enable them, set '--enablePolicyException' to true.
💡 Note: There is a trade-off when deciding which approach to take regarding Namespace exclusions. Please see the documentation at https://kyverno.io/docs/installation/#security-vs-operability to understand the risks.
콘솔에 나타나는 경고는 controller를 하나씩만 설치하여 고가용성에 문제가 되기 때문에 나타납니다. YAML을 이용하거나 고가용성 모드로 설치하고 싶다면 다음 사이트를 참고해 주세요.
https://kyverno.io/docs/installation/methods/
Installation Methods
Methods for installing Kyverno
kyverno.io
앞에서 설명드린 "prod-check" Policy를 먼저 적용하겠습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl apply -f prod-check.yaml
policy.kyverno.io/prod-check created
Policy와 상관없는 beta 네임스페이스에 파드를 생성하는 것은 아무 문제없습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx -n beta
pod/nginx created
그러나 라벨 설정 없이 prod 네임스페이스에 파드를 생성하려 하면 메시지가 나타나며 생성 요청을 거부합니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx -n prod
Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
resource Pod/prod/nginx was blocked due to the following policies
prod-check:
check-for-labels: 'validation error: The label `environment: prod` is required.
rule check-for-labels failed at path /metadata/labels/environment/'
"environment: prod" 라벨을 추가하면 생성이 잘 되는 것을 볼 수 있습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx -n prod -l environment=prod
pod/nginx created
정책과 nginx 파드를 모두 정리하고, 앞에서 설명드린 "disallow-latest-tag" ClusterPolicy를 적용하겠습니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl apply -f disallow-latest-tag.yaml
clusterpolicy.kyverno.io/disallow-latest-tag created
이미지 태그가 없다면 prod, beta 네임스페이스 모두 파드 생성이 거부됩니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx -n prod
Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
resource Pod/prod/nginx was blocked due to the following policies
disallow-latest-tag:
require-image-tag: 'validation failure: validation error: An image tag is required.
rule require-image-tag failed at path /image/'
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx -n beta
Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
resource Pod/beta/nginx was blocked due to the following policies
disallow-latest-tag:
require-image-tag: 'validation failure: validation error: An image tag is required.
rule require-image-tag failed at path /image/'
이미지 태그로 latest를 지정하면, 생성은 허용되나 경고 메시지가 나타납니다.
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl run nginx --image=nginx:latest -n prod
pod/nginx created
[cloudshell-user@ip-10-0-2-90 ~]$ kubectl describe pod nginx -n prod
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning PolicyViolation 13s kyverno-admission policy disallow-latest-tag/validate-image-tag fail: validation failure: validation error: Using a mutable image tag e.g. 'latest' is not allowed. rule validate-image-tag failed at path /image/
Warning PolicyViolation 13s kyverno-admission policy disallow-latest-tag/require-image-tag pass: rule passed
마무리
Kyverno를 실습하기 위해 쿠버네티스 환경을 만들기 번거롭다면 Kyverno Playground를 이용하셔도 됩니다.
https://playground.kyverno.io/
Kyverno Playground
playground.kyverno.io
오늘은 보안 정책 엔진인 Kyverno에 대해 간단히 설명드렸습니다. 도움이 되셨다면 다행이고, 다음에도 좋은 CNCF 프로젝트에 대해 설명드리겠습니다.
오늘의 글은 여기까지입니다. 감사합니다!