はじめてのPluralith~EC2の構成図作成偏~

## はじめに
業務でAWSの構成の一部をTerragruntを使用して管理しているのですが、構成が複雑になってゆくにつれてコードを読んで構成を理解するのが難しい、意図した構成になっているか視覚的になっていないので分かりづらいという問題がありました。
そんなときにPluralithを見つけたので使ってみたいと思います。

前回インストール偏ということでインストールを実施したので
今回はTerraformでEC2を作成するファイルを作成し、作成したEC2をもとにPluralithを使用して構成図を作成してみたいと思います。
Terraform初心者のため一部以下書籍内の「TerraformではじめるAWS構成管理」の手順を参考にして実施しました。
 - [ソフトウェアデザイン 2022年1月号](https://www.amazon.co.jp/o/ASIN/B09M552FPJ/gihyojp-22)

## やりたいこと
Pluralithを使ってAWS環境の構成図を楽に作成したい！

## 環境
OS：Windows11 Pro
Terraform：v1.5.2
pluralith CLI Version： 0.2.2
pluralith Graph Module Version： 0.2.1
AWS CLI：2.4.23

## 前回行ったこと
前回はTerraform、Pluralith、AWS CLIのインストールを行いました。
詳細は以下を見ていただければと思います。
 - [はじめてのPluralith ~インストール編~](https://developer.hashicorp.com/terraform/downloads)


## TerraformでEC2を作成してみる
### 1.クレデンシャルの設定:
 AWSマネジメントコンソール上から「AdministratorAccess」ポリシーがアタッチされたアクセスキーを作成します。
アクセスキーと作成方法の詳細について公式ドキュメントは以下参照。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey

公式では無いのですが、こちらも分かりやすかったのでおすすめです。

https://soypocket.com/it/aws-iam-acceskey-create/


作成ができたら`aws configure`コマンドを実行し、作成したアクセスキーを入力し、デフォルトのリージョンに東京リージョンを指定します。

その後、`aws sts get-caller-identity`コマンドを実行して設定したUserId、Account、Arnが出力されることを確認します。
問題無く表示できたので続いてTerraformのコードを書いてみます。

### 2.コードの実装:
今回はお試し用にAmazon Linux 2023 AMIのt2.microタイプのEC2を作成してみます。
以下main.tfファイルの内容です。

```terr:main.tf
resource "aws_instance" "learn_pluralith" {
  ami           = "ami-08c84d37db8aafe00"# Amazon Linux 2023 AMI
  instance_type = "t2.micro"

  tags = {
    Name = "learn_pluralith"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
```
resourceブロックにAWSインスタンスの情報、providerブロックに使用するクラウドプロバイダの情報を記述します。
amiにはEC2のAMIにAmazon Linux 2023 AMIを設定し、インスタンスタイプにt2.microを指定しています。
タグは特に設定しなくても問題無いのですが、Pluralith学習用ということでlearn_pluralithと設定しています。
そして、クラウドプロバイダにAWSを指定し、東京リージョンを設定しています。

EC2インスタンス作成に必要なterraformファイルの作成ができたので次はTerraformの実行を行います。

### 3.初期化:
最初に実行する際は初期化をする必要があるので`terraform init`コマンドを実行します。
   ```
 PS C:\Users\ユーザー名\workspace\learn_pluralith> terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.13.0...
- Installed hashicorp/aws v5.13.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
   ```
コマンドの実行が成功したようです。
フォルダの方を確認すると以下のようにファイルが追加されていました。


learn_pluralith/
│
└─ .terraform\providers\\...\\terraform-provider-aws_v5.13.0_x5.exe
│
└─ .terraform.lock.hcl
│
└─ main.tf


### 4.実行内容の確認
続いて、`terraform plan`コマンドを実行してmain.tfファイルに記述した内容が問題無いか確認します。

   ```
 PS C:\Users\ユーザー名\workspace\learn_pluralith> terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.learn_pluralith will be created
  + resource "aws_instance" "learn_pluralith" {
      + ami                                  = "ami-08c84d37db8aafe00"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_lifecycle                   = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "learn_pluralith"
        }
      + tags_all                             = {
          + "Name" = "learn_pluralith"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + vpc_security_group_ids               = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if   
you run "terraform apply" now.

   ```

特にエラーは発生しておらず、EC2のAMIやインスタンスタイプ、タグ情報が想定通りになっていることが確認できました。
次は実際に実行して環境に反映してみます。

### 5. 環境への反映
実際にAWS環境に反映するためには`terraform apply`コマンドを実行します。
   ```
PS C:\Users\ユーザー名\workspace\learn_pluralith> terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.learn_pluralith will be created
  + resource "aws_instance" "learn_pluralith" {
      + ami                                  = "ami-08c84d37db8aafe00"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_lifecycle                   = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "learn_pluralith"
        }
      + tags_all                             = {
          + "Name" = "learn_pluralith"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + vpc_security_group_ids               = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.learn_pluralith: Creating...
aws_instance.learn_pluralith: Still creating... [10s elapsed]
aws_instance.learn_pluralith: Still creating... [20s elapsed]
aws_instance.learn_pluralith: Still creating... [30s elapsed]
aws_instance.learn_pluralith: Creation complete after 32s [id=i-00e372ff3399e558f]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

   ```
途中までは`terraform plan`コマンド実行時と同様の内容が出力され、yesを入力するよう求められます。
今回は想定通りの内容なのでyesと入力します。
すると、新たにterraform.tfstateファイルが作成されました。
EC2インスタンスの作成ができたようです。

AWSのマネジメントコンソールから作成したEC2を確認してみます。

### 6.マネジメントコンソールから作成したEC2を確認

![スクリーンショット 2023-08-18 181139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/4b0add1f-72ef-ce12-dc3d-2538060642fa.png)

無事作成できています！
では、お待ちかねの構成図を作成してみます。


## pluralithで作成したEC2の構成図を作成してみる
構成図の作成は`pluralith graph`コマンドを実行します。
   ```
PS C:\Users\ユーザー名\workspace\learn_pluralith> pluralith graph 
⠿ Initiating Graph ⇢ Posting Diagram To Pluralith Dashboard

→ Authentication
  ✔ API key is valid, you are authenticated!

→ Plan
  ✔ Local Execution Plan Generated  
  ✔ Local Plan Cache Created  
  ✔ Secrets Stripped
  - Cost Calculation Skipped

→ Graph
  ✔ Local Diagram Generated  
  ✔ Diagram Posted To Pluralith Dashboard

  → Diagram Pushed To: https://app.pluralith.com/.../pluralith-local-project/runs/.../

   ```

構成図の作成が成功すると、
learn_pluralithフォルダ直下に.pluralithディレクトリが追加されます。
learn_pluralith/
│
├─.pluralith
│   │
│   ├─pluralith.cache.json
│   │
│   ├─pluralith.plan.bin
│   │
│   └─pluralith.state.json
│
├─ .terraform\providers\\...\\terraform-provider-aws_v5.13.0_x5.exe
│
├─ .terraform.lock.hcl
│
└─ main.tf

また、最後にURLが出力され、Pluralithの画面にリダイレクトします。

![スクリーンショット 2023-08-21 190045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/b76a2d0a-e24d-ec3c-bf82-608664d6ac39.png)

![スクリーンショット 2023-08-21 190158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/fd72c9b1-3b6f-293f-76d4-1e041e309a01.png)

EC2だけなので寂しいですが構成図ができていますね。

構成図はPDF形式とPNG形式でエクスポートできるようなのですが、
今回はPNG形式で出力してみます。
![スクリーンショット 2023-08-21 190540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/ef8b2ca9-5dc2-9354-249b-1f1e58e3f948.png)



すべてチェックした状態で出力すると以下のように出力されました。
![project_pluralith-local-project%2Frun_3077753%2Frun_3077753_1692612370127.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/99ba24ad-34c4-8e95-08e6-1c499502737f.png)

どうせならそれぞれチェックを入れた場合の違いも見てみたいので出力してみます。

 * Changesのみチェックを入れた場合
![project_pluralith-local-project%2Frun_3077753%2Frun_3077753_1692612407799.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/4b20ec28-12e5-c784-9f94-c29880c7cf51.png)


 * Driftのみチェックを入れた場合
![project_pluralith-local-project%2Frun_3077753%2Frun_3077753_1692612429444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/44a3c0b4-3f98-ef79-02d9-974b6f3ea75d.png)


 * Costsのみチェックを入れた場合
![project_pluralith-local-project%2Frun_3077753%2Frun_3077753_1692612455485.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/2657432a-8586-669d-adfb-c170843dff65.png)


タグが表示できてるのはもちろんのこと、エクスポート実行時に指定したversionと出力した日付も表示されています。


## お片付け
作成したEC2環境をそのままにしておくと課金され続けてしまうので、`terraform destroy`コマンドを実行してEC2インスタンスを終了させます。
destroy実行時も削除対象の環境の情報が表示され、yesを入力するよう求められます。
こちらも想定通りの内容なのでyesと入力します。
   ```
  PS C:\Users\ユーザー名\workspace\learn_pluralith> terraform destroy
aws_instance.learn_pluralith: Refreshing state... [id=...]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the 
following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_instance.learn_pluralith will be destroyed
  - resource "aws_instance" "learn_pluralith" {
      - ami                                  = "ami-08c84d37db8aafe00" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:...:instance/i-00e372ff3399e558f" -> null
      - associate_public_ip_address          = true -> null
      - availability_zone                    = "ap-northeast-1a" -> null
      - cpu_core_count                       = 1 -> null
      - cpu_threads_per_core                 = 1 -> null
      - disable_api_stop                     = false -> null
      - disable_api_termination              = false -> null
      - ebs_optimized                        = false -> null
      - get_password_data                    = false -> null
      - hibernation                          = false -> null
      - id                                   = "インスタンスID" -> null
      - instance_initiated_shutdown_behavior = "stop" -> null
      - instance_state                       = "running" -> null
      - instance_type                        = "t2.micro" -> null
      - ipv6_address_count                   = 0 -> null
      - ipv6_addresses                       = [] -> null
      - monitoring                           = false -> null
      - placement_partition_number           = 0 -> null
      - primary_network_interface_id         = "network_interface_id" -> null
      - private_dns                          = "private_dns" -> null
      - private_ip                           = "private_ip" -> null
      - public_dns                           = "public_dns" -> null
      - public_ip                            = "public_ip" -> null
      - secondary_private_ips                = [] -> null
      - security_groups                      = [
          - "default",
        ] -> null
      - source_dest_check                    = true -> null
      - subnet_id                            = "subnet_id" -> null
      - tags                                 = {
          - "Name" = "learn_pluralith"
        } -> null
      - tags_all                             = {
          - "Name" = "learn_pluralith"
        } -> null
      - tenancy                              = "default" -> null
      - user_data_replace_on_change          = false -> null
      - vpc_security_group_ids               = [
          - "sg-00bb2eea8f818d4e7",
        ] -> null

      - capacity_reservation_specification {
          - capacity_reservation_preference = "open" -> null
        }

      - cpu_options {
          - core_count       = 1 -> null
          - threads_per_core = 1 -> null
        }

      - credit_specification {
          - cpu_credits = "standard" -> null
        }

      - enclave_options {
          - enabled = false -> null
        }

      - maintenance_options {
          - auto_recovery = "default" -> null
        }

      - metadata_options {
          - http_endpoint               = "enabled" -> null
          - http_protocol_ipv6          = "disabled" -> null
          - http_put_response_hop_limit = 2 -> null
          - http_tokens                 = "required" -> null
          - instance_metadata_tags      = "disabled" -> null
        }

      - private_dns_name_options {
          - enable_resource_name_dns_a_record    = false -> null
          - enable_resource_name_dns_aaaa_record = false -> null
          - hostname_type                        = "ip-name" -> null
        }

      - root_block_device {
          - delete_on_termination = true -> null
          - device_name           = "/dev/xvda" -> null
          - encrypted             = false -> null
          - iops                  = 3000 -> null
          - tags                  = {} -> null
          - throughput            = 125 -> null
          - volume_id             = "volume_id" -> null
          - volume_size           = 8 -> null
          - volume_type           = "gp3" -> null
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.learn_pluralith: Destroying... [id=...]
aws_instance.learn_pluralith: Still destroying... [id=..., 10s elapsed]
aws_instance.learn_pluralith: Still destroying... [id=..., 20s elapsed]
aws_instance.learn_pluralith: Destruction complete after 30s

Destroy complete! Resources: 1 destroyed.

   ```
無事EC2インスタンスを終了できました！

![スクリーンショット 2023-08-18 211627.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/3212af15-f49d-1cee-98f2-0fa063ca0acd.png)


## 所感
改めて、TerraformはコードでAWS環境を作成すると構成内容が確認しやすく、コードさえ書くことができれば環境作成と削除がコマンド一行でできるのは楽で良いなと思いました。
また、Pluralithを使用した構成図の方もコマンド一行ですぐ作成できるのはうれしいですね。

ちなみに、EC2を削除した後でもpluralith graphを実行してから48時間以内は図が確認できますし、48時間経過してしまった後でも再度pluralith graphを実行すればまた図が確認できます。
ローカルでも十分便利な印象です。

リージョンだけでなく費用も表示できるようだったので、もう少し他のサービスも使用したAWS環境を作って一定時間動かした後の構成図も作成してみたくなりました。

## 参考
 [ソフトウェアデザイン 2022年1月号](https://www.amazon.co.jp/o/ASIN/B09M552FPJ/gihyojp-22)

https://nekopunch.hatenablog.com/entry/2021/12/20/115731

https://soypocket.com/it/aws-iam-acceskey-create/

https://docs.pluralith.com/docs/get-started/run-locally/