【Developer Hub 実践|第7回】Golden Pathの実装をマスターしよう - 前編

こんにちは、Red HatでOpenShift関連のプリセールスをしている北村です。

これまで、Developer Hub (Backstage) を使って認証連携やComponentの登録、さらにはSoftware Template機能を用いたシンプルなHello Worldアプリのセルフサービスデプロイをご紹介してきました。

この記事ではより実践的なテンプレート、すなわちGolden Pathを構築するためのSoftware Templateの実装に挑戦します。 なお、実践的なGolden Pathの構築には多数の手順が必要になるので、記事を前編と後編に分けてご紹介します。この記事は前編として周辺ツールの準備とDeveloper Hubとの連携手順をまとめます。

Golden Pathとは

Golden Pathとは、開発のベストプラクティスを実際に動作する環境と共に開発者に提供する仕組みです。 Golden Pathには実際に動くサンプルアプリとそのソースコード、アプリの開発に必要なCIパイプラインやGitOps環境、そしてGolden Pathによって構築された環境の可観測性や、Golden Pathの価値を正しく理解して活用するためのTechDocsが含まれます。

このGolden PathをPlatform Engineering Teamから提供することで、 開発者に守ってほしいルールを付与しつつ、実際に動くアプリとコードを提供することで、開発者のノウハウ習得をサポートします。

このGolden PathこそDeveloper Hubの真価の根幹であり、全てはこのGolden Pathの実行から開発者体験は始まります。 逆にいうと、Developer Hubはただ環境を準備しただけでは価値はあまりなく、このGolden Pathを提供して初めて導入価値が発揮されます。

Golden Pathの実装ステップ

ここからは、Golden Path実現のための実装手順について解説します。 実装手順は大きく分けると以下のステップで進めていきます。

  1. 環境の構築: Golden Path実行に必要な周辺ツールを準備します。今回はSonarqubeをインストールしていきます。
  2. Developer Hub連携: 導入したSonarqubeや、GitHub Actionsとの連携設定を行います。
  3. Skeleton Repositoryの作成: Golden Pathのコピー元となるリポジトリを準備します。この中にはGitHub ActionsのWorkflowも含まれます。
  4. template.yamlの作成: Golden Pathを実行するためのtemplate.yamlを作成します。
  5. Golden Pathの実行・確認: 実際にGolden Pathを実行し、挙動を確認します。

今回は1と2を実装していきます。

今回実装する環境

今回は以下のような環境を構築していきます。

  1. 利用者はDeveloper Hubの画面で必要なパラメータを入力してTemplateを実行する
  2. Skeleton Repoからソースコードを取得し、ユーザーが入力したパラメータを代入する
  3. 新しいGitHubリポジトリ(app用リポジトリとmanifest用リポジトリ)にPushする
  4. Hello worldアプリ用のK8sマニフェストをデプロイするためのApplication CRを作成する
  5. リポジトリの作成を契機にアプリをビルド→デプロイするGitHub Actionsを実行する
  6. ビルドされたコンテナイメージはAWS ECRに保管する
  7. Application CRが新しいGitHubリポジトリ上のK8sマニフェストを検知してアプリをデプロイする

環境の構築

まずはGolden Path実装に必要な周辺ツールを準備します。今回はコードの静的解析としてSonarqubeをROSAクラスター上にインストールして行きます。

Sonarqubeのインストール

SonarqubeはGolden PathでデプロイされるCIパイプライン上でアプリケーションコードの静的解析に使用します。

SonarqubeはHelmでインストールしますが、公式のHelmチャートではOpenShiftのデフォルトのセキュリティ設定の関係でインストールすることができません。そのためGitHubのRed Hat Communities of Practiceにあるhelmチャートを利用します。

# Project作成
oc new-project sonarqube

# リポジトリの追加
helm repo add redhat-cop https://redhat-cop.github.io/helm-charts

# sonarqubeのインストール
helm upgrade --install sonarqube redhat-cop/sonarqube -n sonarqube

しばらくするとリソースがデプロイされるので、RouteのURLを取得してアクセスします。

oc get route -n sonarqube sonarqube -o jsonpath={.status.ingress[0].host}

Sonarqubeのログイン画面が表示されるのでadmin/adminでログインします。

Passwordをアップデートする必要があるので適当に変更します。

Sonarqubeにログインできました。これでいったんSonarqubeのインストールも完了です。

Developer Hub連携

導入したSonarqube、GitHub Actionsとの連携設定を行います。

Dynamic Pluginをインストールする

まずはいつも通りDynamic Pluginをインストールします。dynamic-plugins-rhdh.yamlを変更していきます。GitHub ActionsのPluginと、Sonarqube Pluginを3種類追加します。

dynamic-plugins-rhdh.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: dynamic-plugins-rhdh
  namespace: rhdh
  annotations:
    rhdh.redhat.com/backstage-name: developer-hub
data:
  dynamic-plugins.yaml: |
    includes:
      - 'dynamic-plugins.default.yaml'
    plugins:
    # GitHub Plugins
      - package: ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-org-dynamic
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-plugin-scaffolder-backend-module-github-dynamic
        disabled: false
      # ここから 
      - package: ./dynamic-plugins/dist/backstage-community-plugin-github-actions 
        disabled: false
      # ここまでを追加
    # Kubernetes Plugins
      - package: ./dynamic-plugins/dist/backstage-plugin-kubernetes-backend-dynamic
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-plugin-kubernetes
        disabled: false
    # OpenShift Plugins
      - package: ./dynamic-plugins/dist/backstage-community-plugin-topology
        disabled: false
    # ArgoCD Plugins
      - package: ./dynamic-plugins/dist/roadiehq-backstage-plugin-argo-cd-backend-dynamic
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-community-plugin-redhat-argocd
        disabled: false
      - package: ./dynamic-plugins/dist/roadiehq-scaffolder-backend-argocd-dynamic
        disabled: false
    # Techdocs Plugins
      - package: ./dynamic-plugins/dist/backstage-plugin-techdocs
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-plugin-techdocs-backend-dynamic
        disabled: false
    # ここから下を追加
    # Sonarqube Plugins
      - package: ./dynamic-plugins/dist/backstage-community-plugin-sonarqube
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-community-plugin-sonarqube-backend-dynamic
        disabled: false
      - package: ./dynamic-plugins/dist/backstage-community-plugin-scaffolder-backend-module-sonarqube-dynamic
        disabled: false
  • backstage-plugin-github-actions: GitHub Actionsのワークフロー実行状況や結果をDeveloper Hub上で表示し、CI/CDパイプラインの進捗を可視化します。
  • backstage-community-plugin-sonarqube: SonarQubeのコード品質分析結果や各種メトリクスをフロントエンドで表示するプラグインです。
  • backstage-community-plugin-sonarqube-backend-dynamic: SonarQubeサーバーと動的に連携し、各プロジェクトの分析結果をバックエンドで取得・提供するモジュールです。
  • backstage-community-plugin-scaffolder-backend-module-sonarqube-dynamic: Scaffolderのテンプレート実行時に、SonarQubeによるコード品質チェックを自動化するバックエンドモジュールです。

app-configを変更する

app-config-rhdh.yaml に以下のような設定を追記します。 proxy部分とsonarqube部分の2箇所になります。GitHub Actionsについては、app-configの追記は不要です。

app-config-rhdh.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: app-config-rhdh
  namespace: rhdh
  annotations:
    rhdh.redhat.com/backstage-name: developer-hub
data:
  app-config-rhdh.yaml: |
    app:
    ...omit...
    backend:
    ...omit...
    auth:
    ...omit...
    integrations:
    ...omit...
    signInPage: github
    catalog:
    ...omit...
    enabled:
      kubernetes: true
      argocd: true
      techdocs: true
      sonarqube: true       # ここを追記
    kubernetes:
    ...omit...
    argocd:
    ...omit...
    proxy:
      '/argocd/api':
        target: ${ARGOCD_INSTANCE_URL}/api/v1/
        changeOrigin: true
        secure: false
        headers:
          Cookie:
            $env: ${ARGOCD_AUTH_TOKEN}
      # ここから
      '/sonarqube':
        target: ${SONARQUBE_URL}/api
        allowedMethods: ['GET']
        auth: "${SONARQUBE_USER_TOKEN}:"
      # ここまで追記
    techdocs:
    ...omit...
    # ここから下を追記
    sonarqube:
      baseUrl: ${SONARQUBE_URL}
      apiKey: ${SONARQUBE_USER_TOKEN}

Secretを設定する

最後に必要な変数をSecretに設定していきます。その前にSonarqubeの設定に必要な値を取得しましょう。

Sonarqubeにアクセスして、右上のユーザーアイコンからMy Accountを選択します。

SecurityタブからユーザーTokenを作成します。Token名はrhdhとしました。

ここで表示されたTokenをSecretに設定します。

secrets-rhdh.yaml

apiVersion: v1
kind: Secret
metadata:
  name: secrets-rhdh
  namespace: rhdh
stringData:
  ...omit...
  SONARQUBE_URL: "https://<sonarqubeのURL>"
  SONARQUBE_USER_TOKEN: "<sonarqubeのユーザーToken>"

3つのファイルの反映

変更した3つのファイルをデプロイします。

oc apply -f app-config-rhdh.yaml -f secrets-rhdh.yaml -f dynamic-plugins-rhdh.yaml

これでSonarqubeに関するDeveloper Hubの連携設定が完了しました。

AWS ECRの認証設定を行う

次にAWS ECRに対するPullとPushを行うための認証設定を行います。

今回のGolden Pathでは、GitHub ActionsのWorkflow内でECRへのコンテナイメージPushを行います。そして、ROSA上にデプロイするために特定のサービスアカウントでECRからイメージをPullする必要があります。この2つのアクセスを実現するための設定をここでは行います。

実装イメージは以下のとおりです。

IAMポリシーの作成

ECRへPullとPushを行うためのポリシーを登録します。

push-pull-ecr-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PushPullECR",
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:CreateRepository",
        "ecr:DescribeRepositories",
        "ecr:DeleteRepository",
        "ecr:SetRepositoryPolicy"
      ],
      "Resource": "*"
    }
  ]
}

以下のコマンドでIAMポリシーを作成します。 aws iam create-policy --policy-name PushPullECRPolicy --policy-document file://push-pull-ecr-policy.json

GitHub Actions用IAMロールの作成

【第6回】TechDocsを作成・登録しようで作成したOIDC Providerの情報を使って、GitHub Actions上からECRへイメージをPushするために利用するIAMロールを作成します。

aws iam create-role --role-name GitHubActionsPushECRRole --assume-role-policy-document file://github-assume-role-policy.json

IAMロールとIAMポリシーを紐づけます。

aws iam attach-role-policy --role-name GitHubActionsPushECRRole --policy-arn arn:aws:iam::<AWSアカウントID>:policy/PushPullECRPolicy

これでGitHub Actions側に必要なIAMの準備は完了しました。

次にROSA側のIAMの準備です。

ECR Secret Operatorのインストール

Amazon ECRのプライベートリポジトリからコンテナイメージを取得する際にはAmazon IAMによる認証が必要ですが、認証トークンの有効期間は12時間であり、一定時間ごとに再度トークンを取得する必要があります。その取得・更新を自動化するためのOperatorとして提供されているのがECR Secret Operatorです。

このOperatorはコミュニティプラグインのためRed Hatからの正式なサポートが提供されていませんが、ECRの認証を効率化するために有効なツールですので、今回はこちらを使用していきます。

コンソール上でさくっとインストールしていきましょう。Operator Hubから検索をかけて、該当のOperatorを選択します。

特に設定を変更する必要はなく、すべてデフォルトでインストールしていきます。

するとecr-secret-operatorというNamespaceにOperatorがインストールされます。

このOperatorは、Secretというカスタムリソース(名前が一緒でややこしいですが)をデプロイすると、その情報を元にECRの認証情報(.dockerconfigjson)の通常のSecretを自動生成します。この自動生成されたSecretはECR Secret OperatorとSecretによって管理され、認証情報がExpireしたときに新しい認証情報に自動更新されます。

ECR Secret Operatorに設定するIAMロールの作成

次にこのOperatorがECRの認証トークンを取得するためのIAMロールを作成します。このIAMロールによって、ECRから有効な認証情報(トークン)を取得できるようになります。

実はこのECRの認証トークンを取得するための権限 (ecr:GetAuthorizationToken)は、先ほどのIAMポリシーに付与してあるので、このポリシーをそのまま利用します。そのため、まずは信頼ポリシーを設定するjsonファイルから作成を開始します。

rosa-ecr-assume-role-policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWSアカウントID>:oidc-provider/<OIDCプロバイダー名>"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "<OIDCプロバイダー名>:sub": "system:serviceaccount:ecr-secret-operator:ecr-secret-operator-controller-manager"
                }
            }
        }
    ]
}

このjsonを使ってIAMロールを作成します。

aws iam create-role --role-name ROSAPullECRRole --assume-role-policy-document file://rosa-ecr-assume-role-policy.json

IAMロールとIAMポリシーを紐づけます。

aws iam attach-role-policy --role-name ROSAPullECRRole --policy-arn arn:aws:iam::<AWSアカウントID>:policy/PushPullECRPolicy

これで先ほどの図の青枠の部分まで設定が完了しました。これ以降の部分は後半のGolden Pathによって実装されます。

GitHub Actionsで利用する環境変数・シークレットの登録

最後に、Golden Path内のGitHub Actionsで利用する環境変数・シークレットをOrganizationに登録していきます。

登録する変数の詳細な説明は、後編のCIパイプライン作成の部分で行います。ここでは一旦記載されている内容を登録していきましょう。

登録する環境変数とシークレットは以下の通りです。

Secret

ARGOCD_PASSWORD ArgoCDのadminユーザーのパスワード
ARGOCD_USERNAME admin
GITHUBAPP_ID 第2回で登録したGitHub AppのApp ID
GITHUBAPP_PRIVATE_KEY 第2回で登録したGitHub AppのPrivate Key
SONARQUBE_USER_TOKEN この記事の前半で作成したSonarqubeのユーザートークン

Variables

ARGOCD_INSTANCE_URL ArgoCDのURL(https://は入れない)
SONARQUBE_URL SonarqubeのURL(https://を入れる)

これでGitHub Actionsで利用する変数の登録が完了しました。一旦前編はここで終了です。

おわりに

今回はGolden Path作成に向けた環境の事前準備を行いました。

次回は本題であるGolden Pathの中身を実装していきます。乞うご期待!

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。