見出し画像

CodePipelineを使ってflyway Migrationをしている話

小ネタなんですが、地味に手動でやっていたマイグレーションをCodePipelineに乗せて手動をやめた話を書きます。

こちらを読んでいるみなさんはDBマイグレーションってどうやっていますか?
結構手動でやったりしがちなんですがSSHやAWSのSystemManagerから入ってコマンド打つのはハードル少し高いですよね。

FundsではCodePipelineを使っているのでそのパイプラインの中に組み込んでみました。

どこで実行すべきか

RDSがPrivate Subnetにあり、エンドポイントもインターネットに公開していないため、CIサービスなどから実行は難しく、安全性の観点からしてもこの方法は検討していませんでした。
LambdaやECSも考えましたが、動作頻度や扱い易さからCodeBuildから行うことにしました。

実現した方法

コードとSQLファイルが入ったリポジトリで操作している前提です。
CodePipelineの中にSource→Build→Approval→Migration(アプリとは別のCodeBuild)→Deployの順で走ります。
アプリ用のbuildspec.ymlとは別にマイグレーション用のbuildspec_migration.ymlを用意して、このように書いてみます。

version: 0.2

env:
 variables:
   BUILD_IMAGE: "flyway/flyway:7.5.0"
   PATH: "/path/to/flyway_sql"
 secrets-manager:
   DB_USER: $SECRETS_ARN:username
   DB_PASSWORD: $SECRETS_ARN:password

phases:
 install:
   runtime-versions:
     docker: 18
 build:
   commands:
   - ls -vl $PATH | tee  
     - docker pull $BUILD_IMAGE
     - docker run --rm -v $(pwd)/$PATH:/flyway/sql $BUILD_IMAGE -user=$DB_USER -password=$DB_PASSWORD -url=$DB_URL info
     - docker run --rm -v $(pwd)/$PATH:/flyway/sql $BUILD_IMAGE -user=$DB_USER -password=$DB_PASSWORD -url=$DB_URL migrate

Auroraを使っているので、SecretsManagerにシークレットを納めることができます。こちらから秘匿情報を取得するようにして、CodeBuildのEnvironment設定にはSecretのARNだけ指定します。

はまったポイントなど

1. ディレクトリの場所をデバッグを仕込むなどして確認する

flyway infoはこれから反映するSQLバージョンのファイルの一覧が表示されます。ここでなぜかディレクトリにはファイルがあってもflyway infoの一覧に出てこないことがありました。

+-----------+---------+-------------------------------------------------------------+------+---------------------+---------+
| Category  | Version | Description                                                 | Type | Installed On        | State   |
+-----------+---------+-------------------------------------------------------------+------+---------------------+---------+
| Versioned | 1       | baseline                                                    | SQL  | 2019-01-04 14:23:57 | Success |
| Versioned | 2       | Create fund table                                           | SQL  | 2019-01-04 14:23:57 | Success |
:           :         :                                                             :      :                     :         :
:           :         :                                                             :      :                     :         :
| Versioned | 284     |                                                             | SQL  | 2021-01-19 02:00:35 | Success |
+-----------+---------+-------------------------------------------------------------+------+---------------------+---------+

こちらは単純にホスト側のディレクトリが指定のファイルの置き場所と合っていないため、flywayに認識されていませんでした。
`echo $(pwd)/$PATH |tee` などとして確認する必要がありました。flywayの `-X`オプションなどを入れても詳細に情報が出るのでわかりやすいかと思います。

2.Buildのブランチ指定を確認する

当たり前といえば当たり前なのですが、複数CodeBuildをCodePipelineに含めたことがなかったので、パイプラインの最初に指定したソースのブランチがアプリのビルドの次に行うマイグレーションも同じブランチでやるだろうと想定していました。
しかし、マイグレーションのCodeBuildでも指定のブランチを指定しないと、masterブランチの情報をとってきてしまうようでした。
ブランチごとにProjectを分けていたのでそれぞれにブランチの指定はマストでした。

まとめ

VPC内で実行しているため、立ち上がりは少し時間がかかりますが、Fundsの環境だと30秒くらいで終わっています。
flyway自体の実行時間は `execution time 00:00.090s` とあるので気になるものでもありません。(ファイル数と流すSQLにもよると思います。)

最近、DockerのPullにAnonymous制限がかかったので、CodeBuildの設定にDockerLayerCacheを入れています。
もし自動化を少し考えている場合は試してみるのもありかなと思います。