既存のAWSリソースを簡単にTerraformに落とし込めるTerraCognita

[Saleshub](https://saleshub.jp/info/company)でエンジニアをしております。
安田と申します。

今回は[TerraCognita](https://github.com/cycloidio/terracognita)というツールについて書いてみたいと思います。

AWSやGCPなどのクラウドサービスを利用されているエンジニアは多いと思います。
そしてこれらのサービスをWeb UI上で操作してアプリケーションのクラウド環境を構築している会社や個人も多いと思います。

# Web UIで構築された環境。後で何やったかわからない

その一方で今やクラウド環境はIaC(Infrastructure as code)で構築するのが当たり前でしょう！と言われたりします。実際、Web UIで構築された環境は、構築後時間が経つと「どうなってんだっけ、これ？」ってなったり、構築したメンバーが退職したりすると、引き継いだメンバーにとってトラップだらけのラビリンスになってしまったりします。

じゃあ、どうすればいいのか？
これに答えてくれていたのが、[Terraformer](https://github.com/GoogleCloudPlatform/terraformer)です。

# Terraformer

[手で作られた AWS リソースをできるだけ簡単に Terraform に落とし込む](https://developers.cyberagent.co.jp/blog/archives/33331/)
こちらの記事のタイトルでもわかりますように、Terraformerはクラウドリソースを簡単に Terraform に落とし込むことができるツールです。

Terraformerについては、上記の他にもたくさん記事があります。
[Terraformerを使ってTerraformに既存インフラのリソースをインポートする](https://beyondjapan.com/blog/2020/05/terraformer-import-existing-infrastructure/)
[Terraformerを使用して既存のAWS環境をエクスポートする](https://zoo200.net/export-aws-with-terraformer/)

じゃあ、もう新たに何か記事を書く必要はないんじゃね？となるかもです。
実は自分も上記のようなブログをみながら、このTerraformerも使ってみました。

なんですが、
[手で作られた AWS リソースをできるだけ簡単に Terraform に落とし込む](https://developers.cyberagent.co.jp/blog/archives/33331/)
の手順で言うと「Step4 Terraformer の tfstate をアップグレードする」のところで、作業の前方に見えている「面倒臭さ」にへこたれ、「いや、なんか他にもツールあるじゃろ。」と別のツール探しの旅に出てしまいました。

するとすぐに見つかったのが
[TerraCognita](https://github.com/cycloidio/terracognita)です。

# TerraCognita

上記tfstateのバージョン問題も

:::note info
Terracognita currently imports AWS, GCP, AzureRM and VMware vSphere cloud providers as Terraform (v1.1.9) resource/state.
:::

とあり、Terraformの対応バージョンもTerraformer(0.12)とは異なりだいぶ新しいです。

GithubのContributers数(18)はTerraformer(158)に及ぶべくもないですが、Fork数、Star数も申し分ありません。
Commitが2022/09から2023/01にかけてみられないのが少し気になりましたが、2023/02にはcommitが入っており、issueやPRも活発に見えます。
※上記の数字は2023/03/02時点の数字です。

で、早速使ってみました。自分は手作業で作られたAWS環境を取り込みたかったので、こちらのサイトを参考にしました。
[Import Existing AWS Infrastructure to Terraform](https://towardsaws.com/import-existing-aws-architecture-to-terraform-368b66c48275)

手順は以下の通りです（Mac M2環境）

# TerraCognita手順

## 前提条件
* Terraformがインストールされている
* AWSアカウントが用意されている
* aws cliが実行できる環境が用意されている

## TerraCognitaに関する手順
1\. brewでterracognitaをインストール
```shell
brew install terracognita
```

2\. コマンドを実行する
```shell
terracognita aws --hcl s3 --tfstate terraform.tfstate \
 --aws-default-region us-east-1 -i aws_s3_bucket
```
上記コマンドを実行するとresourcesディレクトリ内にAWSリソースがインポートされます。
オプションの説明は以下の通りです。

| オプション | 説明 | 
|:-----------|:------------|
| aws       | プロバイダ        |
| — hcl        | HCLが書き出されるフォルダ        |
| --tfstate       | tfstateが書き出されるファイル名        |
| — aws-default-region       | AWSのリージョン        |
| -i       | リソースを指定します。 このオプションを指定しない場合は、インポート可能なすべてのリソースをインポートします。 指定できるリソースはterracognita aws resourcesコマンドで確認することができます。      |

# インポートできるリソースの一覧

以下コマンドでawsのどのリソースをインポートできるか確認できます。
これらのリソースは-iオプションでインポート対象として指定することができます。

```shell
terracognita aws resources
```

出力は以下のような感じです。

```shell
~/w/saleshub ❯❯❯ terracognita aws resources
aws_instance
aws_alb
aws_alb_listener
aws_alb_listener_certificate
aws_alb_listener_rule
aws_alb_target_group
aws_alb_target_group_attachment
aws_api_gateway_deployment
aws_api_gateway_resource
aws_api_gateway_rest_api
aws_api_gateway_stage
aws_athena_workgroup
aws_autoscaling_group
aws_autoscaling_policy
aws_autoscaling_schedule
aws_batch_job_definition
aws_cloudfront_distribution
aws_cloudfront_origin_access_identity
aws_cloudfront_public_key
aws_cloudwatch_metric_alarm
aws_dax_cluster
aws_db_instance
aws_db_parameter_group
aws_db_subnet_group
aws_directory_service_directory
aws_dms_replication_instance
aws_dx_gateway
aws_dynamodb_global_table
aws_dynamodb_table
aws_ebs_volume
aws_ecs_cluster
aws_ecs_service
aws_ec2_transit_gateway
aws_ec2_transit_gateway_vpc_attachment
aws_ec2_transit_gateway_route_table
aws_ec2_transit_gateway_multicast_domain
aws_ec2_transit_gateway_peering_attachment
aws_ec2_transit_gateway_peering_attachment_accepter
aws_ec2_transit_gateway_prefix_list_reference
aws_ec2_transit_gateway_route
aws_ec2_transit_gateway_route_table_association
aws_ec2_transit_gateway_route_table_propagation
aws_ec2_transit_gateway_vpc_attachment_accepter
aws_efs_file_system
aws_eip
aws_eks_cluster
aws_elasticache_cluster
aws_elasticache_replication_group
aws_elastic_beanstalk_application
aws_elasticsearch_domain
aws_elasticsearch_domain_policy
aws_elb
aws_emr_cluster
aws_fsx_lustre_file_system
aws_glue_catalog_database
aws_glue_catalog_table
aws_iam_access_key
aws_iam_account_alias
aws_iam_account_password_policy
aws_iam_group
aws_iam_group_membership
aws_iam_group_policy
aws_iam_group_policy_attachment
aws_iam_instance_profile
aws_iam_openid_connect_provider
aws_iam_policy
aws_iam_role
aws_iam_role_policy
aws_iam_role_policy_attachment
aws_iam_saml_provider
aws_iam_server_certificate
aws_iam_user
aws_iam_user_group_membership
aws_iam_user_policy
aws_iam_user_policy_attachment
aws_iam_user_ssh_key
aws_internet_gateway
aws_key_pair
aws_kinesis_stream
aws_lambda_function
aws_launch_configuration
aws_launch_template
aws_lb
aws_lb_cookie_stickiness_policy
aws_lb_listener
aws_lb_listener_certificate
aws_lb_listener_rule
aws_lb_target_group
aws_lb_target_group_attachment
aws_lightsail_instance
aws_media_store_container
aws_mq_broker
aws_nat_gateway
aws_neptune_cluster
aws_rds_cluster
aws_rds_global_cluster
aws_redshift_cluster
aws_route53_delegation_set
aws_route53_health_check
aws_route53_query_log
aws_route53_record
aws_route53_resolver_endpoint
aws_route53_resolver_rule_association
aws_route53_zone
aws_route53_zone_association
aws_route_table
aws_s3_bucket
aws_security_group
aws_ses_active_receipt_rule_set
aws_ses_configuration_set
aws_ses_domain_dkim
aws_ses_domain_identity
aws_ses_domain_mail_from
aws_ses_identity_notification_topic
aws_ses_receipt_filter
aws_ses_receipt_rule
aws_ses_receipt_rule_set
aws_ses_template
aws_sqs_queue
aws_storagegateway_gateway
aws_subnet
aws_volume_attachment
aws_vpc
aws_vpc_endpoint
aws_vpc_peering_connection
aws_vpn_gateway
```

# リソース間の依存関係について

[手で作られた AWS リソースをできるだけ簡単に Terraform に落とし込む](https://developers.cyberagent.co.jp/blog/archives/33331/)の「Terraformer ハードコーディング問題」同様、TerraCognitaの場合も依存関係のあるリソースのIDがハードコードされているケースがありますので、そこは手作業で関連付けを書き換える必要があります。

なお、依存関係をTerraformの変数で解決した状態でインポートしてくれるケースもあるのですが、どのケースにおいてハードコードされ、どのケースで依存関係を解決した状態になるのかは、ちょっと自分は把握できておりません。どなたかこのあたり理解されている方いらっしゃっいましたらご教授いただけますとありがたいです。

# 使用感

自分はTerraCognitaからインポートしたリソースを使って、当該環境をIaC化するのではなく、同様の環境を新しい環境に構築し直す作業をしておりますが、TerraCognitaを利用したことで、かなりの作業を効率化できたと感じています。ありがたいの一言につきます。

一点、TerraCognitaで今一つだなと感じたのは、moduleオプションです。
リソースをモジュールとしてインポートできるのですが、全ての属性が変数化された状態でモジュール化されるので、再利用性は確保されている一方で、普通、大半の属性の値は共通でハードコードされていれば良いはずなので、あまり現実味のないモジュールが出来上がる印象を受けました。

逆にmoduleオプションなしでインポートして、手作業でモジュール化したほうが実際に使えるモジュールをより手数少なく作れるかなと思いました。

# 最後に

[Twitter](https://twitter.com/TakataNoToshi)もやっております。
当記事にご興味お持ちいただけた、もしくはご質問がある等ございましたら、フォローやDMください。

個人的には[Terraformer](https://github.com/GoogleCloudPlatform/terraformer)使ったことがある方に、TerraCognitaを使っていただき、その違い等記事化してくれたらすごく興味あります。なのでどなたかそんな記事書いてくださったら、ご一報いただけると嬉しかったりします。

# 参考にさせていただいた記事
[手で作られた AWS リソースをできるだけ簡単に Terraform に落とし込む](https://developers.cyberagent.co.jp/blog/archives/33331/)
[Terraformerを使ってTerraformに既存インフラのリソースをインポートする](https://beyondjapan.com/blog/2020/05/terraformer-import-existing-infrastructure/)
[Terraformerを使用して既存のAWS環境をエクスポートする](https://zoo200.net/export-aws-with-terraformer/)
[Import Existing AWS Infrastructure to Terraform](https://towardsaws.com/import-existing-aws-architecture-to-terraform-368b66c48275)

※記事内にて引用させていただきました。参考ページの著者の皆様に感謝しております。