KCA(Kyverno Certified Associate)는 CNCF가 2024년 말에 새로 발표한 Kyverno 자격증입니다. 저는 CNCF의 Kubestronaut 멤버 자격으로 KCA 출시 직전 베타 테스터로 시험에 응시했다가 당시 준비가 미흡해 합격하지 못했는데요.

Kyverno와 Policy as Code에 대해 더 공부하고자 최근 KCA 시험을 한 번 더 응시했고, 드디어 합격했습니다. 시험 자료가 많지 않아 불안했는데 다행히 결과가 좋았네요.

이번 응시 경험을 바탕으로, 저처럼 KCA 시험을 준비하는 데 막막함을 느낄 분들을 위해 최근 KCA 시험에 자주 등장했던 핵심 키워드와 개념을 정리해봤습니다.

실습이 아닌 지식과 개념을 평가하는 시험인 만큼, 당락이 결정되는 점수 획득에 도움이 될 수 있을 텐데요. KCA 시험에 관심 또는 응시 계획이 있으시다면 꼭 읽어주세요.

CNCF에서 주최하는 KCA 시험에 자주 등장하는 개념이라면 실제 활용에도 곧잘 쓰인다는 뜻이겠죠? Kyverno에 대해 학습하시는 분들에게도 이번 내용이 도움이 될 거라 생각합니다.


가장 비중이 높은 주제는 Policy 기본 문법

아마 아실 수도 있지만, Kyverno Policy 리소스에서는 여러 Rule을 정의할 수 있습니다. 가장 대표적인 Rule에는 validate(검증), mutate(수정), generate(생성)가 있죠. KCA 시험 범위에서 가장 큰 비중을 차지하는 3가지 핵심 Rule의 문법 중에서도, 최근 시험에서 등장한 주요 키워드를 살펴보겠습니다.

validate Rule의 cel 필드

CEL(Common Expression Language) 문법을 활용해서 validate Rule의 검증 조건을 효율적으로 작성 가능한 validate Rule의 cel 필드의 사용법이 자주 출제되고 있습니다.

validate.cel.expressions 내에 expression 키의 값에 검증 조건을 정의하고, message 키의 값으로 안내할 메시지를 정의 가능한 방식인데요.

Kubernetes 리소스의 검증 대상이 되는 부분은 object.로 명시하며, Kubernetes 리소스가 속한 Namespace를 검증하려면 namespaceObject.로 명시합니다.

CEL은 아래와 같이 프로그래밍 언어에서 보편적으로 지원하는 다양한 연산자를 지원합니다.

  • 비교 연산자(<, >=, != 등)
  • 논리 연산자(||, && 등)
  • 특정 속성이나 값이 객체에 존재하는지 확인(has())
  • 리스트 또는 맵의 모든 요소가 특정 조건을 충족하는지 확인(all())

컨테이너의 Host Port의 허용 범위를 CEL 문법으로 정의한 예시:


validate:
  cel:
    expressions:
    - expression: "object.spec.containers.all(container, !has(container.ports) || container.ports.all(port, !has(port.hostPort) || (port.hostPort >= 5000 && port.hostPort <= 6000)))"
    message: "허용되는 hostPort 범위는 5000 ~ 6000입니다."

mutate Rule의 두 가지 병합 전략

mutate Rule에서는 정책에 의해 변경될 사항을 patchStrategicMergepatchesJson6902 중 하나의 필드로 정의 가능한데요. 두 방식의 차이를 알아두는 것이 중요합니다.

patchStrategicMerge 필드는 리스트로 이루어진 요소를 수정할 때 유용합니다. 수정될 부분을 직관적으로 정의 가능하죠.

patchStrategicMerge 방식으로 imagePullPolicy의 값을 수정하는 예시:


mutate:
  patchStrategicMerge:
    spec:
      containers:
        # image의 값이 ':latest'로 끝나는지 체크
        - (image): "*:latest"
          # imagePullPolicy의 값을 "IfNotPresent"로 설정
          imagePullPolicy: "IfNotPresent"

다음으로 patchesJson6902 필드는 특정 요소를 추가(add), 교체(replace), 제거(remove)할 수 있어 더욱 정교한 수정이 가능한 방식입니다.

patchesJson6902 방식으로 labels 필드의 값을 수정하는 사용 예시:


mutate:
  patchesJson6902: |-
    # 'purpose' Label 제거
    - path: "/metadata/labels/purpose"
      op: remove
    # 'owner' Label 추가 후 해당 값으로 'Aiden' 설정
    - path: "/metadata/labels"
      op: add
      value: {"owner": "Aiden"}

generate Rule의 두 가지 리소스 생성 방식

Kyverno의 generate Rule에서는 data 또는 clone 필드를 이용해서 정책에 의해 새로 생성될 Kubernetes 리소스를 정의할 수 있습니다.

data 필드는 기존에 클러스터에 존재하지 않던 새로운 Kubernetes 리소스를 생성할 때 사용합니다.

generate 필드 안에 새로 생성할 리소스의 apiVersion, kind, name, namespace 등을 정의하고, 그 아래의 data 필드 안에 해당 리소스의 spec 부분을 정의하는 방식입니다.

generate Rule에 의해 새로 생성될 NetworkPolicy 리소스를 data 필드로 정의하는 예시:


generate:
  kind: NetworkPolicy
  apiVersion: networking.k8s.io/v1
  name: deny-all-traffic
  namespace: "{{request.object.metadata.name}}"
  data:  
    spec:
      podSelector: {}
      policyTypes:
      - Ingress
      - Egress

clone 필드는 k8s 클러스터 내에 이미 존재하는 리소스를 복사해서 생성할 때 사용합니다.

generate 필드 안에 새로 생성될 리소스의 apiVersion, kind, name, namespace를 정의하고, 그 아래의 clone 필드 안에 복사할 리소스의 namespacename을 명시하는 방식입니다.

generate Rule에 의해 새로 생성될 Secret 리소스를 clone 필드로 정의하는 예시:


generate:
  kind: Secret
  apiVersion: v1
  name: regcred
  namespace: "{{request.object.metadata.name}}"
  clone:  
    namespace: default
    name: regcred

다음으로, 핵심 Rule 이외에도 알아두면 도움되는 Policy 개념을 짚어보겠습니다.

Rule 검토 대상 리소스를 선별하는 preconditions 필드

Rule의 preconditions 필드는 matchexclude 필드보다 더 정교하게 검토 대상 Kubernetes 리소스를 선별할 수 있습니다. 여러 조건문과 연산자, 필터 등을 활용할 수 있기 때문인데요.

만약 Kubernetes Service에 대한 Rule을 작성하는데 typeNodePort인 Service 리소스만 해당 Rule을 적용시키고 싶다면, 아래와 같이 preconditions 필드를 추가할 수 있습니다.


rules:
- name: validate-nodeport-trafficpolicy
  match:
    any:
    - resources:
        kinds:
        - Service
  preconditions:
    all:
    - key: "{{ request.object.spec.type }}"
      operator: Equals
      value: NodePort

기존 Kubernetes 리소스의 정책 위반을 체크하는 Background Scan 기능

Kyverno의 Policy 단위로 동작하는 Background Scan 기능은 기본적으로 활성화되어 있으며, Policy의 spec.background 필드 값을 false로 명시하면 비활성화할 수 있습니다.

Background Scan은 기본적으로 1시간에 한 번의 주기로 동작하는데요. validate 또는 verifyImages Rule에 대한 위반이 있는지만 체크하고, 만약 위반 사항이 있다면 ClusterPolicyReport 또는 PolicyReport 객체에 해당 위반 사실을 기록합니다.

Rule의 failureAction 값이 Enforce 또는 Audit으로 설정된 것과 상관 없이, Background Scan은 Report에 위반 결과만 기록하는 것이죠.


Kyverno의 High Availability도 알아두자

Kyverno의 가용성을 높이기 위한 HA(High Availability)도 단골 출제 주제입니다. Kyverno는 각기 다른 작업을 담당하는 4개의 컨트롤러로 구성되는데요.

Kyverno의 컨트롤러는 Kubernetes 클러스터에 Deployment로 배포되며, 각 Deployment의 Replica 수를 2개 이상으로 늘림으로써 HA를 실현할 수 있습니다. Kyverno의 4가지 컨트롤러의 HA에 대해서는 아래와 같이 정리할 수 있습니다.

  • Admission Controller

    • validate, mutate Rule과 컨테이너 이미지 검증을 담당
    • Replica 수가 증가할 경우 모든 Replica가 요청을 분산해서 받아 작업
    • HA로 가용성(운영 안정)과 확장성(성능)이 모두 증가
  • Reports Controller

    • Report와 관련된 모든 기능을 담당
    • Replica 수가 증가하더라도 주기적으로 선출된 하나의 Replica만 작업 처리 (리더 선출 방식)
    • HA로 가용성만 증가
  • Background Controller

    • generate Rule과 기존에 존재하는 리소스에 대한 mutate Rule 처리 담당
    • Replica 수가 증가하더라도 리더로 선출된 하나의 Replica만 작업 처리
    • HA로 가용성이 증가하며, 확장성을 늘리려면 컨트롤러 내 Worker 수를 추가(--genWorkers)하는 별도 조치 필요
  • Cleanup Controller

    • CleanupPolicy와 DeletingPolicy 리소스를 처리
    • Cleanup 작업을 위한 CronJob 생성 및 관리 / Kyverno 동작에 필요한 Webhook과 k8s Secret 형태의 인증서도 관리
    • Cleanup 작업 컴포넌트는 리더 선출 없이 모든 Replica가 작업 처리
    • Webhook 및 인증서 관리에는 리더 선출 필요

Kyverno를 클러스터에 설치할 때는 Helm 사용이 권장됩니다. Helm으로 설치되는 Kyverno의 컨트롤러는 기본적으로 Replica 수가 1개씩 배포되는데요.

Helm으로 Kyverno를 설치하는 명령어에 아래와 같이 설정을 추가하면 각 컨트롤러의 Replica 수를 간편하게 지정할 수 있습니다.

helm install kyverno kyverno/kyverno -n kyverno --create-namespace \
--set admissionController.replicas=3 \
--set backgroundController.replicas=2 \
--set cleanupController.replicas=2 \
--set reportsController.replicas=2

Kyverno CLI 명령어

마지막으로 살펴볼 주제는 Kyverno CLI의 명령어입니다. Kyverno CLI는 Kyverno Policy를 Kubernetes 클러스터에 직접 적용하기 전에 로컬 환경에서 테스트하고 검증할 수 있는 유용한 도구인데요.

정책 YAML 파일과 가상의 리소스 YAML 파일을 참조해서 해당 Policy가 의도한 대로 동작하는지 미리 확인할 수 있습니다. Kyverno CLI의 applytest 명령어를 알아보겠습니다.

apply 명령어는 Policy 매니페스트 파일과 정책 대상이 되는 Kubernetes 리소스의 매니페스트 파일을 참조하여 해당 Policy를 dry-run하고 그 결과를 터미널에 표시해줍니다.

mutate Rule이 포함된 Policy가 대상일 경우, apply 명령어의 결과로 해당 Policy에 의해 수정된 Kubernetes 리소스의 매니페스트가 표시되는데요. apply 명령어 예시는 아래와 같습니다.

kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml

다음은 test 명령어입니다. kyverno-test 매니페스트 파일을 참고해서 특정 Policy의 결과가 예상하는 결과와 일치하는지 체크하는 명령어인데요. kyverno-test 매니페스트 파일은 아래와 같이 구성됩니다.

  • policies 필드: Policy 매니페스트 파일 경로
  • resources 필드: 테스트용 k8s 리소스 매니페스트 파일 경로
  • results 필드: 기대하는 Policy 결과를 정의

즉, test 명령어는 테스트 대상 Policy가 어떤 결과를 내야 하는지까지 선언적으로 정의할 수 있다는 점에서 apply 명령어와 차이가 있습니다.


마무리

지금까지 최근 KCA 시험에서 자주 다루는 핵심 키워드와 개념에 대해 알아봤습니다. 부디 이번 아티클이 KCA를 준비하는 분들에게 도움이 되길 바랍니다.

저는 Golden Kubestronaut 타이틀을 목표로 차근차근 CNCF 자격증을 취득 중인데요. 아마 다음 목표는 CGOA(GitOps Certified Associate)가 될 것 같네요.

앞으로도 종종 CNCF 자격증 취득 후기와 주요 출제 키워드를 아티클로 정리해서 공유해보겠습니다.

그럼, 다음에 더 흥미로운 주제로 찾아오겠습니다.

감사합니다.


참고 자료


이번 아티클은 어떠셨나요?

이번 글의 주제에 대해 어떻게 생각하는지 알려주세요! 더 나은 아티클을 전달해드리기 위해 아래 폼에서 짧은 피드백을 받고 있어요.

👉 피드백 보내기 (1~2분 소요)

여러분들의 소중한 의견은 Aiden’s Lab에 큰 힘이 됩니다!