Skip to content

Commit 28f0159

Browse files
authored
Merge pull request #47978 from windsonsea/fgsgc
[zh] Add a blog: 2024-08-22-Fine-grained-SupplementalGroups-control
2 parents ef1c8b6 + 655a0aa commit 28f0159

File tree

3 files changed

+346
-0
lines changed

3 files changed

+346
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: implicit-groups
5+
spec:
6+
securityContext:
7+
runAsUser: 1000
8+
runAsGroup: 3000
9+
supplementalGroups: [4000]
10+
containers:
11+
- name: ctr
12+
image: registry.k8s.io/e2e-test-images/agnhost:2.45
13+
command: [ "sh", "-c", "sleep 1h" ]
14+
securityContext:
15+
allowPrivilegeEscalation: false
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
---
2+
layout: blog
3+
title: 'Kubernetes 1.31:细粒度的 SupplementalGroups 控制'
4+
date: 2024-08-22
5+
slug: fine-grained-supplementalgroups-control
6+
author: >
7+
Shingo Omura (Woven By Toyota)
8+
translator: >
9+
[Michael Yao](https://github.com/windsonsea) (DaoCloud)
10+
---
11+
<!--
12+
layout: blog
13+
title: 'Kubernetes 1.31: Fine-grained SupplementalGroups control'
14+
date: 2024-08-22
15+
slug: fine-grained-supplementalgroups-control
16+
author: >
17+
Shingo Omura (Woven By Toyota)
18+
-->
19+
20+
<!--
21+
This blog discusses a new feature in Kubernetes 1.31 to improve the handling of supplementary groups in containers within Pods.
22+
-->
23+
本博客讨论了 Kubernetes 1.31 中的一项新特性,目的是改善处理 Pod 中容器内的附加组。
24+
25+
<!--
26+
## Motivation: Implicit group memberships defined in `/etc/group` in the container image
27+
28+
Although this behavior may not be popular with many Kubernetes cluster users/admins, kubernetes, by default, _merges_ group information from the Pod with information defined in `/etc/group` in the container image.
29+
30+
Let's see an example, below Pod specifies `runAsUser=1000`, `runAsGroup=3000` and `supplementalGroups=4000` in the Pod's security context.
31+
-->
32+
## 动机:容器镜像中 `/etc/group` 中定义的隐式组成员关系
33+
34+
尽管这种行为可能并不受许多 Kubernetes 集群用户/管理员的欢迎,
35+
但 Kubernetes 默认情况下会将 Pod 中的组信息与容器镜像中 `/etc/group` 中定义的信息进行**合并**
36+
37+
让我们看一个例子,以下 Pod 在 Pod 的安全上下文中指定了
38+
`runAsUser=1000``runAsGroup=3000``supplementalGroups=4000`
39+
40+
{{% code_sample file="implicit-groups.yaml" %}}
41+
42+
<!--
43+
What is the result of `id` command in the `ctr` container?
44+
45+
```console
46+
# Create the Pod:
47+
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/implicit-groups.yaml
48+
49+
# Verify that the Pod's Container is running:
50+
$ kubectl get pod implicit-groups
51+
52+
# Check the id command
53+
$ kubectl exec implicit-groups -- id
54+
```
55+
-->
56+
`ctr` 容器中执行 `id` 命令的结果是什么?
57+
58+
```console
59+
# 创建 Pod:
60+
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/implicit-groups.yaml
61+
62+
# 验证 Pod 的容器正在运行:
63+
$ kubectl get pod implicit-groups
64+
65+
# 检查 id 命令
66+
$ kubectl exec implicit-groups -- id
67+
```
68+
69+
<!--
70+
Then, output should be similar to this:
71+
-->
72+
输出应类似于:
73+
74+
```none
75+
uid=1000 gid=3000 groups=3000,4000,50000
76+
```
77+
78+
<!--
79+
Where does group ID `50000` in supplementary groups (`groups` field) come from, even though `50000` is not defined in the Pod's manifest at all? The answer is `/etc/group` file in the container image.
80+
81+
Checking the contents of `/etc/group` in the container image should show below:
82+
-->
83+
尽管 `50000` 根本没有在 Pod 的清单中被定义,但附加组中的组 ID `50000``groups` 字段)是从哪里来的呢?
84+
答案是容器镜像中的 `/etc/group` 文件。
85+
86+
检查容器镜像中 `/etc/group` 的内容应如下所示:
87+
88+
```console
89+
$ kubectl exec implicit-groups -- cat /etc/group
90+
...
91+
user-defined-in-image:x:1000:
92+
group-defined-in-image:x:50000:user-defined-in-image
93+
```
94+
95+
<!--
96+
Aha! The container's primary user `1000` belongs to the group `50000` in the last entry.
97+
98+
Thus, the group membership defined in `/etc/group` in the container image for the container's primary user is _implicitly_ merged to the information from the Pod. Please note that this was a design decision the current CRI implementations inherited from Docker, and the community never really reconsidered it until now.
99+
-->
100+
原来如此!容器的主要用户 `1000` 属于最后一个条目中的组 `50000`
101+
102+
因此,容器镜像中为容器的主要用户定义的组成员关系会被**隐式**合并到 Pod 的信息中。
103+
请注意,这是当前 CRI 实现从 Docker 继承的设计决策,而社区直到现在才重新考虑这个问题。
104+
105+
<!--
106+
### What's wrong with it?
107+
108+
The _implicitly_ merged group information from `/etc/group` in the container image may cause some concerns particularly in accessing volumes (see [kubernetes/kubernetes#112879](https://issue.k8s.io/112879) for details) because file permission is controlled by uid/gid in Linux. Even worse, the implicit gids from `/etc/group` can not be detected/validated by any policy engines because there is no clue for the implicit group information in the manifest. This can also be a concern for Kubernetes security.
109+
-->
110+
### 这有什么问题?
111+
112+
从容器镜像中的 `/etc/group` **隐式**合并的组信息可能会引起一些担忧,特别是在访问卷时
113+
(有关细节参见 [kubernetes/kubernetes#112879](https://issue.k8s.io/112879)),
114+
因为在 Linux 中文件权限是通过 uid/gid 进行控制的。
115+
更糟糕的是,隐式的 gid 无法被任何策略引擎所检测/验证,因为在清单中没有隐式组信息的线索。
116+
这对 Kubernetes 的安全性也可能构成隐患。
117+
118+
<!--
119+
## Fine-grained SupplementalGroups control in a Pod: `SupplementaryGroupsPolicy`
120+
121+
To tackle the above problem, Kubernetes 1.31 introduces new field `supplementalGroupsPolicy` in Pod's `.spec.securityContext`.
122+
123+
This field provies a way to control how to calculate supplementary groups for the container processes in a Pod. The available policy is below:
124+
-->
125+
## Pod 中的细粒度 SupplementalGroups 控制:`SupplementaryGroupsPolicy`
126+
127+
为了解决上述问题,Kubernetes 1.31 在 Pod 的 `.spec.securityContext`
128+
中引入了新的字段 `supplementalGroupsPolicy`
129+
130+
此字段提供了一种控制 Pod 中容器进程如何计算附加组的方法。可用的策略如下:
131+
132+
<!--
133+
* _Merge_: The group membership defined in `/etc/group` for the container's primary user will be merged. If not specified, this policy will be applied (i.e. as-is behavior for backword compatibility).
134+
135+
* _Strict_: it only attaches specified group IDs in `fsGroup`, `supplementalGroups`, or `runAsGroup` fields as the supplementary groups of the container processes. This means no group membership defined in `/etc/group` for the container's primary user will be merged.
136+
137+
Let's see how `Strict` policy works.
138+
-->
139+
* **Merge**:将容器的主要用户在 `/etc/group` 中定义的组成员关系进行合并。
140+
如果不指定,则应用此策略(即为了向后兼容性而保持的原有行为)。
141+
142+
* **Strict**:仅将 `fsGroup``supplementalGroups``runAsGroup`
143+
字段中指定的组 ID 挂接为容器进程的附加组。这意味着容器的主要用户在 `/etc/group` 中定义的任何组成员关系都不会被合并。
144+
145+
让我们看看 `Strict` 策略是如何工作的。
146+
147+
{{% code_sample file="strict-supplementalgroups-policy.yaml" %}}
148+
149+
<!--
150+
```console
151+
# Create the Pod:
152+
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/strict-supplementalgroups-policy.yaml
153+
154+
# Verify that the Pod's Container is running:
155+
$ kubectl get pod strict-supplementalgroups-policy
156+
157+
# Check the process identity:
158+
kubectl exec -it strict-supplementalgroups-policy -- id
159+
```
160+
-->
161+
```console
162+
# 创建 Pod:
163+
$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/strict-supplementalgroups-policy.yaml
164+
165+
# 验证 Pod 的容器正在运行:
166+
$ kubectl get pod strict-supplementalgroups-policy
167+
168+
# 检查进程身份:
169+
kubectl exec -it strict-supplementalgroups-policy -- id
170+
```
171+
172+
<!--
173+
The output should be similar to this:
174+
-->
175+
输出应类似于:
176+
177+
```none
178+
uid=1000 gid=3000 groups=3000,4000
179+
```
180+
181+
<!--
182+
You can see `Strict` policy can exclude group `50000` from `groups`!
183+
184+
Thus, ensuring `supplementalGroupsPolicy: Strict` (enforced by some policy mechanism) helps prevent the implicit supplementary groups in a Pod.
185+
-->
186+
你可以看到 `Strict` 策略可以将组 `50000``groups` 中排除出去!
187+
188+
因此,确保(通过某些策略机制强制执行的)`supplementalGroupsPolicy: Strict` 有助于防止 Pod 中的隐式附加组。
189+
190+
{{<note>}}
191+
<!--
192+
Actually, this is not enough because container with sufficient privileges / capability can change its process identity. Please see the following section for details.
193+
-->
194+
实际上,这还不够,因为具有足够权限/能力的容器可以更改其进程身份。
195+
有关细节参见以下章节。
196+
{{</note>}}
197+
198+
<!--
199+
## Attached process identity in Pod status
200+
201+
This feature also exposes the process identity attached to the first container process of the container
202+
via `.status.containerStatuses[].user.linux` field. It would be helpful to see if implicit group IDs are attached.
203+
-->
204+
## Pod 状态中挂接的进程身份
205+
206+
此特性还通过 `.status.containerStatuses[].user.linux`
207+
字段公开挂接到容器的第一个容器进程的进程身份。这将有助于查看隐式组 ID 是否被挂接。
208+
209+
```yaml
210+
...
211+
status:
212+
containerStatuses:
213+
- name: ctr
214+
user:
215+
linux:
216+
gid: 3000
217+
supplementalGroups:
218+
- 3000
219+
- 4000
220+
uid: 1000
221+
...
222+
```
223+
224+
{{<note>}}
225+
<!--
226+
Please note that the values in `status.containerStatuses[].user.linux` field is _the firstly attached_
227+
process identity to the first container process in the container. If the container has sufficient privilege
228+
to call system calls related to process identity (e.g. [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html), [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html) or [`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html), etc.), the container process can change its identity. Thus, the _actual_ process identity will be dynamic.
229+
-->
230+
请注意,`status.containerStatuses[].user.linux` 字段中的值是**首次挂接**到容器中第一个容器进程的进程身份。
231+
如果容器具有足够的权限调用与进程身份相关的系统调用(例如
232+
[`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html)
233+
[`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html)
234+
[`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html) 等),
235+
则容器进程可以更改其身份。因此,**实际**的进程身份将是动态的。
236+
{{</note>}}
237+
238+
<!--
239+
## Feature availability
240+
241+
To enable `supplementalGroupsPolicy` field, the following components have to be used:
242+
-->
243+
## 特性可用性
244+
245+
要启用 `supplementalGroupsPolicy` 字段,必须使用以下组件:
246+
247+
<!--
248+
- Kubernetes: v1.31 or later, with the `SupplementalGroupsPolicy` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled. As of v1.31, the gate is marked as alpha.
249+
- CRI runtime:
250+
- containerd: v2.0 or later
251+
- CRI-O: v1.31 or later
252+
253+
You can see if the feature is supported in the Node's `.status.features.supplementalGroupsPolicy` field.
254+
-->
255+
- Kubernetes:v1.31 或更高版本,启用 `SupplementalGroupsPolicy`
256+
[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)
257+
截至 v1.31,此门控标记为 Alpha。
258+
- CRI 运行时:
259+
- containerd:v2.0 或更高版本
260+
- CRI-O:v1.31 或更高版本
261+
262+
你可以在 Node 的 `.status.features.supplementalGroupsPolicy` 字段中查看此特性是否受支持。
263+
264+
```yaml
265+
apiVersion: v1
266+
kind: Node
267+
...
268+
status:
269+
features:
270+
supplementalGroupsPolicy: true
271+
```
272+
273+
<!--
274+
## What's next?
275+
276+
Kubernetes SIG Node hope - and expect - that the feature will be promoted to beta and eventually
277+
general availability (GA) in future releases of Kubernetes, so that users no longer need to enable
278+
the feature gate manually.
279+
280+
`Merge` policy is applied when `supplementalGroupsPolicy` is not specified, for backwards compatibility.
281+
-->
282+
## 接下来
283+
284+
Kubernetes SIG Node 希望并期待此特性将在 Kubernetes 后续版本中进阶至 Beta,
285+
并最终进阶至正式发布(GA),以便用户不再需要手动启用特性门控。
286+
287+
当 `supplementalGroupsPolicy` 未被指定时,将应用 `Merge` 策略,以保持向后兼容性。
288+
289+
<!--
290+
## How can I learn more?
291+
-->
292+
## 我如何了解更多?
293+
294+
<!-- https://github.com/kubernetes/website/pull/46920 -->
295+
296+
<!--
297+
- [Configure a Security Context for a Pod or Container](/docs/tasks/configure-pod-container/security-context/)
298+
for the further details of `supplementalGroupsPolicy`
299+
- [KEP-3619: Fine-grained SupplementalGroups control](https://github.com/kubernetes/enhancements/issues/3619)
300+
-->
301+
- [为 Pod 或容器配置安全上下文](/docs/tasks/configure-pod-container/security-context/)以获取有关
302+
`supplementalGroupsPolicy` 的更多细节
303+
- [KEP-3619:细粒度 SupplementalGroups 控制](https://github.com/kubernetes/enhancements/issues/3619)
304+
305+
<!--
306+
## How to get involved?
307+
308+
This feature is driven by the SIG Node community. Please join us to connect with
309+
the community and share your ideas and feedback around the above feature and
310+
beyond. We look forward to hearing from you!
311+
-->
312+
## 如何参与?
313+
314+
此特性由 SIG Node 社区推动。请加入我们,与社区保持联系,
315+
分享你对上述特性及其他方面的想法和反馈。我们期待听到你的声音!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: strict-supplementalgroups-policy
5+
spec:
6+
securityContext:
7+
runAsUser: 1000
8+
runAsGroup: 3000
9+
supplementalGroups: [4000]
10+
supplementalGroupsPolicy: Strict
11+
containers:
12+
- name: ctr
13+
image: registry.k8s.io/e2e-test-images/agnhost:2.45
14+
command: [ "sh", "-c", "sleep 1h" ]
15+
securityContext:
16+
allowPrivilegeEscalation: false

0 commit comments

Comments
 (0)