Admission Controllers (2025 추가)
December 13, 2025
Admission Controller
Admission Controller vs Scheduler
- 같은 스케줄링 섹션에 있어서 헷갈릴 수 있는데, Custom Scheduler나 Scheduler Profile은 어디까지나 "
Pod스케줄링"을 컨트롤하는 역할이고, - 이 글에서 다루는 Admission Controller는 스케줄링 과정 이전에 kube-apiserver로 들어오는 요청 자체를 검증, 수정, 차단하는 역할이다.
Admission Controller를 Scheduler 주제에서 다루는 이유
Admission Controller는 스케줄링 과정의 핵심인Pod에 직접 접근 및 수정을 하고, 결과적으로 스케줄러가 어떤Node를 선택하게 만드는 구조를 결정하는 전처리 역할을 하기 때문
개념
API Server로 들어오는 요청을 가로채 검증하거나 수정하거나 별도 작업을 수행하는 플러그인이다.
즉, RBAC 이후 단계에서 클러스터 보안과 정책 준수 강화를 위해 작동하는 필터라고 볼 수 있다.
예시
latest태그 금지- root 사용자 실행 금지
PVC에 기본StorageClass자동 추가
Admission Controller 원리
우리가 kubectl로 Pod 생성과 같은 요청을 보내면 요청은 Kubernetes API Server로 전달되고 다음과 같은 단계를 거친다.
- Authentication (인증)
- 요청을 보낸 사용자가 쿠버네티스 클러스터에 접근할 수 있는 유저인지 확인 (
kubeconfig내부 인증서 사용)
- 요청을 보낸 사용자가 쿠버네티스 클러스터에 접근할 수 있는 유저인지 확인 (
- Authorization (인가)
- 해당 사용자가 그 작업을 수행할 권한이 있는지
RBAC(Rule Based Access Control) 규칙으로 판단한다.
- 해당 사용자가 그 작업을 수행할 권한이 있는지
Etcd에 반영
위 과정으로는 'latest이미지 태그 금지', 'root 권한 금지'같은 세부 정책을 구현할 수 없다.
이러한 API 요청 자체를 검증, 수정, 거부하는 기능이 Admission Controller이다.
Admission Controller의 종류
Validating Admission Controller
- 요청을 Validate하여 허용/거부만 한다.
- 예:
NamespaceExits(Deprecated) - 네임스페이스가 없으면 요청을 거부
Mutating Admission Controller
- 요청을 Mutate(변경)한다.
- 예:
DefaultStorageClass-PVC생성 시StorageClass없으면StorageClass자동 추가 - cf) Validate, Mutate 둘 다 하는 컨트롤러도 존재한다.
실행 순서
- Mutate Admission Controllerr -> Validate Admission Controller 순서로 실행된다.
- 왜? -> Mutate에서 바뀐 내용이 Validate 시점에 반영되어야하기 때문이다.
대표 예시
AlwaysPullImagesPod생성 시 항상 이미지를 다시 pull 하도록 강제
DefaultStorageClassPVC에서StorageClass미지정 시 자동으로 기본StorageClass추가
EventRateLimit- API Server로의 이벤트 요청량 제한
NamespaceExists(Deprecated ->NamespaceLifecycle로 통합됨)- 존재하지 않는 namespace에 객체 생성 요청 시 거부
Admission Controller 활성화 방법
Manual Setup으로 설치했을 경우
sudo nano /etc/systemd/system/kube-apiserver.service
ExecStart=/usr/local/bin/kube-apiserver \\
--advertise-address=${INTERNAL_IP} \\
--allow-privileged=true \\
--apiserver-count=3 \\
--authorization-mode=Node, RBAC \\
--bind-address=0.0.0.0 \\
--enable-swagger-ui=true \\
--etcd-servers=https://127.0.0.1:2379 \\
--event-ttl=1h \\
--runtime-config=api/all \\
--service-cluster-ip-range=10.32.0.0/24 \\
--service-node-port-range=30000-32767 \\
--v=2
--enable-admission-plugins=NodeRestriction, # 이 부분에 사용할 Admission Controller들 추가
sudo systemctl daemon-reload
sudo systemctl start kube-apiserver
sudo systemctl enable kube-apiserver
- 위 명령어로
kube-apiserver바이너리 실행 (예시이므로 명령어 본인 환경에 맞게 변경해서 사용)
kubeadm 환경
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --authorization-mode=Node, RBAC
- --advertise-address=${INTERNAL_IP}
- --allow-privileged=true
- --enable-bootstrap-token-auth=true
- --enable-admission-plugins=NodeRestriction, # 이 부분에 사용할 Admission Controller들 추가
image: k8s.gcr.io/kube-apiserver-amd64:v1.11.3
name: kube-apiserver
Admission Webhook
개념
- 기존에 정의되어있는 플러그인들이 아니라 커스텀
Admission Controller을 사용하고 싶을 경우 사용하는 방법이다. Webhook Server로 요청(AdmissionReview)을 보내서Webhook Server에서 요청을 처리하고 결과(Validate의 경우 true/false, Mutate의 경우 바뀐patch)를 받는 방식이다.Webhook Server의 경우 클러스터 밖에 놓든, 안에(Deployment+Service) 놓든 상관없다. 또한, 요청을 받고 가공해서 응답할 수 있는 API 서버라면,Spring으로 개발하든FastAPI로 개발하든Go로 개발하든 상관없다.
동작 흐름
- 사용자가 요청(
Pod,PVC등) 생성 - 기본
Mutating Controllers실행 - 기본
Validating Controllers실행 - Webhooks(Mutating → Validating) 실행
Webhook Server가 JSON 요청(AdmissionReview)을 받고 판단 후 응답- 허용되면 etcd로 저장되고 객체 생성, 거부되면 에러 메시지 출력
구성 방법
Webhook Server배포- 클러스터에
Webhook Configuration적용
예시: Webhook Server
// Spring Boot Webhook Server 예시
@RestController
@RequestMapping("/api/v1/webhook")
public class AdmissionReviewController {
// Validating Webhook 요청 처리
@PostMapping("/validate/pods")
public AdmissionReview validatePods(@RequestBody AdmissionReview review) {
// Pod 검증 로직...
}
// Mutating Webhook 요청 처리
@PostMapping("/mutate/deployments")
public AdmissionReview mutateDeployments(@RequestBody AdmissionReview review) {
// Deployment 변경 로직...
}
}
예시: Webhook Configuration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-validator-config
webhooks:
- name: pod-validation-webhook.example.com
clientConfig:
service:
namespace: default
name: webhook-service
path: "/api/v1/webhook/validate/pods"
port: 443
caBundle: <<YOUR_CA_BUNDLE_BASE64_HERE>>
rules:
- operations: ["CREATE", "UPDATE"] # Pod 생성 및 수정 시 호출
apiGroups: [""] # Core API Group (Pod, Service, Namespace 등)
apiVersions: ["v1"]
resources: ["pods"] # Pod 리소스에 대해 동작
sideEffects: None # 이 웹훅은 클러스터 상태를 변경하지 않음
admissionReviewVersions: ["v1", "v1beta1"] # 지원하는 AdmissionReview API 버전
timeoutSeconds: 5 # 타임아웃 설정 (최대 30초)
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingWebhookConfiguration/MutatingWebhookConfigurationmetadatawebhooksname: 웹훅 이름 작성 (FQDN 형식 권장)clientConfigservice: 외부 서버라면 여기에service대신url사용namespace: Webhook Server Service가 있는 네임스페이스name: Webhook ServerService이름path: Webhook 서버로 보내야하는 요청 경로port
caBundle: API 서버가 웹훅 서버의 TLS 인증서를 신뢰하도록 하는 CA 인증서의 Base64 인코딩 값 (필수 - https 만 가능학고, http 불가능)
rules: 여기에 규칙 설정
레퍼런스
- https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- Udemy - Certified Kubernetes Administrator (CKA) with Practice Tests (Mumshad)