Amazon Web Services ブログ

Amazon EKS で GitOps パイプラインを構築する

この記事は Building a GitOps pipeline with Amazon EKS (記事公開日: 2020 年 12 月 3 日) を翻訳したものです。

本記事は Weaveworks のコンテンツディレクターの Anita Buehrle による寄稿記事です。

このシリーズの第 1 部では、GitOps の歴史、その利点、およびその仕組みについて議論しました。GitOps とは何であるかを理解したので、アプリケーションのデプロイに Flux と Amazon EKS を使用して GitOps パイプラインを設定する方法について詳しく説明します。

AWS での GitOps に何が必要か?

アプリケーションのデプロイ用またはクラスターの構成用の基本的な GitOps パイプラインを作成するために役立つツールがあります。本番環境で実行している場合には、セキュリティを強化するためにベースイメージをスキャンする、追加のコンポーネントも必要になるでしょう。

コンポーネント 実装 備考
Amazon EKS eksctl マネージド Kubernetes クラスター。
Git リポジトリ https://github.com/weaveworks/guestbook-gitops アプリケーションとクラスターマニフェストファイルを含む Git リポジトリ。
CI システム GitHub Actions コードのテストとインテグレーション。CircleCI から GitHub Actions まで何でもかまいません。
CD システム Flux v2 クラスター <-> リポジトリの同期。
コンテナレジストリ Amazon ECR 任意のイメージレジストリで構いません。
シークレット管理 AWS Secrets Manager 必要に応じて AWS Secrets Manager や、Sealed SecretsVault を使用できます。今回の例では特に使用していません。

前提条件

次のサービスが必要です。

  • EKS クラスターを作成できる AWS アカウント
  • GitHub アカウント
  • Amazon ECR
  • Kubectl バージョン 1.18 以降
  • Kustomize

この例では、標準の Guestbook サンプルアプリケーションを EKS にインストールします。次に、ボタンのスタイルを変更し、GitHub Actions と GitOps を使用して EKS に変更をデプロイします。

Part 1: Guestbook アプリケーションのリポジトリを fork します

この手順には GitHub アカウントが必要です。

  • リポジトリを fork して clone します:weaveworks/guestbook-gitops
  • ECR のコンテナレジストリをセットアップした時にいくつかの認証情報と Flux で必要なデプロイキーをリポジトリに追加するので、リポジトリは手元に置いておきます。

Part 2: EKS クラスターを作成します

1. eksctl のアクセス権限を設定します

  • eksctl を実行する前に、CLI を認証して IAM 認証情報が適切に設定されていることを確認します。
  • ECR レジストリからイメージを pull するには、クラスターをセットアップするのと同じユーザーに対して、正しい IAM のアクセス権限を設定する必要があります。
  • コンソールまたはコマンドラインからこのアクセス権限を設定できます。
    • レジストリを作成およびイメージを push/pull するために、AWS 管理ポリシーの “AmazonEC2ContainerRegistryPowerUser” をセットする必要があります。

2. クラスターを立ち上げます

  • コマンドラインツールの eksctlダウンロードしてインストールするか、またはアップデートします。
  • . <(eksctl completion bash) を実行します。
  • eksctl create cluster を実行します。
  • クラスターが起動するまでしばらくかかります。
  • クラスターの作成が完了したら、以下を実行します。
kubectl get pods -A

次のような表示がされるはずです。

NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
kube-system   aws-node-284tq             1/1     Running   0          20m
kube-system   aws-node-csvs7             1/1     Running   0          20m
kube-system   coredns-59dfd6b59f-24qzg   1/1     Running   0          27m
kube-system   coredns-59dfd6b59f-knvbj   1/1     Running   0          27m
kube-system   kube-proxy-25mks           1/1     Running   0          20m
kube-system   kube-proxy-nxf4n           1/1     Running   0          20m

Part 2: ECR のリポジトリを作成し、GitHub Actions のワークフローをセットアップします

このセクションでは、GitHub Actions を使用して ECR レジストリと小さな CI パイプラインをセットアップします。アクションは git push で新しいコンテナを構築し、git-sha を使ってタグ付けし、ECR レジストリに push します。また、イメージタグの変更について Kustomize のファイルを更新してコミットします。新しいイメージがリポジトリに入ると、Flux は新しいイメージを通知して、クラスターにデプロイします。このフロー全体は、Flux を設定した後の次のセクションでより明らかになります。

1. ECR を開始します

クラスターが実行されているのと同じリージョンで ECR を開きます。guestbook リポジトリを作成します。

2. ECR 用のシークレットを指定します

ECR は暗号化されたコンテナリポジトリであるため、ECR との間で pull されるイメージはすべて認証する必要があります。fork した guestbook-gitops リポジトリの [Settings] → [Secrets] タブで ECR 用のシークレットを指定できます。これらは、新しいイメージをコンテナレジストリに push する前に、GitHub Actions のスクリプトで必要になります。
次の 3 つの GitHub シークレットを作成します。

AWS_ACCOUNT_ID
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY

AWS アカウント ID は AWS マネジメントコンソールまたは aws sts get-caller-identity から取得できます。アクセスキー ID とシークレットアクセスキーは ~/.aws/credentials ファイルにあります。

3. GitHub Actions のワークフローを設定します

リポジトリ内の .github/workflows/main.yml のワークフローを表示します。main.yml の 16-20 行目にある環境変数が適切に設定されていることを確認します。

16 AWS_DEFAULT_REGION: us-west-1
17 AWS_DEFAULT_OUTPUT: json
18 AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
19 AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
20 AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

16 行目は EKS クラスターが存在するリージョンです。これは ~/.aws/config 内のリージョン、または aws configure を実行したときに指定したリージョンと一致する必要があります。

訳注: このウォークスルーを実施するには以下の追加の修正が必要です。

  • fork したリポジトリの初期状態では GitHub Actions の実行が有効化されていないため、リポジトリの [Actions] タブで有効化してください。
  • .github/workflows/main.yml で AWS CLI v1 の非推奨コマンドで ECR にログインしようとして失敗するため、以下 2 点を修正してください。
    • envAWS_REGION: ap-northeast-1 を追加してください(リージョンは使用しているリージョンにあわせてください)。
    • name: Setup ECR のステップを以下に変更してください。
    - name: Setup ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1
  • deploy/frontend-deployment.yaml および deploy/kustomization.yaml に AWS アカウント ID とリージョンがハードコードされているため、ご自身の AWS アカウント ID およびリージョンに置き換えてください。
  • 修正後、commit および push してください。

Part 3: Flux をインストールしてリリースを開始します

Flux は Kubernetes クラスターを Git リポジトリなどのソース管理下にある構成と同期させて、デプロイする新しいコードがあるときに、その構成へ自動的に更新します。Kubernetes の拡張 API サーバーを使用して実現しており、Prometheus や Kubernetes エコシステムの他のコアコンポーネントとの統合が可能です。Flux はマルチテナンシーをサポートし、任意の数の Git リポジトリを同期します。

このセクションでは、guestbook-gitops リポジトリの変更を同期するように Flux をセットアップします。この例は、1 つのアプリケーションリポジトリを単一のクラスターに同期する方法を示す非常に単純なパイプラインですが、前述のように、Flux にはもっと多くの機能があります。Flux のすべての機能の概要については、この Flux v2 詳細情報のページを参照してください。

1. MacOS ユーザーの場合、Homebrew で Flux をインストールできます

brew install fluxcd/tap/flux

その他のインストールオプションの場合、Flux CLI のインストールを参照ください。

2. インストールした後、EKS クラスターが前提条件を満たしているかをチェックします

flux check --pre

成功すると、次のような表示が返されます。

► checking prerequisites
✔ kubectl 1.19.3 >=1.18.0
✔ Kubernetes 1.17.9-eks-a84824 >=1.16.0
✔ prerequisites checks passed

Flux は 1 つのディレクトリでのマニフェストの同期をサポートしていますが、YAML が大量にある場合は、Kustomize を使用してそれらを管理するほうが効率的です。Guestbook の例では、すべてのマニフェストがデプロイディレクトリにコピーされて、kustomization ファイルが追加されます。この例では、kustomization ファイルは、デプロイマニフェストの frontend イメージセクションに newTag ディレクティブを含んでいます。

images:
- name: frontend
  newName:guestbook
  newTag: new

前述のように、GitHub Actions スクリプトは、イメージが build されて push された後に、このファイル内のイメージタグを更新して、ECR で新しいイメージが使用可能であることを Flux に示します。

3. クラスターに対して Flux と他のコントローラーをインストールする事前準備をします

  • GitHub トークンを設定します。

Flux の reconciliation リポジトリを作成するには、リポジトリを作成する権限を持つ GitHub アカウントの個人アクセストークンが必要です。トークンは、repo 配下のすべての権限にチェックを付ける必要があります。トークンをコピーして、安全な場所に保管してください。

  • コマンドラインで GitHub の個人アクセストークンとユーザー名をエクスポートします。
export GITHUB_TOKEN=[your-github-token]
export GITHUB_USER=[your-github-username]

4. Flux の reconciliation リポジトリを作成します。この例では fleet-infra と名付けますが、お好みの名前で構いません

このステップでは、プライベートリポジトリが作成され、すべてのコントローラーが EKS クラスターにインストールされます。Flux でリポジトリをブートストラップするとき、リポジトリ内のサブディレクトリのみを指定して、複数のクラスターまたはロケーションに構成を apply することもできます。この例ではシンプルに、1 つのクラスター名を apply するパスにセットします。

flux bootstrap github \
  --owner=$GITHUB_USER \
  --repository=fleet-infra \
  --branch=main \
  --path=[cluster-name] \
  --personal

Flux バージョン 2 を使用すると、複数のクラスターと複数のリポジトリを簡単に操作できます。新しいクラスター構成とアプリケーションは、それぞれに新しいパスを指定して、同じリポジトリから apply できます。

ブートストラップが完了すると、次のようになります。

► connecting to github.com
✔ repository cloned
✚ generating manifests
✔ components manifests pushed
► installing components in flux-system namespace …..
deployment "source-controller" successfully rolled out
deployment "kustomize-controller" successfully rolled out
deployment "helm-controller" successfully rolled out
deployment "notification-controller" successfully rolled out
  • クラスターの flux-system の Namespace をチェックします。
kubectl get namespaces
NAME              STATUS   AGE
default           Active   5h25m
flux-system       Active   5h13m
kube-node-lease   Active   5h25m
kube-public       Active   5h25m
kube-system       Active   5h25m
  • 新しく作成されたプライベートリポジトリの fleet-infra を clone して、その中に cd します。
git clone https://github.com/$GITHUB_USER/fleet-infra
cd fleet-infra
  • guestbook-gitops リポジトリを fleet-infra リポジトリと結び付けます。
flux create source git [guestbook-gitops] \
  --url=https://github.com/[github-user-id/guestbook-gitops] \
  --branch=master \
  --interval=30s \
  --export > ./[cluster-name]/[guestbook-gitops]-source.yaml

ここで、[guestbook-gitops] はアプリケーションまたはサービスの名前、[cluster-name] はクラスター名、[github-user-id/guestbook-gitops] は fork した Guestbook リポジトリです。

  • 新しいリポジトリから ./deploy ディレクトリに apply するように Flux の kustomization を設定します。
flux create kustomization guestbook-gitops \
  --target-namespace=default \
  --source=guestbook-gitops \
  --path="./deploy" \
  --prune=true \
  --interval=1h \
  --export > ./[cluster-name]/guestbook-gitops-sync.yaml
  • すべての変更をリポジトリにコミットします。
git add -A && git commit -m "add guestbook-gitops deploy" && git push
watch flux get kustomizations

guestbook-gitops ソースと Flux の GitOps Toolkit コンポーネントの最新リビジョンが pull されてクラスターにデプロイされているのが確認できるはずです。

NAME            REVISION                                        SUSPENDED       READY   MESSAGE
flux-system     main/e1c2a084e398b9d36ce7f5067c44178b5cf9a126   False           True    Applied revision: main/e1c2a084e398b9d36ce7f5067c44178b5cf9a126
guestbook       master/35147c43026fec5a49ae31371ae8c046e4d5860e False           True    Applied revision: master/35147c43026fec5a49ae31371ae8c046e4d5860e

Guestbook のすべてのサービスがクラスターにデプロイされて実行していることをチェックします。

kubectl get pods -A

以下のような表示がされているはずです。

NAMESPACE     NAME                            READY   STATUS    RESTARTS   AGE
default       redis-master-545d695785-cjnks   1/1     Running   0          9m33s
default       redis-slave-84548fdbc-kbnj      1/1     Running   0          9m33s
default       redis-slave-84548fdbc-tqf52     1/1     Running   0          9m33s
flux          flux-75888db95c-9vsp6           1/1     Running   0          17m
flux          memcached-86869f57fd-42f5m      1/1     Running   0          17m
kube-system   aws-node-284tq                  1/1     Running   0          41m
kube-system   aws-node-csvs7                  1/1     Running   0          41m
kube-system   coredns-59dfd6b59f-24qzg        1/1     Running   0          48m
kube-system   coredns-59dfd6b59f-knvbj        1/1     Running   0          48m
kube-system   kube-proxy-25mks                1/1     Running   0          41m
kube-system   kube-proxy-nxf4n                1/1     Running   0          41m

Flux のトラブルシューティングの Tips

Flux の設定に問題がある場合は、これらのコマンドを実行してすべてのセットアップ方法を確認し、セットアップエラーのトラブルシューティングに役立てます。

flux get sources git
flux get kustomizations

Flux で実行できるすべてのコマンドを表示するには、次のコマンドを実行します。

flux --help

Flux バージョン 2 には多くの新機能があり、Flux バージョン 2 ドキュメントで自分で調べることができます。

5. Guestbook アプリに変更して git push でデプロイします

: 変更を加える前に Guestbook UI を確認したい場合は、php-redis/index.html ファイルにスペースを追加して Git に push することで、ビルドを開始します。

アプリのボタンを簡単に変更して Git に push しましょう。

php-redis/index.html ファイルを開き、15 行目を変更します。

<button type="button" class="btn btn-primary btn-lg" ng-click="controller.onRedis()">Submit</button>

変更後:

<button type="button" class="btn btn-primary btn-lg btn-block" ng-click="controller.onRedis()">Submit</button>

ボタンに変更を加えたら、git addgit commitgit push を実行してください。リポジトリの [Actions] タブをクリックして、パイプラインのテスト、ビルド、およびイメージのタグ付けを確認します。

次に、新しい frontend イメージがデプロイされていることを確認してください。

kubectl get pods -A
NAMESPACE     NAME                            READY   STATUS    RESTARTS   AGE
default       frontend-6f9b84d75d-g48hf       1/1     Running   0          95s
default       frontend-6f9b84d75d-ncqj6       1/1     Running   0          84s
default       frontend-6f9b84d75d-v5pfs       1/1     Running   0          107s
default       redis-master-545d695785-r8ckm   1/1     Running   0          58m
default       redis-slave-84548fdbc-nk4mf     1/1     Running   0          58m
default       redis-slave-84548fdbc-vvmws     1/1     Running   0          58m
flux          flux-75888db95c-pnztj           1/1     Running   0          61m
flux          memcached-86869f57fd-hhqnk      1/1     Running   0          61m
kube-system   aws-node-bcw7j                  1/1     Running   0          67m
kube-system   aws-node-gt52t                  1/1     Running   0          67m
kube-system   coredns-6f6c47b49d-57w8q        1/1     Running   0          74m
kube-system   coredns-6f6c47b49d-k2dc5        1/1     Running   0          74m
kube-system   kube-proxy-mgzwv                1/1     Running   0          67m
kube-system   kube-proxy-pxbfk                1/1     Running   0          67m

Guestbook アプリケーションを表示します

以下のコマンドを使用して、クラスターで実行されているアプリから URL を取得して、ブラウザーで Guestbook の frontend を表示します。

kubectl get service frontend

レスポンスは次のようになります。

NAME       TYPE        CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   ClusterIP   10.51.242.136   109.197.92.229     80:32372/TCP   1m

Flux をセットアップしてあるので、UI に変更を加えると、GitHub Actions を通じて変更を反映して、新しいイメージを build して ECR に push することができます。Flux は新しいイメージを検知して、変更をクラスターにデプロイし、ソフトウェア開発を加速させます。

クリーンアップ

Flux をアンインストールするには以下を実行します。

brew uninstall flux

クラスターを削除するには以下を実行します。

eksctl delete cluster --name [name of your cluster]

まとめ

これらの 2 部の投稿では、GitOps の概念とその起源について説明しました。そして、アプリケーションのデプロイのために GitOps パイプラインを統合する方法をお見せしました。これは GitOps を活用する方法の一例です。

翻訳はソリューションアーキテクトの一杉 (ひとすぎ) が担当しました。原文はこちらです。