Pod 보안 표준

Pod 보안 표준 (Pod Security Standards)

Pod Security Standards가 정의하는 서로 다른 정책 수준에 대해 자세히 살펴볼게요.

Pod Security Standards는 보안 스펙트럼을 폭넓게 커버하기 위해 세 가지 정책을 정의합니다. 이 정책들은 누적적이며 매우 허용적인 것부터 매우 제한적인 것까지 이어져요. 이 가이드는 각 정책의 요구사항을 설명합니다.

프로필 설명
Privileged 제한 없는 정책으로, 가장 넓은 수준의 권한을 제공해요. 이 정책은 알려진 권한 상승을 허용합니다.
Baseline 알려진 권한 상승을 방지하는 최소한의 제한을 가진 정책이에요. 기본(최소로 지정된) Pod 구성을 허용합니다.
Restricted 현재 Pod 하드닝(hardening) 모범 사례를 따르는 강하게 제한된 정책이에요.

프로필 세부사항 (Profile Details)

Privileged

Privileged 정책은 의도적으로 열려 있고 완전히 제한이 없어요. 이 유형의 정책은 주로 특권이 있고 신뢰받는 사용자가 관리하는 시스템 및 인프라 수준 워크로드를 대상으로 합니다.

Privileged 정책은 제한이 없다는 것 자체로 정의됩니다. Privileged 보안 정책이 적용되는 Pod를 정의하면, 그 Pod는 일반적인 컨테이너 격리 메커니즘을 우회할 수 있어요. 예를 들어 노드의 호스트 네트워크에 접근할 수 있는 Pod를 정의할 수 있습니다.

Baseline

Baseline 정책은 알려진 권한 상승을 방지하면서 일반적인 컨테이너화된 워크로드의 채택 용이성을 목표로 해요. 이 정책은 중요하지 않은 애플리케이션의 애플리케이션 운영자와 개발자를 대상으로 합니다. 다음에 나열된 제어 항목들이 강제되거나 금지되어야 합니다.

참고: 이 표에서 와일드카드(*)는 목록의 모든 요소를 나타내요. 예를 들어 spec.containers[*].securityContext는 정의된 모든 컨테이너의 Security Context 객체를 뜻합니다. 나열된 컨테이너 중 하나라도 요구사항을 충족하지 못하면 전체 Pod가 검증에 실패해요.

Windows Pod는 호스트 머신에 대한 특권 접근을 가능하게 하는 HostProcess 컨테이너를 실행할 수 있어요. 호스트에 대한 특권 접근은 Baseline 정책에서 금지됩니다.

기능 상태: Kubernetes v1.26 [stable]

호스트 프로세스 (HostProcess, Windows)

호스트 네임스페이스 공유는 금지되어야 합니다.

제한 필드 (Restricted Fields)

  • spec.securityContext.windowsOptions.hostProcess
  • spec.containers[*].securityContext.windowsOptions.hostProcess
  • spec.initContainers[*].securityContext.windowsOptions.hostProcess
  • spec.ephemeralContainers[*].securityContext.windowsOptions.hostProcess

허용 값 (Allowed Values)

  • 미정의/nil
  • false

호스트 네임스페이스 (Host Namespaces)

호스트 네임스페이스 공유는 금지되어야 합니다.

제한 필드

  • spec.hostNetwork
  • spec.hostPID
  • spec.hostIPC

허용 값

  • 미정의/nil
  • false

특권 컨테이너 (Privileged Containers)

특권 Pod는 대부분의 보안 메커니즘을 비활성화하므로 금지되어야 합니다.

제한 필드

  • spec.containers[*].securityContext.privileged
  • spec.initContainers[*].securityContext.privileged
  • spec.ephemeralContainers[*].securityContext.privileged

허용 값

  • 미정의/nil
  • false

Capabilities

아래에 나열된 것 이상의 추가 capabilities는 금지되어야 합니다.

제한 필드

  • spec.containers[*].securityContext.capabilities.add
  • spec.initContainers[*].securityContext.capabilities.add
  • spec.ephemeralContainers[*].securityContext.capabilities.add

허용 값

  • 미정의/nil
  • AUDIT_WRITE, CHOWN, DAC_OVERRIDE, FOWNER, FSETID, KILL, MKNOD, NET_BIND_SERVICE, SETFCAP, SETGID, SETPCAP, SETUID, SYS_CHROOT

HostPath 볼륨 (HostPath Volumes)

HostPath 볼륨은 금지되어야 합니다.

제한 필드

  • spec.volumes[*].hostPath

허용 값

  • 미정의/nil

호스트 포트 (Host Ports)

HostPorts는 완전히 금지(권장)되거나 알려진 목록으로 제한되어야 합니다.

제한 필드

  • spec.containers[*].ports[*].hostPort
  • spec.initContainers[*].ports[*].hostPort
  • spec.ephemeralContainers[*].ports[*].hostPort

허용 값

  • 미정의/nil
  • 알려진 목록 (내장 Pod Security Admission 컨트롤러는 지원하지 않음)
  • 0

호스트 프로브 / 라이프사이클 훅 (Host Probes / Lifecycle Hooks, v1.34+)

프로브와 라이프사이클 훅의 Host 필드는 금지되어야 합니다.

제한 필드

  • spec.containers[*].livenessProbe.httpGet.host
  • spec.containers[*].readinessProbe.httpGet.host
  • spec.containers[*].startupProbe.httpGet.host
  • spec.containers[*].livenessProbe.tcpSocket.host
  • spec.containers[*].readinessProbe.tcpSocket.host
  • spec.containers[*].startupProbe.tcpSocket.host
  • spec.containers[*].lifecycle.postStart.tcpSocket.host
  • spec.containers[*].lifecycle.preStop.tcpSocket.host
  • spec.containers[*].lifecycle.postStart.httpGet.host
  • spec.containers[*].lifecycle.preStop.httpGet.host
  • spec.initContainers[*].livenessProbe.httpGet.host
  • spec.initContainers[*].readinessProbe.httpGet.host
  • spec.initContainers[*].startupProbe.httpGet.host
  • spec.initContainers[*].livenessProbe.tcpSocket.host
  • spec.initContainers[*].readinessProbe.tcpSocket.host
  • spec.initContainers[*].startupProbe.tcpSocket.host
  • spec.initContainers[*].lifecycle.postStart.tcpSocket.host
  • spec.initContainers[*].lifecycle.preStop.tcpSocket.host
  • spec.initContainers[*].lifecycle.postStart.httpGet.host
  • spec.initContainers[*].lifecycle.preStop.httpGet.host

허용 값

  • 미정의/nil
  • ""

AppArmor

지원되는 호스트에서는 RuntimeDefault AppArmor 프로필이 기본으로 적용됩니다. Baseline 정책은 기본 AppArmor 프로필을 재정의하거나 비활성화하는 것을 방지하거나, 허용된 프로필 집합으로 재정의를 제한해야 해요.

제한 필드

  • spec.securityContext.appArmorProfile.type
  • spec.containers[*].securityContext.appArmorProfile.type
  • spec.initContainers[*].securityContext.appArmorProfile.type
  • spec.ephemeralContainers[*].securityContext.appArmorProfile.type

허용 값

  • 미정의/nil
  • RuntimeDefault
  • Localhost

제한 필드

  • metadata.annotations["container.apparmor.security.beta.kubernetes.io/*"]

허용 값

  • 미정의/nil
  • runtime/default
  • localhost/*

SELinux

SELinux type 설정은 제한되며, 사용자 지정 SELinux user 또는 role 옵션 설정은 금지됩니다.

제한 필드

  • spec.securityContext.seLinuxOptions.type
  • spec.containers[*].securityContext.seLinuxOptions.type
  • spec.initContainers[*].securityContext.seLinuxOptions.type
  • spec.ephemeralContainers[*].securityContext.seLinuxOptions.type

허용 값

  • 미정의/""
  • container_t
  • container_init_t
  • container_kvm_t
  • container_engine_t (Kubernetes 1.31부터)

제한 필드

  • spec.securityContext.seLinuxOptions.user
  • spec.containers[*].securityContext.seLinuxOptions.user
  • spec.initContainers[*].securityContext.seLinuxOptions.user
  • spec.ephemeralContainers[*].securityContext.seLinuxOptions.user
  • spec.securityContext.seLinuxOptions.role
  • spec.containers[*].securityContext.seLinuxOptions.role
  • spec.initContainers[*].securityContext.seLinuxOptions.role
  • spec.ephemeralContainers[*].securityContext.seLinuxOptions.role

허용 값

  • 미정의/""

/proc 마운트 유형 (/proc Mount Type)

기본 /proc 마스크는 공격 표면을 줄이도록 설정되어 있으며, 이를 요구해야 합니다.

제한 필드

  • spec.containers[*].securityContext.procMount
  • spec.initContainers[*].securityContext.procMount
  • spec.ephemeralContainers[*].securityContext.procMount

허용 값

  • 미정의/nil
  • Default

Seccomp

Seccomp 프로필은 명시적으로 Unconfined로 설정되어서는 안 됩니다.

제한 필드

  • spec.securityContext.seccompProfile.type
  • spec.containers[*].securityContext.seccompProfile.type
  • spec.initContainers[*].securityContext.seccompProfile.type
  • spec.ephemeralContainers[*].securityContext.seccompProfile.type

허용 값

  • 미정의/nil
  • RuntimeDefault
  • Localhost

Sysctls

Sysctls는 보안 메커니즘을 비활성화하거나 호스트의 모든 컨테이너에 영향을 줄 수 있으므로, 허용된 "안전한" 부분집합을 제외하고는 금지되어야 합니다. sysctl은 컨테이너나 Pod에서 네임스페이스화되고, 같은 Node의 다른 Pod나 프로세스로부터 격리되어 있으면 안전한 것으로 간주됩니다.

제한 필드

  • spec.securityContext.sysctls[*].name

허용 값

  • 미정의/nil
  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.ip_unprivileged_port_start
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_local_reserved_ports (Kubernetes 1.27부터)
  • net.ipv4.tcp_keepalive_time (Kubernetes 1.29부터)
  • net.ipv4.tcp_fin_timeout (Kubernetes 1.29부터)
  • net.ipv4.tcp_keepalive_intvl (Kubernetes 1.29부터)
  • net.ipv4.tcp_keepalive_probes (Kubernetes 1.29부터)

Restricted

Restricted 정책은 일부 호환성을 희생하더라도 현재 Pod 하드닝 모범 사례를 강제하는 것을 목표로 해요. 보안에 중요한 애플리케이션의 운영자와 개발자, 그리고 신뢰 수준이 낮은 사용자를 대상으로 합니다. 다음에 나열된 제어 항목들이 강제되거나 금지되어야 합니다.

참고: 이 표에서 와일드카드(*)는 목록의 모든 요소를 나타내요. 예를 들어 spec.containers[*].securityContext는 정의된 모든 컨테이너의 Security Context 객체를 뜻합니다. 나열된 컨테이너 중 하나라도 요구사항을 충족하지 못하면 전체 Pod가 검증에 실패해요.

제어 정책
Baseline 정책의 모든 항목

볼륨 유형 (Volume Types)

Restricted 정책은 다음 볼륨 유형만 허용해요.

제한 필드

  • spec.volumes[*]

허용 값

spec.volumes[*] 목록의 각 항목은 다음 필드 중 하나를 null이 아닌 값으로 설정해야 합니다.

  • spec.volumes[*].configMap
  • spec.volumes[*].csi
  • spec.volumes[*].downwardAPI
  • spec.volumes[*].emptyDir
  • spec.volumes[*].ephemeral
  • spec.volumes[*].persistentVolumeClaim
  • spec.volumes[*].projected
  • spec.volumes[*].secret

권한 상승 (Privilege Escalation, v1.8+)

권한 상승(set-user-ID나 set-group-ID 파일 모드를 통한 등)은 허용되지 않아야 합니다. v1.25+에서는 Linux 전용 정책입니다 (spec.os.name != windows).

제한 필드

  • spec.containers[*].securityContext.allowPrivilegeEscalation
  • spec.initContainers[*].securityContext.allowPrivilegeEscalation
  • spec.ephemeralContainers[*].securityContext.allowPrivilegeEscalation

허용 값

  • false

Non-root로 실행 (Running as Non-root)

컨테이너는 non-root 사용자로 실행되도록 요구되어야 합니다.

제한 필드

  • spec.securityContext.runAsNonRoot
  • spec.containers[*].securityContext.runAsNonRoot
  • spec.initContainers[*].securityContext.runAsNonRoot
  • spec.ephemeralContainers[*].securityContext.runAsNonRoot

허용 값

  • true

Pod 수준의 spec.securityContext.runAsNonRoot가 true로 설정되어 있으면 컨테이너 필드는 미정의/nil이어도 됩니다.

Non-root 사용자로 실행 (Running as Non-root user, v1.23+)

컨테이너는 runAsUser를 0으로 설정해서는 안 됩니다.

제한 필드

  • spec.securityContext.runAsUser
  • spec.containers[*].securityContext.runAsUser
  • spec.initContainers[*].securityContext.runAsUser
  • spec.ephemeralContainers[*].securityContext.runAsUser

허용 값

  • 0이 아닌 값
  • 미정의/null

Seccomp (v1.19+)

Seccomp 프로필은 허용된 값 중 하나로 명시적으로 설정되어야 합니다. Unconfined 프로필과 프로필이 없는 경우 모두 금지됩니다. v1.25+에서는 Linux 전용 정책입니다 (spec.os.name != windows).

제한 필드

  • spec.securityContext.seccompProfile.type
  • spec.containers[*].securityContext.seccompProfile.type
  • spec.initContainers[*].securityContext.seccompProfile.type
  • spec.ephemeralContainers[*].securityContext.seccompProfile.type

허용 값

  • RuntimeDefault
  • Localhost

Pod 수준의 spec.securityContext.seccompProfile.type 필드가 적절하게 설정되어 있으면 컨테이너 필드는 미정의/nil이어도 됩니다. 반대로 모든 컨테이너 수준 필드가 설정되어 있으면 Pod 수준 필드는 미정의/nil이어도 됩니다.

Capabilities (v1.22+)

컨테이너는 ALL capabilities를 drop해야 하며, NET_BIND_SERVICE capability만 다시 추가할 수 있습니다. v1.25+에서는 Linux 전용 정책입니다 (.spec.os.name != "windows").

제한 필드

  • spec.containers[*].securityContext.capabilities.drop
  • spec.initContainers[*].securityContext.capabilities.drop
  • spec.ephemeralContainers[*].securityContext.capabilities.drop

허용 값

  • ALL을 포함하는 모든 capabilities 목록

제한 필드

  • spec.containers[*].securityContext.capabilities.add
  • spec.initContainers[*].securityContext.capabilities.add
  • spec.ephemeralContainers[*].securityContext.capabilities.add

허용 값

  • 미정의/nil
  • NET_BIND_SERVICE

정책 구현 (Policy Instantiation)

정책 정의와 정책 구현을 분리하면 기본 강제 메커니즘과 무관하게 클러스터 전반에서 정책에 대한 공통된 이해와 일관된 언어를 가질 수 있어요.

메커니즘이 성숙함에 따라 아래에 정책별로 정의될 것입니다. 개별 정책의 강제 방법은 여기서 정의되지 않습니다.

Pod Security Admission Controller

  • Privileged 네임스페이스
  • Baseline 네임스페이스
  • Restricted 네임스페이스

대안 (Alternatives)

정책을 강제하는 다른 대안들이 쿠버네티스 생태계에서 개발되고 있어요. 예를 들면:

  • Kubewarden
  • Kyverno
  • OPA Gatekeeper

참고: 이 섹션은 쿠버네티스가 필요로 하는 기능을 제공하는 서드파티 프로젝트를 링크합니다. 쿠버네티스 프로젝트 저자들은 알파벳 순으로 나열된 이 프로젝트들에 대해 책임지지 않아요.

Pod OS 필드 (Pod OS field)

쿠버네티스는 Linux 또는 Windows를 실행하는 노드를 사용할 수 있게 해요. 한 클러스터에서 두 종류의 노드를 섞을 수도 있습니다. 쿠버네티스의 Windows는 Linux 기반 워크로드와 다른 몇 가지 제한사항과 차이점이 있어요. 특히 많은 Pod securityContext 필드가 Windows에서는 효과가 없습니다.

참고: v1.24 이전의 Kubelet은 Pod OS 필드를 강제하지 않으며, v1.24보다 이전 버전의 노드가 있는 클러스터라면 Restricted 정책을 v1.25 이전 버전에 고정해야 해요.

Restricted Pod Security Standard 변경 사항

Kubernetes v1.25에서 이뤄진 또 다른 중요한 변경은, Restricted 정책이 pod.spec.os.name 필드를 사용하도록 업데이트되었다는 점이에요. OS 이름을 기반으로 특정 OS에 특정한 일부 정책은 다른 OS에서는 완화될 수 있습니다.

OS별 정책 제어 (OS-specific policy controls)

다음 제어 항목에 대한 제한은 .spec.os.name이 windows가 아닌 경우에만 필요합니다.

  • 권한 상승 (Privilege Escalation)
  • Seccomp
  • Linux Capabilities
  • User namespaces

User Namespaces는 더 높은 격리로 워크로드를 실행하기 위한 Linux 전용 기능이에요. 이것이 Pod Security Standards와 어떻게 함께 동작하는지는 user namespaces를 사용하는 Pod 문서에 설명되어 있습니다.

FAQ

Privileged와 Baseline 사이에 프로필이 없는 이유는 무엇인가요?

여기 정의된 세 프로필은 가장 안전한 것(Restricted)에서 가장 덜 안전한 것(Privileged)으로 명확한 선형적 진행을 가지며, 폭넓은 워크로드 집합을 커버해요. Baseline 정책보다 위에 필요한 권한은 보통 매우 애플리케이션에 특정하기 때문에, 이 틈새에 표준 프로필을 제공하지 않아요. 그렇다고 이 경우 항상 privileged 프로필을 사용해야 한다는 뜻은 아니며, 이 공간의 정책은 사례별로 정의돼야 합니다.

SIG Auth는 다른 프로필에 대한 명확한 필요가 생기면 이 입장을 재고할 수 있어요.

보안 프로필(security profile)과 보안 컨텍스트(security context)의 차이는 무엇인가요?

Security Context는 런타임에 Pod와 Container를 구성해요. Security context는 Pod 매니페스트의 Pod 및 container 스펙 일부로 정의되며, 컨테이너 런타임에 대한 파라미터를 나타냅니다.

Security profile은 Security Context에서 특정 설정과, Security Context 밖의 다른 관련 파라미터를 강제하는 컨트롤 플레인 메커니즘이에요. 2021년 7월 기준으로 Pod Security Policies는 내장 Pod Security Admission Controller를 위해 폐기되었습니다.

샌드박스된 Pod는 어떤가요?

Pod가 샌드박스 처리되는지 여부를 제어하는 API 표준은 현재 없어요. 샌드박스 Pod는 샌드박스 런타임(gVisor나 Kata Containers 등)의 사용으로 식별될 수 있지만, 샌드박스 런타임이 무엇인지에 대한 표준 정의는 없습니다.

샌드박스 처리된 워크로드에 필요한 보호는 다른 것들과 다를 수 있어요. 예를 들어 워크로드가 기본 커널로부터 격리되어 있으면 특권 권한을 제한할 필요가 줄어듭니다. 이는 높은 권한이 필요한 워크로드도 여전히 격리될 수 있게 해줘요.

또한 샌드박스 워크로드의 보호는 샌드박싱 방법에 크게 의존합니다. 그렇기에 모든 샌드박스 워크로드에 단일하게 권장되는 프로필은 없어요.