PodSecurityPolicy 限制 Pod 使用安全上下文中的相关特性
Last updated
Was this helpful?
Last updated
Was this helpful?
PodSecurityPolicy 是一种 集群级别资源,用来限制用户能够在 Pod 的 安全上下文 中使用的各种安全相关的特性。通俗的说,用来限制 Pod 的定义中的安全上下文字段可以指定的相关配置。
🪐 PodSecurityPolicy 是由 API 服务器的 完成的。
当 API 服务器收到 Pod 创建请求时,该准入插件会将 Pod 的定义与已配置的 PodSecurityPolicy 进行校验,集群中可以有多个该资源。若 Pod 符合其中一个资源,插件会根据匹配到的 PodSecurityPolicy 中定义的默认值对 Pod 进行修改,然后将该 Pod 存入 etcd;否则会被立刻拒绝。
🔥 其默认是没有被开启的,需要在启动 API 服务器时指定开启。一旦被开启,集群中的 PodSecurityPolicy 就会起作用,若当前没有任何该资源的话,则意味着任何用户都无法创建 Pod(因为 Pod 无法找到符合其需求的 PodSecurityPolicy 资源,所以通常集群中会存在一条最宽松的 PodSecurityPolicy 资源,保证系统自身可以正常运行、集群管理员可以创建任意安全级别的 Pod,然后再根据需求创建不同安全级别的 PodSecurityPolicy 资源,并将该资源的使用权交由用户,从而实现对用户创建的 Pod 的安全特性的控制)。
再次强调!!只要用户能够使用 PodSecurityPolicy 资源,那么该资源就会对该用户创建的 Pod 生效!!!
🥑 PodSecurityPolicy 可以定义的安全特性如下:
是否允许 Pod 使用宿主机节点的 PID、IPC 以及网络命名空间;
限制 Pod 可以绑定的宿主机节点端口;
容器运行时使用的用户 ID;
是否允许创建拥有特权模式的容器的 Pod;
允许添加哪些内核功能、默认添加哪些内核功能、禁用哪些内核功能;
允许容器使用哪些 SELinux 选项;
容器是否允许使用可写的根文件系统;
允许容器在哪些文件系统组下运行;
允许 Pod 使用哪些类型的存储卷;
🌝 修改 PodSecurityPolicy 对已存在的 Pod 无效,因为该资源是被准入插件使用的,因此仅在创建和更新 Pod 时才会起作用。
PodSecurityPolicy 是集群资源,因此同样可以通过定义 YAML 清单,然后通过 kubectl apply -f
命令生成。下面列举一个案例,创建一个名为 default
的 PodSecurityPolicy 资源,不允许 Pod 使用宿主机的 IPC、PID 以及网络命名空间,Pod 能够使用的宿主机的端口范围为 [1000, 11000] 和 [13000, 14000],不允许 Pod 中包含拥有特权模式的容器,Pod 中容器的根文件系统必须是只读的:
在上面的案例中可以了解到,可以通过 podsecuritypolicy.spec.runAsUser
限制用户 ID,通过 podsecuritypolicy.spec.fsGroup
和 podsecuritypolicy.spec.supplementalGroups
限制用户组 ID。
可以通过不同的 rule
字段进行限制,包括:
RunAsAny:可以使用任何 ID;
MustRunAs:限制可以使用的 ID 范围;
MustRunAsNonRoot (仅适用于 runAsUser
):限制使用 root 用户,即可以使用 ID 为 0 以为的任何 ID;
当使用了 MustRunAs 规则,则必须使用 ranges
字段定义使用的范围(若范围的最小值和最大值为同一个,表示只允许使用该 ID)。
如果 Pod 的安全上下文中相关定义中的任一字段在该范围之外,则会被拒绝创建。
下面展示一个例子:
🚀🚀🚀 对于 runAsUser
限定 Pod 运行时可使用的用户 ID 时,有两种情况需要注意:
Pod 定义中的安全上下文中指定限定范围外的用户 ID,即在 pod.spec.containers.securityContext.runAsUser
或 pod.spec.securityContext.runAsUser
中指定 PodSecurityPolicy 中的 podSecurityPolicy.spec.runAsUser.ranges
中指定的范围外的 ID 时,准入插件会将请求拒绝;
容器的镜像中的默认用户 ID 在PodSecurityPolicy 中的 podSecurityPolicy.spec.runAsUser.ranges
中指定的范围外的 ID 时,PodSecurityPolicy 准入插件会将配置的用户 ID 覆盖容器中的默认 用户 ID;
PodSecurityPolicy 允许在其定义中通过配置下面三个功能,分别配置 Pod 允许添加的内核功能、默认添加的内核功能以及禁止添加的内核功能:
allowedCapabilities
: 允许容器添加的内核功能;
defaultAddCapabilities
: 默认为容器添加的内核功能;
requiredDropCapabilities
: 要求容器禁用的内核功能;
下面展示一个例子:
在 PodSecurityPolicy 的定义的 spec.volumes
列表中可以指定 Pod 可使用的存储卷类型,若为 '*'
,则表示允许使用任意类型的存储卷,或者也可以通过指定卷类型名来单独制定。例如:
首先创建所需的 PodSecurityPolicy 资源;
然后创建 ClusterRole 资源指向该 PodSecurityPolicy 资源;
通过 ClusterRoleBinding 或 RoleBinding 将 ClusterRole 绑定至特定组或特定用户;
🦁 为用户分配 PodSecurityPolicy 的本质是让用户能够使用该资源,只要用户能够使用对应资源,那么这些 PodSecurityPolicy 就会限制该用户创建的 Pod。
听起来感觉用户有点贱,自己限制自己,其实不是这样的,集群管理员在分配用户权限时,往往不会授予其修改、甚至查看 PodSecurityPolicy 资源的权限。
下面展示一个例子。
创建一个名为 psp-no-privileged
的 不允许创建特权模式容器的 Pod 的 PodSecurityPolicy,其 YAML 定义如下:
创建一个名为 psp-no-privileged
的 ClusterRole,指向 psp-no-privileged
这个 PodSecurityPolicy,该 ClusterRole 使用能够执行的操作为 use,并且目前只能通过 YAML 文件定义,不能用命令行创建,定义如下:
创建一个名为 psp-alice
的 ClusterRoleBinding,将名为 psp-no-privileged
的 ClusterRole 与 alice 这个用户进行绑定,该资源可以通过命令行创建,也可以通过 YAML 定义创建:
上述流程执行完成后,用户 alice 目前可以使用该 PodSecurityPolicy 资源,即该用户创建的每个 Pod 请求会受该 PodSecurityPolicy 资源的限制。
为指定用户分配 PodSecurityPolicy 资源需要配合 来实现。总共需要以下几步:
用户的创建可以参考 章节,这里创建的用户名为 alice。