본문 바로가기

Container/Kubernetes

[K8S] Admission Controller

Admission Controller는 kube-apiserver에서 요청을 가로채어 정책을 적용하거나 변경을 가할 수 있는 플러그인 시스템이다. 즉, 클러스터 내부에서 실행될 리소스(Pod, Deployment 등)를 검토하고 승인(또는 거부)하는 역할을 한다.

✅ 보안, 정책 관리, 리소스 제어 등에 사용됨

  • 보안 정책 적용 → root 권한 제한, 특정 네임스페이스 제어
  • 자동화된 정책 관리 → Pod 자동 라벨링, 사이드카 자동 추가
  • 리소스 관리 최적화 → 특정 리소스 사용량 제한
  • 하지만 어떠한 authenticate 관련 기능도 하지 않는다.

✅ Kubernetes API 요청이 etcd에 저장되기 전에 실행됨
✅ Mutating(수정)과 Validating(검증) 컨트롤러로 구분됨

 

📖 Admission Controller의 동작 방식

 

Kubernetes에서 리소스가 생성될 때, 다음과 같은 과정을 수행한다.

  1. 클라이언트 요청 (ex: kubectl apply -f pod.yaml)
  2. API 서버 요청 수신
  3. Authentication (인증) → RBAC Authorization (권한 확인)
  4. Admission Controller가 요청을 검토
    • Validating Admission Controller: 요청을 검토하고 허용/거부 결정
    • Mutating Admission Controller: 요청을 변경 후 승인
  5. etcd에 저장 & 스케줄링 및 실행

Admission Controller가 활성화되면, 특정 규칙을 위반하는 요청을 자동으로 차단할 수 있음
Mutating Admission Controller를 사용하면, 정책에 따라 요청을 자동으로 변경 가능

📖 Admission Controller의 유형

1. Mutating Admission Controller (변경 가능)

  • 요청을 자동으로 수정할 수 있음
  • 예제: MutatingWebhook 사용
  • 예시: default 네임스페이스에 Pod을 배포하면 자동으로 default SecurityContext를 추가

2. Validating Admission Controller (검증 전용)

  • 요청을 검사하고 거부할 수 있음
  • 예제: ValidatingWebhook 사용
  • 예시: 특정 리소스 제한을 초과하는 Pod이 배포되지 않도록 차단

Mutating Admission Controller → 요청을 자동 수정
Validating Admission Controller → 정책을 위반하는 요청 거부

 

📖 활성 / 비활성 방법

Enabled Admission Controllers

# kube-apiserver-controlplane
$ kube-apiserver -h | grep enable-adminssion-plugins

controlplane:~$ kubectl exec -it kube-apiserver-controlplane -n kube-system -- kube-apiserver -h | grep enable-admission-plugins 
      --enable-admission-plugins strings       admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionPolicy, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionPolicy, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.
      
controlplane:~$ kubectl describe pod kube-apiserver -n kube-system | grep enable-admission-plugins
      --enable-admission-plugins=NodeRestriction

 

특정 admission 활성화

# Kubernetes API 서버 실행 옵션에 --enable-admission-plugins 추가

$ kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger,PodSecurityPolicy

# 권장 admission-plugins
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota,PodSecurityPolicy

 

# kube-apiserver.service 업데이트 or
# kube-apiserver.yaml 업데이트
controlplane:/etc/kubernetes/manifests$ cat kube-apiserver.yaml 
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 172.30.1.2:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=172.30.1.2
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction  # 여기에 plugins 업데이트
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-issuer=https://kubernetes.default.svc.cluster.local
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

 

+ 📄 NamespaceAutoProvision 및 NamespaceExists는 deprecate되어 NamespaceLifeCycle로 대체되었다.

  • NamespaceLifeCycle: 존재하지 않는 namespace에 대한 요청을 거부하고, default kube-system, kube-public과 같은 namespace가 삭제될 수 없도록 한다.

특정 plugins 비활성화

  • --disable-admission-plugins
$  grep 'admission' /etc/kubernetes/manifests/kube-apiserver.yaml
    - --enable-admission-plugins=NodeRestriction,NamespaceAutoProvision 
    - --disable-admission-plugins=DefaultStorageClass   # 이렇게 추가해주면 된다.
  • kube-apiserver는 Pod로 실행되기 때문에 ps 명령어로 enable/disable plugins를 확인할 수 있다.
$ ps -ef | grep kube-apiserver | grep admission-plugins
root       17230   17101  0 08:33 ?        00:00:03 kube-apiserver --advertise-address=192.168.63.143 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt --enable-admission-plugins=NodeRestriction,NamespaceAutoProvision --disable-admission-plugins=DefaultStorageClass --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=6443 --service-account-issuer=https://kubernetes.default.svc.cluster.local --service-account-key-file=/etc/kubernetes/pki/sa.pub --service-account-signing-key-file=/etc/kubernetes/pki/sa.key --service-cluster-ip-range=172.20.0.0/16 --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

 

[실습 ] NamespaceAutoProvision

  • NamespaceAutoProvision 활성화 하기
$ kubectl run nginx --image nginx -n blue
Error from server (NotFound): namespaces "blue" not found
# blue namespace가 없기 때문에 pod가 생성되지 않는다. (NamespaceExists admission plugins이 활성화 되어있기 때문이다.)

# 존재하지 않는 namespace를 자동으로 만들어주기 위해서, NamespaceAutoProvision admission controller를 활성화시킬 수 있다.

$ vi /etc/kubernetes/manifests/kube-apiserver.yaml
    - --enable-admission-plugins=NodeRestriction,NamespaceAutoProvision
    
    # kube-apiserver가 restart된다.
  • 존재하지 않는 namespace의 Pod 생성하기
$ kubectl get ns
NAME              STATUS   AGE
default           Active   19m
kube-flannel      Active   19m
kube-node-lease   Active   19m
kube-public       Active   19m
kube-system       Active   19m

$ kubectl run nginx --image nginx -n blue
pod/nginx created
# 오류가 발생하지 않는다.

$ kubectl get ns
NAME              STATUS   AGE
blue              Active   3s  # 자동으로 생성되었다.
default           Active   20m
kube-flannel      Active   19m
kube-node-lease   Active   20m
kube-public       Active   20m
kube-system       Active   20m

# The NamespaceLifecycle admission controller will make sure that requests to a non-existent namespace is rejected 
# and that the default namespaces such as default, kube-system and kube-public cannot be deleted.

 

 

⭐참고: 

반응형

'Container > Kubernetes' 카테고리의 다른 글

[K8S] Autoscaling - HPA  (0) 2025.02.26
[K8S] Mutating/Validating Admission Controller  (0) 2025.02.24
[K8S] Kustomize Overlay/Components  (0) 2025.02.24
[K8S] Kustomize Patches  (0) 2025.02.23
[K8S] Kustomize Transformers  (0) 2025.02.23