第 16 章 管理安全性上下文约束
16.1. 关于安全性上下文约束
与 RBAC 资源控制用户访问的方式类似,管理员可以使用安全性上下文约束 (SCC) 来控制 Pod 的权限。这些权限包括 Pod(容器集合)可以执行的操作以及它们可以访问的资源。您可以使用 SCC 定义 Pod 运行必须满足的一组条件,以便其能被系统接受。
管理员可以借助 SCC 来控制:
- Pod 能否运行特权容器。
- 容器可以请求的功能。
- 将主机目录用作卷。
- 容器的 SELinux 上下文。
- 容器用户 ID。
- 使用主机命名空间和联网。
-
拥有 Pod 的卷的
FSGroup
的分配。 - 允许的补充组的配置。
- 容器是否需要使用只读根文件系统。
- 卷类型的使用。
-
允许的
seccomp
配置集的配置。
Docker 具有允许用于 Pod 的每个容器的默认功能列表。容器使用此默认列表中的功能,但 Pod 清单作者可以通过请求额外功能或移除某些默认行为来修改列表。使用 allowedCapabilities
、defaultAddCapabilities
和 requiredDropCapabilities
参数控制来自 Pod 的此类请求,并且指定可以请求哪些功能、每个容器必须添加哪些功能,以及必须禁止哪些功能。
集群包含八个默认 SCC:
-
anyuid
-
hostaccess
-
hostmount-anyuid
hostnetwork
警告如果在 master 主机上运行额外的工作负载,在提供
hostnetwork
的访问权限时应谨慎操作。在 master 主机上运行hostnetwork
的工作负载与集群上的 root 用户等效,必须获得相应的信任。-
node-exporter
-
nonroot
-
privileged
-
restricted
不要修改默认 SCC。修改默认 SCC 可导致升级 OpenShift Container Platform 时出现问题。如果默认 SCC 不能满足要求,请创建新的 SCC。
特权
SCC 允许:
- 用户运行特权 Pod
- Pod 将主机目录挂载为卷
- Pod 以任意用户身份运行
- Pod 使用任意 MCS 标签运行
- Pod 使用主机的 IPC 命名空间
- Pod 使用主机的 PID 命名空间
- Pod 使用任何 FSGroup
- Pod 使用任何补充组
- Pod 使用任何 seccomp 配置集
- Pod 请求任何功能
受限的
SCC:
- 确保 Pod 无法以特权方式运行。
- 确保 Pod 无法挂载主机目录卷。
- 要求 Pod 以预先分配的 UID 范围内的用户运行。
- 要求 Pod 使用预先分配的 MCS 标签运行。
- 允许 Pod 使用任何 FSGroup。
- 允许 Pod 使用任何补充组。
如需有关各个 SCC 的更多信息,请参阅 SCC 的 kubernetes.io/description
注解。
SCC 由设置和策略组成,它们控制 Pod 能够访问的安全功能。这些设置分为三个类别:
由布尔值控制 |
此类型的字段默认为限制性最强的值。例如, |
由允许的集合控制 | 针对集合检查此类型的字段,以确保其值被允许。 |
由策略控制 | 具有生成某个值的策略的条目提供以下功能:
|
16.1.1. SCC 策略
RunAsUser
-
MustRunAs
- 需要配置runAsUser
。使用配置的runAsUser
作为默认值。针对配置的runAsUser
进行验证。 -
MustRunAsRange
- 如果不使用预分配值,则需要定义最小值和最大值。使用最小值作为默认值。针对整个允许范围进行验证。 -
MustRunAsNonRoot
- 需要 Pod 提交为具有非零runAsUser
或具有镜像中定义的USER
指令。不提供默认值。 -
RunAsAny
- 不提供默认值。允许指定任何runAsUser
。
SELinuxContext
-
MustRunAs
- 如果不使用预分配的值,则需要配置seLinuxOptions
。使用seLinuxOptions
作为默认值。针对seLinuxOptions
进行验证。 -
RunAsAny
- 不提供默认值。允许指定任何seLinuxOptions
。
SupplementalGroups
-
MustRunAs
- 如果不使用预分配值,则需要至少指定一个范围。使用第一个范围内的最小值作为默认值。针对所有范围进行验证。 -
RunAsAny
- 不提供默认值。允许指定任何supplementalGroups
。
FSGroup
-
MustRunAs
- 如果不使用预分配值,则需要至少指定一个范围。使用第一个范围内的最小值作为默认值。针对第一个范围内的第一个 ID 进行验证。 -
RunAsAny
- 不提供默认值。允许指定任何fsGroup
ID。
16.1.2. 控制卷
通过设置 SCC 的 volumes
字段,控制特定卷类型的使用。此字段的允许值与创建卷时定义的卷来源对应:
-
azureFile
-
azureDisk
-
flocker
-
flexVolume
-
hostPath
-
emptyDir
-
gcePersistentDisk
-
awsElasticBlockStore
-
gitRepo
-
secret
-
nfs
-
iscsi
-
glusterfs
-
persistentVolumeClaim
-
rbd
-
cinder
-
cephFS
-
downwardAPI
-
fc
-
configMap
-
vsphereVolume
-
quobyte
-
photonPersistentDisk
-
projected
-
portworxVolume
-
scaleIO
-
storageos
- *(允许使用所有卷类型的一个特殊值)
-
none
(禁止使用所有卷类型的一个特殊值。仅为向后兼容而存在)
为新 SCC 推荐的允许卷最小集合是 configMap
、downAPI
、emptyDir
、persistentVolumeClaim
、secret
和 projected
。
允许卷类型列表并不完整,因为每次发布新版 OpenShift Container Platform 时都会添加新的类型。
为向后兼容,使用 allowHostDirVolumePlugin
将覆盖 volumes
字段中的设置。例如,如果 allowHostDirVolumePlugin
设为 false,但在 volumes
字段中是允许,则将移除 volumes
中的 hostPath
值。
16.1.3. 准入
利用 SCC 的准入控制可以根据授予用户的能力来控制资源的创建。
就 SCC 而言,这意味着准入控制器可以检查上下文中提供的用户信息以检索一组合适的 SCC。这样做可确保 Pod 具有相应的授权,能够提出与其操作环境相关的请求或生成一组要应用到 Pod 的约束。
准入用于授权 Pod 的 SCC 集合由用户身份和用户所属的组来决定。另外,如果 Pod 指定了服务帐户,则允许的 SCC 集合包括服务帐户可访问的所有约束。
准入使用以下方法来创建 Pod 的最终安全性上下文:
- 检索所有可用的 SCC。
- 为请求上未指定的安全性上下文设置生成字段值。
- 针对可用约束来验证最终设置。
如果找到了匹配的约束集合,则接受 Pod。如果请求不能与 SCC 匹配,则拒绝 Pod。
Pod 必须针对 SCC 验证每一个字段。以下示例中只有其中两个字段必须验证:
这些示例是在使用预分配值的策略的上下文中。
FSGroup SCC 策略为 MustRunAs
如果 Pod 定义了 fsGroup
ID,该 ID 必须等于默认的 fsGroup
ID。否则,Pod 不会由该 SCC 验证,而会评估下一个 SCC。
如果 SecurityContextConstraints.fsGroup
字段的值为 RunAsAny
,并且 Pod 规格省略了 Pod.spec.securityContext.fsGroup
,则此字段被视为有效。注意在验证过程中,其他 SCC 设置可能会拒绝其他 Pod 字段,从而导致 Pod 失败。
SupplementalGroups
SCC 策略为 MustRunAs
如果 Pod 规格定义了一个或多个 supplementalGroups
ID,则 Pod 的 ID 必须等于命名空间的 openshift.io/sa.scc.supplemental-groups
注解中的某一个 ID。否则,Pod 不会由该 SCC 验证,而会评估下一个 SCC。
如果 SecurityContextConstraints.supplementalGroups
字段的值为 RunAsAny
,并且 Pod 规格省略了 Pod.spec.securityContext.supplementalGroups
,则此字段被视为有效。注意在验证过程中,其他 SCC 设置可能会拒绝其他 Pod 字段,从而导致 Pod 失败。
16.1.4. SCC 优先级
SCC 有一个优先级字段,它会影响准入控制器尝试验证请求时的排序。在排序时,高优先级 SCC 移到集合的前面。确定了可用 SCC 的完整集合后,按照以下方式排序:
- 优先级最高的在前,nil 视为 0 优先级
- 如果优先级相等,则 SCC 按照限制性最强到最弱排序
- 如果优先级和限制性都相等,则 SCC 按照名称排序
默认情况下,授权给集群管理员的 anyuid
SCC 在 SCC 集合中具有优先权。这使得集群管理员能够以任意用户运行 Pod,而不必在 Pod 的 SecurityContext
中指定 RunAsUser
。若有需要,管理员仍然可以指定 RunAsUser
。