KCA — Kyverno 인증 어소시에이트 · 웹훅 장애를 구분하고 복구하기 · 실습
등록된 웹훅이 응답하지 않는 3초
목표
등록이 남아 있는 웹훅의 응답만 멈추고 Fail·Ignore의 차이를 실제 요청으로 비교합니다. 정상 서버의 명시적 거부, 장애 중 시간 초과·저장, 범위 밖 대조군, 복구를 각각 확인합니다.
왜 중요한가
실패라는 한 단어로 정책의 명시적 거부와 웹훅 호출 오류를 묶으면 대응을 잘못 고릅니다.
정책·등록·응답·이미 실행 중인 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. act 3으로 라벨이 있는 Pod의 저장·UID·Running과 라벨 없는 Pod의 명시적 거부·미저장을 관측하세요. evidence/03.json의 facts.good, bad, existing을 비교합니다. 이전 실습의 파일이나 VM을 가져오지 않습니다.
4. freeze-plan.json에 action=freeze-one-controller-process, 실제 node_uid와 deployment_uid, resume_after_sec=20, signal_identity=pidfd, preserve_webhook=true, evidence_sha256=03.json의 정규 JSON 해시를 기록하세요. act 4는 CRI 컨테이너·Pod UID·PID 시작 시각만 조사하고 아직 정지시키지 않습니다.
5. act 5를 실행하세요. evidence/05.json에서 등록 보존, 정지 구간 안의 정상·위반 요청 시간 초과와 미저장, 범위 밖 대조 요청 저장, 복구 후 위반 거부와 기존 Pod UID를 비교하세요. 명시적 거부와 context deadline exceeded를 구분합니다.
6. policy.json을 바탕으로 policy-ignore.json을 작성하되 spec.failurePolicy만 Ignore로 바꾸세요. act 6은 같은 정책 UID에서 정상 위반 거부를 먼저 확인하고 응답만 짧게 정지합니다. evidence/06.json에서 장애 중 정상·위반 요청 저장, 복구 후 거부, 기존 Pod 생존을 비교하세요.
7. recovery.json에 mode=Ignore, healthy_bad=explicit-deny, existing=same-uid-running, policy_uid=02.json의 facts.policy.metadata.uid, ignore_evidence_sha256=06.json의 정규 JSON 해시를 넣으세요. act 7은 새 이름의 위반 요청을 거부하고 03단계 기준선 Pod의 같은 UID·Running을 확인합니다.
8. report.json에 fail=matching-requests-timeout, ignore=unvalidated-request-stored, healthy_ignore=explicit-deny, control=outside-selector, existing=same-uid-running을 기록하세요. fail_evidence_sha256, ignore_evidence_sha256, recovery_evidence_sha256는 각각 05·06·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개
- 새 VM에서 독립된 실험 범위
- Deny·Fail 정책 직접 작성
- 정상 서버의 허용·거부 기준선
- CRI·Pod·PID 신원과 자동 재개 계획
- 등록을 유지하고 Fail 시간 초과 관측
- Ignore의 정상 거부와 장애 중 저장
- 복구를 새 요청과 이전 UID로 재확인
- 두 장애 결과를 근거와 연결한 보고서