반응형

1. PSA

 

PSA는 Pod가 API Server에 제출될 때 미리 정의된 보안 정책(PSS, Pod Security Standards)에 맞는지 검사하는 내장 Admission Controller입니다. 기존의 PodSecurityPolicy(PSP)가 1.25에서 완전히 제거되면서 그 자리를 대체했습니다.

별도의 외부 도구 없이 namespace 레이블 하나로 Pod의 보안 수준을 강제할 수 있는 것이 특징입니다.

 

PSA는 세 가지 모드로 동작합니다.

모드 동작
enforce 정책 위반 시 Pod 생성 거부
warn 위반 경고를 응답에 포함, 생성은 허용
audit 위반 내용을 audit log에 기록, 생성은 허용

세 모드는 독립적으로 조합할 수 있습니다. 예를 들어 warn으로 시작해 영향 범위를 파악한 뒤 enforce로 전환하는 점진적 적용이 가능합니다.

 

2. PSS

PSA가 검사하는 기준은 PSS로 정의된 세 가지 레벨입니다.

각 레벨이 구체적으로 제한하는 항목은 다음과 같습니다.

레벨 주요 제한 항목
privileged 제한 없음. 클러스터 인프라 컴포넌트 전용
baseline hostNetwork/hostPID/hostIPC 금지, 위험한 capabilities 금지, hostPath 볼륨 금지
restricted baseline 포함 + 반드시 non-root 실행, seccompProfile 필수, allowPrivilegeEscalation: false 필수, capabilities는 NET_BIND_SERVICE만 허용

 

3. 사전 준비

Kubernetes 1.23 이상(GA는 1.25+)이면 별도 설치 없이 PSA를 사용할 수 있습니다.

kubectl version --short
# Server Version: v1.25.0 이상이면 PSA 기본 활성화

 

PSA가 활성화되어 있는지 확인합니다.

# AdmissionRegistration Resource 확인
kubectl get --raw /apis/admissionregistration.k8s.io/v1 | grep -i psa
# API Server 플래그 확인
kubectl get pod -n kube-system kube-apiserver-<node> -o yaml | grep enable-admission
# 개별 Pod 내부에 레이블 확인
pod-security.kubernetes.io/<MODE>: <LEVEL>
pod-security.kubernetes.io/<MODE>-version: <VERSION>   # 선택 사항

 

 

4. 실습

4-1. 테스트용 namespace 생성

kubectl create namespace restricted
kubectl label namespace restricted \
  pod-security.kubernetes.io/enforce=restricted

restict 모드이므로 restricted 기준에 맞지 않는 Deployment 자체가 생성이 되지 않습니다. 경고를 하나씩 살펴보며 문제를 해결해봅시다.

4-2. 기본 pod 생성 시도

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-unprivileged
  namespace: restricted
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged
          ports:
            - containerPort: 80
 
 
kubectl apply -f nginx-deployment.yaml
 

 

4-3. 2차 수정 — allowPrivilegeEscalation 추가

allowPrivilegeEscalation != false를 추가하여 수정합니다.

      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged
          ports:
            - containerPort: 80
          securityContext:
            allowPrivilegeEscalation: false   # 추가
 
 
kubectl apply -f nginx-deployment.yaml

 

4-4. 3차 수정 — capabilities drop ALL + runAsNonRoot 추가

capabilities.drop: ALL 과 runAsNonRoot 를 추가하여 권한을 제어합니다.

      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged
          ports:
            - containerPort: 80
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL               # 추가
            runAsNonRoot: true      # 추가
 
kubectl apply -f nginx-deployment.yaml

 

 

경고가 1개(seccompProfile)만 남습니다

 

4-5. 4차 수정 — seccompProfile 추가

restricted 레벨은 seccompProfile을 RuntimeDefault 또는 Localhost로 명시하도록 요구합니다.

      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged
          ports:
            - containerPort: 80
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
            seccompProfile:
       		  type: RuntimeDefault # container 레벨에서 추가

 

 

배포 및 Pod 상태를 확인하면 정상적으로 적용됩니다.

 

5. 주의할 점

이미 워크로드가 실행 중인 namespace에 enforce를 바로 붙이면 기존 Pod는 영향받지 않지만, 신규 Pod 배포가 즉시 차단될 수 있습니다. 적용 전에 --dry-run으로 영향 범위를 확인합니다.

# enforce 적용 시 영향받을 Pod 미리 확인
kubectl label namespace prod \
  pod-security.kubernetes.io/enforce=restricted \
  --dry-run=server

 

또는 warn 모드를 먼저 붙여 일정 기간 경고를 수집한 뒤 enforce로 교체하는 방식이 안전합니다.

# 1단계: warn으로 관찰
kubectl label namespace prod pod-security.kubernetes.io/warn=restricted

# 경고 확인 후 2단계: enforce 추가
kubectl label namespace prod pod-security.kubernetes.io/enforce=restricted
반응형

+ Recent posts