Skip to content
Published on

Pod Security Standards(PSA/PSS) 실전 가이드

공유하기
Authors
Pod Security Standards Guide

1. Pod Security Standards란?

Kubernetes 1.25부터 PodSecurityPolicy(PSP)가 완전히 제거되고, Pod Security Admission(PSA)이 기본 보안 메커니즘이 되었습니다. PSA는 Pod Security Standards(PSS)라는 3단계 보안 프로파일을 기반으로 동작합니다.

PSP에서 PSA로의 전환 배경

PSP는 복잡한 RBAC 설정이 필요하고 디버깅이 어려웠습니다. PSA는 namespace 라벨만으로 간단하게 보안 정책을 적용할 수 있어 운영 부담이 크게 줄었습니다.

2. 3가지 보안 프로파일

Privileged (특권)

모든 것이 허용되는 프로파일입니다. 시스템 수준 워크로드(CNI, 스토리지 드라이버 등)에 사용합니다.

# kube-system namespace에 Privileged 적용
apiVersion: v1
kind: Namespace
metadata:
  name: kube-system
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: privileged

Baseline (기본)

알려진 권한 상승을 방지하면서 대부분의 워크로드가 동작할 수 있는 프로파일입니다.

제한 항목:

  • hostNetwork, hostPID, hostIPC 사용 금지
  • privileged 컨테이너 금지
  • 위험한 capabilities 추가 금지 (NET_RAW 등)
  • hostPath 볼륨 금지
apiVersion: v1
kind: Namespace
metadata:
  name: app-staging
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Restricted (제한)

가장 엄격한 프로파일로, 보안 모범 사례를 강제합니다.

추가 제한 항목:

  • runAsNonRoot 필수
  • Seccomp 프로파일 설정 필수
  • 모든 capabilities drop 필수
  • allowPrivilegeEscalation: false 필수
apiVersion: v1
kind: Namespace
metadata:
  name: app-production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

3. PSA 동작 모드

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

모드동작용도
enforce위반 Pod 생성 거부실제 정책 적용
audit감사 로그 기록모니터링
warn사용자에게 경고 표시마이그레이션 준비
# namespace에 라벨 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

4. Restricted 프로파일 호환 Pod 작성

Restricted를 만족하는 Pod spec 예제입니다:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: app-production
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginx:1.27-alpine
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        runAsNonRoot: true
        runAsUser: 1000
        capabilities:
          drop:
            - ALL
      resources:
        limits:
          memory: '128Mi'
          cpu: '500m'
        requests:
          memory: '64Mi'
          cpu: '250m'
      volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /var/cache/nginx
        - name: run
          mountPath: /var/run
  volumes:
    - name: tmp
      emptyDir: {}
    - name: cache
      emptyDir: {}
    - name: run
      emptyDir: {}

5. 마이그레이션 전략

기존 클러스터를 PSA로 마이그레이션하는 단계별 접근법입니다.

Step 1: 현재 상태 감사

# 모든 namespace에 대해 dry-run 검사
kubectl label --dry-run=server --overwrite ns --all \
  pod-security.kubernetes.io/enforce=baseline

# 특정 namespace의 위반 사항 확인
kubectl get pods -n my-app -o json | \
  kubectl apply --dry-run=server -f - 2>&1 | grep -i "warning"

Step 2: warn/audit 모드로 시작

# 먼저 warn과 audit만 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/warn=baseline \
  pod-security.kubernetes.io/audit=baseline

Step 3: 위반 워크로드 수정

# audit 로그에서 위반 사항 확인
kubectl logs -n kube-system -l component=kube-apiserver | \
  grep "pod-security.kubernetes.io"

Step 4: enforce 모드 활성화

# 충분한 테스트 후 enforce 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=baseline \
  --overwrite

6. Namespace별 예외 처리

특정 워크로드가 상위 권한이 필요한 경우, namespace를 분리하는 것이 권장됩니다:

# 모니터링 에이전트용 별도 namespace
apiVersion: v1
kind: Namespace
metadata:
  name: monitoring-agents
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: restricted
---
# 일반 앱용 namespace
apiVersion: v1
kind: Namespace
metadata:
  name: production-apps
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

7. AdmissionConfiguration으로 클러스터 기본값 설정

API 서버 설정으로 클러스터 전체 기본 정책을 지정할 수 있습니다:

# /etc/kubernetes/psa-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
  - name: PodSecurity
    configuration:
      apiVersion: pod-security.admission.config.k8s.io/v1
      kind: PodSecurityConfiguration
      defaults:
        enforce: 'baseline'
        enforce-version: 'latest'
        audit: 'restricted'
        audit-version: 'latest'
        warn: 'restricted'
        warn-version: 'latest'
      exemptions:
        usernames: []
        runtimeClasses: []
        namespaces:
          - kube-system
          - kube-public
          - istio-system

8. 실전 트러블슈팅

흔한 오류와 해결법

# 오류: Pod 생성 거부
# Error: pods "my-pod" is forbidden: violates PodSecurity "restricted:v1.30"

# 1. 어떤 필드가 위반인지 확인
kubectl describe pod my-pod -n production-apps 2>&1

# 2. 임시로 warn 모드에서 상세 확인
kubectl label namespace production-apps \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/warn=restricted \
  --overwrite

자주 발생하는 위반 체크리스트

#!/bin/bash
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  echo "=== Namespace: $ns ==="
  kubectl get pods -n "$ns" -o json | \
    jq -r '.items[] | select(
      .spec.containers[].securityContext == null or
      .spec.securityContext == null
    ) | .metadata.name'
done

9. 퀴즈

Q1: PSA의 세 가지 동작 모드는 무엇이며, 각각의 역할은?
  1. enforce: 정책을 위반하는 Pod의 생성을 거부합니다.
  2. audit: 위반 사항을 감사 로그에 기록하지만 Pod 생성은 허용합니다.
  3. warn: kubectl 사용자에게 경고 메시지를 표시하지만 Pod 생성은 허용합니다.

마이그레이션 시에는 warn/audit를 먼저 적용하고, 충분한 검증 후 enforce를 활성화하는 것이 안전합니다.

Q2: Restricted 프로파일에서 반드시 설정해야 하는 securityContext 항목 4가지는?
  1. runAsNonRoot: true — root 사용자로 실행 금지
  2. allowPrivilegeEscalation: false — 권한 상승 금지
  3. capabilities.drop: ["ALL"] — 모든 Linux capabilities 제거
  4. seccompProfile.type: RuntimeDefault — Seccomp 프로파일 설정

이 4가지를 모두 설정하지 않으면 Restricted namespace에서 Pod 생성이 거부됩니다.

Q3: 기존 클러스터를 PSA로 마이그레이션할 때 권장되는 단계는?
  1. 현재 상태 감사: dry-run으로 위반 사항 파악
  2. warn/audit 적용: 실제 차단 없이 모니터링
  3. 위반 워크로드 수정: securityContext 추가, 권한 최소화
  4. enforce 활성화: 충분한 테스트 후 실제 정책 적용
  5. 클러스터 기본값 설정: AdmissionConfiguration으로 신규 namespace에 자동 적용

점진적 접근이 핵심이며, 절대 한 번에 enforce를 적용하지 않습니다.