在 Kubernetes 上部署 Backstage:从本地 minikube 到生产集群的完整实践指南

在 Kubernetes 上部署 Backstage:从本地 minikube 到生产集群的完整实践指南 在 Kubernetes 上部署 Backstage从本地 minikube 到生产集群的完整实践指南【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage本文基于 docs/deployment/k8s.md 编写配套仓库源码与 contrib 示例作为补充依据。导读Backstage 是一个用于构建开发者门户Developer Portal的开源框架其设计目标之一就是适配容器化部署模型Backstage 本身是一个无状态应用数据全部存放在外部 PostgreSQL 数据库中因此非常适合运行在 Kubernetes 集群上。本文完整讲解如何在 Kubernetes 上从零部署一套 Backstage涵盖本地 minikube 环境搭建、命名空间创建、PostgreSQL 数据库Secret / PersistentVolume / Deployment / Service创建、Backstage 应用实例Secret / Deployment / Service创建以及生产化部署的后续步骤。读完本文你将能够使用kubectl与 minikube 在本地搭建并验证一套完整的 Backstage 环境理解并编写 Backstage 部署所需的全部 Kubernetes 对象定义Namespace、Secret、PersistentVolume、PersistentVolumeClaim、Deployment、Service将 Backstage 配置app-config.yaml与 Kubernetes 环境变量、Secret 打通实现数据库连接与鉴权配置注入掌握生产部署的收尾工作可靠的持久卷、Ingress/负载均衡暴露服务、镜像更新策略。部署模型总览Kubernetes 是用于部署、扩缩容和管理容器化应用的系统。Backstage 天然适配这一模型它以无状态应用stateless application的形式运行配合外部 PostgreSQL 数据库持久化数据。值得注意的一点是Backstage 软件目录Software Catalog的实体定义文件本身也使用 Kubernetes 对象格式这一点在 descriptor-format.md 中有详细说明。也就是说如果你已经熟悉 Kubernetes 的 YAML 对象写法那么阅读 Backstage 的实体定义文件也会相当顺手。由于 Kubernetes 集群的部署工具与模式多种多样官方文档给出的核心建议是在已有 Kubernetes 环境上部署 Backstage 时用你部署其他一切服务的方式来部署它。本文提供的是在典型集群中让 Backstage 跑起来所需的基础 Kubernetes 对象定义。一个完整的部署由两大块组成PostgreSQL 数据库通过独立的 Kubernetes Deployment 运行使用 Secret 保存凭据、PersistentVolume/PersistentVolumeClaim 持久化数据、Service 提供稳定的访问入口Backstage 应用实例通过 Kubernetes Deployment 运行打包好的 Docker 镜像通过 Secret 注入鉴权 Token 等敏感配置通过 Service 将 7007 端口暴露给集群内其他组件。本地测试环境kubectl minikube在生产集群部署之前可以先用本地环境验证上述所有概念。需要两个工具kubectlKubernetes 命令行工具用于向集群下发各种对象定义minikube在本地机器上创建一个单节点 Kubernetes 集群。以 Mac Homebrew 为例的安装方式如下其他平台请参考 minikube 官方安装文档$ brew install minikube $ minikube start ... Done! kubectl is now configured to use minikube cluster and default namespace by default.minikube start完成后kubectl会被自动配置为指向名为minikube的集群与default命名空间。此时执行kubectl命令所做的变更都会应用到该本地集群可以验证系统组件是否正常运行$ kubectl get pods -A当教程结束后使用minikube stop停止集群以释放资源。提示minikube 也可以用于本地构建并安装 Backstage 镜像详见下文「创建 Backstage deployment」小节中关于minikube docker-env的用法。创建命名空间Namespace在多租户环境下部署通常被分配到独立的命名空间中以实现服务隔离。可以通过kubectl直接创建$ kubectl create namespace backstage namespace/backstage created也可以先编写 Namespace 定义文件再应用# kubernetes/namespace.yaml apiVersion: v1 kind: Namespace metadata: name: backstage$ kubectl apply -f kubernetes/namespace.yaml namespace/backstage created后续所有与 Backstage 相关的对象Secret、PVC、Deployment、Service 等都将放在backstage命名空间下并在各自定义中通过namespace: backstage显式声明。创建 PostgreSQL 数据库生产环境中 Backstage 使用 PostgreSQL 作为数据库。为了将数据库与 Backstage 应用部署隔离可以为 PostgreSQL 单独创建一个 Kubernetes Deployment。整个过程分为四步Secret凭据、持久化存储PV/PVC、Deployment数据库实例、Service访问入口。创建 PostgreSQL Secret首先创建一个 Kubernetes Secret保存 PostgreSQL 的用户名与密码。该 Secret 同时会被 PostgreSQL 数据库和 Backstage 两个 Deployment 引用# kubernetes/postgres-secrets.yaml apiVersion: v1 kind: Secret metadata: name: postgres-secrets namespace: backstage type: Opaque data: POSTGRES_USER: YmFja3N0YWdl POSTGRES_PASSWORD: aHVudGVyMgKubernetes Secret 中的 data 字段是base64 编码的。可以在命令行生成$ echo -n backstage | base64 YmFja3N0YWdl安全提醒Secret 只是 base64 编码并未加密。请务必为集群启用 Kubernetes Encryption at Rest。如果希望把 Secret 存进 Git可以考虑 SealedSecrets 或其他解决方案。应用该 Secret$ kubectl apply -f kubernetes/postgres-secrets.yaml secret/postgres-secrets created创建 PostgreSQL 持久化存储PV PVCPostgreSQL 需要持久卷来存储数据。下面同时创建一个PersistentVolumePV与PersistentVolumeClaimPVC。本例声明了整块卷但 PVC 实际上也可以只申请卷的一部分容量# kubernetes/postgres-storage.yaml apiVersion: v1 kind: PersistentVolume metadata: name: postgres-storage namespace: backstage labels: type: local spec: storageClassName: manual capacity: storage: 2G accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain hostPath: path: /mnt/data --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-storage-claim namespace: backstage spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 2G该文件包含两种 kind 的定义用一行**三连横线---**分隔。这种语法便于将相关联的 Kubernetes 定义合并到单个文件中一次性应用。注意卷标签中的type: local它使用 Kubernetes 节点上的本地磁盘创建卷。在生产场景中通常应改用可用性更高的 PersistentVolume 类型如云厂商的块存储、网络附加存储等这一点会在「进一步步骤」中再次强调。应用存储卷与声明$ kubectl apply -f kubernetes/postgres-storage.yaml persistentvolume/postgres-storage created persistentvolumeclaim/postgres-storage-claim created创建 PostgreSQL Deployment接下来为数据库本身创建 Kubernetes Deployment 描述文件# kubernetes/postgres.yaml apiVersion: apps/v1 kind: Deployment metadata: name: postgres namespace: backstage spec: replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:13.2-alpine imagePullPolicy: IfNotPresent ports: - containerPort: 5432 envFrom: - secretRef: name: postgres-secrets env: - name: POSTGRES_HOST value: postgres.backstage - name: POSTGRES_PORT value: 5432 volumeMounts: - mountPath: /var/lib/postgresql/data name: postgresdb subPath: data volumes: - name: postgresdb persistentVolumeClaim: claimName: postgres-storage-claim对 Kubernetes 新手来说这段定义信息量较大拆开来看metadata块描述了这个 Deployment应用的一个或多个实例的基本信息spec块描述期望状态desired state请求 Kubernetes 创建 1 个副本正在运行的 PostgreSQL 实例并用给定的 podtemplate创建副本template 中又包含 Kubernetes 元数据与期望状态template 的spec中定义了一个容器来源于官方发布的postgres:13.2-alpineDocker 镜像暴露 5432 端口PostgreSQL 默认端口envFromsecretRef让 Kubernetes 把之前创建的 Secret 中的值注入为容器环境变量volumeMounts引用了为部署创建的持久卷挂载路径为 PostgreSQL 期望的数据目录/var/lib/postgresql/data并使用subPath: data隔离出独立子目录volumes中通过persistentVolumeClaim引用前面创建的 PVCpostgres-storage-claim。应用 PostgreSQL Deployment 并查看 Pod 状态$ kubectl apply -f kubernetes/postgres.yaml deployment.apps/postgres created $ kubectl get pods --namespacebackstage NAME READY STATUS RESTARTS AGE postgres-56c86b8bbc-66pt2 1/1 Running 0 21s进入 Pod 验证数据库可连接$ kubectl exec -it --namespacebackstage postgres-56c86b8bbc-66pt2 -- /bin/bash bash-5.1# psql -U $POSTGRES_USER psql (13.2) backstage# \q bash-5.1# exit创建 PostgreSQL Service数据库 Pod 已经运行但其他 Pod 如何连接它Kubernetes Pod 是瞬态的——它们可能被停止、重启或动态创建因此不应直接连接 Pod而应创建 KubernetesService。Service 负责跟踪 Pod 并将流量导向正确的位置# kubernetes/postgres-service.yaml apiVersion: v1 kind: Service metadata: name: postgres namespace: backstage spec: selector: app: postgres ports: - port: 5432这里的selector: app: postgres与 PostgreSQL Deployment 中 pod template 的标签app: postgres对应Service 会将流量路由到带有该标签的 Pod。应用该 Service$ kubectl apply -f kubernetes/postgres-service.yaml service/postgres created $ kubectl get services --namespacebackstage NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE postgres ClusterIP 10.96.5.103 none 5432/TCP 29s创建完成后集群内的其他 Pod包括 Backstage可以通过服务名postgres访问数据库。创建 Backstage 实例数据库就绪后开始创建 Backstage 实例步骤与 PostgreSQL 部署类似。创建 Backstage Secret对于 Backstage 的配置类 Secret如鉴权 Token可以参照上面的 PostgreSQL Secret 方式创建同样需要 base64 编码# kubernetes/backstage-secrets.yaml apiVersion: v1 kind: Secret metadata: name: backstage-secrets namespace: backstage type: Opaque data: GITHUB_TOKEN: VG9rZW5Ub2tlblRva2VuVG9rZW5NYWxrb3ZpY2hUb2tlbg应用该 Secret$ kubectl apply -f kubernetes/backstage-secrets.yaml secret/backstage-secrets created创建 Backstage Deployment创建 Backstage Deployment 前需要先构建 Docker 镜像具体方法见 docs/deployment/docker.md。本例使用标准的host build方式前端被打包进后端镜像并由后端一并提供。创建 Backstage Deployment 描述文件# kubernetes/backstage.yaml apiVersion: apps/v1 kind: Deployment metadata: name: backstage namespace: backstage spec: replicas: 1 selector: matchLabels: app: backstage template: metadata: labels: app: backstage spec: containers: - name: backstage image: backstage:1.0.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 7007 envFrom: - secretRef: name: postgres-secrets - secretRef: name: backstage-secrets # 如果应用启用了健康检查取消注释 # https://backstage.io/docs/plugins/observability#health-checks # readinessProbe: # httpGet: # port: 7007 # path: /healthcheck # livenessProbe: # httpGet: # port: 7007 # path: /healthcheck要点说明镜像引用生产部署中image通常是一个完整的容器仓库 URL例如 AWS 的 ECR。本地用 minikube 测试时可以把本地 Docker 守护进程指向 minikube 内置的 Docker 仓库然后重新构建镜像完成安装$ eval $(minikube docker-env) $ yarn build-image --tag backstage:1.0.0数据库连接无需额外配置网络由于 PostgreSQL Service 运行在同一个集群中Kubernetes 会自动把POSTGRES_HOST和POSTGRES_PORT环境变量注入 Backstage 容器此处的POSTGRES_HOST即服务名postgres。这些变量配合 Secret 注入的凭据可以在 Backstage 的app-config.yaml中直接使用backend: database: client: pg connection: host: ${POSTGRES_HOST} port: ${POSTGRES_PORT} user: ${POSTGRES_USER} password: ${POSTGRES_PASSWORD}如果有app-config.production.yaml也需要同步应用这段配置。关于${...}环境变量语法与 PostgreSQL 客户端的更多说明可参考 docs/getting-started/config/database.md。重要修改app-config.yaml后务必重新构建 Docker 镜像改动才会进入新的镜像。健康检查探针Probe上面被注释的readinessProbe/livenessProbe对应后端/healthcheck路由。在新版后端系统中健康检查由 Root Health 服务提供rootHttpRouter默认暴露/.backstage/health/v1/readiness与/.backstage/health/v1/liveness端点详见 docs/backend-system/core-services/root-health.md并可通过backend.health.headers为健康检查响应追加自定义响应头例如在多变服务环境中用于唯一标识本服务的service-name头。在配置探针时请依据所部署 Backstage 版本实际启用的健康检查路径进行调整。应用 Deployment 并确认运行状态$ kubectl apply -f kubernetes/backstage.yaml deployment.apps/backstage created $ kubectl get deployments --namespacebackstage NAME READY UP-TO-DATE AVAILABLE AGE backstage 1/1 1 1 1m postgres 1/1 1 1 10m $ kubectl get pods --namespacebackstage NAME READY STATUS RESTARTS AGE backstage-54bfcd6476-n2jkm 1/1 Running 0 58s postgres-56c86b8bbc-66pt2 1/1 Running 0 9m如果遇到问题可以查看 Pod 中的容器日志-f表示持续跟踪输出# -f 跟踪日志pod -c container 指定容器 $ kubectl logs --namespacebackstage -f backstage-54bfcd6476-n2jkm -c backstage创建 Backstage Service与 PostgreSQL Service 类似需要为 Backstage 创建一个 Kubernetes Service将请求连接到正确的 Pod# kubernetes/backstage-service.yaml apiVersion: v1 kind: Service metadata: name: backstage namespace: backstage spec: selector: app: backstage ports: - name: http port: 80 targetPort: http这里selector告诉 Service 要指向哪些 Pod端口映射把常规 HTTP 的 80 端口转换为 Pod 上的后端 HTTP 端口7007即 Deployment 中containerPort: 7007对应name: http的端口。应用该 Service$ kubectl apply -f kubernetes/backstage-service.yaml service/backstage created至此一个可运行的 Backstage 部署已经完成。要一睹成果可以把本地端口转发到该 Service$ sudo kubectl port-forward --namespacebackstage svc/backstage 80:80 Forwarding from 127.0.0.1:80 - 7007输出显示 7007 是因为port-forward本身并不真正支持 Service——它会“作弊”地查找该 Service 的第一个 Pod并连接到映射的 Pod 端口。同时app-config.yaml中的app.baseUrl与backend.baseUrl需要与这里的转发地址一致本例使用默认 HTTP 端口 80故省略端口号# app-config.yaml app: baseUrl: http://localhost organization: name: Spotify backend: baseUrl: http://localhost listen: port: 7007 cors: origin: http://localhost如果使用了鉴权提供者auth provider参见 docs/auth/index.md也需要为它配置同样的地址鉴权弹窗才能正常工作。完成以上步骤后在浏览器打开http://localhost即可访问部署在 Kubernetes 上的 Backstage 实例。生产化部署的进一步步骤上述流程已经走完了 Backstage 上 Kubernetes 的大部分路径但距离完整的生产部署还有几步收尾工作使用更可靠的持久卷上面配置的PersistentVolume使用的是 Kubernetes 节点本地存储type: local/hostPath。生产环境应替换为云磁盘、网络附加存储NAS或其他比节点生命周期更持久的存储方案以避免节点重建导致数据丢失。暴露 Backstage Service上文创建的 Kubernetes ServiceClusterIP默认无法从集群外部访问。通常通过以下两种方式之一暴露Kubernetes Ingress在集群入口统一做路由与可选TLS 终止外部负载均衡器直接为 Service 分配外部可访问的 IP。更新 Deployment 镜像要将 Kubernetes 部署更新到新发布的 Backstage Docker 镜像版本只需修改backstage.yaml中的镜像 tag然后重新应用$ kubectl apply -f kubernetes/backstage.yaml生产环境下该镜像 tag 通常是一个完整的容器仓库 URL指向存放构建产物的地方——可以是自建的基础设施也可以是云厂商提供的托管仓库。仓库配套资源可参考的 Kubernetes 示例当前仓库的 contrib/kubernetes/basic_kubernetes_example_with_helm 目录提供了额外的参考实现值得对照阅读裸 YAML 版本app.yaml前端 Deployment镜像spotify/backstage:latest端口 80、backend.yaml后端 Deployment镜像spotify/backstage-backend:latest端口 7007、service.yaml分别为前端 Service 80 端口与后端 Service 7007 端口、ingress.yaml将/路由到前端 Service、/backend路由到后端 Service——这个示例演示了前端与后端分离部署的形态Helm 版本backstage/目录下包含Chart.yaml、values.yaml与templates/deployment.yaml、service.yaml、ingress.yaml、_helpers.tpl。values.yaml中对app与backend两套组件分别提供了replicaCount、image.repository/image.tag/image.pullPolicy、service.type/service.port、ingresshosts / tls / annotations、resources、securityContext等可调参数模板中还内置了 liveness / readiness 探针对根路径做 HTTP 检查与imagePullSecrets支持。注意该 contrib 目录的 README 明确标注为 deprecated官方推荐使用由 Backstage 社区维护的 Backstage Helm Charts同时这些示例仅展示最小化配置并未包含安全加固的最佳实践生产环境请参考 Kubernetes 官方安全文档与所在组织的规范。总结本文完整演示了 Backstage 在 Kubernetes 上的部署路径从本地 minikube 验证环境出发依次创建命名空间、PostgreSQL 的 Secret / PVPVC / Deployment / Service再到 Backstage 的 Secret / Deployment / Service最后通过kubectl port-forward在浏览器中访问实例。这套对象定义完整覆盖了「无状态应用 外部数据库」的部署模型而contrib目录中的 Helm 与前后端分离示例则为生产化提供了更多形态参考。将本地存储替换为高可用持久卷、通过 Ingress 或负载均衡暴露服务、按发布节奏滚动更新镜像即可平滑过渡到完整的生产部署。【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考