今回は以前のGitHub Flowの構成例に続き、GitLab Flowの実現を目指した例を考えました。
なお、今回は前回と大部分同じ構成なので、説明を省いている箇所があります。
GitLab Flowとは
GitLab Flowも開発ワークフローの一種で、以下のようなルールに従って開発を行います。
- 開発はmasterからfeatureブランチを作成して行う
- featureブランチでの開発後、Merge Requestを提出
- レビュー実施後、問題なければmasterブランチへマージ
- masterブランチからステージング環境へデプロイ
- ステージング環境で確認後、masterからpre-prodブランチへマージ
- pre-prodブランチからpre-production環境へデプロイ
- pre-prodからprodブランチへマージ
- prodブランチからprod環境へデプロイ
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を適用する想定です。
※参考:
今回も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