Tagbangers Blog

環境別のリソースを Bitbucket Pipeline を用いてデプロイする方法

弊社の一部プロジェクトでは Bitbucket Cloud を利用しています

Bitbucket Cloud には CI/CD ツールとして Bitbucket Pipeline が組み込まれています

Bitbucket Pipeline は通常、下記のようなフローを行うプロジェクトを想定して案内されています

  1. プロジェクトのビルド & テスト
  2. テスト環境へのデプロイ
  3. 本番環境へのデプロイ

一方で今回ご紹介するのは下記のような環境別にリソースを同一のリポジトリで管理しているプロジェクト向けのパイプラインです

  • Static Resource files (S3 にデプロイなど)
  • Kubernetes Manifest files
  • Terraform Template files

リポジトリ構成

下記のように環境別にディレクトリを用意して、コンテンツを管理します

.
├ stage # テスト環境用
│ └ ...
├ prod  # 本番環境用
│ └ ...
└ bitbucket-pipelines.yml

Bitbucket Pipeline は CI/CD で何を行うかを宣言的に行うため、リポジトリルートの bitbucket-pipelines.yml に記述をします

バージョン管理対象に含まれるため、ロールバックや編集履歴が追いやすい利点があります

今回達成させるデプロイフロー

  1. 開発者がメインブランチから作業ブランチを切って、リソースを更新
  2. メインブランチに向けて Pull Request を作成
  3. Pull Request をマージ
  4. 更新があったデプロイ先に対してデプロイ準備が自動で整う
  5. 開発者が同意を行い対象にリソースをデプロイする

Pipeline 記述内容

最終的な bitbucket-pipelines.yml は下記のようになります

pipelines:
  branches:
    master:
      - step:
          name: Before deployment
          clone:
            enabled: false
          script:
            - echo .
      - step:
          name: Deploy to Staging
          condition:
            changesets:
              includePaths:
                - stage/**
          trigger: manual
          deployment: Staging
          script:
            - # Write deploy command
      - step:
          name: Deploy to Production
          condition:
            changesets:
              includePaths:
                - prod/**
          trigger: manual
          deployment: Production
          script:
            - # Write deploy command

順を追って説明します

パイプラインの開始条件を定義

bitbucket-pipelines.yml を設定する

pipelines:
  branches:
    master:
      - step:

定義のルートプロパティとして pipelines を定義します

次に、どのタイミングでパイプラインを開始するか指定を行います

# 特定のブランチが更新されたときに開始
pipelines:
  default: # 指定されたブランチ以外の  push 時に開始
    - step:
  branches:
    master: # master ブランチの  push 時に開始
      - step:
    feature/*: # 'feature/' で始まるブランチの  push 時に開始
# プルリクエストの対象ブランチが更新された時に開始
pipelines:
  pull-requests:
    '**':
      - step:
# 手動・もしくはスケジュールで開始
pipelines:
  custom:
    sonar: # UI に表示されるパイプライン名
      - step:

いずれの条件の場合でも、Bitbucket Pipeline の UI から特定のブランチ・条件のパイプラインを開始することができます

今回はメインブランチにマージをした際に自動でパイプラインが開始されてほしいためブランチタイプとして master を指定しています

デプロイスクリプトを定義

- step:
    name: Deploy to Staging
    script:
      - echo 'Hello, World'
      - some-deploy-command execute

パイプライン内での処理は step という単位で区切られ、実行するコマンドを script に配列として定義します

今回の場合はデプロイする処理をこの中に記述します

ある程度決まった処理はパイプを用いることで簡略化できます

Bitbucket Pipelines でパイプを使用する

例えば AWS EKS への Kubernetes Manifest のデプロイの場合は下記のパイプが利用できます

Bitbucket Pipelines Pipe: AWS EKS run command

- pipe: atlassian/aws-eks-kubectl-run:2.2.0
  variables:
    AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
    AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
    CLUSTER_NAME: $CLUSTER_NAME
    KUBECTL_COMMAND: $KUBECTL_COMMAND

なお、環境変数はリポジトリの設定項目から指定できます

リポジトリ全体で参照する変数 

デプロイ環境ごとに参照する変数

ステップを Deployments に登録

デプロイを設定、監視する

- step:
    name: Deploy to Staging
    deployment: Staging
    script:

ステップに deployment プロパティをセットすることで実行後に Deployments 項目に履歴が登録されます




Deployments からは関連 Pull Request やファイル差分の確認ができます

ステップを手動で実行するまで保留

パイプライン トリガー

- step:
    name: Deploy to Staging
    trigger: manual
    deployment: Staging
    script:

trigger: manual を追加することでそのデプロイステップを明示的に実行するまで保留します

UI から deploy ボタンを押すとデプロイ前の確認画面が出るようになります

デプロイ先や差分などの最終確認を行うことができるため、慎重にデプロイを行いたい場合はこの定義をお勧めします

特定のファイルの差分がある場合のみステップを実行

Conditional steps and improvements to logs in Bitbucket Pipelines

- step:
    name: Deploy to Staging
    condition:
      changesets:
        includePaths:
          - stage/**

condition を定義することでステップの開始条件を指定できます

現在利用できるのは condition.changesets.includePaths のみとなり、対象ファイルを配列で指定します

指定したファイルが前回パイプラインが稼働してから差分がない場合はステップが自動的にスキップされるため、必要のないデプロイを防げます

今回の場合は環境ごとにディレクトリを分けているので、変更のあった環境のみデプロイを行わせるために指定を行っています

注意点

最初のステップに trigger: manual を設定することはできない

何故か仕様として設定できないため、今回は回避策として「何も行わない」ステップを定義しています

pipelines:
  branches:
    master:
      - step:
          name: Before deployment
          clone:
            enabled: false
          script:
            - echo . # 何もしない
      - step:
          name: Deploy to Staging

clone.enabled: false を定義することでリポジトリクローンの処理が省かれ、若干実行速度を短縮できます

デプロイステップを並列実行することはできない

parallel プロパティを用いることで複数ステップを並列実行することができます

並列ステップのセットアップまたは実行

例えば依存しない複数のモジュールのビルドを並列実行することで実行時間の短縮ができます(Bitbucket Pipeline では基本的にスケーラブルな Docker コンテナで実行されるため並列実行におけるパフォーマンスの劣化を気にしなくて良い)

pipelines:
  default:
    - parallel:
      - step:
          script:
            - echo 'モジュールA のビルド'
      - step:
          script:
            - echo 'モジュールB のビルド'

今回の場合テスト環境のデプロイと本番環境のデプロイはそれぞれ依存しないので、parallel を利用したいですが、これも仕様として deployment の場合のみ並列実行が行えません

そのため先にどちらかのデプロイが必要となります

対策として condition を入れて変更のないデプロイメントを自動省略できるようにしていますが、両方の環境のリソースを更新した場合は順にデプロイする必要があります

デプロイメントの定義順に沿ってステップを定義する必要がある

リポジトリのデプロイメント設定にてデプロイ環境の定義ができますが、ここの順番(TestStagingProduction)の順番に step の順番も定義しないとエラーになります

# この定義はエラーになる
- step:
    deployment: Production
- step:
    deployment: Staging

補足、改善点

デプロイ画面の差分表示はリポジトリ全体の差分として表示される

例えば、テスト環境のみのデプロイであっても本番環境用のディレクトリの差分が表示されてしまうため、混乱しないよう注意する必要があります

本番環境のデプロイの差分であるがテスト環境のファイルの差分も含まれる 

事前に静的なパイプライン定義を行ってからコミットをする

今回のようなリポジトリ内でパイプラインを宣言的に正義する方法では、コミットしてリポジトリにプッシュするまで結果が確認できない という特徴があります

これにより

  1. 定義ファイルを編集
  2. コミット & プッシュ
  3. パイプライン実行でエラー

の手順を繰り返すことが特に構築初期段階では多いです

一方でエラー内容で多い点として下記があげられます

  • 定義方法が間違っている
  • YAML の文法が間違っている

パイプラインツールではこういったケースに備えて設定ファイルの静的解析ツールを用意しているのもが多く、Bitbucket Pipeline にも存在します

Validator for bitbucket-pipelines.yml

上記のツールでは静的解析に加えてパイプラインの構築サポートも機能として含まれているため、活用すると構築の工数を節約できることが期待できます

Pull Request で検証デプロイを行う

「パイプラインの開始条件」で説明したように Pull Request 上で開始するパイプラインの定義が行えます

Terraform Template や Kubernates Manifest などの Dry-run が行えるリソースに関しては、事前にデプロイ検証が行えているとレビュワーがより安心してマージを行えるようになります

Pull Request 画面には Pipeline のステータスが表示されます

またマージできる条件として「Pipeline が成功していること」を追加できるため、検証済みでないとマージできないよう厳しく設定することも可能です

マージ前にチェックを提案または要求する

Bitbucket Pipeline には Pipeline が成功した後に自動マージを行う機能も提供しているため活用するとスムーズに運用が行えるでしょう

Automatic Merging When Builds Pass

必ずメインブランチからデプロイを行う

分岐したそれぞれのブランチからデプロイを行ってしまうと、他のユーザが異なるデプロイを行う際に意図しない差分が発生することにつながります

今回は master ブランチの更新時のみパイプラインが開始されるようにしていますが、UI からパイプラインを手動で開始する際はどのブランチでも開始することができるため注意が必要です

Preminum プランを用いている場合は、設定画面から特定のブランチ・ユーザのみデプロイを行えるよう設定が可能なのでご活用ください

Bitbucket Cloud Premium plan




master ブランチの更新を Pull Request からのみ許可させることをリポジトリ設定から行うこともできます

ブランチ権限の使用

最後に

Tagbangers は Atlassian のソリューションパートナーとして、今回紹介した Bitbucket Cloud も含め Atlassian 製品の導入についてのコンサルティング・環境構築・サポート・アドオンの開発を行っております

アトラシアンサポートサイト

興味のある方は是非お問い合わせください