본문 바로가기
IT/k8s

[k8s] Pod Security Standards 마이그레이션: Kubernetes PSP에서 안전하게 전환하기

by 수누다 2026. 7. 14.
반응형

Pod Security Standards 마이그레이션: Kubernetes PSP에서 안전하게 전환하기

Kubernetes 클러스터를 오래 운영했다면 PSP(PodSecurityPolicy) 때문에 한 번쯤 머리가 아팠을 겁니다. 저도 그랬습니다. 그런데 PSP는 Kubernetes 1.21에서 deprecated 되었고, Kubernetes 1.25에서 완전히 제거됐습니다. 그래서 Pod Security Standards 마이그레이션은 이제 선택이 아니라 업그레이드와 운영 안정성을 위해 꼭 챙겨야 할 작업이 됐습니다. 이번 글에서는 Kubernetes 보안 관점에서 PSP 대체 수단인 PSS(Pod Security Standards)Pod Security Admission으로 어떻게 안전하게 전환하는지, 실무 기준으로 차근차근 정리해보겠습니다.

처음엔 저도 PSS가 너무 단순해 보여서 오히려 불안했습니다. PSP처럼 세부 필드를 다 적는 방식에 익숙하면 더 그렇게 느껴지거든요. 그런데 실제로 운영해보니 팀 공통 보안 기준을 맞추는 데는 훨씬 현실적이더라고요. 대신 전환 순서를 잘못 잡으면 배포가 갑자기 막힐 수 있습니다. 여기서 핵심은 처음부터 enforce로 가지 말고 warn, audit로 먼저 관찰하는 것입니다.

Pod Security Standards 마이그레이션 개요를 보여주는 Kubernetes 보안 아키텍처 이미지

PSP에서 PSS와 Pod Security Admission으로 넘어가는 흐름을 한눈에 보여주는 개요 이미지입니다.

왜 Pod Security Standards 마이그레이션이 중요한가

예전 방식인 PSP는 표현력은 강했지만 운영 피로도도 높았습니다. 반면 PSS는 Privileged, Baseline, Restricted라는 공통 보안 레벨을 제공해서 팀 간 기준을 맞추기 훨씬 쉽습니다. 여러 네임스페이스를 운영하는 환경에서는 긴 정책 객체를 계속 유지하는 것보다, 보안 수준을 레벨로 선언하는 편이 관리가 훨씬 단순합니다.

제가 직접 겪어보니 Pod Security Standards 마이그레이션의 장점은 분명했습니다. 신규 팀원에게 설명하기 쉽고, 클러스터 업그레이드 때 정책 호환성 이슈가 크게 줄어듭니다. 다만 PSP처럼 아주 세밀한 예외 제어를 기대하면 아쉬울 수 있습니다. 그런 경우에는 OPA Gatekeeper나 Kyverno 같은 정책 엔진을 함께 쓰는 구성이 더 잘 맞습니다.

Pod Security Standards 마이그레이션 기준: PSP와 PSS는 무엇이 다를까

처음 보면 이름만 바뀐 것처럼 느껴질 수 있는데 구조는 꽤 다릅니다. PSP는 정책 리소스를 만들고 RBAC으로 사용자나 서비스어카운트와 연결하는 방식이었습니다. 반면 PSS는 네임스페이스에 보안 수준을 라벨로 선언하고, Pod Security Admission이 그 기준으로 파드를 검사합니다.

항목 PSP PSS + Pod Security Admission
정책 방식 세부 필드 기반 정책 객체 사전 정의된 보안 표준 레벨
적용 범위 RBAC과 연결해 사용 네임스페이스 라벨 기반 적용
운영 난이도 높은 편 상대적으로 단순
이식성 클러스터별 편차 큼 표준화하기 좋음
세밀한 예외 처리 강점 제한적, 필요 시 별도 정책 엔진 보완

PSS의 핵심 레벨은 아래처럼 이해하면 편합니다.

  • Privileged: 사실상 제한이 거의 없는 수준입니다. 시스템 워크로드나 인프라성 컴포넌트에 가깝습니다.
  • Baseline: 일반 애플리케이션에 적용하기 좋은 현실적인 최소 보호선입니다.
  • Restricted: 현재 권장되는 강한 하드닝 기준입니다. 대신 기존 애플리케이션은 여기서 많이 걸릴 수 있습니다.

Pod Security Admission 적용 방법: 전환 전에 꼭 확인할 것

Pod Security Admission은 파드 생성 시점에 PSS 기준을 검사하는 내장 Admission Controller입니다. 다만 여기서 하나 짚고 갈 점이 있습니다. warnaudit는 Deployment 같은 워크로드 리소스에도 경고를 보여주지만, enforce는 최종적으로 생성되는 Pod에 적용됩니다. 이 차이를 알고 있어야 배포 시 메시지를 덜 헷갈립니다.

  1. enforce: 정책을 어기면 Pod 생성이 거부됩니다.
  2. audit: 생성은 허용되지만 감사 로그에 위반 정보가 남습니다.
  3. warn: 생성은 허용되지만 클라이언트에 경고가 표시됩니다.

실무에서 자주 하는 실수가 바로 여기입니다. 바로 enforce부터 켜버리면 그동안 관성적으로 돌아가던 워크로드가 한꺼번에 실패할 수 있거든요. 저도 테스트 환경에서 ingress controller가 안 떠서 꽤 오래 본 적이 있습니다. 알고 보니 hostNetwork와 securityContext 설정이 기준에 안 맞았더라고요. 이런 경험을 한 번 하면 warn, audit부터 가야 하는 이유가 확실히 보입니다.

전환 전 체크리스트

  • 현재 클러스터에서 PSP를 실제로 쓰는 네임스페이스가 어디인지 확인합니다.
  • 권한 상승 허용 여부를 점검합니다.
  • root 실행, hostPath 마운트, hostNetwork 사용 여부를 확인합니다.
  • DaemonSet, CSI, 모니터링 에이전트처럼 예외가 필요한 워크로드를 분리합니다.
  • 애플리케이션 네임스페이스와 시스템 네임스페이스를 같은 기준으로 묶지 않습니다.

실전 구현: Pod Security Standards 마이그레이션 순서

여기서는 제가 실제로 권장하는 순서를 정리해보겠습니다. 핵심은 단순합니다. 관찰 먼저, 강제는 나중. 이 순서만 지켜도 사고 확률이 확실히 줄어듭니다.

1. 현재 네임스페이스 라벨 상태 확인

kubectl get ns --show-labels

기존에 이미 pod-security 관련 라벨이 붙어 있는지 먼저 확인합니다. 다른 운영자가 먼저 설정해둔 경우도 생각보다 자주 있습니다. 이 상태를 모르고 덮어쓰면 원인 파악이 더 어려워집니다.

2. 먼저 warn, audit 모드로 Baseline 적용

kubectl label ns my-app \
  pod-security.kubernetes.io/warn=baseline \
  pod-security.kubernetes.io/audit=baseline \
  --overwrite

처음부터 Restricted로 가고 싶어도 일단 Baseline부터 보는 편이 안전합니다. 여기서 어떤 워크로드가 경고를 내는지 파악해야 다음 단계가 보입니다. 이 단계가 생각보다 중요하더라고요.

3. 버전 라벨도 함께 명시해 드리프트 줄이기

kubectl label ns my-app \
  pod-security.kubernetes.io/warn-version=v1.36 \
  pod-security.kubernetes.io/audit-version=v1.36 \
  --overwrite

버전 라벨은 선택 사항이지만 운영에선 거의 필수에 가깝습니다. PSS 해석 기준은 Kubernetes 마이너 버전에 따라 달라질 수 있어서, 테스트와 운영 클러스터의 결과가 어긋나는 일을 줄여주거든요. 다만 예시 값을 그대로 복붙하기보다는 현재 클러스터의 마이너 버전에 맞춰 적는 게 맞습니다.

4. 경고 메시지로 문제 워크로드 찾기

kubectl apply -f deployment.yaml

배포 시 warn 메시지가 뜨면 그 내용을 기준으로 수정합니다. warn과 audit는 Deployment 같은 워크로드 리소스에도 적용되기 때문에, 이 단계에서 꽤 많은 힌트를 얻을 수 있습니다. 흔히 손보게 되는 포인트는 아래와 같습니다.

  • runAsNonRoot: non-root 실행 강제
  • allowPrivilegeEscalation: false 설정
  • seccompProfile: RuntimeDefault 적용
  • capabilities: 불필요한 Linux capability 제거
Pod Security Admission과 네임스페이스 라벨 기반 PSS 적용 방법을 설명하는 이미지

네임스페이스에 warn, audit, enforce 라벨을 붙이는 방식과 적용 흐름을 보여주는 이미지입니다.

5. 매니페스트 보안 컨텍스트 정리

아래 예시는 Restricted로 가기 전에 가장 자주 쓰는 기본 골격입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: web-app
          image: nginx:stable
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
          ports:
            - containerPort: 80

이 예시는 아주 화려하지는 않지만, 실제로 많이 걸리는 조건을 담고 있습니다. 특히 runAsNonRoot는 이미지 자체가 non-root 실행을 지원해야 제대로 동작합니다. 오래된 이미지라면 매니페스트만 고쳐서는 해결이 안 되고, 컨테이너 이미지 베이스부터 손봐야 할 때가 있습니다.

6. 문제 없으면 enforce 전환

kubectl label ns my-app \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/enforce-version=v1.36 \
  --overwrite

여기서도 한 번에 모든 네임스페이스를 바꾸는 건 추천하지 않습니다. 서비스 영향이 낮은 곳부터 묶어서 적용하고, 모니터링으로 이상이 없는지 확인한 뒤 확대하는 방식이 제일 덜 아픕니다. 이거 진짜 차이가 큽니다.

Restricted까지 가려면 어떤 점을 더 봐야 하나

Pod Security Standards 마이그레이션을 시작하면 많은 팀이 최종 목표를 Restricted로 잡습니다. 방향은 맞습니다. 다만 현실적으로 모든 워크로드가 바로 들어가지는 않더라고요. 특히 아래 항목은 자주 발목을 잡습니다.

  1. 레거시 이미지가 root 실행을 전제로 만들어져 있음
  2. initContainer에서 과한 권한을 사용함
  3. 모니터링, 스토리지, 네트워크 에이전트가 호스트 접근을 필요로 함
  4. hostPath 사용이 습관처럼 들어가 있음

그래서 저는 보통 네임스페이스를 이렇게 나눕니다.

네임스페이스 유형 권장 레벨 비고
일반 애플리케이션 Baseline 또는 Restricted 신규 서비스는 Restricted 목표
운영 도구 Baseline 필요 권한 확인 후 점진 강화
시스템 워크로드 Privileged 또는 별도 예외 관리 CNI, CSI, 일부 에이전트 주의

트러블슈팅: Pod Security Standards 마이그레이션에서 자주 막히는 지점

문서만 보면 금방 끝날 것 같지만, 운영 환경에 붙이면 여기서 한 번씩 다 막힙니다. 저도 몇 번은 꽤 돌아갔습니다. 그래서 아래 포인트는 미리 보고 들어가는 편이 좋습니다.

1. 배포가 갑자기 거부될 때

enforce가 켜진 네임스페이스에 정책 위반 Pod가 들어가면 바로 거부됩니다. 이 경우 이벤트와 매니페스트를 같이 봐야 합니다.

kubectl describe pod <pod-name> -n my-app
kubectl get events -n my-app --sort-by=.lastTimestamp

경고 문구만 보고 대충 고치면 같은 문제를 반복하기 쉽습니다. 어떤 필드가 위반인지 정확히 확인하고, Pod 템플릿 기준으로 수정해야 합니다.

2. 시스템 네임스페이스까지 묶어서 막힐 때

이 부분은 정말 조심해야 합니다. kube-system 같은 곳에 일반 앱과 같은 Restricted를 걸면 예상치 못한 장애가 날 수 있습니다. 네트워크 플러그인, 스토리지 드라이버, 노드 에이전트가 영향을 받는 경우가 대표적입니다. 실제 운영에선 시스템성 워크로드를 별도 기준으로 다루는 게 훨씬 안전합니다.

3. warn은 뜨는데 배포가 되니까 그냥 넘길 때

처음엔 "배포는 되네" 하고 넘기기 쉽습니다. 그런데 나중에 enforce로 바꾸는 순간 한꺼번에 터집니다. 그래서 warn 단계에서 바로 티켓을 만들고, 팀별 수정 일정을 잡아두는 편이 훨씬 낫습니다.

4. PSP 기능과 1:1 대응을 기대할 때

PSP 대체라고 해서 완전히 같은 경험을 기대하면 실망할 수 있습니다. PSS는 표준 보안 레벨을 제공하는 방식이고, 세밀한 조직별 규칙은 별도 정책 도구가 더 적합합니다. 이 차이를 이해하고 설계해야 전환 이후 불만도 줄어듭니다.

검증: Pod Security Admission이 제대로 동작하는지 확인하는 방법

적용 후에는 라벨만 붙였다고 끝이 아닙니다. 검증이 꼭 필요합니다. 제가 보통 확인하는 항목은 아래와 같습니다.

  1. 네임스페이스 라벨이 의도한 값으로 들어갔는지 확인
  2. warn 메시지가 줄거나 사라졌는지 확인
  3. 문제 Pod 없이 롤링 업데이트가 완료되는지 확인
  4. 시스템 워크로드가 영향 없이 유지되는지 확인
kubectl get ns my-app --show-labels
kubectl rollout status deploy/web-app -n my-app
kubectl get pods -n my-app

조금 더 확실히 보려면 의도적으로 정책 위반 Pod를 하나 던져보는 것도 방법입니다. 다만 이 테스트는 운영 네임스페이스가 아니라 테스트 네임스페이스에서만 하는 편이 안전합니다.

apiVersion: v1
kind: Pod
metadata:
  name: pss-test
  namespace: my-app
spec:
  hostNetwork: true
  containers:
    - name: busybox
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      securityContext:
        allowPrivilegeEscalation: true

Baseline이나 Restricted enforce가 걸려 있다면 이런 Pod는 거부되는 게 정상입니다. hostNetwork는 Baseline부터 금지되고, allowPrivilegeEscalation은 Restricted에서 금지되기 때문에 테스트용으로 확인하기 좋습니다.

Pod Security Standards 마이그레이션 검증 결과를 보여주는 Kubernetes 보안 이미지

정책 위반 테스트와 정상 배포가 어떻게 다르게 보이는지 검증 결과를 시각화한 이미지입니다.

운영 팁: 네임스페이스 전략을 먼저 정하면 훨씬 편합니다

제가 여러 번 해보니, PSS 적용 방법에서 제일 중요한 건 YAML 문법보다 운영 기준이었습니다. 다시 말해 "어떤 네임스페이스를 어떤 신뢰 수준으로 볼 것인가"를 먼저 정해야 합니다. 이 기준이 없으면 팀마다 예외 요청이 쌓이고, 결국 정책이 누더기가 되더라고요.

  • 신규 서비스는 기본적으로 Baseline 또는 Restricted로 시작합니다.
  • 예외가 필요한 시스템성 워크로드는 별도 네임스페이스로 분리합니다.
  • warn과 audit 결과를 주기적으로 점검해 enforce 후보를 올립니다.
  • 정책 예외는 문서화하고 만료 시점을 정합니다.

이런 방식으로 가면 Kubernetes 보안이 특정 담당자 감에 의존하지 않고 팀 표준으로 자리 잡습니다. 이전에 정리한 RBAC 글이 있다면 같이 연결해두는 것도 좋습니다. 내부 링크 흐름이 생기면 독자 입장에서도 이해가 더 빨라지고, SEO 측면에서도 분명 도움이 됩니다.

정리: PSP에서 PSS로 갈아탈 때 기억할 것

오늘 내용을 짧게 정리하면 이렇습니다. Pod Security Standards 마이그레이션은 단순한 기능 교체가 아니라, 보안 운영 방식을 표준화하는 작업입니다. PSP보다 세밀한 제어는 줄었지만, 네임스페이스 단위로 기준을 맞추기 쉬워졌고, Pod Security Admission으로 warn, audit, enforce를 단계적으로 운영할 수 있게 됐습니다.

저도 처음엔 이 구조가 너무 단순한 것 아닌가 싶었습니다. 그런데 실제로는 팀 단위 운영에 더 잘 맞더라고요. 다만 무작정 enforce부터 걸면 안 됩니다. 꼭 warn, audit으로 현재 상태를 먼저 파악하고, Restricted는 목표로 두되 시스템 워크로드 예외를 현실적으로 분리해 가져가면 훨씬 수월합니다.

지금 클러스터 업그레이드를 앞두고 있다면 이번 주에라도 테스트 네임스페이스 하나 만들어 Baseline warn부터 붙여보세요. 생각보다 빨리 문제가 보입니다. 그리고 이전에 다뤘던 RBAC 정리 글도 함께 보면 흐름이 더 잘 잡힐 겁니다. 다음 글에서는 Kyverno나 Gatekeeper로 PSS의 빈틈을 어떻게 보완하는지도 이어서 정리해보겠습니다.

PSP 대체와 Pod Security Standards 보안 레벨 비교를 정리한 인포그래픽 이미지

PSP와 PSS의 차이, 적용 순서, 운영 체크포인트를 한 장으로 정리한 요약 인포그래픽입니다.

자주 묻는 질문

PSS만으로 PSP를 완전히 대체할 수 있나요?

기본적인 표준화 목적에는 충분한 경우가 많습니다. 다만 세밀한 조건 제어나 예외 검증이 많다면 Kyverno나 Gatekeeper 같은 정책 엔진을 함께 검토하는 편이 좋습니다.

처음부터 Restricted로 가도 되나요?

신규 서비스만 있고 이미지와 매니페스트를 처음부터 통제할 수 있는 환경이라면 가능합니다. 하지만 기존 워크로드가 있다면 Baseline warn, audit부터 시작하는 편이 훨씬 안전합니다.

Pod Security Admission은 어디에 적용되나요?

네임스페이스 라벨 기준으로 해당 네임스페이스의 Pod 생성에 영향을 줍니다. 또 warn과 audit는 Deployment 같은 워크로드 리소스에도 힌트를 주기 때문에, 네임스페이스 전략과 배포 검증 루틴을 함께 가져가는 게 중요합니다.

반응형