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. 퀴즈
1. **enforce**: 정책을 위반하는 Pod의 생성을 거부합니다.
2. **audit**: 위반 사항을 감사 로그에 기록하지만 Pod 생성은 허용합니다.
3. **warn**: kubectl 사용자에게 경고 메시지를 표시하지만 Pod 생성은 허용합니다.
마이그레이션 시에는 warn/audit를 먼저 적용하고, 충분한 검증 후 enforce를 활성화하는 것이 안전합니다.
1. **runAsNonRoot: true** — root 사용자로 실행 금지
2. **allowPrivilegeEscalation: false** — 권한 상승 금지
3. **capabilities.drop: ["ALL"]** — 모든 Linux capabilities 제거
4. **seccompProfile.type: RuntimeDefault** — Seccomp 프로파일 설정
이 4가지를 모두 설정하지 않으면 Restricted namespace에서 Pod 생성이 거부됩니다.
1. **현재 상태 감사**: dry-run으로 위반 사항 파악
2. **warn/audit 적용**: 실제 차단 없이 모니터링
3. **위반 워크로드 수정**: securityContext 추가, 권한 최소화
4. **enforce 활성화**: 충분한 테스트 후 실제 정책 적용
5. **클러스터 기본값 설정**: AdmissionConfiguration으로 신규 namespace에 자동 적용
점진적 접근이 핵심이며, 절대 한 번에 enforce를 적용하지 않습니다.
현재 단락 (1/174)
Kubernetes 1.25부터 PodSecurityPolicy(PSP)가 완전히 제거되고, **Pod Security Admission(PSA)**이 기본 보안 메커니즘이 되었습...