FluxでGitOpsフローを構築してリリースした話


どういう話

先日リリースされたサービスで、自分がインフラとそれに付随するデプロイフローを構築したので、その備忘録。

あと、k8s周りを調べるとハンズオンが結構多かった印象だったので、実際にリリースまでしたものをアウトプットしたかった。

前提

Fargateを利用していますが、Fargate特有の話はあまりないです。
アプリケーションコードはGitHub, インフラコードはCodeCommitで管理しています。

※インフラコードをCodeCommitで管理している理由は、コード上に時々必要になる12桁のAWSIDは秘匿情報と考えており、
これを(privateとはいえ)GitHub上のリポジトリで管理するのは得策ではないと考えたためです。
CodeCommit上であれば、そもそもCodeCommitにアクセスするのにAWSの認証が必要なので安全であると考えています。
Fargateでは当時kubernetes-external-secretsなどを使うことができなかったための苦肉の策です。

出てくるもの

Flux GitOpsフローを構築するのに使っています(メインの話)
FluxCloud FluxからのイベントをキャッチしSlackに通知するためにつかってます
CircleCI CIとして使ってます

GitOpsって何?

WeaveWorksが提唱するデプロイフローです。

Guide To GitOps
コマンドラインツールを用いずにCI/CDを行うGitOpsとは?

超絶簡単に言うと、"全ての変更はGit上のコードとして履歴が管理される"フローです。

デプロイフロー

メインの話です。
GitOpsを提唱しているWeaveWorksが開発しているFluxを用いたフローを構築しました。

アプリケーションコードの場合

  1. githubにアプリケーションコードをcommitする
  2. CicleCIがECRにイメージをpush
  3. イメージのpushを検知したfluxがCodeCommit上のmanifestファイルを更新してcommit
  4. 更新されたmanifestファイルを元にfluxがk8sクラスターを更新する

インフラ(k8s)コードの場合

  1. CodeCommitにcommitする
  2. commitをfluxが検知し、manifestファイルを元にk8sクラスターを更新する

Flux設定

Fluxのdeployment.ymlは最初から色々なものが書かれていますが、触ったところは大きく2つです。

  1. gitリポジトリとECR設定
deployment.yml
args:
- --git-url=ssh://********************@git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/*********
- --git-branch=master
- --git-path=k8s/production
- --git-label=flux
- --git-user=flux
- [email protected]
- --registry-ecr-region=ap-northeast-1
- --registry-ecr-exclude-id=[]
  1. fluxcloud設定
deployment.yml
args:
- --connect=ws://fluxcloud

デプロイ方法

staging

developブランチにpushされると自動でstaging環境にデプロイされます。

circleci/config.yml
register_staging_image:
  jobs:
    - aws-ecr/build-and-push-image:
        executor:
          name: aws-ecr/default
          use-docker-layer-caching: true
        account-url: ECR_URL
        create-repo: false
        dockerfile: .dockerenv/Dockerfile.production
        path: .
        region: AWS_DEFAULT_REGION
        repo: STG_REPO_NAME
        tag: "${CIRCLE_SHA1}"
        filters:
          branches:
            only: develop

production

github上でmasterブランチに対してリリースタグを打つとproduction環境にデプロイされます。

リリースバージョンは1.0.0や1.0.0.0.1など、数字とピリオドの組み合わせのみにしてあります。

circleci/config.yml
register_production_image:
  jobs:
    - aws-ecr/build-and-push-image:
        executor:
          name: aws-ecr/default
          use-docker-layer-caching: true
        account-url: ECR_URL
        create-repo: false
        dockerfile: .dockerenv/Dockerfile.production
        path: .
        region: AWS_DEFAULT_REGION
        repo: PRD_REPO_NAME
        tag: "${CIRCLE_TAG}"
        filters:
          branches:
            ignore: /.*/
          tags:
            only: /[0-9]+(\.[0-9]+)+/

ロールバック

FluxがcodeCommit上の変更を検知してk8sクラスターを更新してくれるので、
codeCommit上で目当てのバージョンまでrevertするか、イメージタグを変更してcommitすると変更できます。

デプロイ通知

FluxCloudを用いてwebhookを通じてSlackにデプロイ通知を送信しています。

deployment.yml
        - name: SLACK_URL
          value: "https://hooks.slack.com/services/******/**********/**************"
        - name: SLACK_CHANNEL
          value: "channel"
        - name: SLACK_USERNAME
          value: "Production Deployment"
        - name: SLACK_ICON_EMOJI
          value: ":kyaru-chan:"
        - name: GITHUB_URL
          value: "https://ap-northeast-1.console.aws.amazon.com/codesuite/codecommit/repositories/**********"

総括

少し前まではcapistranoなどを使って手作業でデプロイしていたので、相当楽で便利になりました。
このフローを最初に作ってしまえばエンジニアは開発に集中できるし、デザイナーやコーダーといった方のコミットでも自動でstagingにデプロイされるので、ある意味エンジニアを開放しているのかもしれないです。

アプリケーション周りも頑張ったのでそっちも書くかもしれません