You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Role Binding时查找ServiceAccount报错问题排查

跨命名空间使用ServiceAccount执行Helm Post-Install Hook Job失败问题解决

我创建了一个包含Post-Install Hook Job模板、自定义资源及ConfigMap的Helm Chart,Job代码如下:

apiVersion: batch/v1
kind: Job
metadata:
  name: postinstall-hook
  annotations:
    "helm.sh/hook": "post-install"
    "helm.sh/hook-delete-policy": hook-succeeded # 不加这个注解Hook不会自动删除
spec:
  serviceAccountName: {{ .Values.serviceAccount }}
  automountServiceAccountToken: true
  template:
    spec:
      containers:
      - name: kubectl
        image: bitnami/kubectl
        imagePullPolicy: Always
        command: ["/bin/bash", "-c", "while true; do running_jobs=$(kubectl get jobs -n {{ .Release.Namespace }} -o jsonpath='{.items[?(@.status.active==1)].metadata.name}'); if [ -z \"$running_jobs\" ]; then echo \"All jobs have completed\"; break; else echo \"Waiting for the following jobs to complete: $running_jobs\"; sleep 30; fi; done"]
      restartPolicy: Never
      terminationGracePeriodSeconds: 10

我使用devops命名空间下的devops-deploy ServiceAccount进行Helm部署,原本该账号仅拥有devops命名空间权限,现在需要在k6命名空间部署,因此已为其配置了k6命名空间的Role和RoleBinding。但部署时Job执行失败,报错如下:

Error creating: pods "postinstall-hook-" is forbidden: error looking up service account ns2/serviceaccountname: serviceaccount "serviceaccount" not found

该ServiceAccount确实不存在于k6命名空间,但我希望直接使用devops命名空间中已存在的ServiceAccount,并已配置了相关RBAC规则,完整的ServiceAccount及RBAC清单如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: devops-deploy
  namespace: devops
automountServiceAccountToken: false

---

apiVersion: v1
kind: Secret
metadata:
  name: devops-deploy-secret
  namespace: devops
  annotations:
    kubernetes.io/service-account.name: devops-deploy
type: kubernetes.io/service-account-token

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: devops-deploy-role
  namespace: devops
rules:
- apiGroups: ["apps"]
  resources: ["deployments","replicasets"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create","get","watch","list","update","patch","delete"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["serviceaccounts"]
  verbs: ["*"]
- apiGroups: ["extensions"]
  resources: ["ingresses"]
  verbs: ["*"]
- apiGroups: ["autoscaling"]
  resources: ["horizontalpodautoscalers"]
  verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["*"]
- apiGroups: ["k6.io"]
  resources: ["k6s"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: ["batch", "extensions"]
  resources: ["jobs"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: devops-deploy-rb
  namespace: devops
subjects:
- kind: ServiceAccount
  name: devops-deploy
roleRef:
  kind: Role
  name: devops-deploy-role
  apiGroup: rbac.authorization.k8s.io

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: job-exec-from-ns1
  namespace: k6
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: devops-deploy-role
subjects:
- kind: ServiceAccount
  name: devops-deploy
  namespace: devops

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kube-describe-cr
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","create","delete","update","list","watch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-describe-crb
subjects:
- kind: ServiceAccount
  name: devops-deploy
  namespace: devops
roleRef: 
  kind: ClusterRole
  name: kube-describe-cr
  apiGroup: rbac.authorization.k8s.io

问题根源

Kubernetes中,Pod的serviceAccountName字段默认会在当前Pod所在命名空间查找对应的ServiceAccount。你的Hook Job部署在k6命名空间,所以Kubernetes会尝试在k6下找指定的ServiceAccount,而非devops命名空间的,这就是报错的核心原因。

解决步骤

  1. 修改Job模板,指定ServiceAccount的命名空间
    Kubernetes 1.24及以上版本支持通过嵌套的serviceAccount字段指定ServiceAccount的命名空间,替代原有的serviceAccountName。修改后的Job模板如下:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: postinstall-hook
      annotations:
        "helm.sh/hook": "post-install"
        "helm.sh/hook-delete-policy": hook-succeeded
    spec:
      template:
        spec:
          serviceAccount:
            name: {{ .Values.serviceAccount }}
            namespace: devops # 明确指定ServiceAccount所在的命名空间
          automountServiceAccountToken: true
          containers:
          - name: kubectl
            image: bitnami/kubectl
            imagePullPolicy: Always
            command: ["/bin/bash", "-c", "while true; do running_jobs=$(kubectl get jobs -n {{ .Release.Namespace }} -o jsonpath='{.items[?(@.status.active==1)].metadata.name}'); if [ -z \"$running_jobs\" ]; then echo \"所有Job已完成\"; break; else echo \"等待以下Job完成: $running_jobs\"; sleep 30; fi; done"]
          restartPolicy: Never
          terminationGracePeriodSeconds: 10
    

    若你的Kubernetes版本低于1.24,不支持上述嵌套字段,需手动挂载ServiceAccount Token:

    • 从devops命名空间获取devops-deploy-secret的内容
    • 在Job的Pod模板中,将该Secret挂载到/var/run/secrets/kubernetes.io/serviceaccount路径
  2. 验证RBAC权限有效性
    执行以下命令,确认devops-deploy账号拥有k6命名空间下Job相关的权限:

    kubectl auth can-i list jobs -n k6 --as=system:serviceaccount:devops:devops-deploy
    

    返回yes则权限配置正确。

  3. 确认Token自动挂载配置
    你的devops-deploy ServiceAccount设置了automountServiceAccountToken: false,但Job模板中开启了automountServiceAccountToken: true,该配置会覆盖ServiceAccount的默认设置,确保Pod能正确挂载Token,无需修改。

内容的提问来源于stack exchange,提问作者Ido Segal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 10:07:57