3. 用户、组与服务账户管理

在 OpenShift 中,权限治理的第一步不是分配角色,而是把“身份”理清楚。OpenShift 的身份体系分为两条线:一条面向人,即 User(用户) 与 Group(组);另一条面向工作负载,即 ServiceAccount(服务账户)。前者通常由外部身份提供者(如 LDAP、OIDC、HTPasswd)同步而来,后者由集群自身在命名空间内创建和管理。理解这两条线的创建、同步与绑定方式,是后续 RBAC 授权、镜像拉取、令牌分发的基础。

一、用户与组:身份从哪里来

OpenShift 本身不存储用户密码,它是一个“身份消费者”。用户对象(User)在集群中通常是只读的,由身份提供者(Identity Provider,IdP)在用户首次登录时自动创建。管理员真正需要配置的是 OAuth 配置 与 身份提供者,而不是手工创建 User。常见的 IdP 类型包括:

  • HTPasswd:用一份 htpasswd 文件保存用户名与 bcrypt 密码哈希,适合实验与小型环境。
  • LDAP:对接企业目录,支持按组同步,是生产环境最常见的方式。
  • OIDC:对接 Keycloak、Azure AD、Okta 等,使用标准声明映射用户与组。

以 HTPasswd 为例,创建身份提供者的核心是先生成密码文件,再把它挂载进 OAuth 配置。示例命令如下(示例参数,非实测结果):

# 生成 htpasswd 文件(示例用户 dev1、dev2)
htpasswd -c -B -b /tmp/users.htpasswd dev1 'Passw0rd!'
htpasswd -B -b /tmp/users.htpasswd dev2 'Passw0rd!'

# 创建 Secret 承载该文件
oc create secret generic htpass-secret \
  --from-file=htpasswd=/tmp/users.htpasswd \
  -n openshift-config

# 将 Secret 关联到 OAuth 的 htpasswd 身份提供者
oc edit oauth cluster

在 oauth/cluster 中,需要声明 identityProviders 的 type: HTPasswd 并引用该 Secret。保存后 OAuth Pod 会自动滚动重启,随后用户即可登录。登录成功后,可用 oc get users 看到自动生成的 User 对象,用 oc get identities 看到身份映射。

二、组的创建与同步

组是权限治理的“批量单位”。与其给 50 个人逐个绑定 RoleBinding,不如把他们放进一个 Group,再给 Group 绑定角色。组有两种来源:

  • 手工组:直接创建 Group 对象并维护 users 列表,适合小规模或临时场景。
  • 同步组:由 LDAP/OIDC 的组声明自动同步,成员随目录变化自动更新,适合企业环境。

手工创建组并加入用户的示例:

oc adm groups new dev-team
oc adm groups add-users dev-team dev1 dev2
oc get group dev-team -o yaml

对于 LDAP 同步,需要在 oauth/cluster 中配置 ldap 提供者,并设置 groupMembership 属性(如 member、uniqueMember),同时通过 oc adm groups sync 或定时任务把目录组同步为 OpenShift Group。同步后的组名通常带有前缀,例如 ldap-dev-team,便于与手工组区分。

组同步的关键是“映射规则”:LDAP 的 cn 或 sAMAccountName 决定组名,member 决定成员。映射写错会导致组存在但成员为空,这是排障时最先检查的点。

三、标签管理:让身份可被选择

标签(Label)是 OpenShift 中“按条件选择对象”的通用机制。对用户和组而言,标签的价值在于:可以用 oc get users -l 快速筛选,也可以让某些自动化策略按标签生效。例如给组打上部门标签:

oc label group dev-team department=engineering
oc label group ops-team department=operations

# 按标签筛选
oc get groups -l department=engineering

标签本身不授予权限,但它让“谁属于哪个部门、哪个环境”变得可查询、可审计。在后续章节中,ClusterRoleBinding 也可以结合标签做批量治理。

四、ServiceAccount:工作负载的身份

ServiceAccount(SA)是 Pod 在集群内的身份。每个命名空间默认有一个 default SA。当 Pod 未指定 SA 时,就使用它。SA 的创建非常简单:

oc create serviceaccount app-sa -n myproject
oc get sa app-sa -n myproject -o yaml

创建后,SA 会自动关联一个 长期令牌 Secret(在较新版本中默认不再自动生成,需要显式创建),以及可选的 镜像拉取密钥(imagePullSecret)。SA 的核心用途有三类:

  1. 作为 Pod 身份:在 Deployment 的 spec.template.spec.serviceAccountName 中引用,Pod 内即可用挂载的令牌访问 API。
  2. 绑定镜像拉取密钥:私有镜像仓库的凭据以 Secret 形式存在,通过 imagePullSecrets 绑定到 SA,Pod 拉镜像时自动使用。
  3. 绑定 RBAC 角色:通过 RoleBinding 把 SA 与 Role 关联,控制它能操作哪些资源。

五、令牌与镜像拉取密钥的绑定

令牌绑定有两种方式。第一种是让 SA 引用一个 kubernetes.io/service-account-token 类型的 Secret:

# 创建长期令牌 Secret 并绑定到 SA
oc create token app-sa -n myproject --duration=24h
# 或创建 Secret 方式
oc apply -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: app-sa-token
  namespace: myproject
  annotations:
    kubernetes.io/service-account.name: app-sa
type: kubernetes.io/service-account-token
EOF

第二种是使用 oc create token 生成短期令牌,适合 CI/CD 或临时调试。短期令牌不会持久化到 Secret,安全性更高。

镜像拉取密钥的绑定则分两步:先创建 docker-registry 类型的 Secret,再把它挂到 SA 上。

# 1. 创建镜像仓库凭据
oc create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=devuser \
  --docker-password='S3cret!' \
  -n myproject

# 2. 绑定到 ServiceAccount
oc secrets link app-sa regcred --for=pull -n myproject

绑定后,使用 app-sa 的 Pod 在拉取 registry.example.com 的镜像时会自动携带该凭据。可以用 oc get sa app-sa -o yaml 查看 imagePullSecrets 字段确认绑定生效。

不要把长期令牌 Secret 提交到 Git 仓库,也不要在多个命名空间复用同一个 SA 令牌。令牌泄露等同于身份泄露,应优先使用短期令牌并配合最小权限 RoleBinding。

六、身份治理的整体关系

把上述内容串起来看:外部 IdP 提供用户与组,OpenShift 将其同步为 User/Group 对象;命名空间内创建 ServiceAccount 供工作负载使用;令牌与镜像拉取密钥通过 Secret 与 SA 绑定;最后通过 RoleBinding/ClusterRoleBinding 把身份与权限连接起来。下图展示了这条身份与凭据的流转关系。

外部身份提供者 LDAP / OIDC / HTPasswd 用户目录 + 组声明 同步 User / Group 集群身份对象 标签:department=... 绑定 RoleBinding / ClusterRoleBinding 把身份映射到权限 Role / ClusterRole 命名空间 myproject ServiceAccount app-sa 工作负载身份 令牌 Secret service-account-token 短期 / 长期 镜像拉取密钥 docker-registry Secret regcred Pod / Deployment serviceAccountName: app-sa 拉取私有镜像 绑定 secrets link 引用 挂载 imagePullSecrets 身份(User/Group/SA)→ 凭据(Token/Secret)→ 权限(RBAC)→ 工作负载

从图中可以看到,用户与组解决“谁是人”,ServiceAccount 解决“谁是工作负载”,令牌与镜像拉取密钥解决“凭据从哪来”,而 RBAC 解决“能做什么”。四者环环相扣,缺一不可。实际治理中,建议遵循三条原则:用户与组尽量由 IdP 同步而非手工维护;ServiceAccount 按应用粒度创建,避免共用 default;令牌优先使用短期形式,镜像拉取密钥按命名空间隔离并定期轮换。