【问题标题】:Terraform EKS configmaps is forbiddenTerraform EKS 配置图被禁止
【发布时间】:2021-11-17 16:28:37
【问题描述】:

我正在尝试使用TerraformAWS EKS 上部署Kubernetes 集群,从Gitlab CI 管道运行。我的代码目前启动并运行了一个完整的集群,除了有一个步骤尝试将节点(单独创建)添加到集群中。

当它尝试这样做时,这是我收到的错误:

│ Error: configmaps is forbidden: User "system:serviceaccount:gitlab-managed-apps:default" cannot create resource "configmaps" in API group "" in the namespace "kube-system"
│ 
│   with module.mastercluster.kubernetes_config_map.aws_auth[0],
│   on .terraform/modules/mastercluster/aws_auth.tf line 63, in resource "kubernetes_config_map" "aws_auth":
│   63: resource "kubernetes_config_map" "aws_auth" {
│ 

Terraform 我相信正在尝试编辑 kube-system 命名空间中的 configmap aws_auth,但由于某种原因,它没有这样做的权限?

我在 Stackoverflow 上找到了与几年前不同的答案,目前与文档中关于添加 aws_eks_cluster_auth 数据源并将其添加到 kubernetes 提供程序的内容相匹配。

我目前的配置如下:

data "aws_eks_cluster" "mastercluster" {
    name    = module.mastercluster.cluster_id
}

data "aws_eks_cluster_auth" "mastercluster" {
    name    = module.mastercluster.cluster_id
}

provider "kubernetes" {
    alias   = "mastercluster"

    host                    = data.aws_eks_cluster.mastercluster.endpoint
    cluster_ca_certificate  = base64decode(data.aws_eks_cluster.mastercluster.certificate_authority[0].data)
    token                   = data.aws_eks_cluster_auth.mastercluster.token

    load_config_file        = false
}

奇怪的是,这以前对我有用。我已经使用这种方法成功部署了多个集群。这个配置与我之前的配置几乎相同,只是集群的名称不同。我完全不知道为什么这可能会出错。

【问题讨论】:

    标签: amazon-web-services kubernetes terraform gitlab-ci amazon-eks


    【解决方案1】:

    使用semver 锁定hashicorp provider 版本

    这就是为什么在 terraform 清单中使用 semver 如此重要的原因。

    根据Terraform documentation

    Terraform 提供者通过 Terraform 和目标 API 之间的通信来管理资源。每当目标 API 更改或添加功能时,提供者维护者都可以更新和版本化提供者。

    当多个用户或自动化工具运行相同的 Terraform 配置时,他们都应该使用相同版本的所需提供程序。

    Kubernetes 使用RBAC 规则

    有一个关于此问题的 Github 问题:v2.0.1: Resources cannot be created. Does kubectl reference to kube config properly? · Issue #1127 · hashicorp/terraform-provider-kubernetes,错误消息与您的情况相同。

    还有one of the comments answers:

    顺便说一句,这看起来与集群中的RBAC 规则有关(可能已由 helm chart 安装)。此命令可能有助于诊断与错误消息中的服务帐户相关的权限问题。

    $ kubectl auth can-i create namespace --as=system:serviceaccount:gitlab-prod:default
    $ kubectl auth can-i --list --as=system:serviceaccount:gitlab-prod:default
    

    您或许可以将该列表与集群中的其他用户进行比较:

    kubectl auth can-i --list --namespace=default --as=system:serviceaccount:default:default
    
    $ kubectl auth can-i create configmaps
    yes
    
    $ kubectl auth can-i create configmaps --namespace=nginx-ingress --as=system:serviceaccount:gitlab-prod:default
    no
    

    并调查相关的集群角色:

    $ kube describe clusterrolebinding system:basic-user
    Name:         system:basic-user
    Labels:       kubernetes.io/bootstrapping=rbac-defaults
    Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
    Role:
      Kind:  ClusterRole
      Name:  system:basic-user
    Subjects:
      Kind   Name                  Namespace
      ----   ----                  ---------
      Group  system:authenticated
    
    
    $ kubectl describe clusterrole system:basic-user
    Name:         system:basic-user
    Labels:       kubernetes.io/bootstrapping=rbac-defaults
    Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
    PolicyRule:
      Resources                                      Non-Resource URLs  Resource Names  Verbs
      ---------                                      -----------------  --------------  -----
      selfsubjectaccessreviews.authorization.k8s.io  []                 []              [create]
      selfsubjectrulesreviews.authorization.k8s.io   []                 []              [create]
    

    我的猜测是有问题的图表或 Terraform 配置负责创建服务帐户以及 [集群] 角色和角色绑定,但它可能以错误的顺序执行此操作,或者不是幂等的(所以你会得到不同重新安装与初始安装的结果)。但是我们需要看到一个重现这个错误的配置。在我对AKSEKSGKEminikube 上的第 2 版提供程序的测试中,我没有看到这个问题出现。

    随意浏览这些构建特定集群并将它们与 Kubernetes 和 Helm 提供程序一起使用的工作示例。略读配置可能会给您一些进一步排除故障的想法。

    如何解决RBAC 问题

    至于错误

    Error: configmaps is forbidden: User "system:serviceaccount:kube-system:default" cannot list
    

    great explanation by @m-abramovich

    首先,给新手一些信息。
    在 Kubernetes 中有:

    • 帐户 - 类似于您的 ID。示例:约翰
    • 角色 - 项目中的某个组允许做某事。示例:cluster-admin、it-support、...
    • 绑定 - 将帐户加入角色。 “John in it-support” - 是一种绑定。

    因此,在我们上面的消息中,我们看到我们的 Tiller 作为在命名空间“kube-system”注册的帐户“默认”。很可能您没有将他绑定到足够的角色。

    现在回到问题上来。
    我们如何跟踪它:

    • 检查您是否有特定的 帐户 用于分蘖。通常它具有相同的名称 - “tiller”:
      kubectl [--namespace kube-system] get serviceaccount
      如果没有,请创建:
      kubectl [--namespace kube-system] create serviceaccount tiller
    • 检查您是否有 roleclusterrole(对于新手来说,集群角色“更好” - 它是集群范围的,不像命名空间范围的角色)。如果这不是生产,您可以使用高权限角色“cluster-admin”:
      kubectl [--namespace kube-system] get clusterrole
      您可以通过以下方式查看角色内容:
      kubectl [--namespace kube-system] get clusterrole cluster-admin -o yaml
    • 检查第一个子句中的 account“tiller”是否与您认为足够的 clusterrole“cluster-admin”绑定:
      kubectl [--namespace kube-system] get clusterrolebinding
      如果根据名称很难弄清楚,您可以简单地创建新的:
      kubectl [--namespace kube-system] create clusterrolebinding tiller-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
    • 最后,当你有了账号、角色以及它们之间的绑定后,你可以检查一下你是否真的是这个账号:
      kubectl [--namespace kube-system] get deploy tiller-deploy -o yaml

    我怀疑您的输出将没有设置“serviceAccount”和“serviceAccountName”:

    dnsPolicy: ClusterFirst
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    terminationGracePeriodSeconds: 30
    

    如果是,则添加一个您希望tiller 使用的帐户:
    kubectl [--namespace kube-system] patch deploy tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
    (如果您使用 PowerShell,请查看下面来自 @snpdev 的帖子)
    现在你重复前面的检查命令,看看有什么不同:

    dnsPolicy: ClusterFirst
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    serviceAccount: tiller                     <-- new line
    serviceAccountName: tiller          <-- new line
    terminationGracePeriodSeconds: 30
    

    资源:

    【讨论】:

    • 非常感谢您的超级深入的回答。我做了更多的挖掘,似乎没有创建 aws-auth 配置映射,即使它应该是并且 gitlab 有权限。发生这种情况是因为出于某种原因,Terraform 尝试将 configmap 放在 localhost 上的集群中,而不是 EKS 集群中。由于 Terraform 在 pod 内运行,因此它运行的集群会回复身份验证问题。这似乎与我试图在一次 Terraform 运行中添加两个集群这一事实有关。
    猜你喜欢
    • 2020-09-01
    • 2021-06-24
    • 2021-06-16
    • 2018-12-14
    • 2021-09-28
    • 2019-11-28
    • 2020-01-15
    • 2019-12-21
    • 2020-11-29
    相关资源
    最近更新 更多