限制pod使用安全相关的特性
已经介绍了如何在部署 pod时在任一宿主节点上做任何想做 的事。 比如, 部署一个特权模式的 pod 。 很明显, 需要有一种机制阻止用户使用其中的部分功能。 集群管理入员可以通过创建 PodSecurityPolicy资源来限制对以上提到的安全相关的特性的使用。
PodSecurityPolicy资源介绍
PodSecurityPolicy 是一种集群级别(无命名空间)的资源, 它定义了用户能否在 pod 中使用各种安全相关的特性。 维护 PodSecurityPolicy 资源中配置策略的工作由集成在 API 服务器中的 PodSecurityPolicy 准入控制插件完成
当有人向
API
服务器发送
pod
资源时,
PodSecurityPolicy 准入控制插件会将这个 pod 与已经配置的 PodSecurityPolicy 进行校验。 如果这个 pod 符合集群中已有安全策略, 它会被接收并存入 etcd; 否则它会立即被拒绝。 这个插件也会根据安全策略中配置的默认值对 pod 进行修改。
了解 PodSecurityPolicy 可以做的事
一个 PodSecurityPolicy 资源可以定义以下事项:
• 是否允许 pod
使用宿主节点的
PID
、
IPC
、 网络命名空间
•
pod
允许绑定的宿主节点端口
• 容器运行时允许使用的用户 ID
• 是否允许拥有特权模式容器的 pod
• 允许添加哪些内核功能, 默认添加哪些内核功能, 总是禁用哪些内核功能
• 允许容器使用哪些 SELinux
选项
• 容器是否允许使用可写的根文件系统
• 允许容器在哪些文件系统组下运行
• 允许 pod
使用哪些类型的存储卷
检视一个 PodSecurityPolicy 样例
以下代码清单展示了一个 PodSecurityPolicy 的样例。 它阻止了 pod 使用宿主节点的 PID、 IPC、 网络命名空间, 运行特权模式的容器, 以及绑定大多数宿主节点的端口(除11 000-11 000和13 000-14 000范围内的端口)。 它没有限制容器运行时使用的用户、用户组和SELinux 选项。
以上样例的大部分选项是不言自明的,特别是当你已经阅读了本章前几节的内容时。这个PodSecurityPolicy在集群中创建成功之后,API服务器将不再允许之前
样例中的特权pod。例如
$ kubectl create -f pod-privileged.yaml
Error from server (Forbidden): error when crea七ing "pod-privileged.yaml"
pods "pod-privileged" is forbidden: unable to validate agains七 any pod
security policy: [spec.containers[OJ .securityContex七.privileged: 工nvalic
value: true: Privileged containers are not allowed]
类似地,集群中不能再部署使用宿主节点的PID、IPC、网络命名空间的pod了。
因为以上策略中的readOnlyRootFilesystem选项己设置为true, 容器的根文件系统将变为只读(容器只能写入挂载的存储卷)。
了解 runAsUser、 fsGroup 和 supplementalGroup 策略
前面的例子中的策略
没有对容器运行时可以使用的用户和用户组施加任何限制
,因为它们在runAsUser、fsGroup、supplementalGroups等字段中使用
了runA
sAny规则。
如果需要限制容器可以使用的用户和用户组ID,
可以将规则改为MustRunAs
, 并指定允许使用的ID范围。
使用MustRunAs规则
来看以下的例子。为了只允许容器以用户ID 2的身份运行并限制默认的文件系统组和增补组ID在2-10或20-30的范围(包含临界值)内,需要在PodSecurityPolicy资源中加入如以下代码清单所示片段。
![](https://i-blog.csdnimg.cn/blog_migrate/c2f37b32be4a78de328a0dae9e4a63bc.png)
如果pod spec试图将其中的任一字段设置为该范围之外的值,这个pod将不会被API服务
器接收。可以通过删除之前的PodSecurityContextPolicy, 并通过psp-must-run-as.yam!
文件创建一个新的来实践这一点。
注意 修改策略对已经存在的pod无效,因为PodSecurityPolicy资原仅在创建和升级po d 时起作用。
部署runAsUser在指定范围之外的pod
如果尝试使用之前的pod-as-user-guest.yaml 文件部署一 个pod, 其中指定了容器运行的用户ID为405, API服务器会拒绝这个pod:
$ kubectl create -f pod -as - user-guest. yaml
Error from server (Forbidden): error when creating "pod-as-user-guest . yaml"
pods pod-as user-guest" is forb dden: able to validate against pod
secur ty poli cy : [securityContext runAsUser: Inval value 405 UID on
cont 工口er main does ot match required ra ge Found 405, allowed : [(2 2)] J
好,这个是显然的。但是如果部署
pod
时没
有指定 ruAs
User
属性,但用户
ID
被注入到镜像的情况下(在
Docke
le
中使用
USER
命令),会发生什么?
部署镜像中用户 ID 在指定范围之外的 pod
笔者创建了
个不同版本的
Node.js
镜像,在
全书
的例子中使用
。这
个镜像被
配置为使用用户
ID为5的用户运行。该镜像使用的 Dockerfi
le
以下代码清单所示。
笔者将这个镜像命名为 uk
sa/kubia-
run-
as-
user ,
上传到
Docker
Hub 。如果使用这个镜像创建 pod, API 服务器不
会拒绝
$ kubectl run run-as-5 --image luksa/kubia-run-as-user-5 --restart Never
pod ” r un as-5 ’I created
与之前不同,
API
服务器
接收了这
pod,
kubelet
也运行了这个容器。接下来查看这 容器使用的用户
ID 和用户组 ID:
$ kubectl exec run-as-5 -- id
uid=2(bin) gid=2(bin) groups=2(bin)
可以
看到,这个容器运行时使用的用户
ID 为2,就是在 Po
dSecurit
yP
olicy
中指定的
ID PodSecurityPolicy
可以
将硬编码覆盖到镜像中的用户
ID。
在runAsUser 字段中使用 mustRunAsNonRoot 规则
runAsUs
er
宇段
中还可以
使用另一种
规则:
mustRunAsNonRoot
。正如
名,它将阻止用户部署以 root
用户运行的容器
。在
此种情况下,
spec
容器中必须指runAs
User字段,并且不能为
root
用户的
ID
),或者容器的镜像本身指定了用一
个非 0的用户 ID
运行。这种做法的好处己经在之前介绍过。