Amazon EKS, ArgoCD, GitHub Actionsを使用したCICDの構築

# はじめに
現在私が携わっているプロジェクトでは、ArgoCD,GitHub Actionsを使用して、EKS上に構築されているアプリケーションをデプロイしております。
どのように実現しているか紹介したいと思います。


# 概要
以下のプロセスでアプリケーションのデプロイを自動で行っております。

- アプリケーションのソースコードをGitHub上のリポジトリのブランチにマージ
- ブランチへのマージをトリガーにGitHub Actionsのワークフローが実行される
- 上記ワークフローの処理により、以下の処理が実行される
    - Docker Imageの作成
    - ECRへのImage Push
    - 別リポジトリで管理されているmanifest fileのimageタグを上記で作成されたImageのタグに更新 
- ワークフローの結果をSlack通知
- ワークフローによってArgoCD監視対象のmanifest fileが更新され、ArgoCDのAutoSync(自動同期)が実行される
- AutoSyncによって最新のmanifestがEKSにApplyされる
- 上記Applyにより、最新Imageでpodが起動し、API・画面の自動テストが実行される
- テストが正常に完了すれば、古いPodが削除され最新のPodに切り替わる
- 自動テストのレポート結果をS3に配置
- Slackで結果を通知


![CICD.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896507/2a0f1d43-4cbe-b10b-29ad-a649f67a543d.png)


# 詳細
### GitHub Actionsについて
使用しているGitHubのリポジトリがPrivate Repositoryで、接続IPが制限されている場合があると思います。
その場合は、[self-hosted runners](https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners)を利用し、EC2上でGitHub Actionsのワークフローを実行することでGitHub Actionsのワークフローの実行環境のIPを固定にすることができます。



### ArgoCDについて

ArgoCDでは、GitHub Repositoryの監視と、最新のmanifestのapplyを行います。
[ArgoCD導入方法](https://argo-cd.readthedocs.io/en/stable/getting_started/)

GitHub Repositoryの監視に関しては、以下のmanifest fileで設定可能です。
以下のようにExternalSecretを使用することでcredential情報をファイルに記載することなく設定できます。

[リポジトリ監視設定について](https://argo-cd.readthedocs.io/en/stable/user-guide/private-repositories/)
[ExternalSecretについて](https://qiita.com/araryo/items/27991699f20fb024bc24)


```
apiVersion: v1
kind: Secret
metadata:
  name: repo-app-manifest
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/xxx/xxx
---
apiVersion: kubernetes-client.io/v1
kind: ExternalSecret
metadata:
  name: private-repo-creds
  namespace: argocd
spec:
  backendType: secretsManager
  dataFrom:
    - argocd-manifest-credentials
  template:
    metadata:
      labels:
        argocd.argoproj.io/secret-type: repo-creds

```

### 自動テストについて

k8sのRolloutで指定できる[postPromotionAnalysis](https://argo-rollouts.readthedocs.io/en/stable/features/bluegreen/#postpromotionanalysis)という機能を使用し自動テストを実行しております。

AnalysisTemplateというリソースを作成し、postPromotionAnalysisの設定値に作成したAnalysisTemplateを指定することで、podデプロイ時にAnalysisTemplateに定義された処理を実行します。

例えば、以下のようにAnalysisTemplateでapiテストを実行するコンテナ(自作のコンテナです)を起動するジョブを定義します。

```
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  namespace: default
  name: api-test
spec:
  metrics:
  - name: api-test
    failureLimit: 1
    provider:
      job:
        spec:
          backoffLimit: 0
          template:
            spec:
              containers:
              - name: api-test
                image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/xxx:1.0
              restartPolicy: Never
```

そして、以下のようにpostPromotionAnalysisで上記のAnalysisTemplateのnameを指定することで、podデプロイ時にapiテストを実行するコンテナを起動します。そしてそのコンテナが正常終了すれば古いpodが削除され、最新のpodに切り替わりデプロイ完了となります。

```
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: demo-app
spec:
  template:
    metadata:
    spec:
      containers:
      - name: demo-app
        image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/xxx:latest
         :
         :
  strategy:
    blueGreen:
      autoPromotionEnabled: true
      activeService: demo-app
      postPromotionAnalysis:
        templates:
        - templateName: api-test
        :
        :
```

ちなみに、templateで指定するAnalysisTemplateは以下のように複数指定できます。

```
      postPromotionAnalysis:
        templates:
        - templateName: ui-test
        - templateName: api-test
```


AnalysisTemplateで起動するコンテナの処理の中では、自動テストの実行処理以外に、テストレポートのS3配置とテスト結果のslack通知を実装しており、テストの結果確認をslackから行うことが可能となっております。

S3に配置したレポートは、CloudFront経由で参照できるようにし、
テスト結果の概要(テストの実行件数や成功率など)とCloudFrontへのリンクをslack通知することで、開発者は結果をすぐに確認できます。