LabHub
배우기 러닝패스 코스

KCA — Kyverno 인증 어소시에이트 · 웹훅 장애를 구분하고 복구하기 · 실습

정책은 남았는데 위반 Pod가 생성됐다

LabHub 에서 이어서 보기

목표

정책 객체가 남아도 호출 등록이 제거되면 Fail의 호출 실패 처리를 시험한 것이 아닙니다. 정상 축소 뒤 등록·응답의 복구 시각과 객체 UID를 비교하고 server dry-run으로 검증과 저장을 구분합니다.

왜 중요한가

실패라는 한 단어로 정책의 명시적 거부와 웹훅 호출 오류를 묶으면 대응을 잘못 고릅니다.
정책·등록·응답·이미 실행 중인 Pod를 따로 관측해야 합니다. 두 실습은 각각 새 VM에서
시작하며 다른 실습의 자료가 필요 없습니다. 학생 전용 VM 밖에서 장애를 만들지 마세요.

정상 축소는 55초 복구 감시자, 응답 중단은 pidfd와 20초 자동 재개 타이머를 사용합니다.
이 실습은 55분을 예상합니다. 기본 세션은 60분이며 만료 전에 필요하면 +시간으로
연장하세요. 최대 180분이고 종료 시 VM과 파일은 사라집니다. 필요한 자료를 먼저 내려받으세요.

모든 학생 파일은 /root/kca-webhook 아래입니다. 각 act N의 원자료는 evidence/NN.json에
저장되며 내용은 facts에서 읽습니다. 설명에 나오는 02.json 등은 이 evidence 경로입니다.
정규 JSON 해시는 /opt/fixtures/kca_webhook_common.py의 digest(read(경로))이며
sha256sum의 파일 바이트 해시와 다릅니다. Python에서 sys.path에 /opt/fixtures를 추가해 사용하세요.

단계

1. inspect로 이번 VM의 vm.node_uid와 namespaces를 확인하세요. scope.json에 target=kca-webhook-target, control=kca-webhook-control, node_uid, namespaces를 기록합니다. namespaces는 실제 이름을 키, UID를 값으로 둡니다. act 1로 이번 VM의 범위를 보존하세요.
2. policy.json에 policies.kyverno.io/v1의 ValidatingPolicy를 작성하세요. 이름 kca-webhook-label, validationActions=[Deny], failurePolicy=Fail, webhookConfiguration.timeoutSeconds=3, evaluation.background.enabled=false입니다. matchConstraints.namespaceSelector.matchLabels는 kubernetes.io/metadata.name=kca-webhook-target이고 resourceRules는 apiGroups=[빈 문자열], apiVersions=[v1], operations=[CREATE], resources=[pods]입니다. validations의 expression은 "'environment' in object.metadata.?labels.orValue({})", message는 KCA_ENVIRONMENT_REQUIRED입니다. 불필요한 필드 없이 작성하고 act 2로 실제 등록을 확인하세요.
3. registration.json에 service=kyverno-svc, namespace=kyverno, path=/vpol/kca-webhook-label, selector_target=kca-webhook-target, selector_source=namespace-label, operation=CREATE, resource=pods, failure_policy=Fail, timeout_seconds=3, policy_uid=02.json의 facts.policy.metadata.uid를 기록하세요. act 3으로 등록과 범위 밖 무라벨 요청의 저장 UID를 관측하세요.
4. act 4를 실행하세요. evidence/04.json의 facts.good는 라벨이 있는 Pod의 저장 UID, bad는 라벨 누락의 명시적 거부·미저장, existing은 같은 UID의 Running이어야 합니다. 에러 원문과 저장 여부를 함께 읽으세요.
5. shutdown-plan.json에 action=observe-graceful-shutdown, inspect의 controller.metadata.uid를 deployment_uid로, replicas_before=1, replicas_during=0, replicas_after=1, restore_deadline_sec=55를 기록하세요. act 5는 전용 VM 컨트롤러를 정상 축소하고 복구합니다. evidence/05.json에서 같은 정책 UID, 등록 부재, 위반 저장, 복구 뒤 거부와 새 컨트롤러 Pod를 구분하세요.
6. recovery.json에 05.json의 facts.replicas_restored_at, facts.recovery.registered_at, facts.recovery.response_at를 각각 같은 이름의 키로 옮기세요. replicas_mean=desired-count-not-policy-readiness, controller_pod=replaced, policy=same-uid, shutdown_evidence_sha256=05.json의 정규 JSON 해시를 적습니다. act 6은 새 위반 요청의 거부와 기준선 Pod 생존을 다시 확인합니다.
7. dryrun.json에 mode=server, admission=evaluated, good=accepted-not-stored, bad=explicit-deny, existing=same-uid-running, evidence_sha256=06.json의 정규 JSON 해시를 기록하세요. act 7은 새 이름으로 server dry-run을 수행합니다. evidence/07.json의 정상 Pod 응답과 저장 부재, 위반 요청의 명시적 거부를 비교하세요.
8. report.json에 shutdown=registration-removed-not-fail-bypass, policy=same-uid, controller_pod=replaced, existing=same-uid-running, dryrun=admission-without-storage를 기록하세요. shutdown_evidence_sha256와 dryrun_evidence_sha256에는 05.json과 07.json의 정규 JSON 해시를 넣습니다. act 8 뒤 전체 채점을 다시 실행하세요.

참고

명령은 python3 /opt/fixtures/kca_webhook_lab.py inspect, act 1부터 act 8,
grade 1부터 grade 8입니다. grade는 입력과 보존한 실제 관측을 읽으며 장애를 다시 만들지 않습니다.
완료 act는 자료와 자원을 보존합니다. 부분 입력도 자동 덮어쓰지 않습니다.
중단된 실행은 결과가 불확실하므로 실패 원자료를 내려받고 새 실습에서 재현하세요.
정책 대상은 CREATE pods입니다. 모든 API·모든 설치 버전·고가용성에 일반화하지 마세요.
[Kubernetes 서버 dry-run](https://kubernetes.io/docs/reference/using-api/api-concepts/#dry-run)

단계 8개

  1. VM과 대상·대조 범위
  2. Deny·Fail 정책 직접 작성
  3. 호출 등록의 범위를 요청으로 확인
  4. 정상 허용·거부와 기존 Pod 기준선
  5. 정상 종료 뒤 정책과 등록의 다른 수명
  6. 복구 시각과 실제 거부를 따로 검증
  7. 서버 검증 성공과 저장 성공 구분
  8. 서로 다른 객체의 수명으로 사고 보고