Teche Note
1043 文字
5 分
TerraformでHasuraをHerokuにデプロイ

モチベが脆弱なので、趣味開発のアウトプットをかましていきます

解決したい問題#

「Herokuになんと、ワンクリックでデプロイ出来ちゃいます!!」という売り文句。

いったい何がどうデプロイされてて、ワンクリックした結果何が起きてるか怖いこと、ありませんか?

ありますね。Terraformでリライトしましょう。

完成品の.tfは最後にまとめて載せます

CI/CDはTerraform Cloud#

1人で使う分には無料、かつTerraformの実行環境やtfstate保存場所を考えずに済むので採用してみました。

Automate Terraform with GitHub Actions の記事をそのままなぞると、

  1. Terraformのリポジトリに変更をpushするとterraform planし、plan結果をPRにコメントしてくれる
  2. マージしたらapplyが走る

までできます。

workflow

Terraform内部で使うSecretはTerraform Cloud上で登録、

Terraform CloudのAPI tokenはリポジトリのSecretに登録することになります。

Herokuまわり#

Herokuアカウントを作成し、API tokenを払い出してTerraform Cloudに登録しましょう。

なお、今回はHerokuにDockerをデプロイすることになるので、

resource "heroku_app" の中で stack = "container"

を定義してやる必要があります。ref

また、デプロイするリソースの置き場としてHasuraが管理しているGitHubのurlを指定していますが、

tagを打たないとデプロイできない(?)っぽいがオリジナルにtagがない & オリジナルがちょっとstaleなので、

forkして自分のリポジトリにタグを打って管理することにしました。

一部抜粋

resource "heroku_app" "foobar" {
    name   = "foobar"
    region = "us"
    // for docker
    stack  = "container"
}

resource "heroku_build" "foobar" {
  app        = heroku_app.foobar.id

  source {
    // fork of https://github.com/hasura/graphql-engine-heroku
    url     = "https://github.com/mihirat/graphql-engine-heroku/archive/v0.1.0.tar.gz"
    version = "v0.1.0"
  }
}

DBはaddonとして追加できるので、postgresを追加します。

無料目的なのでhobby-devを忘れずに。

# Create a database, and configure the app to use it
resource "heroku_addon" "db" {
  app  = heroku_app.foobar.name
  plan = "heroku-postgresql:hobby-dev"
}

また、Hasura側でGraphQLのadmin secretなどが必要になるので、 環境変数の設定も同時に行います。

変数の中身も同じくTerraform Cloudで定義。

resource "heroku_app_config_association" "foobar" {
  app_id = heroku_app.foobar.id

  sensitive_vars = {
    HASURA_GRAPHQL_ADMIN_SECRET = var.hasura_admin_secret
    HASURA_GRAPHQL_JWT_SECRET   = var.hasura_jwt_secret
  }
}

TerraformでBEを管理するのはどうなんだ問題はあるんですが、

Hasuraの更新を頻繁に行うことはないと判断し、いったんTerraformに寄せています。1人月だし。

Hasura周り#

Hasuraでは、GUIでぽちぽちDBスキーマを編集した操作をmigrationファイルに保存し、 それを別環境でCLIにて再現することが可能です。ref

devで試行錯誤したスキーマをprodに反映するために、リポジトリにmigration結果を残しておきます。

1人開発じゃなかったら、localで試行錯誤したmigrationをdev / prodに反映していくべきでしょうか。

prodにapplyするのはCIで設定して、tagうちで発火するなどにすると良さそう。

一人なのでそこまでしてないですが。

ちなみに今回リポジトリを増やすのが面倒だったので、Terraform管理リポジトリに hasura/ を生やしてます。

HasuraのリソースをいじっただけなのにTerraform用のGitHub Actionsが発火するのが嫌だったので、

GitHub Action で特定のディレクトリ配下に変更があったときのみワークフローを実行する を参考にして設定をいじりました。

最終成果物#

こんな感じ。

locals {
  app_name = "sample-api-dev"
}

resource "heroku_app" "sample" {
  name   = local.app_name
  region = "us"
  stack  = "container"
}

resource "heroku_addon" "sample_db" {
  app  = heroku_app.sample.name
  plan = "heroku-postgresql:hobby-dev"
}

resource "heroku_build" "sample" {
  app = heroku_app.sample.name

  source {
    url     = "https://github.com/mihirat/graphql-engine-heroku/archive/v0.1.0.tar.gz"
    version = "0.1.0"
  }
}

resource "heroku_app_config_association" "sample" {
  app_id = heroku_app.sample.id

  sensitive_vars = {
    HASURA_GRAPHQL_ADMIN_SECRET = var.hasura_admin_secret
    HASURA_GRAPHQL_JWT_SECRET   = var.hasura_jwt_secret
  }
}

resource "heroku_formation" "sample" {
  app        = heroku_app.sample.name
  type       = "web"
  quantity   = 1
  size       = "free"
  depends_on = [heroku_build.sample]
}

まとめ#

  • 無料範囲でサーバーだけでなくCI/CDまで全部できるの素晴らしいですね!
  • Hasuraは面白い。開発が早くてアプデ追従大変そう