Kyverno는 CNCF 프로젝트로, K8S의 Policy를 동적으로 관리할 수 있는 Policy-as-Code이다.
Dynamic Admission Control로 실행되며, Mutating/Validating admission 에서 동작하여 허용/거부 결과를 반환한다.
Admission Controller는 쿠버네티스에서 인증/인가 단계를 거치고 나서 실행되는 컨트롤러인데 API로의 요청을 가로채서 변경 또는 허용/거부를 할 수 있다.
그래서 Kyverno 정책을 사용하여 validate(검증), mutate(변경), generate(생성), verify images(이미지 검증)을 하면 보안 표준을 시행할 수 있다.
또한, Kyverno 정책은 리소스의 kind, name, label selectors 등을 match시켜 사용한다.
Match와 Exclude는 정책을 적용할 대상이며,
Kyverno가 적용할 수 있는 정책은 Validate, Mutate, Generate, Verify Images가 있다.
실습으로 동작을 확인해 볼 것이다.
resourceFiltersExcludeNamespaces
로 정책에서 제외할 네임스페이스를 지정할 수 있다.
cat << EOF > kyverno-value.yaml
config:
resourceFiltersExcludeNamespaces: [ kube-system ]
EOF
네임스페이스를 생성하고 헬름으로 배포한다.
kubectl create ns kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --version 3.2.0-rc.3 -f kyverno-value.yaml -n kyverno
설치 확인
ClusterPolicy를 생성한다
validationFailureAction
은 Enforce로 지정하고 대상은 POD이다.
validate
부분에서 labels에서 key 값에 team이 있어야 POD 생성이 가능하다.
kubectl create -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-team
match:
any:
- resources:
kinds:
- Pod
validate:
message: "label 'team' is required"
pattern:
metadata:
labels:
team: "?*"
EOF
ClusterPolicy 생성 확인
레이블 지정 없이 POD 생성 시도
레이블 key에 team이 있으니까 생성됨
policyreport 확인해 보면?
results
에 pass
확인!
ClusterPolicy를 생성한다
이번엔 mutate
에 +(team)으로 labels의 key 값에 team이 없으면 team=bravo를 생성하고 key 값에 team이 있으면 생성하지 않는다.
마찬가지로 대상은 POD이다.
kubectl create -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-labels
spec:
rules:
- name: add-team
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
metadata:
labels:
+(team): bravo
EOF
ClusterPolicy 생성 확인
label에 key 값이 team인지 아닌지에 따라 mutate 동작 유무가 달라졌다!
테스트 secret을 하나 생성했다.
kubectl -n default create secret docker-registry **regcred** \
--docker-server=myinternalreg.corp.com \
--docker-username=john.doe \
--docker-password=Passw0rd123! \
--docker-email=john.doe@corp.com
ClusterPolicy를 생성한다
모든 네임스페이스를 대상으로 하며,
generate
를 통해 default 네임스페이스의 regcred라는 secret을 복제해서 생성한다.
kubectl create -f- << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: sync-secrets
spec:
rules:
- name: sync-image-pull-secret
match:
any:
- resources:
kinds:
- Namespace
generate:
apiVersion: v1
kind: Secret
name: regcred
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: regcred
EOF
새로운 네임스페이스를 만들자 마자 동일한 secret이 바로 생성되었다.
default와 mytestns 둘다 같은 이름의 secret이 있다!
기존 네임스페이스에는 영향을 주지 않고 신규 네임스페이스를 생성할 때만 영향을 주는가해서 테스트해 보았다
ClusterPolicy를 생성하기 전에 만든 testns1과 2에는 영향받지 않고 testns3에만 secret이 생성된 걸 알 수 있었다.
재밌었다!
Admission Control을 맞닥뜨렸을 때가 어려웠지,
막상 Kyverno를 알고 실습하니 이해하기가 수월했다.
동작 방식도 이해가 되고 활용법도 어렵지 않아서 꼭 실습해 보기를 추천한다!
특히 나는 generate가 맘에 들었다.
대상의 리소스가 생성될 때마다 규칙대로 무언가 실행된다는 것은 운영의 편리성이 증가할 것 같기 때문이다.
안녕하세요.