Kubernetes v1.33:細粒度 SupplementalGroups 控制功能進入 Beta 階段
新欄位 supplementalGroupsPolicy
在 Kubernetes v1.31 中作為可選的 Alpha 特性引入,並已在 v1.33 中升級為 Beta;相應的功能門控(SupplementalGroupsPolicy
)現已預設啟用。此功能可以對容器中的附加組(supplemental groups)進行更精確的控制,從而加強安全態勢,尤其是在訪問卷時。此外,它還提高了容器中 UID/GID 詳細資訊的透明度,從而提供更好的安全監督。
請注意,此 Beta 版本包含一些行為上的破壞性變更。詳情請參閱Beta 版本中引入的行為變更和升級注意事項部分。
動機:容器映象中 /etc/group
定義的隱式組成員關係
儘管大多數 Kubernetes 叢集管理員/使用者可能沒有意識到,但 Kubernetes 預設情況下會*合併*來自 Pod 的組資訊與容器映象中 /etc/group
定義的資訊。
讓我們看一個例子,下面的 Pod 清單在 Pod 的安全上下文中指定了 runAsUser=1000
、runAsGroup=3000
和 supplementalGroups=4000
。
apiVersion: v1
kind: Pod
metadata:
name: implicit-groups
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
containers:
- name: ctr
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
在 ctr
容器中執行 id
命令的結果是什麼?輸出應類似於:
uid=1000 gid=3000 groups=3000,4000,50000
附加組(groups
欄位)中的組 ID 50000
是從哪裡來的,儘管 50000
根本沒有在 Pod 的清單中定義?答案是容器映象中的 /etc/group
檔案。
檢查容器映象中 /etc/group
的內容,應該會顯示如下內容:
user-defined-in-image:x:1000:
group-defined-in-image:x:50000:user-defined-in-image
這表明容器的主使用者 1000
在最後一條目中屬於組 50000
。
因此,在容器映象中為容器主使用者在 /etc/group
中定義的組成員關係會*隱式地*與 Pod 的資訊合併。請注意,這是當前 CRI 實現從 Docker 繼承的設計決策,社群至今從未真正重新考慮過它。
這有什麼問題?
從容器映象中的 /etc/group
中*隱式*合併的組資訊存在安全風險。這些隱式 GID 無法被策略引擎檢測或驗證,因為它們在 Pod 清單中沒有任何記錄。這可能導致意外的訪問控制問題,尤其是在訪問卷時(詳見 kubernetes/kubernetes#112879),因為檔案許可權在 Linux 中由 UID/GID 控制。
Pod 中細粒度的附加組控制:supplementaryGroupsPolicy
為了解決上述問題,Pod 的 .spec.securityContext
現在包含了 supplementalGroupsPolicy
欄位。
此欄位允許你控制 Kubernetes 如何計算 Pod 內容器程序的附加組。可用的策略有:
Merge:將合併容器主使用者在
/etc/group
中定義的組成員關係。如果未指定,將應用此策略(即為了向後相容而保持現有行為)。Strict:只有在
fsGroup
、supplementalGroups
或runAsGroup
中指定的組 ID 會作為附加組附加到容器程序中。容器主使用者在/etc/group
中定義的組成員關係將被忽略。
讓我們看看 Strict
策略是如何工作的。下面的 Pod 清單指定了 supplementalGroupsPolicy: Strict
apiVersion: v1
kind: Pod
metadata:
name: strict-supplementalgroups-policy
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
supplementalGroupsPolicy: Strict
containers:
- name: ctr
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
在 ctr
容器中執行 id
命令的結果應類似於:
uid=1000 gid=3000 groups=3000,4000
你可以看到 Strict
策略能夠從 groups
中排除組 50000
!
因此,確保 supplementalGroupsPolicy: Strict
(透過某種策略機制強制執行)有助於防止 Pod 中出現隱式的附加組。
說明
具有足夠許可權的容器可以更改其程序身份。supplementalGroupsPolicy
隻影響初始程序身份。詳情請參閱下一節。Pod 狀態中附加的程序身份
此功能還透過 .status.containerStatuses[].user.linux
欄位公開了附加到容器首個程序的程序身份。這有助於檢視是否附加了隱式組 ID。
...
status:
containerStatuses:
- name: ctr
user:
linux:
gid: 3000
supplementalGroups:
- 3000
- 4000
uid: 1000
...
說明
請注意,status.containerStatuses[].user.linux
欄位中的值是*首次附加*到容器中第一個程序的程序身份。如果容器具有足夠的許可權來呼叫與程序身份相關的系統呼叫(例如 setuid(2)
、setgid(2)
或 setgroups(2)
等),容器程序可以更改其身份。因此,*實際*的程序身份將是動態的。Strict
策略需要較新的 CRI 版本
實際上,CRI 執行時(例如 containerd、CRI-O)在計算要附加到容器的附加組 ID 方面扮演著核心角色。因此,SupplementalGroupsPolicy=Strict
需要支援此功能的 CRI 執行時(SupplementalGroupsPolicy: Merge
可以與不支援此功能的 CRI 執行時一起工作,因為該策略是完全向後相容的)。
以下是一些支援此功能的 CRI 執行時及其所需的版本:
- containerd:v2.0 或更高版本
- CRI-O:v1.31 或更高版本
並且,你可以在節點的 .status.features.supplementalGroupsPolicy
欄位中檢視是否支援該功能。
apiVersion: v1
kind: Node
...
status:
features:
supplementalGroupsPolicy: true
Beta 版本中引入的行為變更
在 Alpha 版本中,當一個帶有 supplementalGroupsPolicy: Strict
的 Pod 被排程到一個不支援該功能的節點上時(即 .status.features.supplementalGroupsPolicy=false
),該 Pod 的附加組策略會靜默地回退到 Merge
。
在 v1.33 中,此功能已進入 Beta 階段,以更嚴格地執行策略,即 kubelet 會拒絕其節點無法確保指定策略的 Pod。如果你的 Pod 被拒絕,你將看到帶有 reason=SupplementalGroupsPolicyNotSupported
的警告事件,如下所示:
apiVersion: v1
kind: Event
...
type: Warning
reason: SupplementalGroupsPolicyNotSupported
message: "SupplementalGroupsPolicy=Strict is not supported in this node"
involvedObject:
apiVersion: v1
kind: Pod
...
升級注意事項
如果你已經在使用此功能,特別是 supplementalGroupsPolicy: Strict
策略,我們假設你叢集的 CRI 執行時已經支援此功能。在這種情況下,你無需擔心上述的 Pod 拒絕問題。
但是,如果你的叢集:
- 使用了
supplementalGroupsPolicy: Strict
策略,但是 - 其 CRI 執行時尚不支援該功能(即
.status.features.supplementalGroupsPolicy=false
),
你需要在升級叢集時為行為變更(Pod 拒絕)做好準備。
我們推薦幾種方法來避免意外的 Pod 拒絕:
- 在升級 Kubernetes 的同時或之前升級你叢集的 CRI 執行時
- 為你的節點新增一些標籤,描述 CRI 執行時是否支援此功能,併為帶有
Strict
策略的 Pod 新增標籤選擇器以選擇此類節點(但是,在這種情況下,你需要監控Pending
狀態的 Pod 數量,而不是 Pod 拒絕)。
參與進來
此功能由 SIG Node 社群推動。請加入我們,與社群聯絡,分享你關於上述功能及其他方面的想法和反饋。我們期待你的迴音!
我如何瞭解更多資訊?
- 有關
supplementalGroupsPolicy
的更多詳細資訊,請參閱為 Pod 或容器配置安全上下文 - KEP-3619:細粒度的 SupplementalGroups 控制