🤖

既に出来ているAWSサービス環境にterraformを入れるときのサポートツールの話

2024/12/19に公開

アドベントカレンダー二回目だーい!!
昨日はこんどーさんの今年の振り返りでした。
https://adventar.org/calendars/11216

いやまぁ今年の一番のびっくりポイントはこんどーさんの結婚だったかもしれませんねぇ。
詳しく色々話を聞きたいのに!!そういう場がリモートだとない!!悲しい!!!
プライベートで遊ぶ事はあれど、こういう話ってなかなかねー、リモートだと出来ないですよねぇ。
まー素面だと話す方も聞く方も照れくさい所があったりするかもなので、
こういうときこそお酒の力を使いたい所。
つまり!東京に戻って!飲み会がしたい!!
しかし、諸事情があって!外に出れない!!

うがー

あ、諸事情については前の私のアドカレをご覧ください(#PR)
そんな事はいいんですよ
zennの記事なので技術記事です

スタート地点:IaCがなかった

転職先に、私は「インフラ一人目」として入社しました。(重要)
状況としてはIaCの仕組みが全く存在しない状態でした。
AWSでの構成はすべてコンソールで管理され、手作業で設定されている状況…。

Terraform導入への決断

選択する理由としては、もうterraformが現状のデファクトだと思っているからです。
CFnも選択肢としてはあるのですが、terraformの方が感覚にはあってます。

え、Ansibleでステートレスなインフラストラクチャの管理?何を寝ぼけた事を言ってるんですか。時代はterraformですよterraform。
Ansibleのクラウドパッケージより、人が多いterraformを使うのが……

ぎゃー!過去の自分に石を投げられるー……!
まぁ、そんな改宗もした2024年でした。

で、いざterraformを入れようとしたのですが。
何もない状態で、一からコードに起こすのは辛い。そこで、自動化ツールをいくつか試みたのです。

Terraformer

最初に試したのがTerraformerでした。既存のAWSリソースをスキャンし、TerraformのHCLコードを生成する便利なツールです。

  • メリット:手作業なしで既存のリソースをコード化できる。
  • デメリット:サポートされていないリソースがあり、完全にカバーすることができない。

とくに、terraformerは公式の自動生成があるというので使いたいリソースが使えない事があり、更新が止まってしまっていたのでした。
しかし、上半期ぐらいはterraformerとfujiwaraさんのtfstate-meargeでなんとかしてました。
https://sfujiwara.hatenablog.com/entry/tfstate-merge

Terraform公式のImport機能

Terraform自体にも既存リソースをコード化するためのimport機能があります。しかし、問題点がいくつかありました:

  • 管理外のリソースは見つけてこないといけない
    • 当時はリソースは自分で探して来ないといけなかった気がしました。
    • 大量に未管理のものがある当時は一個一個リソースを持ってくるのが大変でした。
  • 手動で保管が必要
    • 手動でリソースを入れても、そのあとで修正が必要でした。

自作ツールの検討

結果、自分の一番アジャストするものは自分で作ろう!として作る事に。

terraform-aws-migrator

https://github.com/cahlchang/terraform-aws-migrator
このツールは、既存のAWSリソースからTerraformコードを自動生成するためのものです。

使い方はとても簡単!

  • インストール
pip install git+https://github.com/cahlchang/terraform-aws-migrator.git
  • 管理外コードの探索
python -m terraform_aws_migrator --tf-dir ~/path/to/terraform

このような感じで見てくれてます。
(これは、自分のAWSアカウントに対してstateファイルなしの状態で走らせてるので、すべてのコードが未管理として検知されてます。実際未管理です)

morin $ python -m terraform_aws_migrator --tf-dir ~/git/path/to/terraform
Failed to load generator role: attempted relative import with no known parent package
⠋ Reading Terraform state... [00:00]Scanning directory for Terraform files: /path/to/terraform
Found local state files: ['/path/to/terraform/.terraform/terraform.tfstate']
Reading state file: /path/to/terraform/.terraform/terraform.tfstate
Successfully read state file: /path/to/.terraform/terraform.tfstate
Found S3 backend configuration: {'bucket': 'example-bucket', 'key': 'example.tfstate', 'region': 'ap-northeast-1', 'profile': 'example', 'encrypt': True}
Reading Terraform state... [00:00]Reading state file from S3 example-bucket/terraform.tfstate

Total managed resources found: 0
Found 0 managed resources in Terraform state
Found 0 managed resources in Terraform state [00:00]
Found 5 unmanaged Virtual Private Clouds [00:01]
Found 11 unmanaged Security Groups [00:01]
Found 10 unmanaged Lambda Functions [00:02]
Found 1 unmanaged table [00:03]
Found 4 unmanaged API Gateway REST APIs [00:04]
Found 1 unmanaged Route 53 Hosted Zones [00:06]
Found 5 unmanaged CloudFront Distributions [00:08]
Found 13 unmanaged S3 Buckets [00:13]
Found 19 unmanaged IAM Roles [00:27]
Found 19 unmanaged IAM Role Policies [00:27]
Found 12 unmanaged role_policy_attachment [00:27]
Found 5 unmanaged user [00:32]
Found 8 unmanaged user_policy_attachment [00:32]
Found 1 unmanaged IAM Groups [00:33]
Found 13 unmanaged IAM Policies [00:40]
⠹ Reading Terraform state... [00:40]
⠹ Collecting IAM Policies... [00:40]

Total execution time: [00:40]

Unmanaged AWS Resources:
========================================

Resource Summary:
- Found 4 unmanaged API Gateway REST APIs
- Found 5 unmanaged CloudFront Distributions
- Found 1 unmanaged table
- Found 11 unmanaged aws_security_group
- Found 5 unmanaged aws_vpc
- Found 1 unmanaged aws_iam_group
- Found 13 unmanaged IAM Policies
- Found 19 unmanaged aws_iam_role
- Found 19 unmanaged aws_iam_role_policy
- Found 12 unmanaged role_policy_attachment
- Found 5 unmanaged user
- Found 8 unmanaged user_policy_attachment
- Found 10 unmanaged Lambda Functions
- Found 1 unmanaged Route 53 Hosted Zones
- Found 13 unmanaged S3 Buckets

Detailed Resources:

API Gateway REST APIs:
  ID: XXXXXXX
  ARN: arn:xxxx

  ID: XXXXXX
  ARN: arn:xxxx

  ID: XXXXXXXXXX
  ARN: arn:xxxx
  Tags:
    managed_by: terraform
    repository: cahlchang/cocbotkp-discord-terraform-state

パスを通せばコマンドとしても使用可能です。

  • HCLの自動生成
    IAMロールなどの未管理リソースに対して、自動でコードを生成することも可能です:
python -m terraform_aws_migrator.main --tf-dir ~/path/to/terraform --generate --type aws_iam_role

(.venv) morin:work$ python -m terraform_aws_migrator.main --tf-dir ~/path/to/terraform --generate --type aws_iam_role

Total managed resources found: 0
Found 0 managed resources in Terraform state
Found 0 managed resources in Terraform state [00:00]
Collecting aws_iam_role, aws_iam_role_policy, aws_iam_role_policy_attachment...
Found unmanaged IAM Roles: example-role-1 [00:26]
Found unmanaged IAM Roles: example-role-2 [00:26]
#(中略)
⠙ Reading Terraform state...  [00:26]
⠙ Collecting AWS resources... [00:26]

Total execution time: [00:26]
resource "aws_iam_role" "example-role-1" {
  name = "example-role-1"
  path = "/"
  assume_role_policy = jsonencode({
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
})
  tags = {
    "any_key" = "any_value"
  }
}
#(以下にHCLが続く)

現状の課題と今後の展望

課題

  • 自動生成の対象はまだ一部(現在はaws_iam_roleのみ)。

今後の展望

  • 自動生成対象を広げる。AWS以外のリソースにも対応する可能性あり。
  • ツール名はAWS専用ではないので、今後必要に応じて変更するかも。

最後に:PR募集中!

このツールはまだ発展途上ですが、もし興味を持っていただけたらぜひGitHubでWatchやStarをお願いします!
また、アイデアや機能追加の提案があれば、PRも大歓迎です!

こんな時間になった理由

こんな時間まで書いているのは、ツールがまだ完成していないからです……。
アドベントカレンダーに向けてもうちょっと完成させたかった……。
ただ、terraformで一番時間かかるのはどれが使われているかどれが使われてないか、の判断とかなんですよね。
そういう事に時間が使えるようにするためにも、自動化とかで時間を出来るだけ効率良く使えるようにしたいものです。

AWSのIaCの効率化は私がエンジニア続ける限り必要になってくるので、引き続き開発を続けます!
(現状でも未管理リソース確認にはいいと思うんだ・・・)。
完成版を次の機会には紹介できるよう頑張ります!

この記事が、一つでもIaCになっていないコードを減らすようになれば、と思い!

アドベントカレンダーだった

さて、明日は……不知火ねーさんですね!
私の中で早くオフライン飲み会したい人ナンバーワンです……色々お世話になったのにずっと会えずに淋しい限り……
生存報告予定との事ですが、近況が気になります!

Discussion