READYFOR Tech Blog

READYFOR のエンジニアブログ

EKS/Fargate + ArgoCD でボット環境を GitOps 化してみた話

こんにちは。READYFOR で SRE として働いている jedipunkz 🚀 と申します。👋

READYFOR では今後のサービス環境として AWS ECS の導入決めて現在作業中なのですが、ご存知の通り 2020 年現在の SRE / インフラ界隈の主なネタは Kubernetes が主流になっています。そこで、我々 SRE が管理しているボット環境 (今までは docker-compose で半自動化されていました) を EKS を使って GitOps 化しようということになり無事導入が出来たので、構成や技術要素について記したいと思います。

(この記事は個人ブログの内容とだいぶ被ります)

どんなボットが動いているの?

まず SRE チームがボット開発に用いてる言語は Go 言語です。主に aws-sdk-go を使ってボットを開発しています。私達はコミュニケーションツールとして Slack を使っているので Slack ボット化するためにボットフレームワーク slack-go を使っています。

f:id:readyfor:20210106160852p:plain

ただ、まだボットの数が少なく主に利用されてるのは Ansible を実行するモノです。開発環境へアプリをデプロイするのに Ansible を使っているためです。もうすぐ ECS 化するので役割はそろそろ終えるのですが...。 利点は開発者だけでなく非エンジニアの方が GitHub のブランチ上のアプリの動作をしたい際に Slack を使って簡単にアプリの動作ができるところです。また今後は自動化目的でもっと沢山のボットを開発していきたいです。

f:id:readyfor:20201227201630p:plain

EKS/Fargate vs EKS/EC2

EKS の利用を検討する際に Fargate タイプと EC2 タイプがあります。2020年初頭に評価した際には ALB Ingress Controller と HPA のための Metrics Server が正常に動作しない状態だったので、まだ EC2 タイプを選択すべきなのかな...とぼんやり考えたのですが AWS 的にも Fargate を推してる気もするし再度評価実施しました。結果ドキュメントもソフトウェアもだいぶ更新されていて ALB Ingress Controller も Metrics Server もあっけなく動作し、今回のボット環境も EKS/Fargte を選択しました。

(ちょっと余談) そもそもサービス環境はなぜ EKS でなく ECS?

AWS ECS の導入を始めようとしていると前述しましたが、なぜサービス環境には EKS ではなく ECS を選択したかというと、この両者で下記の観点で評価実施しました。

※ () 内はまだ未実施。

  • コード化
  • オートスケール
  • ロードバランサ
  • 機密情報の格納展開
  • CI/CD, GitOps
  • ロギング
  • メトリクス収集
  • モニタリング
  • カナリーリリース等のリリース方式
  • (バッチ)
  • (サービスメッシュ)

結果的にインフラをデプロイする主な機能 (特に ALB Ingress Controller, Metric Server) を時前で Pod として運用するのは運用コストが高い、という判断をしました。Pod の調子が悪いからロードバランサがデプロイできない!というのは辛いです。自分の務めている会社は少人数で運用コストを減らすという視点で技術を選択しているので今の時点では ECS を選択するのは必然でした。ECS であれば Terraform -> AWS API で確実に必要なインフラがデプロイ出来ますし。また Manifest を使って AWS インフラをデプロイするのも個人的には導入に懸念をもった点でした。自分たちの扱うインフラのコードが yaml ファイルになるという点です。Terraform コードであれば、リソース間の依存関係を人間が読む事も容易ですが単なる yaml ファイルになるとそれも難しくなりそうです。

また READYFOR ではメトリクス・ログ・サービス監視に Datadog を用いています。ECS との親和性は非常に高く Sidecar で Datadog Agent を起動することでサービス Pod のログ転送・メトリクス監視が容易でした。また私の同僚が検証し、先日の弊社のアドベントカレンダー でも記されていますが ECS + CodeDeploy + GitHub Actions の組み合わせで Blue Green デプロイが容易に行えた点は非常にメリットでした。問題があれば切り戻しも簡単です。また GitHub Actions で awscli を使っても良かったのですが Go 言語で ECS リソースを操作するコードを Lambda 化して GitHub Actions から叩くようにしました。これによって アプリエンジニアの方が PR を作ると同時に ECS 上にアプリをデプロイし GitHub PR 上に「この PR の内容でアプリをデプロイしました。URL は http://... です!」と言ったよう PR 中にコメントさせることが出来ました。

この辺りの EKS or ECS については後日 READYFOR Tech Blog でも記事にしようかと考えています。

ボット環境を GitOps 化する全体構成

さて本題に戻りますが、EKS でボット環境を GitOps 化した全体構成は下記のとおりとなります。

        (3 get manifest
        +----------------------------------------+
        |                                        |
+----------------+   (2      +----------------+  |
| GitHub Actions |---------> | ECR Repository |  |
+----------------+           +----------------+  |
+                            + (4 pull image     |
| (1 merge to master         |                   |
|                            +----------------+  |
|                            |      Bots      |  |
|                            +----------------+  |
|                            |     ArgoCD     |--+
+----------------+           +----------------+    +---------------+
|    Engineer    |           |   EKS/Fargate  |--->|  EFS Volumes  |
+----------------+           +----------------+    +---------------+

処理の流れは、下記のとおりです。

  • (1 Engineer がアプリ用 Git レポジトリの master ブランチへ Push
  • (2 GitHub Actions により Docker コンテナビルド, ECR への Push & Kustomize によりコンテナイメージタグが更新
  • (3 ArgoCD が GitHub 上の Manifest ファイルの更新をトリガに EKS へローリングデプロイ開始
  • (4 ArgoCD によって新たに指定されたイメージを ECR から Pull しデプロイ完了

Terraform による EKS, EFS, Kubernetes ALB Ingress Controller の構築

EKS, EFS はもちろんですが、Kubernetes のリソースである ALB Ingress Controller 周りのリソースも Terraform 化して構築しました。また御存知の通り現在 EKS では Pod 単位に AWS IAM Role の権限をマッピング出来る Service Account による RBAC が利用できます。ボットを稼働させる Pod はもちろん、ALB Ingress Controller Pod への権限付与もこの Service Account による RBAC を用いて権限付与しています。これで、Pod 内から AWS リソースに対しての操作を許可することが出来ます。なお、この RBAC は比較的新しめの AWS SDK であれば認証時に特になにかすること無く認証が通ります。

なお、ALB Ingress Controller のために Terraform で作成したリソースは下記のとおりです。

  • aws_iam_openid_connect_provider
  • tls_certificate
  • kubernetes_cluster_role
  • kubernetes_cluster_role_binding
  • kubernetes_cluster_role_binding
  • kubernetes_deployment

なぜ EFS を使っているか ?

EFS は 永続的なストレージとして利用しています。今後は不要になる可能性が高いのですが前述した Ansible を使ったボットは Playbook を収めた Git レポジトリにアクセスしてデプロイを実行します。コンテナに Git レポジトリを収めるのはコンテナイメージサイズが肥大化しますし良くないと判断しました。結果、EKS から EFS を Volume マウントして Ansible を実行します。また Ansible 以外のボットも環境ごとの情報を格納した yaml ファイルを扱うのですが、その yaml ファイルを EFS 上に Kubernetes Secrets として展開しています。

ArgoCD を選択した理由

ArgoCD が CNCF にジョインしたというニュースが今年の夏頃?ありました。また同時に検討していた Flux がちょうどメジャーバージョンアップをして、だいぶ利用方法やドキュメントが刷新されました。また一世代前のバージョンはメンテナンスモードに突入。新しいバージョンは利用方法が少し複雑化していましたし CLI は劇的に利用方法が変化していました。ということで GitOps をしたいという要望だけ満たせれば良いので CNDF の ArgoCD を利用することにしました。

ArgoCD はボットと同じ EKS クラスタ上にデプロイしました。UI は普段利用しないので Ingress は設定せず EKS Fargate Profile の稼働しているプライベートサブネット上で起動させました。ArgoCD アプリは下記の手順で作成します。

$ argocd app create hello --repo https://github.com/jedipunkz/no-exsist-bot-repo.git --path bots/hello/manifests/envs/dev --dest-server https://kubernetes.default.svc --dest-namespace infra-bot
$ argocd app set hello --sync-policy automated
$ arogcd app set hello --auto-prune

この操作で ArgoCD が GitHub 上の Manifests の変化に応じてボットのコンテナイメージを ECR から取得して GitOps を実現してくれます。

Kustomize で環境

下記のために Kustomize を導入しました。ArgoCD は勿論 Kustomize で構成された Manifest を認識出来ます。

  • 環境毎の Manifest をいい感じに環境分離
  • コンテナイメージの更新

具体的なディレクトリ構成は下記のとおりになります。

bots
└── ansible
    ├── Dockerfile
    ├── README.md
    ├── bot.go
    ├── go.mod
    ├── go.sum
    ├── main.go
    ├── manifests
    │   ├── base
    │   │   ├── bot-deployment.yaml
    │   │   ├── bot-svc.yaml
    │   │   └── kustomization.yaml
    │   ├── envs
    │   │   ├── dev
    │   │   │   ├── deployment.yaml
    │   │   │   └── kustomization.yaml
    │   │   └── prd
    │   │       ├── deployment.yaml
    │   │       └── kustomization.yaml
    │   └── manual
    │       └── secrets.yaml
    └── requirements.txt

GitHub Actions を用いた Docker ビルド, ECR イメージプッシュ, Kustomize Edit

GitHub Actions を使ってボットの追加・編集 PR をマージしたタイミングで

  • Docker ビルド
  • ECR へのプッシュ
  • Kustomize Edit をして Manifest に記しているコンテナイメージのタグを更新
  • コンテナイメージタグが修正された Manifest の変更内容を Git Commit & Push

をしています。GitHub Actions の処理としてはこれだけで、あとは ArgoCD が GitHub 上の Manifests の更新に反応して自動で GitOps してくれます。

まとめ

構成する技術要素としては以上です。先に述べましたが Kubernetes を SRE として運用することは昨今の SRE/インフラ界隈のトレンドを押さえるという意味で意味があることですし、今回数ヶ月ぶりに EKS を評価・検証して、技術として速いスピードで成熟しているのを実感しました。今後 EKS を本番サービスでも利用することもあるかもしれないです。ALB Ingress Controller, Metrics Server だけではなく ArgoCD も今年の2月に評価した際よりだいぶ完成度が増している気がします。

また今回はここ数ヶ月の EKS の基本的な動作の把握に留めましたが、今後は Kubernetes の周辺の技術を使った新しいアーキテクチャの理解と導入検討を考えてみたいと思っています。