본문 바로가기

Infrastructure/Kubernetes

[Pod] 사용자 네임스페이스

사용자 네임스페이스

쿠버네티스 공식문서를 확인하며 사용자 네임스페이스에 대해서 기억해야 하는 부분을 기록한다.

  • 사용자 네임스페이스를 사용하면 컨테이너 내부에서 실행 중인 사용자를 호스트의 사용자로부터 격리할 수 있다.
  • 컨테이너에서 루트로 실행되는 프로세스는 호스트에서 다른 사용자로 실행할 수 있다. 프로세스는 사용자 네임스페이스 내부의 작업에 대한 모든 권한을 갖지만 네임스페이스 외부의 작업에 대해서는 권한이 없다.
  • 사용자 네임스페이스 기능을 사용하여 손상된 컨테이너가 동일한 노드의 호스트 또는 다른 파드에 미칠 수 있는 피해를 줄일 수 있다.
  • 사용자 네임스페이스가 활성화되면 막을 수 있는 보안 취약점 중에 높음 및 보안으로 취급되는 것들이 있다.
  • 사용자 네임스페이스가 추후로 발생하는 보안 취약점 또한 완화할 것으로 예상된다.
  • 모든 CRI에서 지원하지는 않고 v1.25 기준 CRI-O만 지원한다. 또한 Linux 전용 기능이므로 다른 OS에서는 지원하지 않는다.
  • 파드는 pod.spec.hostUsers 필드를 false로 설정하여 사용자 네임스페이스를 사용하도록 선택할 수 있다.
  • kubelet은 파드가 매핑되는 호스트 UID/GID를 선택하고 동일한 노드에 있는 두 개의 상태 비저장 파드가 동일한 매핑을 사용하지 않도록 보장하는 방식으로 변경합니다.
  • pod.spec 필드의 runAsUser, runAsGroup, fsGroup 등은 항상 컨테이너 내부의 사용자를 의미한다.
  • 사용자 네임스페이스가 활성화된 경우 유효한 UID/GID는 0-65535범위이며 runAsUser, runAsGroup 등에 적용된다.
  • UID/GID를 사용하는 파일 중 범위를 벗어나게 되면 overflow ID에 포함되는 것으로 표시된다. 65534 user/group 으로 실행되더라도 해당 파일을 수정할 수 없다.
  • 루트 권한으로 실행되어야 하지만 다른 호스트 네임스페이스나 리소스에 액세스하지 않는 대부분의 애플리케이션은 사용자 네임스페이스가 활성화된 경우 변경이 필요없이 계속해서 정상적으로 실행되어야 한다.

[정리]

사용자 네임스페이스를 사용하면 컨테이너 내부에서 실행 중인 사용자를 호스트의 사용자로부터 격리할 수 있으며 이러한 격리를 통해 손상된 컨테이너가 다른 컨테이너에 주는 악영향을 감소시킬 수 있으며 많은 보안 취약점으로부터 안전할 수 있다. 하지만 v1.25 버전 기준으로 모든 컨테이너 런타임이 지원하는 것은 아니기 때문에 자신이 사용하는 컨테이너 런타임이 지원하는지 확인해야 한다.


스테이트리스 파드에 대한 사용자 네임스페이스 이해

  • 기본 구성이 있는 여러 컨테이너 런타임은 격리를 위해 Linux 네임스페이스를 사용한다. 몇몇 컨테이너 런타임들은 Linux 네임스페이스 대신 VM을 사용하는 경우도 있다.
  • 파드를 생성할 때 기본적으로 몇 가지 새로운 네임스페이스가 격리에 사용된다. 여기에는 컨테이너 네트워크를 격리하는 네트워크 네임스페이스, 프로세스 보기를 격리하는 PID 네임스페이스 등이 포함되며 이는 컨테이너가 루트 권한으로 실행될 수 있고 호스트의 루트가 아닌 사용자에게 매핑될 수 있음을 의미한다.
  • 컨테이너 내부에서 프로세스는 루트 권한으로 실행 중이라고 생각하지만 실제로 프로세스는 호스트에 대한 권한이 없다. 예를 들어 컨테이너 프로세스가 호스트에서 실행 중인 사용자를 확인하는 경우 이를 확인할 수 있다.
  • 컨테이너 프로세스가 호스트에서 ps를 실행하고 있는 사용자를 확인하는 경우 이를 확인할 수 있다. ps가 보여주는 사용자는 컨테이너 내에서 명령 id를 실행하는 경우 표시되는 사용자와 동일하지 않다.
  • 이러한 추상화는 컨테이너 관리가 호스트를 탈출하는 것과 같은 문제를 미리 차단할 수 있다.
  • 컨테이너가 호스트에서 권한이 없는 사용자로 실행되고 있다는 점을 감안할 때 호스트에 대해 수행할 수 있는 작업은 제한된다.
  • 각 파드의 사용자는 호스트의 겹치지 않는 다른 사용자에게 매핑되므로 다른 파드에도 수행할 수 있는 작업이 제한된다.
  • 파드에 부여된 기능도 파드 사용자 네임스페이스로 제한되며 대부분 유효하지 않으며 일부는 완전히 무효화 되기도 한다. 아래는 두 가지 예시이다.
    • CAP_SYS_MODULE: 사용자 네임스페이스를 사용하여 파드에 부여된 경우 아무런 효과가 없으며 파드는 커널 모듈을 로드할 수 없다.
    • CAP_SYS_ADMIN: 파드의 사용자 네임스페이스로 제한되며 외부에서는 유효하지 않다.
  • 사용자 네임스페이스를 사용하지 않고 루트로 실행되는 컨테이너는 컨테이너 브레이크아웃의 경우 노드에 대한 루트 권한을 갖으며, 일부 기능은 컨테이너에 부여된 경우 호스트에서도 유효하다.

[정리]

대부분의 컨테이너 런타임은 컨테이너의 격리를 위해 Linux 네임스페이스를 사용한다. 파드를 생성할 때 기본적으로 몇 가지 새로운 네임스페이스가 격리되어 사용되며 이것은 컨테이너가 루트 권한으로 실행될 수 있고 호스트의 루트가 아닌 사용자에게 매핑될 수 있음을 의미한다.

컨테이너는 호스트에서 권한이 없는 사용자로 실행되고 있기 때문에 호스트에 대해 수행할 수 있는 작업은 제한된다. 또한 사용자는 호스트의 겹치지 않는 다른 사용자에게 매핑되므로 다른 파드에서도 수행할 수 있는 작업이 제한된다.


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

  • 호스트는 파일과 호스트의 프로세스는 0 - 65535 범위의 UID/GID를 사용하는 것이 좋다.
  • kubelet은 파드에 그보다 높은 UID/GID를 할당한다. 따라서 가능한 많은 격리를 보장하려면 호스트의 파일과 호스트의 프로세스에서 사용하는 UID/GID가 0 - 65535 범위에 있어야 한다.
  • 이 권장 사항은 CVE-2021-25741과 같은 CVE의 영향을 완화하는 데 중요하고 파드는 잠재적으로 호스트의 임의 파일을 읽을 수 있다.
  • 파드와 호스트의 UID/GID가 겹치지 않으면 파드가 수행할 수 있는 작업이 제한된다.
  • 파드의 UID/GID는 호스트의 파일 소유자 그룹과 일치하지 않는다.

[정리]

kubelet은 0 - 65535 범위 이상의 값을 UID/GID 값을 할당하기 때문에 호스트의 파일과 프로세스는 0 - 65535 범위 내의 값을 사용하는 것이 좋다.


제한 사항

  • 파드에 대해 사용자 네임스페이스를 사용할 때 다른 호스트 네임스페이스를 사용할 수 없다. 특히 hostUsers: false로 설정하는 경우 아래의 설정이 불가능하다.
    • hostNetwork: true
    • hostIPC: true
    • hostPID: true
  • 파드는 볼륨을 전혀 사용하지 않거나 볼륨을 사용하는 경우 아래의 볼륨 유형만 허용된다.
    • configmap
    • secret
    • projected
    • downwardAPI
    • emptyDir
  • 파드가 이러한 볼륨의 파일을 읽을 수 있도록 보장하기 위해 파드의.spec.securityContext.fsGroup속성을 0으로 지정해야 한다.

참고 자료