Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Terraform Workspacesの弱点をcountやmovedでカバーしつつ開発を進めた話

trunkatree
September 14, 2023

Terraform Workspacesの弱点をcountやmovedでカバーしつつ開発を進めた話

2023/09/14 HashiTalks: Japan 2023 での発表スライドです。
https://events.hashicorp.com/hashitalksjapan

trunkatree

September 14, 2023
Tweet

More Decks by trunkatree

Other Decks in Programming

Transcript

  1. 自己紹介 株式会社ROBOT PAYMENT / SRE 遠藤 幹太 GitHub, X: @trunkatree

    最近は開発組織のスケールを支える基盤や仕組 みの構築に取り組んでいます 2
  2. 4

  3. 5

  4. サンプルコード(Terraform Workspacesを用いているコードの例) resource "aws_rds_cluster" "sample" { cluster_identifier = "sample-cluster-${terraform.workspace}" engine_version

    = "5.7.mysql_aurora.2.11.2" // 省略 } resource "aws_rds_cluster_instance" "sample" { count = terraform.workspace == "prod" ? 2 : 1 identifier = "sample-${terraform.workspace}-${count.index}" instance_class = var.rds["${terraform.workspace}.instance_class"] // 省略 } resource "aws_rds_cluster_parameter_group" "sample" { name = "sample-${terraform.workspace}" family = "aurora-mysql5.7" // 省略 } resource "aws_db_parameter_group" "sample" { name = "sample-${terraform.workspace}" family = "aurora-mysql5.7" // 省略 } 11
  5. コードを一時的にリファクタリングして対応する module に count を導入する 新/旧の2つのバージョンのmoduleを用意して、環境によって使い分ける ↑ moduleのバージョン管理をするようなもの module "database"

    { + count = // 省略 + source = "../modules/database" } * ローカルModuleのバージョンはコード全体のバージョン管理と一体となっているた め、ローカルModule単体ではバージョン管理できない https://developer.hashicorp.com/terraform/language/v1.3.x/modules/syntax#versi on 14
  6. 初期状態のコード ./database/main.tf module "database" { source = "../modules/database" } ./modules/database/main.tf

    resource "aws_rds_cluster" "sample" { cluster_identifier = "sample-cluster-${terraform.workspace}" // 省略 } ・・・ 15
  7. 対応の流れ 1. 【事前作業】 datababse module に count を導入する database-v2 module

    を作成する 2. 【Auroraアップグレード作業】(各workspaceにて) database module から database-v2 module に移行する terraform apply を実行する 3. 【事後作業】 不要となった database module を削除する database-v2 module を database module に名前変更する 16
  8. datababse module に count を導入する count を導入するとリソースアドレスにインデックスが付与されるため、terraform planの結果に差分が出てしまいます。そこで moved を併せて利用することで、planで

    差分を出さずにリファクタリングすることができます。 module "database" { + count = contains(["prod", "demo", "test1", "test2", "test3"], terraform.workspace) ? 1 : 0 + source = "../modules/database" } + moved { + from = module.database + to = module.database[0] + } 【事前作業】 18
  9. countのみ追加した場合: create/destroy の差分と認識されてしまう $ terraform plan ・・・ # module.database.aws_db_parameter_group.sample will

    be destroyed # (because module.database is not in configuration) - resource "aws_db_parameter_group" "sample" { ・・・ # module.database[0].aws_db_parameter_group.sample will be created + resource "aws_db_parameter_group" "sample" { ・・・ countと併せてmovedを追加した場合: 差分は0件 $ terraform plan ・・・ # module.database.aws_db_parameter_group.sample has moved to module.database[0].aws_db_parameter_group.sample resource "aws_db_parameter_group" "sample" { ・・・ Plan: 0 to add, 0 to change, 0 to destroy. ・・・ 【事前作業】 19
  10. database-v2 module を作成する Auroraアップグレード後のコードをこちらに用意しておきます。 $ tree -d | grep -e

    database -e modules ├── database ├── modules │ ├── database │ ├── database-v2 $ module "database" { count = contains(["prod", "demo", "test1", "test2", "test3"], terraform.workspace) ? 1 : 0 source = "../modules/database" } + module "database-v2" { + count = contains([], terraform.workspace) ? 1 : 0 + + source = "../modules/database-v2" + } 【事前作業】 20
  11. database module から database-v2 module に移行する Auroraアップグレード作業をAWSマネジメントコンソールから実施するとともに、 コード上では database module

    から database-v2 module に更新します。 "test1" の場合 ↓ module "database" { - count = contains(["prod", "demo", "test1", "test2", "test3"], terraform.workspace) ? 1 : 0 + count = contains(["prod", "demo", "test2", "test3"], terraform.workspace) ? 1 : 0 source = "../modules/database" } module "database-v2" { - count = contains([], terraform.workspace) ? 1 : 0 + count = contains(["test1"], terraform.workspace) ? 1 : 0 source = "../modules/database-v2" } 【Auroraバージョンアップ作業】(各workspaceにて) 22
  12. コードを更新した後、terraform state mv コマンドを実行し、移行作業を完了させま す。 使用する module を database-v2 に移行することが、コード上のアップグレード作業

    になります。 $ terraform state mv module.database[0] module.database-v2[0] Move "module.database[0]" to "module.database-v2[0]" Successfully moved 1 object(s). $ * 私たちが実施した際は terraform state mv コマンドで行いましたが、 tfmigrate などのツールを活用させていただくとPRベースな変更ができ、よりよいフローになり そうです。 【Auroraバージョンアップ作業】(各workspaceにて) 23
  13. terraform apply を実行する Aurora本体はAWSマネジメントコンソールを操作してアップグレードしましたが、 パラメータなどその他の設定は terraform apply コマンドで反映させます。 あわせてAuroraインスタンスの再起動なども行います。 $

    terraform apply これにてAuroraアップグレード作業は完了で、database-v2 module によって構成管 理している状態になりました。 【Auroraバージョンアップ作業】(各workspaceにて) 24
  14. 不要となった database module を削除する すべての環境で database-v2 module への移行が完了したので、不要となった database module

    と、count 導入時に追加した moved を削除します。 - module "database" { - count = contains([], terraform.workspace) ? 1 : 0 - - source = "../modules/database" - } - module "database-v2" { count = contains(["prod", "demo", "test1", "test2", "test3"], terraform.workspace) ? 1 : 0 source = "../modules/database-v2" } - moved { - from = module.database - to = module.database[0] - } 【事後作業】 26
  15. database module のコードもディレクトリごと削除しちゃいます。 $ tree -d | grep -e database

    -e modules ├── database ├── modules │ ├── database-v2 $ 【事後作業】 27
  16. database-v2 module を database module に名前変更する module やディレクトリの名前を変更してもともとのコードに近づけます。 count も不要となったので削除します。

    moved を追加しておくことによって、terraform plan で差分を出すことなくリファク タリングすることができます。 - module "database-v2" { - count = contains(["prod", "demo", "test1", "test2", "test3"], terraform.workspace) ? 1 : 0 - - source = "../modules/database-v2" - } + module "database" { + source = "../modules/database" + } + moved { + from = module.database-v2[0] + to = module.database + } 【事後作業】 28
  17. おまけ せっかくなので terraform state mv コマンドを実行してキレイにしておきます。 $ terraform state mv

    module.database-v2[0] module.database これで moved も削除することができます。 - moved { - from = module.database-v2[0] - to = module.database - } * moved は削除せずに残すことが推奨されています。今回の場合は、まわりの開発状 況を把握できている状況だったため、問題ないと判断し削除しました。 https://developer.hashicorp.com/terraform/language/v1.3.x/modules/develop/refa ctoring#removing-moved-blocks 【事後作業】 29
  18. まとめ Terraform Workspacesの弱点 = workspace間で構成に差異があるのは扱いづらい → module 単位でハンドリングすることで対応 moved によって

    terraform plan で差分を出さずにリファクタリングできる → 手作業ではなくPRベースで変更できる → 小さな単位でmainブランチにmergeできる → レビューが容易になる → 作業内容が明確になる → ミスを抑制できる 32