Backstage Kubernetes 插件如何配置认证以访问集群?
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
在 Backstage 中接入了 Kubernetes 插件后,常见的问题是:前端实体页面看不到任何集群资源,或者只看到集群名却加载不出对象。根本原因几乎都是插件的认证没有配好。本文的任务是:完成 Kubernetes 插件的安装后,在app-config.yaml中为集群选择并配置认证方式(authProvider),配合 RBAC 权限和实体关联标注,最终让 Software Catalog 实体页面上的 Kubernetes 标签正常列出该实体对应的 pods、services、deployments 等资源。适用环境是已经按 Getting Started 指南搭建好的 Backstage 实例。
先安装 Kubernetes 前端与后端插件
认证配置依附于插件本身,两步安装缺一不可。在 Backstage 根目录执行:
yarn --cwd packages/app add @backstage/plugin-kubernetes前端插件安装后通过默认 feature discovery 自动生效,会为关联了 Kubernetes 资源的实体页面添加 "Kubernetes" 标签。
然后安装后端插件:
yarn --cwd packages/backend add @backstage/plugin-kubernetes-backend并在packages/backend/src/index.ts中注册:
const backend = createBackend(); // Other plugins... backend.add(import('@backstage/plugin-kubernetes-backend')); backend.start();理解两类认证提供者,选择你的 authProvider
Backstage 的 Kubernetes 认证由KubernetesAuthProviders完成(注意它和 Backstage 应用自身的登录认证不是同一套东西)。文档把它们分为两类,这决定了认证配置的写法:
- Server Side Providers:认证的是你的应用。任何登录了 Backstage 的用户(包括 guest)都获得同一套 Kubernetes 访问权限。可用值:
aws、azure、googleServiceAccount、localKubectlProxy、serviceAccount。 - Client Side Providers:认证的是用户。每个用户会被要求提供凭据,只能访问自己被授权的资源。可用值:
aks、google、oidc。如果集群已配置但用户无权限,该集群会列出但看不到资源,错误表现为401或类似错误。
authProvider字段的完整取值与含义:
| 值 | 说明 |
|---|---|
aks | 使用用户的 AKS access token(来自 Microsoft auth provider)访问 AKS 集群 |
aws | 使用 AWS 凭据访问 EKS 集群资源 |
azure | 使用 Azure Identity 访问集群资源 |
google | 使用用户的 Google access token 访问 GKE 集群 |
googleServiceAccount | 使用 Google Cloud 服务账号凭据访问集群资源 |
oidc | 使用 OIDC token 认证;必须同时设置oidcTokenProvider,且集群须支持 OIDC(文档指出 AKS 集群当时不支持 OIDC) |
serviceAccount | 使用 Kubernetes 服务账号访问 API;须同时设置serviceAccountToken,否则 Backstage 必须运行在集群内 |
以下按文档给出三条主配置路径:本地/自建集群的serviceAccount、AWS 的aws、以及oidc。
路径一:serviceAccount(本地集群与自建集群)
在app-config.yaml中通过clusterLocatorMethods的config方法声明集群。完整示例(本地 minikube,来自 configuration 文档):
kubernetes: serviceLocatorMethod: type: 'multiTenant' clusterLocatorMethods: - type: 'config' clusters: - url: http://127.0.0.1:9999 name: minikube authProvider: 'serviceAccount' skipTLSVerify: false skipMetricsLookup: true serviceAccountToken: ${K8S_MINIKUBE_TOKEN} caData: ${K8S_CONFIG_CA_DATA} caFile: '' # local path to CA file关键字段说明(均以上下文文档为准):
url:Kubernetes control plane 的 base URL,可通过kubectl cluster-info的 "Kubernetes master" 结果获得。name:集群在 Software Catalog Kubernetes 页面中显示的名称,在clusters数组内必须唯一。serviceAccountToken:serviceAccount认证提供者使用的 token,这里以环境变量注入。文档同时提醒:除非你有有效的凭据轮换机制,或只有一个同时运行 Backstage 与全部服务的集群,否则该方式不太适合生产环境。caData:base64 编码的 PEM 格式 CA bundle,可从kubeconfig(通常是~/.kube/config)的clusters[*].cluster.certificate-authority-data字段获取。GKE 可用gcloud container clusters describe <YOUR_CLUSTER_NAME> --zone=<YOUR_COMPUTE_ZONE> --format="value(masterAuth.clusterCaCertificate)"获取。skipTLSVerify:是否跳过 API server 的 TLS 证书校验,默认false。skipMetricsLookup:是否跳过 pod 的 CPU/内存指标查询,默认false。
如果authProvider: serviceAccount的集群省略了serviceAccountToken字段,Backstage 会忽略配置的 URL 和证书数据,改用 in-cluster client 方式访问。
获取 long-lived service account token
假设你已在NAMESPACE命名空间创建了名为SERVICE_ACCOUNT_NAME的服务账号并授予足够权限。按 Kubernetes 版本获取 token(<NAMESPACE>、<SERVICE_ACCOUNT_NAME>、<SECRET_NAME>替换为你的实际值):
Kubernetes 1.24 之前,可以读取服务账号自动生成的 token:
kubectl -n <NAMESPACE> get secret $(kubectl -n <NAMESPACE> get sa <SERVICE_ACCOUNT_NAME> -o=json \ | jq -r '.secrets[0].name') -o=json \ | jq -r '.data["token"]' \ | base64 --decodeKubernetes 1.24 及以后,先创建绑定服务账号的 Secret,等待 token controller 填充后取回:
kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: <SECRET_NAME> namespace: <NAMESPACE> annotations: kubernetes.io/service-account.name: <SERVICE_ACCOUNT_NAME> type: kubernetes.io/service-account-token EOFkubectl -n <NAMESPACE> get secret <SECRET_NAME> -o go-template='{{.data.token | base64decode}}'集群侧 RBAC 权限
插件所需的集群侧权限是 read-only cluster wide。以下 manifest 来自文档,能确保插件正常工作:
--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: backstage-read-only rules: - apiGroups: - '*' resources: - pods - pods/log - configmaps - services - deployments - replicasets - horizontalpodautoscalers - ingresses - statefulsets - limitranges - resourcequotas - daemonsets verbs: - get - list - watch - apiGroups: - batch resources: - jobs - cronjobs verbs: - get - list - watch - apiGroups: - metrics.k8s.io resources: - pods verbs: - get - list将<NAMESPACE>等替换为实际值后,把该 ClusterRole 绑定到你的服务账号再应用即可。
路径二:aws(EKS 集群)
使用aws认证提供者时,除 Kubernetes 配置外还必须配置 AWS 认证。它通过 AWS IAM 向目标账号认证,支持三种凭据来源:静态 Access keys、通过 assume role 生成的短期 Access keys,或用于 OIDC federation(如 GCP Workload Identity Federation)的 web identity token 文件。前两种需要安装并配置 AWS CLI。
静态密钥的 AWS 配置块:
aws: mainAccount: accounts: - accountId: '<account-number>' accessKeyId: ${AWS_ACCESS_KEY_ID} secretAccessKey: ${AWS_SECRET_ACCESS_KEY} region: <region> accountDefaults:Assume role 环境则改为:
aws: mainAccount: roleName: <name-of-the-role-to-assume> region: <region> accounts: accountDefaults:非 AWS 环境(例如 GCP Workload Identity Federation)可使用 web identity token 文件:
aws: accountDefaults: roleName: <name-of-the-role-to-assume> webIdentityTokenFile: <path-to-token-file>对应的 Kubernetes 配置(authMetadata中的 key 即文档中的authMetadata注解项,${...}为环境变量,尖括号项替换为你的实际值):
kubernetes: serviceLocatorMethod: type: 'multiTenant' clusterLocatorMethods: - type: 'config' clusters: - url: https://<unique-identifier>.<region>.eks.amazonaws.com name: ${CLUSTER_NAME_TO_DISPLAY} authProvider: 'aws' caData: ${EKS_CA_DATA} authMetadata: kubernetes.io/aws-assume-role: ${ROLE_ARN_TO_ASSUME} kubernetes.io/aws-external-id: ${ID_FROM_AWS_ADMIN} kubernetes.io/x-k8s-aws-id: ${CLUSTER_NAME_IN_AWS_CONSOLE}集群 URL 和 CA 直接从 AWS 控制台获取:进入EKS>Your cluster>Overview>Details,分别在 'API server endpoint' 和 'Certificate authority' 下找到。kubernetes.io/aws-assume-role设置为要 assume 的角色 ARN,kubernetes.io/aws-external-id对应 STSAssumeRoleAPI 的ExternalId参数。当设置了kubernetes.io/aws-assume-role时,会用角色 ARN 中的 account ID 去匹配accounts或accountDefaults配置,匹配到的凭据作为 assume role 的源凭据。
注意:上述两个 section(AWS 配置块与 Kubernetes 配置块)都需要存在,aws认证提供者才生效。
路径三:oidc(用户级认证,可选分支)
oidc使用 OIDC token 向 Kubernetes API 认证,oidcTokenProvider指定从哪个 Backstage auth provider 取 id token,该 provider 必须已在auth下正确配置:
kubernetes: clusterLocatorMethods: - type: 'config' clusters: - name: test-cluster url: http://localhost:8080 authProvider: oidc oidcTokenProvider: okta # This value needs to match a config under auth.providers auth: providers: okta: development: clientId: ${AUTH_OKTA_CLIENT_ID} clientSecret: ${AUTH_OKTA_CLIENT_SECRET} audience: ${AUTH_OKTA_AUDIENCE}前端开箱即支持的值:gitlab(对应应用需被授予openidscope)、google、microsoft、okta、onelogin。文档特别提醒oidcTokenProvider只是 token 的 issuer,例如可以用microsoft作为 EKS 集群的 issuer。
Azure(AKS)配置说明
azure提供者在服务端通过 Azure CLI 认证,前提是集群已启用 Microsoft Entra authentication。步骤:在 Backstage 运行的环境安装 Azure CLI;在服务器终端执行az login登录;在 Azure Console 进入 AKS 集群资源页,按Connect标签的步骤设置订阅并获取kubectl集成凭据;然后配置:
kubernetes: clusterLocatorMethods: - type: 'config' clusters: - name: My AKS cluster url: ${AZURE_CLUSTER_API_SERVER_ADDRESS} authProvider: azure skipTLSVerify: trueAPI server 地址从 Azure 控制台的集群资源页Overview>Properties>Networking复制。
将实体与集群资源关联
认证配好后,还要让 Backstage 知道哪些集群资源属于哪个实体。在实体的catalog-info.yaml中添加注解:
annotations: 'backstage.io/kubernetes-id': dice-roller可选地用backstage.io/kubernetes-namespace限定命名空间查找。对应的 Kubernetes 资源(service、deployment、ingress 等)需要带相同 key 的 label:
metadata: labels: 'backstage.io/kubernetes-id': <BACKSTAGE_ENTITY_NAME>k8s-app-name与service-entity-name可以不同,但文档建议保持一致。也可用backstage.io/kubernetes-label-selector写自定义 label selector 查询替代精确 id 匹配(label selector 优先级高于 annotation/service id)。
验证配置是否生效
用文档给出的 curl 命令检查集群是否已连通({{backstage-backend-url}}:{{backstage-backend-port}}替换为你的 Backstage 后端实际地址,:service-entity-name与服务名替换为实际实体名):
curl --location --request POST 'http://<backstage-backend-host>:<port>/api/kubernetes/services/<service-entity-name>' \ --header 'Content-Type: application/json' \ --data-raw '{ "entity": { "metadata": { "name": "<service-entity-name>" } } }'成功的判断方式是:响应items中包含对应cluster和resources(services、pods 等),且errors为空。文档示例响应结构:
{ "items": [ { "cluster": { "name": "<cluster-name>" }, "resources": [ { "type": "services", "resources": [ { "metadata": { "labels": { "backstage.io/kubernetes-id": "<service-entity-name>" }, "name": "<k8s-app-name>", "namespace": "<namespace>" } } ] } ], "errors": [] } ] }(以上尖括号均为占位符,实际输出中的名称以你环境为准。)最后到 Backstage 实体页面确认 Kubernetes 标签中能看到这些资源。
排查与限制
- Kubernetes 标签什么都不显示:先确认
catalog-info.yaml注解与集群资源 label 是否匹配,这是文档列出的最常见原因;再用上面的 curl 命令区分是"集群没连通"还是"实体没关联上"。 - 用户看不到资源但集群已列出:这是 client side 提供者的正常行为——用户未被授权访问该集群时错误显示为
401或类似,需要为该用户配置集群侧授权。 localKubectlProxy假定本地有kubectl proxy(默认端口 8001)在运行,文档明确它只用于本地开发,不应在生产环境使用。- catalog cluster locator 不支持
serviceAccount:把 token 放在 catalog 实体注解里是不安全的,因此 catalog 定位器会忽略使用serviceAccount策略的实体,且serviceAccountToken等敏感 key 不能从 catalog 实体提供。 - 多个定位器共存时:可将
clusterLocatorContinueOnError设为true,这样单个定位器(如某个 GKE 项目的权限错误)失败时,其余成功定位器返回的集群仍会返回;默认false时任一失败会导致整个集群列表请求失败。
完成认证配置、RBAC 授权与实体关联后,实体页面的 Kubernetes 标签即可展示真实资源。如需进一步限制谁可以调用/clusters、/services/:serviceId、/resources、/proxy等端点,可结合权限框架配置kubernetes.clusters.read、kubernetes.resources.read与kubernetes.proxy权限,见 Permissions 文档。完整认证机制与自定义AuthenticationStrategy的说明见 Kubernetes Authentication 与 Authentication Strategies,各配置字段的细节见 Configuring Kubernetes integration。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考