Pod Security Admission 下未创建实例 Pod

症状

Keycloak 自定义资源已被接受,StatefulSet 也已创建,但之后没有任何进展。 Pod 始终不会出现,实例也永远不会变为就绪状态。

StatefulSet 的事件包含以下原因:

create Pod <instance>-0 in StatefulSet <instance> failed error:
pods "<instance>-0" is forbidden: violates PodSecurity "restricted:latest":
allowPrivilegeEscalation != false (container "keycloak" must set securityContext.allowPrivilegeEscalation=false),
unrestricted capabilities (container "keycloak" must set securityContext.capabilities.drop=["ALL"]),
runAsNonRoot != true (pod or container "keycloak" must set securityContext.runAsNonRoot=true)

自定义资源自身的状态可能完全不显示错误:Operator 提交的对象已被接受,而被拒绝的是 Pod。

确认命名空间正在强制实施该配置文件:

kubectl get ns <namespace> -o jsonpath='{.metadata.labels}'

pod-security.kubernetes.io/enforce: restricted 标签就是该条件。

在此版本中,Operator 已处理此问题

从 26.7.4 开始,Operator 会为其生成的 Pod 设置符合 restricted 的安全上下文, 因此,普通的 Keycloak 资源在 enforce=restricted 命名空间中无需额外配置即可通过准入。 它会在 Pod 级别设置:

  • runAsNonRoot: true
  • seccompProfile.type: RuntimeDefault

并在容器上设置:

  • allowPrivilegeEscalation: false
  • runAsNonRoot: true
  • seccompProfile.type: RuntimeDefault
  • capabilities.drop: ["ALL"]

Realm 导入和更新 Job 也会应用相同的上下文,因此升级和 Realm 导入同样可以通过准入。

runAsUser 是特意不设置的:服务器镜像已经声明了非 root 用户,而固定 ID 会与 OpenShift 的 SCC 分配的每命名空间 UID 范围冲突。 readOnlyRootFilesystem 也不会设置——restricted 不要求该设置。

如果仍然看到拒绝

上述每个字段都会独立设置默认值,而你显式设置的值始终优先。因此,只有在某些配置将其中一个字段设置为不符合要求的值时, 才会再次出现拒绝。发生这种情况的位置是 spec.unsupported.podTemplate:

spec:
  unsupported:
    podTemplate:
      spec:
        securityContext:
          runAsNonRoot: false      # <- your value wins, and it is not compliant

查看 Pod 实际获得的配置:

kubectl -n <namespace> get pod <pod> \
  -o jsonpath='{.spec.securityContext}{"\n"}{.spec.containers[0].securityContext}{"\n"}'

移除有问题的覆盖设置,或将其修改为符合要求的值。

capabilities.drop 会在你已有的任何 capabilities 块中设置默认值,因此添加 capability 不会无意中移除配置文件所要求的 drop: ["ALL"]。

早期版本

在 26.7.4 之前的版本中,Operator 不设置安全上下文,普通资源会被拒绝。 通过 spec.unsupported.podTemplate 提供安全上下文:

spec:
  unsupported:
    podTemplate:
      spec:
        securityContext:
          runAsNonRoot: true
          seccompProfile:
            type: RuntimeDefault
        containers:
          - securityContext:
              allowPrivilegeEscalation: false
              runAsNonRoot: true
              capabilities:
                drop:
                  - ALL
              seccompProfile:
                type: RuntimeDefault

容器条目不包含 name:该模板是 Operator 构建资源的基础,Operator 会自行填充容器名称和镜像。

备选方案:放宽命名空间限制

如果命名空间不需要强制执行 restricted,请改为将其标记为 baseline:

kubectl label ns <namespace> pod-security.kubernetes.io/enforce=baseline --overwrite

仅在安全策略允许的情况下使用此方法。


Keycloak™ 是 The Linux Foundation 的商标。Alauda 是独立供应商。本产品与 The Linux Foundation 不存在关联,也未获得其认可或赞助。所有商标均为其各自所有者的财产,此处仅用于标识目的。