Kubernetes v1.35: 세밀한 보조 그룹 제어가 GA로 승격
Source: Kubernetes Blog
졸업 알림
Kubernetes SIG Node를 대표하여, fine‑grained supplemental groups control가 Kubernetes v1.35에서 General Availability (GA) 로 졸업하게 되었음을 알려드립니다!
- 새로운 pod 필드
supplementalGroupsPolicy는 v1.31에서 opt‑in alpha 기능으로 도입되었으며, v1.33에서 beta 로 졸업했고, 이제 GA 입니다. - 이 기능은 Linux 컨테이너의 supplemental groups에 대한 정밀한 제어를 제공하여 보안을 강화합니다—특히 볼륨에 접근할 때.
- 또한 컨테이너 내부의 UID/GID 세부 정보를 투명하게 하여 보안 관리가 향상됩니다.
업그레이드 참고 – v1.32 이하 버전에서 업그레이드하는 경우, 베타(v1.33) 이후 도입된 동작상의 호환성 깨짐을 유의하시기 바랍니다. 자세한 내용은 이전 블로그의 behavioral changes와 upgrade considerations 섹션을 참고하십시오.
Motivation: Implicit group memberships defined in /etc/group
많은 클러스터 관리자/사용자는 눈치채지 못할 수도 있지만, Kubernetes는 기본적으로 파드의 그룹 정보를 컨테이너 이미지 내부의 /etc/group 파일과 병합합니다.
Example manifest
apiVersion: v1
kind: Pod
metadata:
name: implicit-groups-example
spec:
securityContext:
runAsUser: 1000 # UID
runAsGroup: 3000 # primary GID
supplementalGroups: [4000]
containers:
- name: example-container
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: ["sh", "-c", "sleep 1h"]
securityContext:
allowPrivilegeEscalation: false
What does id show inside the container?
uid=1000 gid=3000 groups=3000,4000,50000
50000 GID는 파드 매니페스트에 정의되어 있지 않음에도 나타납니다.
이는 컨테이너 이미지의 /etc/group 파일에서 온 것입니다:
user-defined-in-image:x:1000:
group-defined-in-image:x:50000:user-defined-in-image
주 사용자(UID 1000)는 그룹 50000에 속해 있으므로, Kubernetes는 해당 그룹을 컨테이너의 보조 그룹에 암묵적으로 병합합니다.
Why is this a problem?
- 암묵적인 GID는 정책 엔진에 보이지 않으며, 파드 스펙에 나타나지 않습니다.
- 특히 볼륨에 접근할 때 예기치 않은 접근 제어 문제를 일으킬 수 있습니다(see kubernetes/kubernetes#112879).
세분화된 보조 그룹 제어 – supplementalGroupsPolicy
Pod의 .spec.securityContext에 이제 supplementalGroupsPolicy 필드가 포함됩니다. 이 필드는 Kubernetes가 컨테이너 프로세스에 대한 보조 그룹을 어떻게 계산할지 결정합니다.
| 정책 | 설명 |
|---|---|
| Merge (기본) | 기존 동작을 유지합니다 – 기본 사용자의 /etc/group 에서 가져온 그룹 멤버십이 병합되어 Pod에 정의된 그룹과 함께 적용됩니다. |
| Strict | fsGroup, supplementalGroups, runAsGroup 에 명시된 GID만 적용됩니다. /etc/group 에서 가져온 그룹 멤버십은 무시됩니다. |
Strict 정책 예시
apiVersion: v1
kind: Pod
metadata:
name: strict-supplementalgroups-policy-example
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
supplementalGroupsPolicy: Strict
containers:
- name: example-container
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: ["sh", "-c", "sleep 1h"]
securityContext:
allowPrivilegeEscalation: false
컨테이너 내부에서 id 명령을 실행하면 다음과 같이 표시됩니다:
uid=1000 gid=3000 groups=3000,4000
원하지 않는 그룹 50000이 더 이상 나타나지 않습니다.
supplementalGroupsPolicy: Strict 를 적용하면(예: 정책 엔진을 통해) 암묵적인 보조 그룹이 Pod에 추가되는 것을 방지할 수 있습니다.
Note: 충분한 권한을 가진 컨테이너는 시작 후에도 프로세스 ID를 변경할 수 있습니다.
supplementalGroupsPolicy는 초기 프로세스 ID에만 영향을 미칩니다.
Pod 상태에서 연결된 프로세스 ID 노출
이 기능은 초기 프로세스 ID를 pod 상태에 추가합니다:
status:
containerStatuses:
- name: ctr
user:
linux:
uid: 1000
gid: 3000
supplementalGroups:
- 3000
- 4000
Important:
status.containerStatuses[].user.linux에 있는 값은 첫 번째 연결된 ID를 나타냅니다. 컨테이너가setuid(2),setgid(2),setgroups(2)등을 호출할 수 있다면, 이후에 ID를 변경할 수 있어 실제 런타임 ID가 동적으로 변할 수 있습니다.
특권 상승 완화
컨테이너가 ID를 변경하는 능력을 제한하려면 다음과 같은 간단한 완화 방안을 고려하십시오:
- 컨테이너의
securityContext에서 privilege: false와 allowPrivilegeEscalation: false를 설정합니다. - Pod Security Standards의 Restricted 정책에 맞추어 pod를 구성합니다.
TL;DR
supplementalGroupsPolicy(v1.35에서 GA) 는 기존 Merge 동작과 숨겨진 그룹 멤버십을 제거하는 Strict 모드 중 하나를 선택할 수 있게 합니다.- Strict(또는 정책을 통해 강제 적용) 를 사용하여
/etc/group에서 암시적으로 포함되는 그룹으로 인한 보안 예기치 못한 상황을 방지하세요. - 초기 ID가 이제 pod 상태에 표시되어 그룹 할당을 감사하고 검증하는 데 도움이 됩니다.
개요
- kubelet은 NRI 플러그인이나 컨테이너 런타임의 내부 작동을 볼 수 없습니다.
- 클러스터 관리자(또는 로컬‑admin 권한을 가진 고권한 워크로드)는 모든 파드의 보조 그룹을 변경할 수 있습니다.
- 이는 Kubernetes 제어 범위를 벗어나며 보안 강화된 노드에서는 고려할 필요가 없습니다.
Strict Policy Requires Up‑to‑Date Container Runtimes
고수준 컨테이너 런타임(예: containerd, CRI‑O)은 컨테이너에 연결될 보조 그룹 ID를 계산하는 역할을 담당합니다. 따라서 supplementalGroupsPolicy: Strict는 이 기능을 지원하는 CRI 런타임이 필요합니다.
- 이전 동작(
supplementalGroupsPolicy: Merge)은 해당 기능을 지원하지 않는 런타임에서도 작동합니다. 이는 완전히 이전 버전과 호환되기 때문입니다.
Supported CRI Runtimes
| Runtime | Minimum Version |
|---|---|
| containerd | v2.0 or later |
| CRI‑O | v1.31 or later |
기능 지원 확인
노드에서 해당 기능이 활성화되어 있는지 확인하려면 status.features.supplementalGroupsPolicy 필드를 사용합니다 (KEP‑5328: Node Declared Features에서 도입된 status.declaredFeatures와는 다릅니다).
apiVersion: v1
kind: Node
...
status:
features:
supplementalGroupsPolicy: true
모범 사례
- 컨테이너 런타임이 이 기능을 보편적으로 채택함에 따라, 많은 보안 정책이 더 강력한 보안을 위해 Strict 동작을 적용하기 시작할 것입니다.
- 이미지에 내장된 기본값에 의존하지 말고 Pod 사양에 모든 보조 그룹을 명시적으로 선언하여 이 적용에 대비하십시오.
참여하기
이 개선은 SIG Node 커뮤니티에 의해 주도되었습니다.
토론에 참여하고, 아이디어를 공유하며, 이 기능 및 관련 주제에 대한 피드백을 제공해 주세요. 커뮤니티는 여러분의 의견을 기다리고 있습니다!
자세히 알아보기
- Pod 또는 컨테이너에 대한 보안 컨텍스트 구성 –
supplementalGroupsPolicy에 대한 자세한 안내. - KEP‑3619 – 세분화된 SupplementalGroups 제어.