1. 引言

Helm 是 Kubernetes 的包管理工具,已经成为 DevOps 工具链中的核心组件之一。它简化了在 Kubernetes 集群上部署和管理应用程序的流程。

然而,和所有强大的工具一样,Helm 有时也会抛出一些令人摸不着头脑的错误,例如在执行 helm list 时出现的错误信息:Error: configmaps is forbidden: User “system:serviceaccount:kube-system:default” cannot list configmaps in the namespace “kube-system”

本文将深入分析该错误的根源,并提供多种解决方案。我们从权限模型(RBAC)出发,逐步探讨不同场景下的解决办法,帮助你快速定位并修复问题。


2. 错误分析

错误信息 configmaps is forbidden: User “system:serviceaccount:kube-system:default” cannot list configmaps in the namespace “kube-system” 明确指出这是一个权限问题。

Kubernetes 使用基于角色的访问控制(RBAC)机制来管理集群资源的访问权限。这意味着,任何用户、服务账户或组件在访问 API 时都必须经过身份认证和授权。

默认情况下,Helm 使用的是 kube-system:default 服务账户,它在 kube-system 命名空间中没有足够的权限来列出 ConfigMap。这种限制是为了安全考虑,避免服务账户拥有不必要的权限。

因此,要解决这个问题,我们需要为 Helm 使用的服务账户授予适当的权限。


3. 初步排查步骤

在尝试解决权限问题之前,先确认几个基础点。

3.1. 验证 Helm 与 Kubernetes 版本

确保 Helm 与 Kubernetes 的版本兼容:

$ helm version
version.BuildInfo{
  Version:"v3.13.3", 
  GitCommit:"3a31588ad33fe3b89af5a2a54ee1d25bfe6eaa5e", 
  GitTreeState:"clean", 
  GoVersion:"go1.20.5"
}

$ kubectl version
Client Version: version.Info{
  Major:"1", 
  Minor:"28", 
  GitVersion:"v1.28.2", 
  GitCommit:"89a4ea3e1e4ddd7f7572286090859619aa2dc4ba", 
  GitTreeState:"clean", 
  BuildDate:"2023-09-13T09:35:49Z", 
  GoVersion:"go1.20.8", 
  Compiler:"gc", 
  Platform:"linux/amd64"
}
Server Version: version.Info{
  Major:"1", 
  Minor:"28", 
  GitVersion:"v1.28.2", 
  GitCommit:"89a4ea3e1e4ddd7f7572286090859619aa2dc4ba", 
  GitTreeState:"clean", 
  BuildDate:"2023-09-13T09:29:07Z", 
  GoVersion:"go1.20.8", 
  Compiler:"gc", 
  Platform:"linux/amd64"
}

确保 Helm 与 Kubernetes 的版本是兼容的。如果你使用的是 Helm 2,建议尽快升级到 Helm 3。

3.2. 确认 Helm 使用的命名空间

如果 Helm 不在 kube-system 命名空间下运行,你可能需要指定命名空间:

$ helm list --namespace kube-system
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
kube-system-release     kube-system     3               2023-06-30 14:00:00.000000 +0000 UTC    deployed        kube-system-chart-3.0.0 3.0.0

确保 Helm 正确指向了你期望的命名空间。

3.3. 检查 RBAC 是否启用

确认集群是否启用了 RBAC:

$ kubectl api-versions | grep rbac
rbac.authorization.k8s.io/v1

如果输出中包含 rbac.authorization.k8s.io/v1,说明 RBAC 已启用。

3.4. 查看当前服务账户权限

查看默认服务账户在 kube-system 命名空间中的权限:

$ kubectl auth can-i --list \
  --namespace kube-system \
  --as system:serviceaccount:kube-system:default
Resources                                       Non-Resource URLs   Resource Names                     Verbs
selfsubjectaccessreviews.authorization.k8s.io   []                  []                                 [create]
selfsubjectrulesreviews.authorization.k8s.io    []                  []                                 [create]
configmaps                                      []                  []                                 [get list watch]
...

如果 configmapsverbs 包含 get, list, watch,说明该服务账户已有足够权限。否则就需要手动授权。


4. 为默认服务账户授予权限

最直接的解决方案是为 Helm 使用的服务账户添加权限。

4.1. 授予只读权限

如果你只需要查看资源,可以授予 view 权限:

$ kubectl create rolebinding default-view \
  --clusterrole=view \
  --serviceaccount=kube-system:default \
  --namespace=kube-system
rolebinding.rbac.authorization.k8s.io/default-view created

此命令将 view 角色绑定到 kube-system 命名空间下的 default 服务账户,赋予其只读权限。

4.2. 授予管理员权限

如果你需要安装或升级 Chart,可以授予 cluster-admin 权限:

$ kubectl create clusterrolebinding add-on-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:default
clusterrolebinding.rbac.authorization.k8s.io/add-on-cluster-admin created

⚠️ 注意:这种方式虽然方便,但会赋予服务账户集群管理员权限,存在安全风险。建议根据实际需求授予最小权限。


5. Helm 2 中为 Tiller 创建专用服务账户

如果你仍在使用 Helm 2,建议不要使用默认服务账户,而是为 Tiller 创建一个专用服务账户。

5.1. 创建服务账户

$ kubectl create serviceaccount --namespace kube-system tiller
serviceaccount/tiller created

5.2. 创建 ClusterRoleBinding

$ kubectl create clusterrolebinding tiller-cluster-rule \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:tiller
clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created

5.3. 初始化 Helm 使用新账户

$ helm init --service-account tiller --upgrade
$HELM_HOME has been configured at /home/user/.helm.
Tiller (the Helm server-side component) has been upgraded to the current version.
Happy Helming!

✅ 优势:比直接使用默认账户更安全,权限更集中。


6. 限制 Helm 2 的访问范围到特定命名空间

在多租户环境中,可以将 Tiller 限制在特定命名空间内运行,以提升安全性。

6.1. 创建新命名空间

$ kubectl create namespace tiller-world
namespace/tiller-world created

6.2. 创建服务账户

$ kubectl create serviceaccount tiller --namespace tiller-world
serviceaccount/tiller created

6.3. 定义 Role

创建文件 role-tiller.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tiller-manager
  namespace: tiller-world
rules:
- apiGroups: ["", "batch", "extensions", "apps"]
  resources: ["*"]
  verbs: ["*"]

应用该角色:

$ kubectl create -f role-tiller.yaml
role.rbac.authorization.k8s.io/tiller-manager created

6.4. 创建 RoleBinding

创建文件 rolebinding-tiller.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tiller-binding
  namespace: tiller-world
subjects:
- kind: ServiceAccount
  name: tiller
  namespace: tiller-world
roleRef:
  kind: Role
  name: tiller-manager
  apiGroup: rbac.authorization.k8s.io

应用该绑定:

$ kubectl create -f rolebinding-tiller.yaml
rolebinding.rbac.authorization.k8s.io/tiller-binding created

6.5. 初始化 Helm 使用新命名空间

$ helm init \
  --service-account tiller \
  --tiller-namespace tiller-world
$HELM_HOME has been configured at /home/user/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Happy Helming!

6.6. 设置环境变量

$ export TILLER_NAMESPACE=tiller-world

✅ 优势:Tiller 仅在指定命名空间内操作,避免权限泛滥。


7. 升级到 Helm 3 以移除 Tiller

Helm 3 引入了客户端无服务器架构,彻底移除了 Tiller 组件,简化了部署流程并提升了安全性。

如果你还在使用 Helm 2,建议尽快升级。

安装 Helm 3

# Linux 示例
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh

使用 Helm 2to3 插件迁移

$ helm plugin install https://github.com/helm/helm-2to3
$ helm 2to3 convert <release_name>

✅ 优势:无 Tiller、无需复杂权限配置、更安全。


8. 总结

方案 是否推荐 说明
赋予默认服务账户 view 权限 简单有效,适合只读需求
赋予 cluster-admin 权限 ⚠️ 快速但存在安全风险
为 Tiller 创建专用服务账户 Helm 2 场景推荐
限制 Tiller 到特定命名空间 ✅✅ 提升安全性,适合多租户
升级到 Helm 3 ✅✅✅ 最推荐方案,无 Tiller、权限更简洁

如果你在使用 Helm 时遇到类似权限问题,建议优先考虑使用 Helm 3 或为 Tiller 创建专用服务账户。避免直接赋予默认服务账户过高的权限,遵循最小权限原则是保障 Kubernetes 安全的最佳实践。


原始标题:Fixing Helm List ConfigMap Error in Kubernetes