亚马逊AWS官方博客

使用 Backstage 和 ACK 简化基础设施和应用程序部署

简介

在当今快节奏的数字化时代,组织越来越多地转向像 Amazon Elastic Kubernetes Service (EKS) 这样的容器编排平台来高效管理其应用程序。然而,配置 EKS 集群和部署应用程序的复杂性可能会带来重大挑战,特别是对于那些努力在开发过程中保持敏捷性和速度的团队而言。在本文中,我们将演示如何使用 Backstage 和 AWS Controllers for Kubernetes (ACK) 来简化您的资源配置和应用程序部署。

自助服务门户和 Backstage

随着现代架构模式的发展,软件开发变得越来越复杂,组织可能会发现他们的开发过程因技能不匹配或低效的内部流程而放缓。

内部开发者平台 (IDP, Internal Developer Platform) 应运而生,以应对这一挑战。IDP 是一个综合的工具和技术集合,通过提供自助服务功能、减少障碍、并简化开发生命周期来赋予开发人员能力。

自助服务门户通常是 IDP 的用户界面组件,为开发人员提供直观的界面来访问平台功能。Backstage 是一个 CNCF 开源项目,提供了一个集中的开发者门户,集成了开发人员日常工作所需的各种工具、服务和资源。Backstage 还具有高度可扩展性,可通过插件轻松集成 GitHub Actions、Kubernetes 等各种服务。

通过基于 Backstage 构建定制的 IDP,组织可以让开发人员自助配置基础设施、应用程序和其他资源,与其独特的业务需求保持一致。这种方法有助于减轻运营团队的负担,并加快软件产品的交付速度。

AWS Controllers for Kubernetes (ACK)

AWS Controllers for Kubernetes (ACK) 是一个开源项目,它使您能够直接从 Kubernetes 管理 AWS 服务。通过利用 Custom Resource Definitions (CRDs) 和控制器,ACK 允许您使用标准的 Kubernetes API 和工具创建、配置和管理 AWS 资源。使用 ACK,您可以直接从 Kubernetes 集群声明式地定义和配置 Amazon Elastic Kubernetes Service (EKS)、Amazon Elastic Container Service (ECS)、Amazon Relational Database Service (RDS) 等 AWS 服务。这种方法简化了云原生应用程序的管理,统一了控制平面并减少了对单独管理工具或 API 的需求。ACK 简化了 Kubernetes 与 AWS 服务的集成,使您能够无缝地利用这两个平台的强大功能。

ACK 在需要管理 AWS 资源和 Kubernetes 工作负载的场景中特别有用,例如为应用程序配置 AWS 服务或自动化基础设施的创建和配置。通过利用 Kubernetes 原生 API 和工具,ACK 增强了开发人员体验,降低了运营复杂性,并在整个云原生环境中促进了一致性。下图演示了如何通过 ACK 配置 AWS 资源。

解决方案概述

在本文中,我们将演示如何使用 Backstage 和 ACK 构建自助服务门户。这将使您的开发人员能够自行配置基础设施资源和应用程序。

整体解决方案包括以下步骤:

  1. 设置一个 EKS 集群作为中心集群(Hub cluster),充当中央控制器来管理您所有租户账户中的基础设施资源和应用程序组件。
  2. 在本地机器上构建和部署 Backstage 作为自助服务门户。
  3. 在中心集群上部署 ACK 以根据 Kubernetes CRD 配置 AWS 资源。
  4. 使用 Backstage 的脚手架功能定义您的基础设施资源模板。
  5. 当开发人员选择通过 Backstage 门户创建资源时,Backstage 将触发 GitHub Actions 来部署 ACK CRD。
  6. 然后 ACK 将根据部署的 CRD 配置必要的 AWS 资源,如 EKS 集群。
  7. 一旦基础设施资源创建完成,Backstage 就可以使用 Kubernetes 插件连接到 EKS 集群。
  8. 然后开发人员可以定义应用程序模板并直接通过 Backstage 门户创建应用程序。
  9. 创建应用程序后,开发人员将能够在 Backstage 服务页面上查看其状态(例如 GitHub 工作流状态、Pod 状态)。

这个解决方案允许您的开发人员自助配置基础设施和应用程序,减轻了运营团队的负担并促进了产品的更快交付。

方案整体架构图

前置条件

在本文中,我们将在本地基于 Backstage 构建 IDP。Backstage 的 Catalog metadata 将发布并注册到 GitHub,然后触发工作流。我们使用内存中的 SQLite 数据库来跟踪状态。

  • 一个已经创建好的EKS 集群,用于安装 ACK。
  • 访问基于 Unix 的操作系统,如 Linux、MacOS 或 Windows Subsystem for Linux
  • 具有安装相关依赖项权限的账户。
  • 已安装 curlwget
  • 已安装 js Active LTS Release
  • 安装 yarn
  • 安装 docker
  • 安装 git
  • 已准备好用于 OAuth App 身份验证的 Github clientId 和 clientSerect。
  • 已准备好用于 Catalog Discovery 的 Github token

Walkthrough

步骤 1:  创建 Backstage 应用程序

首先让我们创建一个工作目录:

mkdir backstage-workshop
cd backstage-workshop

然后使用 npx 创建 Backstage 应用程序 – 这是一个随着 Node.js 预装的工具。工具向导会询问应用程序的名称(这里我们输入 my-backstage)。该名称将作为当前工作目录中的子目录创建。该过程需要几分钟时间。

npx @backstage/create-app

使用以下命令启动 Backstage 应用程序:

cd my-backstage
yarn dev

访问 http://localhost:3000/

现在我们可以在本地运行 Backstage 了。注意,目前运行的只是一个最基本的 backstage,只有有限的功能,我们还需要完成更多的工作来实现我们需求。

步骤 2:  设置 ACK EKS 控制器

  • 部署 ACK EKS 控制器 – 下面的命令将在 Hub EKS 集群上部署 ack-eks-controller Helm chart。
    export SERVICE=eks 
    export RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/${SERVICE}-controller/releases/latest | jq -r '.tag_name | ltrimstr("v")')
    export ACK_SYSTEM_NAMESPACE=ack-system
    export AWS_REGION=<region>
    
    aws ecr-public get-login-password --region us-east-1 | \
      helm registry login public.ecr.aws \
      --username AWS \
      --password-stdin
    
    helm upgrade -i --create-namespace \
      -n $ACK_SYSTEM_NAMESPACE ack-$SERVICE-controller \
      oci://public.ecr.aws/aws-controllers-k8s/$SERVICE-chart \
      --version=$RELEASE_VERSION \
      --set=aws.region=$AWS_REGION \
      --set=metrics.service.create=true \
      --set=deployment.replicas=2 \
      --set=reconcile.defaultMaxConcurrentSyncs=50 \
      --set=resources.limits.memory=1Gi \
      --set=resources.limits.cpu=500m
    
  • 一旦 ACK 控制器在 Hub EKS 集群上运行,我们需要一个 IAM 角色,控制器将代入该角色来配置 AWS 资源。请参考这些步骤,使用 IAM Roles for Service Accounts (IRSA) 设置 ACK。
  • 现在我们已经准备就绪,可以从 Hub EKS 集群使用 ACK 配置租户 EKS 集群。以下代码片段将创建一个 EKS 集群和一个托管节点组。
    apiVersion: eks.services.k8s.aws/v1alpha1
    kind: Cluster
    metadata:
      name: "${CLUSTER_NAME}"
    spec:
      name: "${CLUSTER_NAME}"
      roleARN: "${CLUSTER_ROLE}"
      accessConfig:
        authenticationMode: API_AND_CONFIG_MAP
      version: "${VERSION}"
      resourcesVPCConfig:
        endpointPrivateAccess: true
        endpointPublicAccess: true
        subnetIDs:
          - "${SUBNET_01}"
          - "${SUBNET_02}"
    ---
    apiVersion: eks.services.k8s.aws/v1alpha1
    kind: Nodegroup
    metadata:
      name:"${NODEGROUP_NAME}"
    spec:
      name: "${NODEGROUP_NAME}"
      clusterName:     "${CLUSTER_NAME}"
      subnets:
        - "${SUBNET_01}"
        - "${SUBNET_02}"
      nodeRole: "${NODEGROUP_ROLE}"
      scalingConfig:
        minSize: 1
        maxSize: 2
        desiredSize: 1
    
  • 在本博客中,我们基于上面的清单文件创建了一个 Helm chart 来部署 EKS 集群。
  • 现在应该可以在 Hub EKS 集群中看到租户 EKS 集群和节点组 CR 的状态。
  • 删除租户 EKS 集群和节点组 CR 以清理测试资源。
    kubectl delete nodegroup ack-eks-nodegroup
    kubectl delete cluster ack-eks-cluster
    

步骤 3:  通过 Backstage 配置 EKS 模板

Backstage 中的 Golden Path 是指一组定义良好的最佳实践和标准化工作流程,指导开发团队高效构建和部署软件。它作为一个推荐的框架,帮助团队避免常见的陷阱,减少复杂性,并确保项目的一致性。脚手架功能是在 Backstage 中实现 Golden Path 的主要方式。脚手架允许团队使用预定义的模板创建新的组件或服务。这确保了所有新项目都遵循相同的结构和最佳实践。

Backstage 本身并不实现部署任务执行,这通常依赖于其他 CI/CD 工具来实现。这里我们使用 GitHub Actions 来完成部署。首先,我们在 GitHub 上创建一个仓库 – eks-creation-ack,并配置 GitHub Actions 工作流。该工作流定义了部署步骤 – 调用 ACK 使用 Helm 创建 EKS 集群。稍后,脚手架模板将在资源创建期间调用 Github action。

工作流代码片段:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Create new EKS Cluster using ACK
        run: |
          helm install myack/eks --name ${CLUSTER_NAME} --region ${REGION} --version ${VERSION}

接下来我们将创建一个 EKS 脚手架模板。

cd my-backstage
mkdir templates/eks-cluster

我们将 EKS 模板的元数据和代码放在创建的目录中,这是目录内容的结构:

.
├── content
│   └── catalog-info.yaml
└── template.yaml

catalog-info.yaml – 此文件用于定义 Backstage 目录中 EKS 集群组件的元数据。它包括组件类型、所有者、生命周期阶段以及任何相关资源或依赖项的信息。这些元数据帮助 Backstage 管理和显示目录中的 EKS 集群,允许用户轻松发现和与之交互。

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: ${{ values.destination.repo }}
  annotations:
    github.com/project-slug: ${{values.destination.owner + "/" + values.destination.repo}}
  description: ${{ values.name }} created by ACK
spec:
  type: service
  owner: user:guest
  lifecycle: experimental

template.yaml – 此文件是创建 EKS 集群的主模板配置。它定义了脚手架设置所需的参数和步骤,包括创建过程中需要的任何用户输入。该文件与 Backstage 脚手架集成,根据定义的模板生成必要的资源和配置。它还将触发我们在上一步中创建的 eks-creation-ack 中的 github 工作流。

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: eks-cluster
  title: Create an Amazon EKS Cluster
spec:
  owner: user:guest
  type: service

  parameters:
    <<define parameters here>>

  steps:
    - id: fetch-base
      name: Fetch Base
      action: fetch:template
      input:
        url: ./content
        values:
          destination: ${{ parameters.repoUrl | parseRepoUrl}}
    - id: publish
      name: Publish
      action: publish:github
      input:
        allowedHosts: ['github.com']
        description: This is ${{ parameters.name }}
        repoUrl: ${{ parameters.repoUrl }}
        repoVisibility: public
    #Start a GitHub Action to Create an EKS cluster with ACK
    - id: github-action
      name: Trigger GitHub Action
      action: github:actions:dispatch
      input:
        workflowId: workflow.yml
        repoUrl: https://github.com/<acount or org>/eks-creation-ack
        branchOrTagName: 'main'
        workflowInputs:
          clusterName: ${{ parameters.clusterName }}
          region: ${{ parameters.region }}
          version: ${{ parameters.version }}
  
  # The final step is to register our new component in the catalog.
    - id: register
      name: Register
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
        catalogInfoPath: '/catalog-info.yaml'

接下来我们需要安装与 github 项目交互的插件。

此外,为了使这些插件生效,我们还需要更新 app-config.yaml 中的配置。

  • 获取 github token 并更新集成。
    integrations:
      github:
        - host: github.com
          token: ${GITHUB_TOKEN}
    
  • 配置 github CLIENT_ID 和 CLIENT_SECRET 并更新身份验证提供程序。
    auth:
      providers:
        github:
          development:
            clientId: ${AUTH_GITHUB_CLIENT_ID}
            clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
    
  • 更新目录以导入模板文件。
    catalog:
      import:
        entityFilename: catalog-info.yaml
        pullRequestBranchName: backstage-integration
      rules:
        - allow: [Component, System, API, Resource, Location]
      locations:
        - type: file
          target: ../../templates/eks-cluster/template.yaml
          rules:
            - allow: [Template, User, Group]
    

重新启动 backstage 并导航到主页,就可以看我们刚刚创建的脚手架模板了。单击”CHOOSE”按钮创建新组件。

输入 template.yaml 中定义的所需参数。

检查并确认我们刚刚输入的参数。

等待步骤完成,然后单击”OPEN IN CATALOG”查看我们刚刚创建的组件。

导航到”GITHUB ACTIONS”,我们可以看到已经触发了 Github 工作流,并且 Backstage 单一的视图窗口查看工作流的状态。

EKS 的创建过程需要一些时间,稍等一会我们就可以使用以下 kubectl 命令连接到 Hub EKS 集群并检查集群状态。

$ kubectl get cluster
NAME       VERSION   STATUS   SYNCED   AGE
test-eks001   1.30      ACTIVE   True     30m
$ kubectl get nodegroup
NAME                 CLUSTER    VERSION   STATUS   DESIREDSIZE   MINSIZE   MAXSIZE   SYNCED   AGE
ack-mng-01  test-eks001   1.30      ACTIVE   1             1         2         True     30m

步骤 4:  应用程序部署

此步骤涉及创建应用程序模板,将应用程序部署到刚刚创建的 EKS 集群。

Backstage 中的 Kubernetes 是一个为服务所有者而不是集群管理员设计的工具。开发人员可以轻松检查他们的服务的健康状况。安装 Kubernetes 插件与 EKS 集成。然后我们需要做的就是配置 Backstage,使其知道如何找到我们创建的 EKS 集群。有多种 “cluster locator” 机制可以用于此目的,为了让这个示例简单,我们使用 `config` 定位器,其中我们直接在配置文件中输入 Kubernetes 信息。

kubernetes:
  serviceLocatorMethod:
    type: multiTenant
  clusterLocatorMethods:
    - type: 'config'
      clusters:
      - url: <EKS api server endpoint>
        name: test-eks001
        authProvider: 'aws'
        skipTLSVerify: true
        skipMetricsLookup: true

与创建集群类似,下一步是创建部署应用程序的模板(注意,这里我们为每个应用分别定义了自己的 Github workflow,而不是共用一个,这是和创建的 EKS 的脚手架模板不同的地方)。

cd my-backstage
mkdir templates/eks-app
.
├── content
│   ├── .github
│   │   └── workflows
│   │       └── workflow.yml
│   ├── app
│   │   └── deployment.yaml
│   └── catalog-info.yaml
└── template.yaml

现在我们可以看到一个新的模板,允许我们将应用程序部署到 EKS。我们在此模板中使用 entityPicker 和 catalogFilter 创建了一个环境字段,环境指向我们刚刚创建好的 EKS 集群。

创建完成后,我们可以在 Backstage 的单窗口视图上查看应用程序的相关信息,如代码存储库、GitHub 工作流的执行状态以及创建的 Pod 的运行状态等。通过这种方法,我们可以避免开发人员在不同工具之间切换,从而提高效率。

我们可以很容易地查看已部署 EKS 中的应用程序的状态,副本数量,事件以及资源使用率等信息。

资源清理

  • 删除 backstage 工作文件夹和文件:rm -rf my-backstage && cd .. && rmdir backstage-workshop
  • 从 Hub EKS 集群卸载 ACK
  • 删除 Hub 和应用程序的 EKS 集群
  • 删除 Backstage 创建的 github 存储库

总结

恭喜!您已经完成了如何使用 Backstage 和 ACK 构建开发人员门户的演练。

通过这个练习,您已经学习了:

  • 如何通过使用 ACK 和 Kubernetes CRD 配置 AWS 资源,如 EKS 集群。
  • 如何通过 Backstage 门户向您的开发人员公开这些自助服务配置功能。

为了演示目的,我们在本地机器上运行了 Backstage。但是,在生产环境中,您可以将 Backstage 打包为容器镜像并直接部署到您的 EKS 集群

通过利用 Backstage 和 ACK,您可以让开发人员自助访问所需的资源,简化您的开发流程并促进软件产品的更快交付。

行动起来吧!

这个示例是构建您的内部开发者平台(IDP)的起点。我们建议您进一步探索 ACK 和 Backstage 的高级功能,以根据您的具体需求定制解决方案。

此外,您可能会发现 Cloud Native Operational Excellence (CNOE) 网站上的最佳实践和参考架构对您很有帮助。CNOE 是一个社区驱动的,汇集了不同企业的努力来协调、贡献和提供关于优化使用 CNCF 技术以实现云效率的指导。

本篇作者

叶鹏勇

亚马逊云科技解决方案架构师,负责容器以及 DevOps 相关领域的方案和架构设计工作。在容器、微服务、SRE 相关领域有多年的实战经验。

王祥彦

亚马逊云科技容器解决方案架构师。有丰富的中间件平台及应用容器化实践经验,熟悉 Kubernetes 及云原生开源社区解决方案。