LabHub
学习 学习路径 课程

KCA — Kyverno 认证助理

标签规则被放宽了,却没有人发现

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

Kyverno CLI 의 apply·test·jp 로 정책이 무엇을 거부하고 무엇을 바꾸고 무엇을 만드는지 클러스터에 올리기 전에 판정하고, 그 판정을 시험 묶음과 CI 스크립트로 고정합니다.

왜 중요한가

어드미션 정책은 틀리면 조용합니다. 검증 규칙을 느슨하게 고친 실수는 아무 요청도 막지 않을 뿐 오류를 내지 않고, 변형 규칙의 앵커 하나는 이미 값이 있는 리소스를 건드리는지 아닌지를 바꿉니다. 운영 클러스터에서 그 차이를 발견하면 이미 늦습니다. kyverno test 는 "이 리소스는 통과, 저 리소스는 실패, 이 리소스는 이렇게 바뀐다" 는 기대를 먼저 적어 두고 엔진의 실제 판정과 비교합니다. 그래서 정책을 고친 사람이 의도하지 않은 완화를 했을 때 시험이 먼저 빨간불을 켭니다. 클러스터에 없는 ConfigMap 이나 API 호출 결과는 values 파일로 채우고, 조건식의 JMESPath 는 kyverno jp 로 따로 돌려 보면서 정책 저장소를 코드처럼 검증합니다.

단계

  1. /root/kca-cli/validate/policy.yaml 에 ClusterPolicy require-team 을 작성하세요. 규칙 check-team 은 Pod 를 골라 metadata.labels.team 이 비어 있지 않은 값이어야 한다고 요구하고 failureAction 은 Enforce 입니다. /root/kca-cli/validate/resources.yaml 에는 Pod good(라벨 team=pay), 라벨 없는 Pod bad, 파드 템플릿에 team 라벨이 없는 Deployment web 을 둡니다(모두 namespace default). kyverno apply--policy-report 를 붙여 실행하고 표준 출력을 /root/kca-cli/apply-report.yaml 에 저장하세요.
  2. /root/kca-cli/validate/kyverno-test.yaml 에 Test 를 작성하세요(apiVersion cli.kyverno.io/v1alpha1). policies 는 policy.yaml, resources 는 resources.yaml 이고, results 에 good 은 pass, bad 는 fail, Deployment web 은 1단계 보고서에 나온 자동 생성 규칙 이름으로 fail 을 기대합니다. kyverno test /root/kca-cli/validate 가 3건 모두 통과해야 합니다.
  3. /root/kca-cli/validate/root/kca-cli/regressed 로 통째로 복사하고, 복사본의 policy.yaml 에서 team 키만 등가 앵커 =(team) 으로 바꾸세요(라벨이 없으면 통과하게 되는 흔한 실수). kyverno test /root/kca-cli/regressed --remove-color 의 출력 전체를 /root/kca-cli/regression.txt 에 저장하고 종료 코드도 확인하세요. 요약 줄과 종료 코드만 보지 말고 표의 RESULT·REASON 열에서 기대와 실제가 어긋난 행을 찾습니다. 원본 validate 는 그대로 통과해야 합니다.
  4. /root/kca-cli/mutate/ 에 ClusterPolicy add-managed-by(규칙 add-label, Pod 에 managed-by: kyverno 라벨을 없을 때만 추가하는 추가 앵커 사용), resources.yaml(라벨 없는 Pod plain, managed-by: helm 라벨이 있는 Pod owned), 변형 뒤 기대 모습 patched.yaml(plain 에 라벨이 붙은 Pod), kyverno-test.yaml 을 두세요. 시험은 plain 을 patchedResources 와 비교해 pass, owned 는 skip 을 기대하고 kyverno test /root/kca-cli/mutate 가 통과해야 합니다.
  5. /root/kca-cli/generate/ 에 ClusterPolicy ns-quota(규칙 gen-quota, Namespace 가 생기면 그 네임스페이스에 ResourceQuota default-quotaspec.hard.pods: "10" 으로 생성, synchronize false), resources.yaml(Namespace team-a), 기대 생성물 generated.yaml, kyverno-test.yaml(team-a 에 대해 generatedResource 비교, pass)을 두고 kyverno test /root/kca-cli/generate 를 통과시키세요.
  6. /root/kca-cli/context/ 에 ClusterPolicy allowed-registries 를 두세요. 규칙 check-registry 는 Pod 에 대해 컨텍스트 reg 로 ConfigMap platform/registry-config 를 읽고, foreach 로 모든 컨테이너 이미지가 reg.data.allowed(쉼표로 구분한 패턴 목록) 중 하나에 맞지 않으면 거부합니다(Enforce). resources.yaml 에는 이미지가 registry.lab/web:1.0 하나인 Pod internal, 거기에 docker.io/busybox:1.36 컨테이너 sidecar 를 더한 Pod external 을 둡니다. 클러스터가 없으므로 values.yaml(kind Values)로 reg.data.allowedregistry.lab/* 로 채우고, kyverno-test.yaml 의 variables 로 연결해 internal pass, external fail 을 통과시키세요.
  7. /root/kca-cli/jp/query.txt 에 JMESPath 식 하나를 쓰세요. Pod 객체를 입력으로 받아 이미지가 registry.lab/ 로 시작하지 않는 컨테이너의 이름 목록을 돌려줘야 합니다. /root/kca-cli/jp/external.yaml 에 6단계의 Pod external 한 개만 두고, kyverno jp query -i jp/external.yaml -q jp/query.txt 의 출력을 /root/kca-cli/jp/result.json 에 저장하세요.
  8. /root/kca-cli/ci.sh 를 실행 가능한 스크립트로 만드세요. 첫 인자로 루트 디렉터리(없으면 /root/kca-cli)를 받아 그 아래 validate·mutate·generate·context 네 디렉터리에 각각 kyverno test 를 돌리고, 하나라도 실패하면 0 이 아닌 값으로 끝나야 합니다. 3단계에서 본 것처럼 종료 코드가 0 이어도 출력 표에 기대와 실제가 어긋난 행(REASON 이 Want ...)이 있으면 실패로 처리해야 합니다. regressed 는 돌리지 않습니다. 채점기는 복사본의 정책·시험을 여러 방식으로 망가뜨려 스크립트가 실패하는지 봅니다.

참고

정책을 올리기 전에 엔진에 먼저 물어본다

/root/kca-cli/validate/policy.yaml 에 ClusterPolicy require-team 을 작성하세요. 규칙 check-team 은 Pod 를 골라 metadata.labels.team 이 비어 있지 않은 값이어야 한다고 요구하고 failureAction 은 Enforce 입니다. /root/kca-cli/validate/resources.yaml 에는 Pod good(라벨 team=pay), 라벨 없는 Pod bad, 파드 템플릿에 team 라벨이 없는 Deployment web 을 둡니다(모두 namespace default). kyverno apply--policy-report 를 붙여 실행하고 표준 출력을 /root/kca-cli/apply-report.yaml 에 저장하세요.

kyverno apply <정책> --resource <리소스> 형태입니다. Pod 대상 규칙이 Deployment 에도 적용되는지, 적용된다면 규칙 이름이 무엇으로 보고되는지 보고서에서 확인하세요. 위반이 있으면 종료 코드가 0 이 아닙니다.

기대 결과를 먼저 적어 두는 시험

/root/kca-cli/validate/kyverno-test.yaml 에 Test 를 작성하세요(apiVersion cli.kyverno.io/v1alpha1). policies 는 policy.yaml, resources 는 resources.yaml 이고, results 에 good 은 pass, bad 는 fail, Deployment web 은 1단계 보고서에 나온 자동 생성 규칙 이름으로 fail 을 기대합니다. kyverno test /root/kca-cli/validate 가 3건 모두 통과해야 합니다.

results 항목마다 policy·rule·resources·kind·result 를 씁니다. Pod 규칙에서 자동 생성된 규칙은 이름 앞에 접두사가 붙습니다.

라벨 규칙을 풀었는데 시험이 먼저 알아챘다

/root/kca-cli/validate/root/kca-cli/regressed 로 통째로 복사하고, 복사본의 policy.yaml 에서 team 키만 등가 앵커 =(team) 으로 바꾸세요(라벨이 없으면 통과하게 되는 흔한 실수). kyverno test /root/kca-cli/regressed --remove-color 의 출력 전체를 /root/kca-cli/regression.txt 에 저장하고 종료 코드도 확인하세요. 요약 줄과 종료 코드만 보지 말고 표의 RESULT·REASON 열에서 기대와 실제가 어긋난 행을 찾습니다. 원본 validate 는 그대로 통과해야 합니다.

=(key) 는 키가 있을 때만 값을 검사합니다. 라벨 맵은 있는데 team 이 없는 리소스가 어느 것인지 보세요. 이 이미지의 CLI(1.13.2)는 fail 을 기대한 리소스가 pass 로 판정되면 REASON 에 그 불일치를 적고도 요약과 종료 코드는 통과로 내보냅니다(실측). 시험 도구가 모든 불일치를 실패로 세는지는 이렇게 일부러 망가뜨려 봐야 압니다.

바뀐 결과까지 비교하는 mutate 시험

/root/kca-cli/mutate/ 에 ClusterPolicy add-managed-by(규칙 add-label, Pod 에 managed-by: kyverno 라벨을 없을 때만 추가하는 추가 앵커 사용), resources.yaml(라벨 없는 Pod plain, managed-by: helm 라벨이 있는 Pod owned), 변형 뒤 기대 모습 patched.yaml(plain 에 라벨이 붙은 Pod), kyverno-test.yaml 을 두세요. 시험은 plain 을 patchedResources 와 비교해 pass, owned 는 skip 을 기대하고 kyverno test /root/kca-cli/mutate 가 통과해야 합니다.

+(key): value 는 키가 없을 때만 넣습니다. 이미 라벨이 있는 리소스에서는 규칙이 아무것도 바꾸지 않으므로 결과가 pass 가 아닐 수 있습니다. patchedResources 는 파일 이름입니다.

만들어질 객체를 미리 비교하는 generate 시험

/root/kca-cli/generate/ 에 ClusterPolicy ns-quota(규칙 gen-quota, Namespace 가 생기면 그 네임스페이스에 ResourceQuota default-quotaspec.hard.pods: "10" 으로 생성, synchronize false), resources.yaml(Namespace team-a), 기대 생성물 generated.yaml, kyverno-test.yaml(team-a 에 대해 generatedResource 비교, pass)을 두고 kyverno test /root/kca-cli/generate 를 통과시키세요.

생성할 객체의 namespace 는 요청 객체의 이름을 변수로 씁니다. 기대 생성물에는 metadata.namespace 까지 들어가야 비교가 맞습니다.

클러스터 없이 ConfigMap 컨텍스트를 채운다

/root/kca-cli/context/ 에 ClusterPolicy allowed-registries 를 두세요. 규칙 check-registry 는 Pod 에 대해 컨텍스트 reg 로 ConfigMap platform/registry-config 를 읽고, foreach 로 모든 컨테이너 이미지가 reg.data.allowed(쉼표로 구분한 패턴 목록) 중 하나에 맞지 않으면 거부합니다(Enforce). resources.yaml 에는 이미지가 registry.lab/web:1.0 하나인 Pod internal, 거기에 docker.io/busybox:1.36 컨테이너 sidecar 를 더한 Pod external 을 둡니다. 클러스터가 없으므로 values.yaml(kind Values)로 reg.data.allowedregistry.lab/* 로 채우고, kyverno-test.yaml 의 variables 로 연결해 internal pass, external fail 을 통과시키세요.

CLI 는 컨텍스트의 configMap 을 조회할 수 없으므로 규칙 단위 values 로 변수 값을 줍니다. 쉼표 문자열을 목록으로 바꾸는 JMESPath 함수가 있습니다. AnyNotIn 은 값 목록의 와일드카드를 이해합니다.

조건식을 정책 밖에서 먼저 돌려 본다

/root/kca-cli/jp/query.txt 에 JMESPath 식 하나를 쓰세요. Pod 객체를 입력으로 받아 이미지가 registry.lab/ 로 시작하지 않는 컨테이너의 이름 목록을 돌려줘야 합니다. /root/kca-cli/jp/external.yaml 에 6단계의 Pod external 한 개만 두고, kyverno jp query -i jp/external.yaml -q jp/query.txt 의 출력을 /root/kca-cli/jp/result.json 에 저장하세요.

필터 식 [?조건] 과 문자열 함수 starts_with 를 씁니다. JMESPath 에서 문자열 리터럴은 작은따옴표입니다(백틱은 JSON 리터럴). 채점기는 다른 Pod 로도 식을 돌려 봅니다.

정책 저장소의 CI 문지기

/root/kca-cli/ci.sh 를 실행 가능한 스크립트로 만드세요. 첫 인자로 루트 디렉터리(없으면 /root/kca-cli)를 받아 그 아래 validate·mutate·generate·context 네 디렉터리에 각각 kyverno test 를 돌리고, 하나라도 실패하면 0 이 아닌 값으로 끝나야 합니다. 3단계에서 본 것처럼 종료 코드가 0 이어도 출력 표에 기대와 실제가 어긋난 행(REASON 이 Want ...)이 있으면 실패로 처리해야 합니다. regressed 는 돌리지 않습니다. 채점기는 복사본의 정책·시험을 여러 방식으로 망가뜨려 스크립트가 실패하는지 봅니다.

출력을 변수나 파일로 받아 종료 코드와 불일치 문구를 둘 다 검사합니다. 반복문에서 첫 실패로 끝내든 모두 돌린 뒤 모아서 끝내든 결과 코드만 정확하면 됩니다. 색 코드가 섞이면 문자열 검색이 빗나가니 --remove-color 를 쓰세요.