$30 off During Our Annual Pro Sale. View Details »

巨大 tfstate に立ち向かう技術

Hayato Kawai
November 13, 2024
340

巨大 tfstate に立ち向かう技術

HashkTalks: Japan 2024 での登壇資料です。

イベントページ: https://events.hashicorp.com/hashitalksjapan
アーカイブ (YouTube): https://www.youtube.com/watch?v=XaAuWXZ28lA

Hayato Kawai

November 13, 2024
Tweet

Transcript

  1. © 2024 Wantedly, Inc. 自己紹介 名前 Fohte (ふぉーて) 川井 颯人

    (Hayato Kawai) 所属 ウォンテッドリー株式会社 趣味 🎮 🎹 https://techbookfest.org/product/fqhYCspDK80WBrGWJkEkP8?productVariantID=gzf9 X203XXhW87rBQnRxW2 Vim 入門書の 同人誌を作りました
  2. © 2024 Wantedly, Inc. 究極の適材適所により、 シゴトでココロオドルひとを ふやすために Wantedlyはパーパス‧共感を軸にした、⼈と会社との出会いを2012 年から創出。 はたらくすべての⼈が共感を通じて「であい」「つながり」「つなが

    りを深める」ためのビジネスSNS「Wantedly」を提供しています。 1⼈でも多くの⼈がワクワクしたり、熱中してシゴトと向き合えるよ うな世界を実現するために、国境を超えて「はたらくすべての⼈の イ ンフラ」を創っていきます。 ウォンテッドリーの提供サービス
  3. © 2024 Wantedly, Inc. 次世代型 採用管理システム 採⽤プロセスの悩みを解決 途中辞退を防ぐための業務を効率化 • 繰り返しフローで候補者管理を⾃動化

    • 複数名の⾃動⽇程調整で80%時間を削減 多様化する採⽤プロセスに対応 • 最適な選考プロセスを⾃由⾃在に構築 • 多様なメンバーに適した権限 構造化⾯接で⾼精度の⾒極め可能 • 採⽤基準の標準化‧カスタマイズ • 各項⽬の評価を定量化 ウォンテッドリーの提供サービス (Wantedly Hire)
  4. © 2024 Wantedly, Inc. 今日持ち帰ってほしいこと • 巨大な tfstate はつらい •

    が分割するのも一筋縄ではいかない • 完璧を目指さず徐々に移行していこう
  5. © 2024 Wantedly, Inc. Wantedly を支えるインフラ環境 • アプリケーションは Amazon EKS

    上で 動いている • Google Cloud も 一部で利用 https://docs.wantedly.dev/fields/infrastructure/infrastructure
  6. © 2024 Wantedly, Inc. Terraform の利用箇所 青枠は Terraform で 管理している

    (つまりほとんどが Terraform 管理) https://docs.wantedly.dev/fields/infrastructure/infrastructure
  7. © 2024 Wantedly, Inc. Terraform の CI/CD: GitHub Actions &

    tfaction • ウォンテッドリーでは CI 環境として GitHub Actions を利用 中 • Terraform の CI/CD を GitHub Actions で実現する フレームワークである tfaction を利用している ◦ https://github.com/suzuki-shunsuke/tfaction ◦ tfaction さえ導入すれば GitHub 上で Terraform の運用フローが作れる
  8. © 2024 Wantedly, Inc. tfaction の紹介 • GitHub での開発フローに則って terraform

    plan/apply が できる ◦ PR を立てたら terraform plan が実行される ◦ PR merge 時に terraform apply される ◦ plan, apply 結果は PR にコメントされる https://suzuki-shunsuke.github.io/tfaction/docs/
  9. © 2024 Wantedly, Inc. tfaction の紹介 • monorepo に対応 ◦

    1 つのリポジトリ内に複数の tfstate (= terraform init するディレクトリ) を置ける ◦ それぞれのディレクトリに変更があったときだけ plan/apply される • terraform apply 失敗時のフローも用意されている ◦ https://suzuki-shunsuke.github.io/tfaction/docs/feature/follow-up-pr • import や state mv などもコード管理・CI/CD できる ◦ https://suzuki-shunsuke.github.io/tfaction/docs/feature/tfmigrate
  10. © 2024 Wantedly, Inc. Terraform の CI/CD: Renovate • Terraform

    本体や provider、tfaction などの更新に 追従するための仕組みとして Renovate を利用 • 利用しているバージョンを検知 => 更新があれば更新 PR を作成してくれる https://docs.renovatebot.com/
  11. © 2024 Wantedly, Inc. 言葉の定義: tfstate とはなにか • ここでは便宜上 "tfstate"

    を 「terraform init を実行するディレクトリ」とします ◦ *.tfstate というファイル (Terraform の state) がこの単位で作られること から "tfstate" と呼んでいます
  12. © 2024 Wantedly, Inc. Terraform ディレクトリ構成 • 単一リポジトリで管理 • aws/

    ◦ CloudFront や WAF など 複数アプリケーションで跨いで 利用するリソース • eks/ ◦ EKS の Cluster, Node など • monolith/ ◦ それ以外 https://docs.wantedly.dev/fields/infrastructure/infrastructure
  13. © 2024 Wantedly, Inc. このディレクトリ構成の課題 • monolith がとにかく巨大になった ◦ 先に述べたディレクトリ構成は明確な決まりがなかった

    ▪ 「とりあえず monolith に置く」が多発 ◦ resource 数は 1,000 をゆうに超える ◦ plan/apply に 5 分以上かかる 😇
  14. © 2024 Wantedly, Inc. monolith tfstate を分割する機運が生まれる • 障害対応等で迅速に apply

    したいときに plan/apply が遅 くて困る • configuration drift 発生時に apply できなくなる ◦ Terraform 外で変更が発生したときに、その変更が巻き戻らないように Terraform コードへの変更が必要 ◦ ちょっとした変更を加えたくても、まず drift を解消する手間がある
  15. © 2024 Wantedly, Inc. monolith tfstate を分割する機運が生まれる • どのリソースがどこに定義されているのかわからない ◦

    特に新しく参加したインフラメンバーにとって認知負荷が高い ◦ これもリソース定義が多すぎることが原因のひとつ
  16. © 2024 Wantedly, Inc. plan/apply はなんとか高速化できる、が… • 速度は並列数を上げると一定の改善ができた ◦ terraform

    plan/apply には -parallelism オプションがある ▪ デフォルト: 10 ▪ これを 30 など増やせばよい ◦ 5 分くらいが 2 分くらいまで短縮された 🎉
  17. © 2024 Wantedly, Inc. plan/apply はなんとか高速化できる、が… • が、今度は各サービスの API rate

    limit に引っ掛かる 問題が顕在化 ◦ 具体的には大量に ElastiCache 系のリソースを定義している箇所で Describe* 系の API が多数発行され rate limit に引っ掛かっていた ◦ API rate limit に引っ掛かると、大体の場合は時間を置いて plan/apply をやり直す必要があり、かなりの手間
  18. © 2024 Wantedly, Inc. 解決したい課題 • plan/apply を高速化したい • rate

    limit に引っ掛からないようにしたい • 人にとってわかりやすい構成にしたい
  19. © 2024 Wantedly, Inc. 課題にどう立ち向かうか • monolith tfstate を細かい単位で分割していく ◦

    tfstate を小さくすればその分 plan/apply 速度は改善するはず ◦ rate limit にも引っ掛かりにくくなるはず ◦ tfstate の分割単位を工夫すれば人にとって分かりやすくなるはず
  20. © 2024 Wantedly, Inc. tfstate 指針を決める tfstate の分割指針 • アプリケーションや

    サービスごとに tfstate を わける • 環境ごとに tfstate を わける 例 • visit/ ◦ sandbox/, qa/, prod/ • hire/ ◦ sandbox/, qa/, prod/ • datadog/ ◦ sandbox/, qa/, prod/
  21. © 2024 Wantedly, Inc. 分割は一筋縄ではいかない • 実際に分割するのはハードルが高い ◦ 1,000 以上のリソースを適切な粒度で分割する、というのは時間がかかる

    ▪ 数が多いと単に時間がかかる ◦ 「適切な粒度」というのも先の例に嵌らないものもあり難しい ▪ 困る例: 複数のアプリケーションから参照されている Aurora cluster は どう分割する? • =>「初めから完璧を目指さない」という方針で進める
  22. © 2024 Wantedly, Inc. 徐々に分割する • 直近の例: Wantedly Hire 系のリソース定義は

    hire/ 下に 置く • ただし必ず従わなくてもよい ◦ tfstate の新規作成が手間なら一旦 monolith tfstate に置いてもよい ◦ 「分割」はあくまでも困り事を解消するための手段なので、本来の仕事を優先する ◦ 分割によって困り事が増えるのは本末転倒
  23. © 2024 Wantedly, Inc. 徐々に分割する すでに monolith tfstate にあるリソースはどうする? •

    すべては分割せず、困ったものから tfstate を 分割していく
  24. © 2024 Wantedly, Inc. 徐々に分割する • 具体例: rate limit に引っ掛かりがちだった

    ElastiCache の定義のみ elasticache/ ディレクトリに切り出す ◦ 本来は ElastiCache が使われているサービスごとに分割したい ▪ (Wantedly Visit で使っている ElastiCache は visit 配下に置く、など) ◦ しかし「サービスごと」という分割の粒度を決めるのは、それはそれで大変 ◦ 直近の困り事の解決を優先して、一旦分割しやすい elasticache/ という粒度で分割 する
  25. © 2024 Wantedly, Inc. 分割して得られた嬉しさ • 「完璧を目指さない」という方針のため分割は道半ば • それでも直近の問題は解消された ◦

    5 分かかっていた plan/apply は 10 秒ほどで終わるようになった ◦ 分割したディレクトリで configuration drift が発生しても 他のディレクトリに影響がなくなった ◦ API rate limit に引っ掛からなくなった
  26. © 2024 Wantedly, Inc. ファイルの見通しもよくなった • monolith tfstate はファイル単位でも monolithic

    になっ ていた ◦ 例: ElastiCache cluster の定義はすべて elasticache.tf に置く ◦ 中には 4,000 行近くのファイルも…
  27. © 2024 Wantedly, Inc. Renovate PR を分割する • Renovate が作成する

    PR の分割単位はパッケージごと ◦ 例: AWS provider の更新 PR、Google Cloud provider の更新 PR、… • つまり複数 tfstate をまたいで 1 つの PR が作成される
  28. © 2024 Wantedly, Inc. Renovate PR を分割する これのつらいところ: • AWS

    provider の更新があると大量の tfstate を変更した PR が作られる ◦ 分割した tfstate ではほぼ全て AWS provider に依存しているため • 頻繁に & 大量に plan/apply されるため CI 時間も無駄 ◦ Renovate はベースブランチに更新があるとその更新を取り込むため、 頻繁に実行される
  29. © 2024 Wantedly, Inc. Renovate PR を分割する • 対策: Renovate

    PR を tfstate ごとに分割する ◦ renovate.json 例: { "packageRules": [ { "matchManagers": ["terraform"], "matchDatasources": ["terraform-provider"], "additionalBranchPrefix": "{{packageFileDir}}-", "commitMessagePrefix": "{{packageFileDir}}: ", }, ] }
  30. © 2024 Wantedly, Inc. 分割によって見えてきた新たな課題 • Renovate PR が多い ◦

    tfstate の数 × provider 等のバージョン更新の回数だけ PR が作成される ◦ 特に AWS provider は更新頻度も高く、利用している tfstate も多い • tfstate ごとに分けるほどでもないファイルの変更が困難 ◦ 例: tflint の設定ファイルは共通のルールを使いたい ◦ Renovate と同様に複数の tfstate をまたいだ変更になるため plan/apply の 回数が多くなる
  31. © 2024 Wantedly, Inc. 今日持ち帰ってほしいこと (再掲) • 巨大な tfstate はつらい

    • が分割するのも一筋縄ではいかない • 完璧を目指さず徐々に移行していこう