Admission Webhook 모범 사례

Admission Webhook 모범 사례 (Admission Webhook Good Practices)

Kubernetes에서 admission webhook을 설계하고 배포할 때 알아두면 좋은 모범 사례와 고려 사항을 정리한 페이지예요. admission webhook 서버를 운영하는 클러스터 운영자나, API 요청을 수정하거나 검증하는 서드파티 애플리케이션을 만드는 분들에게 유용하죠.

출처: Kubernetes 공식 문서 — Admission Webhook Good Practices

좋은 webhook 설계의 중요성

admission control은 create, update, delete 요청이 Kubernetes API로 보내질 때마다 동작해요. admission controller가 정해진 기준에 맞는 요청을 가로채서, mutating admission webhook이나 validating admission webhook으로 보내죠. 이 webhook들은 대개 객체 스펙의 특정 필드가 존재하도록 하거나 특정 허용 값을 갖도록 보장하는 역할을 해요.

webhook은 Kubernetes API를 확장하는 강력한 메커니즘이지만, 잘못 설계하면 클러스터의 객체들에 대한 통제력이 크기 때문에 워크로드 중단을 자주 일으켜요. 게다가 Kubernetes는 릴리스마다 API를 추가·수정하고, beta/stable로 승격하거나 deprecate 하면서 API가 계속 바뀌므로, 이전 버전에서 잘 동작하던 webhook이 최신 API 변경과 조화를 이루지 못할 수 있어요. 클러스터를 새 버전으로 업그레이드한 뒤 예상치 못한 동작이 나타날 수 있는 거죠.

내가 admission webhook을 쓰는지 확인하기

직접 webhook을 운영하지 않더라도 클러스터에서 실행 중인 서드파티 애플리케이션이 mutating/validating admission webhook을 쓸 수 있어요. 확인 명령은 다음과 같아요.

kubectl get mutatingwebhookconfigurations
kubectl get validatingwebhookconfigurations

admission control 메커니즘 고르기

Kubernetes는 여러 admission control/정책 강제 옵션을 제공해요. 일반적으로 webhook admission control은 확장 가능한 방식으로 로직을 선언·구성하고 싶을 때 쓰고, CEL 기반 내장 admission control은 webhook 서버를 운영하는 오버헤드 없이 더 단순한 로직을 선언하고 싶을 때 써요. 가능하면 CEL 기반 방식을 권장해요.

  • Mutating admission webhook: admission 전에 API 요청을 가로채 Custom 로직으로 수정. 외부 API 호출 같은 복잡한 수정에 적합.
  • Mutating admission policy: CEL 표현식으로 요청을 수정. 라벨이나 replica 수 조정 같은 단순 수정에 적합.
  • Validating admission webhook: 복잡한 정책 선언으로 검증.
  • Validating admission policy: CEL 표현식으로 검증.

CustomResourceDefinition을 쓴다면, CustomResource 스펙 검증이나 기본값 설정에 webhook을 쓰지 마세요. CRD 자체에서 검증 규칙과 기본값(defaulting)을 정의할 수 있어요.

성능과 지연 시간

요약하면 다음과 같아요.

  • webhook을 통합하고 webhook당 API 호출 수를 제한한다.
  • 같은 동작을 반복하는 webhook을 audit 로그로 확인한다.
  • webhook 가용성을 위해 로드 밸런싱을 쓴다.
  • 각 webhook에 작은 timeout 값을 설정한다.
  • webhook 설계 시 클러스터 가용성 요구를 고려한다.

Mutating admission webhook은 순차적으로 호출돼요. 그래서 mutating webhook이 많을수록 지연 시간이 커질 위험이 커져요 (validating webhook은 병렬로 호출됨). 서로 비슷한 변형을 수행하는 webhook을 통합하고, 요청당 webhook 수를 줄이는 게 좋아요.

또한 우연히 서로 충돌하는 컨트롤러 간의 루프를 방지해야 해요. 예를 들어 내 webhook이 추가한 라벨을 다른 컨트롤러가 지우면, 내 webhook이 다시 호출돼서 루프가 생기죠. audit 정책으로 RequestResponse 레벨, verbs: ["patch"], omitStages: RequestReceived를 설정해 재호출 여부를 확인해 보세요.

webhook은 API 요청 지연에 더해지므로 되도록 빠르게(보통 밀리초 단위) 평가해야 해요. 작은 timeout을 쓰고, 고가용성을 위해 로드 밸런서(예: ClusterIP Service 뒤에 여러 백엔드)를 활용하세요. 노드 다운타임이나 존 장애 시 Pod가 NotReady로 표시되며 mutating webhook이 재호출될 수 있다는 점도 설계에 고려해야 해요.

요청 필터링

  • webhook 범위 제한: kube-system 네임스페이스의 객체는 되도록 매칭하지 마세요. node lease(Lease 객체), TokenReview·SubjectAccessReview는 mutate 하지 마세요. namespaceSelector로 특정 네임스페이스에만 한정하세요.
  • match conditions로 세밀하게 필터링: 요청 조건을 정확히 맞추면 불필요한 webhook 호출을 줄일 수 있어요.

Mutating webhook 배포

  1. webhook 서버를 설치하고 시작한다.
  2. failurePolicyIgnore로 설정해 잘못된 webhook으로 인한 중단을 피한다.
  3. namespaceSelector를 테스트 네임스페이스로 설정한다.
  4. MutatingWebhookConfiguration을 배포해 테스트 네임스페이스에서 모니터링하고, 문제가 없으면 다른 네임스페이스로 확산한다.

Mutating webhook은 강력한 컨트롤러이므로 RBAC로 접근을 제한하세요. admissionregistration.k8s.io/v1 그룹의 MutatingWebhookConfigurations에 대한 create/update/patch/delete/deletecollection 권한을 신뢰할 수 있는 주체에게만 부여하세요.

좋은 구현 예시

이 예시들은 시작점으로 삼되, 그대로 쓰지 말고 내 환경에 맞게 설계하세요.

더 알아보기 (Learn more)