TECHSTEP

ITインフラ関連の記事を公開してます。

【メモ】AWS CodeCommit / CodeBuild + Flux を使ったGitLab Flowの構築

今回は以前のGitHub Flowの構成例に続き、GitLab Flowの実現を目指した例を考えました。

なお、今回は前回と大部分同じ構成なので、説明を省いている箇所があります。

GitLab Flowとは

GitLab Flowも開発ワークフローの一種で、以下のようなルールに従って開発を行います。

  1. 開発はmasterからfeatureブランチを作成して行う
  2. featureブランチでの開発後、Merge Requestを提出
  3. レビュー実施後、問題なければmasterブランチへマージ
  4. masterブランチからステージング環境へデプロイ
  5. ステージング環境で確認後、masterからpre-prodブランチへマージ
  6. pre-prodブランチからpre-production環境へデプロイ
  7. pre-prodからprodブランチへマージ
  8. prodブランチからprod環境へデプロイ

f:id:FY0323:20220224220011p:plain

GitLab Flowではmasterブランチのほかに、デプロイする環境用のブランチを用意します。ステージング環境で動作を確認した後、別の環境用ブランチへマージを行い、それぞれのブランチから環境へのデプロイを行います。hotfixによるバグ対応は、masterブランチで確認後、hotfixブランチを別ブランチへマージすることで対応します。

GitLab Flowの利点として、本番環境へのデプロイのタイミングを制御できること、各環境でテスト済みであることが保証できること、などが挙げられます。GitHub Flowでは、featureブランチをマージするたびに本番環境へデプロイ出来ることを想定しますが、リリース時間をコントロールできないようなアプリケーション(例:iOSアプリケーションなど)には適応が難しい場合があります。またソースコードをマージするのと別のタイミングにリリースを行いたい場合も、GitHub Flowでは難しくなります。

一方、コミット先のブランチを誤ると、誤って別の環境にデプロイされてしまうこと、GitHub Flowに比較するとフローが複雑であることが、欠点として考えられます。GitLab Flowではデプロイする環境ごとにブランチを分けているので、マージする先のブランチを間違えてしまうと、いきなり本番環境へのデプロイが発生してしまう可能性があります。これを防ぐため、ブランチに対する操作を制限する、などの設定を行うことが必要です。

※参考:

全体像

今回のパイプラインの全体像は以下の通りです。前回の構成とほぼ同じですが、FluxによるEKSへのデプロイ先が複数存在し、それぞれブランチと紐づいている点が違います。

GitLab Flowは codecommit-cd というKubernetesマニフェスト用のリポジトリに対して適用しています。なお codecommit-ci というアプリケーション用リポジトリは、前回と同様GitHub Flowを適用する想定です。

※参考:

f:id:FY0323:20220224215359p:plain

今回もEKSへのデプロイはFluxを利用しました。ただし、Fluxで利用する機能は、環境によって変更しています。

staging環境は、CIでコンテナイメージをビルド・プッシュしたのをトリガーに、自動的にアプリケーションをデプロイします。一方pre-prod・prod環境は、それぞれブランチへマージが行われたのをトリガーに、アプリケーションのデプロイを行います。そのため、staging環境では、CodeCommitリポジトリ・ECRレジストリをモニタリングするためのリソースを、pre-prod・prod環境ではCodeCommitリポジトリをモニタリングするリソースを作成します。

なお、今回はすべての環境で同じマニフェストファイルを利用しています。実際は環境ごとに異なる設定を導入することが多いですが、今回は Deployment / Service だけを使うシンプルな構成のため、共通のファイルを使うことにしました。

実際の開発フローは以下のような流れを想定しています。今回の新規追加分は 太字 で示しています。

  • 開発者はアプリケーションの機能追加・修正のためにmainブランチからfeatureブランチを作成する
  • featureブランチ上で開発を行い、mainブランチに対するPRを作成する
  • PRの作成を検知して自動テストが実行される
  • テストに合格したらレビューを依頼し、修正などを経てmainブランチへマージする
  • mainブランチへマージされると、コンテナイメージのビルドを実行する
  • 新しいコンテナイメージがPushされるのを検知し、マニフェストのイメージタグの書き換えと、ステージング環境への自動デプロイが実行される
  • ステージング環境での動作確認を完了後、mainブランチからpre-prodブランチへのPRを作成・レビュー依頼をする
  • pre-prodブランチへマージをすると、pre-prod環境への自動デプロイが実行される
  • pre-prod環境での動作確認を完了後、pre-prodブランチからprodブランチへのPRを作成・レビュー依頼をする
  • prodブランチへマージをすると、prod環境への自動デプロイが実行される

開発の流れ

ここでは追加した部分だけ追記します。

ステージング環境での動作確認を完了後、mainブランチからpre-prodブランチへのPRを作成・レビュー依頼をする

pre-prod環境用のマニフェストファイルに修正を行い、mainブランチからpre-prodブランチへのPRを作成します。マニフェストファイルの修正は、コンテナイメージタグの変更を想定します。

pre-prodブランチへマージをすると、pre-prod環境への自動デプロイが実行される

mainブランチからpre-prodブランチへマージを行うと、マニフェストファイルの変更をFluxが検知して、pre-prod環境への自動デプロイを実行します。

pre-prod環境での動作確認を完了後、pre-prodブランチからprodブランチへのPRを作成・レビュー依頼をする

pre-prod環境向けと同様、prod環境用のマニフェストファイルを修正し、PRを作成します。

prodブランチへマージをすると、prod環境への自動デプロイが実行される

prodブランチへマージを行うことで、prod環境への自動デプロイを実行します。

環境構築

今回の環境構築は、前回のものと大部分重なっているため、差分だけ紹介しています。

CodeCommit / CodeBuildの作成

今回は以下のマニフェストファイルを使用しました。前回と比べ、承認ルールテンプレート、IAMポリシーの追加をしています。ここでは追加した分だけ載せています。

sample-resources.yaml

  IAMPolicy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties: 
      Description: prohibit direct push to codecommit
      Path: /
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Deny
            Action: 'codecommit:GitPush'
            Resource: '*'
            Condition:
              "StringEqualsIfExists":
                "codecommit:References": # 対象のブランチを追加
                  - "refs/heads/main"
                  - "refs/heads/pre-prod"
                  - "refs/heads/prod"
              "Null":
                "codecommit:References": 
                  - "false"
(中略)
 
  # Approval Rule Template
  RuleTemplate:
    Type: Community::CodeCommit::ApprovalRuleTemplate
    Properties:
      Name: !Ref RuleTemplateName
      Description: test rule
      Content:
        Version: "2018-11-08"
        DestinationReferences: # 対象のブランチを追加
          - "refs/heads/main"
          - "refs/heads/pre-prod"
          - "refs/heads/prod"
        Statements:
          - Type: "Approvers"
            NumberOfApprovalsNeeded: 1
            ApprovalPoolMembers:
              - "*"

Fluxのインストール

EKSクラスターを作成後、各環境ごとにFluxをインストールします。

今回ステージング環境には前回と同じリソースの作成をしますが、pre-prod / prod環境では不要なリソースは作成せず、以下のものを作成します。

  • GitRepository
  • Kustomization

使用するマニフェストファイルは以下の通りです。GitRepository で指定するブランチ名を変更しています。

---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
  name: codecommit-cd
  namespace: flux-system
spec:
  interval: 1m
  url: https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/codecommit-cd
  ref:
    branch: pre-prod # ブランチ名を変更
  gitImplementation: libgit2
  secretRef:
    name: https-credentials
---
apiVersion: v1
kind: Secret
metadata:
  name: https-credentials
  namespace: flux-system
type: Opaque
data:
  username: <base64 encoded username>
  password: <base64 encoded password>
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: codecommit-cd
  namespace: flux-system
spec:
  interval: 5m0s
  path: ./manifest
  prune: true
  sourceRef:
    kind: GitRepository
    name: codecommit-cd
  validation: client