안녕하세요! 쿠버네티스 보안과 운영의 안정성을 책임지는 Kyverno 마스터 가이드, 그 세 번째 시간입니다. 🛡️
지난 시간에는 Helm을 이용한 기본적인 설치와 values.yaml 최적화의 겉핥기를 해보았는데요. 오늘은 운영 환경(Production)에서 절대 놓쳐서는 안 될 가장 중요한 주제, "Kyverno 고가용성(HA) 구성과 리소스 할당 전략"에 대해 아주 깊이 있게 다뤄보겠습니다. 🚀
Kyverno는 단순한 도구가 아니라 클러스터의 '관문'입니다. 이 관문이 무너지면 클러스터 전체가 마비될 수 있다는 사실, 알고 계셨나요? 10분만 투자해서 여러분의 클러스터를 철벽 방어로 만들어 보세요!

🏗️ 1. 왜 Kyverno는 고가용성(HA)이 필수일까요?
Kyverno는 쿠버네티스의 Admission Webhook으로 동작합니다. 이게 무슨 뜻일까요?
사용자가 kubectl apply를 실행하면 API 서버는 Kyverno에게 "이거 배포해도 돼?"라고 물어봅니다. 만약 이때 Kyverno Pod이 죽어있거나 응답을 못 하면 어떻게 될까요?
- Fail Close 설정 시: 보안을 위해 모든 리소스 생성이 차단됩니다. (서비스 배포 불가! 🔥)
- Fail Open 설정 시: 보안 검사 없이 리소스가 배포되어 클러스터가 위험에 노출됩니다.
따라서 Kyverno를 여러 대 띄우는 HA(High Availability) 구성은 선택이 아닌 필수입니다.
👥 2. 복제본(Replica) 구성 전략: 3의 법칙
운영 환경에서는 최소 3개의 복제본을 권장합니다.
왜 2개가 아니라 3개인가요? 🧐
- 업그레이드 중 가용성: 하나를 업데이트하는 동안 다른 하나에 문제가 생겨도 마지막 보루가 남아야 합니다.
- 쿼럼(Quorum) 유지: 분산 시스템에서 안정적인 합의와 부하 분산을 위해 홀수 개의 복제본이 유리합니다.
values.yaml 설정 예시:
replicaCount: 3
📍 3. Pod 분산 정책: "한 바구니에 담지 마라"
복제본을 3개 띄웠는데, 하필 그 3개가 모두 같은 워커 노드(Node)에 배포되었다면? 그 노드가 죽는 순간 Kyverno도 전멸입니다. 이를 방지하기 위해 Topology Spread Constraints를 사용해야 합니다.
- 목표: Kyverno Pod들을 서로 다른 노드, 더 나아가 서로 다른 가용 영역(AZ)에 흩어 놓기!
- 효과: 특정 노드나 존에 장애가 발생해도 서비스가 유지됩니다.
values.yaml 설정 예시:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/instance: kyverno
⚡ 4. 리소스 할당(Resource Allocation): "굶기지도 말고, 폭식하게 두지도 마라"
Kyverno는 클러스터 내의 모든 API 요청을 가로채서 검사합니다. 클러스터 규모가 커질수록 Kyverno가 사용하는 CPU와 메모리도 늘어납니다.
① Requests & Limits 설정 🔋
Kyverno가 안정적으로 숨 쉴 수 있는 공간을 마련해줘야 합니다.
- CPU: 정책 검사 시 연산이 집중되므로 너무 낮게 잡으면 API 응답 속도가 느려집니다. (Latency 증가)
- Memory: 클러스터에 리소스가 많을수록 캐싱을 위해 메모리를 더 많이 사용합니다. OOM(Out Of Memory) 킬러의 타겟이 되지 않도록 여유 있게 잡아주세요.
② 실전 권장 사양 (중소규모 클러스터 기준)
admissionController:
container:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
Tip: 대규모 클러스터에서는 메모리를 1Gi 이상으로 증설하는 것을 고려해야 합니다.
🛡️ 5. 안전 장치: PDB (Pod Disruption Budget)
클러스터 점검이나 노드 교체 작업 시, 쿠버네티스는 Pod을 다른 노드로 옮깁니다(Eviction). 이때 Kyverno Pod이 한꺼번에 모두 종료되는 대참사를 막기 위해 PDB를 설정합니다.
- 기능: "어떤 상황에서도 Kyverno Pod은 최소 N개 이상 떠 있어야 해!"라고 강제하는 규칙입니다.
values.yaml 설정 예시:
podDisruptionBudget:
minAvailable: 1 # 적어도 하나는 살려둬!
🚦 6. Webhook 타임아웃 튜닝
API 서버가 Kyverno의 대답을 얼마나 기다려줄지 결정하는 설정입니다.
- 너무 짧으면: 네트워크 지연 시 정상적인 요청도 거절될 수 있습니다.
- 너무 길면: Kyverno에 문제가 생겼을 때 전체 클러스터의 API 응답이 느려져 사용자가 답답함을 느낍니다.
보통 15초 내외가 가장 적당한 합의점입니다.
💾 부록: 운영 환경을 위한 종합 values.yaml 샘플
위에서 설명한 고가용성(HA), 리소스 할당, 분산 정책, 그리고 PDB 설정까지 모두 집약된 실무용 설정 파일입니다. 이 내용을 my-values.yaml로 저장하여 사용하세요.
# =========================================================
# Kyverno Production-Ready Configuration
# =========================================================
# 1. 복제본 설정 (고가용성 확보)
replicaCount: 3
# 2. Pod 중단 예산 (유지보수 중 가용성 보장)
podDisruptionBudget:
minAvailable: 1
# 3. Pod 분산 정책 (노드 장애 대비)
# 특정 노드에 Pod이 쏠리지 않도록 물리적으로 분산 배포합니다.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/instance: kyverno
# 4. 리소스 할당 (성능 및 안정성 최적화)
# 클러스터 규모에 따라 아래 수치를 조정하세요.
admissionController:
container:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# 5. 웹훅 타임아웃 및 재시도 설정
# 네트워크 지연으로 인한 오탐 방지를 위해 15초로 설정합니다.
webhook:
timeoutSeconds: 15
# 6. 배경 스캔 컨트롤러 (이미 배포된 리소스 감시)
backgroundController:
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
# 7. 리소스 정리 컨트롤러 (Cleanup 정책 활성화)
cleanupController:
enabled: true
resources:
requests:
cpu: 50m
memory: 64Mi
# 8. 모니터링 활성화
# Prometheus가 설치되어 있다면 메트릭을 수집할 수 있습니다.
metricsService:
enabled: true
🚀 설정 적용 방법
위의 설정 파일을 준비했다면, 터미널에서 다음 명령어를 실행하여 클러스터에 적용하세요.
# 네임스페이스가 없다면 생성
kubectl create namespace kyverno --dry-run=client -o yaml | kubectl apply -f -
# Helm을 통한 설치 및 업데이트
helm upgrade --install kyverno kyverno/kyverno \
--namespace kyverno \
--values my-values.yaml
💡 설치 후 최종 확인 리스트
- [ ] kubectl get pod -n kyverno 명령어로 3개의 Pod이 서로 다른 노드에 떠 있는지 확인하세요.
- [ ] kubectl get pdb -n kyverno 명령어로 PDB가 정상적으로 생성되었는지 확인하세요.
- [ ] kubectl logs를 통해 Webhook 등록 과정에서 TLS 에러가 없는지 체크하세요.
🔍 설치 후 검증 - "내 Kyverno는 정말 건강한가?"
Helm 설치 명령어가 성공했다고 해서 모든 설정이 완벽하게 끝난 것은 아닙니다. Kyverno가 클러스터의 관문으로서 제대로 작동하는지 확인하는 체크리스트 3가지를 꼭 수행해야 합니다.
① CRD(Custom Resource Definitions) 확인
Kyverno는 정책을 정의하기 위해 여러 개의 커스텀 리소스를 사용합니다. 아래 명령어를 통해 Kyverno 관련 CRD들이 모두 정상적으로 생성되었는지 확인하세요.
kubectl get crd | grep kyverno
주요 CRD 목록:
- clusterpolicies.kyverno.io: 클러스터 전체에 적용되는 정책
- policies.kyverno.io: 특정 네임스페이스에 적용되는 정책
- policyreports.kyverno.io: 정책 준수 여부를 기록하는 보고서
- admissionreports.kyverno.io: 리소스 생성 시 검사 결과를 담은 보고서
② Admission Webhook 상태 점검 🔗
Kyverno는 쿠버네티스 API 서버와 Webhook으로 통신합니다. 이 연결 고리가 끊기면 정책이 적용되지 않습니다.
# Mutating Webhook 확인
kubectl get mutatingwebhookconfigurations | grep kyverno
# Validating Webhook 확인
kubectl get validatingwebhookconfigurations | grep kyverno
출력 결과에 kyverno-resource-mutating-webhook-cfg와 같은 항목이 보여야 하며, AGE가 설치 시간과 일치해야 합니다.
③ 시스템 구성 요소 및 가용성 확인 🚦
앞서 values.yaml에서 설정한 **3개의 복제본(Replica)**이 서로 다른 노드에 잘 배포되어 Running 상태인지 확인합니다.
# 모든 Kyverno 관련 Pod 상태 확인
kubectl get pods -n kyverno -o wide
# 서비스 상태 확인 (특히 Metrics 포트 8000 확인)
kubectl get svc -n kyverno
-o wide 옵션을 사용해 각 Pod이 서로 다른 NODE에 배포되었는지(Topology Spread 적용 여부)를 눈으로 직접 확인하는 것이 중요합니다.
🛠️ 트러블슈팅: 상태가 좋지 않을 때(NotReady)
만약 Pod이 Running 상태가 아니거나 Webhook 에러가 발생한다면 다음 로그를 확인하세요.
# 특정 Pod의 로그 실시간 확인
kubectl logs -f -n kyverno -l app.kubernetes.io/instance=kyverno
- 대부분의 원인: TLS 인증서 발급 오류, 리소스 할당 부족(OOM), 또는 노드 간 네트워크 통신 차단(Security Group/Network Policy) 때문일 가능성이 높습니다.
🌟 마치며: 안정적인 보안은 인프라 설계부터!
Kyverno를 고가용성으로 구성하는 것은 단순히 보안 도구를 설치하는 것을 넘어, 클러스터 전체의 안정성을 설계하는 과정입니다.
- 3개 이상의 복제본을 유지하고,
- Topology Spread로 물리적 장애에 대비하며,
- PDB와 적절한 리소스 할당으로 내부적인 안정성을 확보하세요.
이렇게 튼튼하게 기초를 다져놓아야만, 나중에 복잡한 정책(Policy)들을 추가해도 클러스터가 흔들리지 않습니다. 💪
오늘의 가이드가 여러분의 즐거운 쿠버네티스 운영에 도움이 되었길 바랍니다!
궁금한 점은 언제든 댓글로 남겨주세요! 😊
'클라우드 > Kyverno' 카테고리의 다른 글
| Kyverno 정책의 정교한 설계: Match/Exclude와 Any/All 완벽 가이드 🎯 (0) | 2026.01.05 |
|---|---|
| [Kyverno] Policy(네임스페이스 단위) vs ClusterPolicy(클러스터 전체)의 차이 (0) | 2026.01.05 |
| [kyverno]🛠️ 왜 Helm으로 설치해야 할까요? (0) | 2026.01.05 |
| 🏗️ Kyverno 아키텍처: 왜 "Kubernetes Native"인가? (0) | 2026.01.05 |
| 🚫 Kyverno는 왜 ValidatingWebhookConfiguration과 MutatingWebhookConfiguration을 제어할 수 없을까? (0) | 2025.12.30 |