사용자 네임스페이스

기능 상태: Kubernetes v1.25 [alpha]

이 페이지에서는 사용자 네임스페이스가 쿠버네티스 파드에서 사용되는 방법에 대해 설명한다. 사용자 네임스페이스는 컨테이너 내에서 실행 중인 사용자와 호스트의 사용자를 분리할 수 있도록 한다.

컨테이너에서 루트(root)로 실행되는 프로세스는 호스트에서 다른 (루트가 아닌) 사용자로 실행될 수 있다. 즉, 프로세스는 사용자 네임스페이스 내부 작업에 대해 특권을 갖지만(privileged) 네임스페이스 외부의 작업에서는 특권을 갖지 않는다.

이러한 기능을 사용하여 훼손(compromised)된 컨테이너가 호스트나 동일한 노드의 다른 파드에 미칠 수 있는 손상을 줄일 수 있다. HIGH 또는 CRITICAL 등급의 일부 보안 취약점은 사용자 네임스페이스가 Active 상태일 때 사용할 수 없다. 사용자 네임스페이스는 일부 미래의 취약점들도 완화시킬 수 있을 것으로 기대된다.

시작하기 전에

이것은 리눅스 전용 기능이다. 또한 컨테이너 런타임에서 이 기능을 쿠버네티스 스테이트리스(stateless) 파드와 함께 사용하려면 지원이 필요하다.

  • CRI-O: v1.25에는 사용자 네임스페이스가 지원된다.

  • containerd: 1.7 릴리즈에서 지원이 계획돼 있다. 자세한 내용은 containerd 이슈 #7063를 참조한다.

cri-dockerd에서의 지원은 아직 계획되지 않았다.

개요

사용자 네임스페이스는 컨테이너의 사용자를 호스트의 다른 사용자에게 매핑할 수 있는 리눅스 기능이다. 또한 사용자 네임스페이스의 파드에 부여된 기능은 네임스페이스 내부에서만 유효하고 외부에서는 무효하다.

파드는 pod.spec.hostUsers 필드를 false로 설정해 사용자 네임스페이스를 사용하도록 선택할 수 있다.

kubelet은 동일 노드에 있는 두 개의 스테이트리스 파드가 동일한 매핑을 사용하지 않도록 보장하는 방식으로 파드가 매핑된 호스트 UID나 GID를 선택한다.

pod.specrunAsUser, runAsGroup, fsGroup 등의 필드는 항상 컨테이너 내의 사용자를 가리킨다.

이 기능을 활성화한 경우 유효한 UID/GID의 범위는 0부터 65535까지이다. 이는 파일 및 프로세스(runAsUser, runAsGroup 등)에 적용된다.

이 범위를 벗어나는 UID/GID를 사용하는 파일은 오버플로 ID, 주로 65534(/proc/sys/kernel/overflowuid/proc/sys/kernel/overflowgid에서 설정됨)에 속하는 것으로 간주된다. 그러나 65534 사용자/그룹으로 실행하더라도 이러한 파일을 수정할 수 없다.

루트로 실행돼야 하지만 다른 호스트 네임스페이스나 리소스에 접근하지 않는 대부분의 애플리케이션은 사용자 네임스페이스를 활성화한 경우 변경할 필요 없이 계속 정상적으로 실행돼야 한다.

스테이트리스 파드의 사용자 네임스페이스 이해하기

기본 설정의 여러 컨테이너 런타임(Docker Engine, containerd, CRI-O 등)은 격리를 위해 리눅스 네임스페이스를 사용한다. 다른 기술도 존재하며 위와 같은 런타임에도 사용할 수 있다. (예를 들어, Kata Container는 리눅스 네임스페이스 대신 VM을 사용한다.) 이 페이지는 격리를 위해 리눅스 네임스페이스를 사용하는 컨테이너 런타임에 주안을 둔다.

파드를 생성할 때 기본적으로 컨테이너의 네트워크를 분리하는 네임스페이스, 프로세스 보기를 분리하는 PID 네임스페이스 등 여러 새로운 네임스페이스가 격리에 사용된다. 사용자 네임스페이스를 사용하면 컨테이너의 사용자와 노드의 사용자가 격리된다.

이는 컨테이너가 루트로 실행될 수 있고 호스트의 루트가 아닌 사용자에게 매핑될 수 있다는 것을 의미한다. 컨테이너 내부에서 프로세스는 자신이 루트로 실행된다고 생각하지만 (따라서 apt, yum 등과 같은 도구가 정상적으로 작동) 실제로 프로세스는 호스트에 대한 권한이 없다. 예를 들어, 컨테이너 프로세스가 호스트에서 ps를 실행하고 있는 사용자를 확인하는 경우 이를 확인 할 수 있다. 사용자 ps는 컨테이너 안에서 명령 id를 실행하면 나타나는 사용자와 동일하지 않다.

이 추상화는 컨테이너가 호스트로 탈출하는 것과 같은 상황을 제한한다. 컨테이너가 호스트에서 권한이 없는 사용자로 실행 중이기 때문에 호스트에게 수행할 수 있는 작업은 제한된다.

또한, 각 파드의 사용자는 호스트의 서로 겹치지 않는 다른 사용자에게 매핑되므로 다른 파드에 대해서도 수행할 수 있는 작업이 제한된다.

파드에 부여된 기능 또한 파드 사용자 네임스페이스로 제한되는데 대부분 유효하지 않고 심지어 일부는 완전히 무효하다. 다음은 두 가지 예시이다.

  • CAP_SYS_MODULE은 사용자 네임스페이스를 사용하여 파드에 부여돼도 아무런 효과가 없으며 파드는 커널 모듈을 로드할 수 없다.
  • CAP_SYS_ADMIN은 파드의 사용자 네임스페이스로 제한되며 네임스페이스 외부에서는 유효하지 않다.

사용자 네임스페이스를 사용하지 않고 루트로 실행되는 컨테이너는 컨테이너 브레이크아웃(container breakout)의 경우 노드에 대한 루트 권한을 가진다. 컨테이너에 일부 기능이 부여된 경우 호스트에서도 해당 기능이 유효하다. 사용자 네임스페이스를 사용할 경우 이 중 어느 것도 사실이 아니다.

사용자 네임스페이스 사용 시 변경사항에 대한 자세한 내용은 man 7 user_namespace를 참조한다.

사용자 네임스페이스를 지원하도록 노드 설정하기

호스트의 파일 및 프로세스에서 0 ~ 65535 범위의 UID/GID를 사용하는 것이 좋다.

kubelet은 파드에 그것보다 더 높은 UID/GID를 할당한다. 따라서 가능한 많은 격리를 보장하려면 호스트의 파일 및 호스트의 프로세스에 사용되는 UID/GID가 0-65535 범위여야 한다.

이 권장 사항은 파드가 호스트의 임의의 파일을 잠재적으로 읽을 수 있는 CVE-2021-25741과 같은 CVE의 영향을 완화하기 위해 중요하다. 파드와 호스트의 UID/GID가 겹치지 않으면 파드가 수행할 수 있는 작업이 제한된다. 즉, 파드 UID/GID가 호스트의 파일 소유자/그룹과 일치하지 않게 된다.

제약 사항

파드에 사용자 네임스페이스를 사용하는 경우 다른 호스트 네임스페이스를 사용할 수 없다. 특히 hostUsers: false를 설정하면 다음 중 하나를 설정할 수 없다.

  • hostNetwork: true
  • hostIPC: true
  • hostPID: true

파드는 볼륨을 전혀 사용하지 않거나 볼륨을 사용하는 경우에는 다음 볼륨 유형만 사용할 수 있다.

  • configmap
  • secret
  • projected
  • downwardAPI
  • emptyDir

파드가 이러한 볼륨의 파일을 읽을 수 있도록 하기 위해 파드에 .spec.securityContext.fsGroup0으로 지정한 것처럼 볼륨이 생성된다. 이 값이 다른 값으로 지정되면 당연히 이 다른 값이 대신 적용된다.

이로 인해 볼륨의 특정 항목에 대한 defaultModemode가 그룹에 대한 권한 없이 지정되었더라도 이러한 볼륨에 대한 폴더와 파일은 그룹에 대한 권한을 갖는다. 예를 들어 파일에 소유자에 대한 권한만 있는 방식으로 이러한 볼륨을 마운트할 수 없다.

이 페이지는 쿠버네티스가 필요로 하는 기능을 제공하는 써드파티 프로젝트 또는 제품에 대해 언급하고 있습니다. 쿠버네티스 프로젝트 저자들은 이러한 써드파티 프로젝트 또는 제품에 대해 책임지지 않습니다. CNCF 웹사이트 가이드라인에서 더 자세한 내용을 확인합니다.

다른 써드파티 링크를 추가하는 변경을 제안하기 전에, 컨텐츠 가이드를 확인해야 합니다.