首页 > 解决方案 > 在 gitlab CI 中连接到 kubernetes 集群时出现禁止错误

问题描述

我正在尝试在我的自托管 gitlab 实例中访问我的 kubernetes 集群,如文档中所述。

deploy:
  stage: deployment
  script: 
    - kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run=client | kubectl apply -f -

但我确实得到了错误

Error from server (Forbidden): error when retrieving current configuration of:
Resource: "/v1, Resource=secrets", GroupVersionKind: "/v1, Kind=Secret"
Name: "gitlab-registry", Namespace: "gitlab"
from server for: "STDIN": secrets "gitlab-registry" is forbidden: User "system:serviceaccount:gitlab:default" cannot get resource "secrets" in API group "" in the namespace "gitlab"

我不明白这个错误。为什么我会收到禁止错误?


更新

kubernetes 集群在实例级别集成在 gitlab 中。

但是kubectl config view在 CI 管道中运行给了我

apiVersion: v1
clusters: null
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null

更新2

感谢 AndD,可以使用此角色/服务帐户创建密钥:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  namespace: gitlab
  name: gitlab-deploy
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: use-secrets
  namespace: gitlab
subjects:
- kind: ServiceAccount
  name: default
  namespace: gitlab
roleRef:
  kind: ClusterRole
  name: gitlab-deploy
  apiGroup: rbac.authorization.k8s.io

但是对这个 namespace.yaml 文件运行一个简单的应用程序

apiVersion: v1
kind: Namespace
metadata:
  name: myns

给我一个类似的错误:

Error from server (Forbidden): error when retrieving current configuration of:
Resource: "/v1, Resource=namespaces", GroupVersionKind: "/v1, Kind=Namespace"
Name: "myns", Namespace: ""
from server for: "namespace.yaml": namespaces "myns" is forbidden: User "system:serviceaccount:gitlab:default" cannot get resource "namespaces" in API group "" in the namespace "myns"

即使对于不同的命名空间,我也使用 ClusterBinding 来实现它。我究竟做错了什么?

标签: kubernetesgitlabgitlab-ci

解决方案


Kubernetes 使用基于角色的访问控制 (RBAC) 来防止 Pod 和用户能够与集群中的资源进行交互,除非他们未经授权。

从错误中,您可以看到 Gitlab 正在尝试使用该secrets资源,并且它正在其命名空间中用作ServiceAccount服务default帐户。

这意味着 Gitlab 未配置为使用特定的 ServiceAccount,这意味着它使用了默认服务帐户(集群的每个命名空间中都有一个默认服务帐户)


您可以使用Role/ClusterRoleRoleBinding/将角色身份验证和权限附加到服务帐户ClusterRoleBinding

角色或 ClusterRoles 描述权限。例如,角色可以是:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: gitlab
  name: secret-user
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

并且这表明“谁拥有这个角色,可以用秘密做任何事情(所有动词),但只能在命名空间中gitlab

如果要在所有命名空间中授予通用权限,可以使用 ClusterRole 代替,这非常相似。

创建角色后,您可以将其附加到用户、组或服务帐户,例如:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: use-secrets
  namespace: gitlab
subjects:
subjects:
- kind: ServiceAccount
  name: default
  namespace: gitlab
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role # this must be Role or ClusterRole
  name: secret-user # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

这会将先前创建的角色绑定到ServiceAccount命名空间中的调用默认值gitlab

然后,在命名空间中运行并使用服务帐户的所有Pod将能够使用(使用角色中列出的动词),但只能在角色指定的命名空间中使用。gitlabdefaultsecrets


如您所见,Kubernetes 的这一方面非常复杂且功能强大,因此请查看文档,因为它们很好地解释了事情并且还充满了示例:

服务帐户 - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

RBAC - https://kubernetes.io/docs/reference/access-authn-authz/rbac/

RBAC 资源列表 -如何引用角色定义中的所有子资源?


更新

你没有做错什么。只是您正在尝试使用该资源namespace,但 Gitlab 没有 Bind 可以访问该类型的资源。有了你ClusterRole,你只是给了它访问权限secrets,但仅此而已。

考虑赋予 ClusterRole 更多权限,将其更改为列出您需要访问的所有资源:

rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["secrets", "namespaces", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

例如,这将提供对机密、命名空间和 Pod 的访问权限。

作为替代方案,您可以将 Gitlab 的服务帐户绑定cluster-admin到直接授予它访问所有内容的权限。

kubectl create clusterrolebinding gitlab-is-now-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=gitlab:default

在这样做之前,请考虑以下事项:

细粒度的角色绑定提供了更高的安全性,但需要更多的管理工作。更广泛的授权可以为 ServiceAccounts 提供不必要的(并且可能会升级)API 访问,但更易于管理。

因此,首先决定 Gitlab 可以使用哪些资源,然后创建一个 Role / ClusterRole 只允许访问这些资源(以及您需要的动词),这样会更加安全


推荐阅读