【Terraform】コード作成〜クラウド環境に適用するまでの流れ

## はじめに
Terraformでのコード作成〜クラウド環境(AWS環境)に適用するまでの流れについて書きたいと思います。

:::note warn
Terraformのコード作成方法や環境構築等の準備については今回は省略します。
あくまでもクラウド環境にTerraformのコードを適用するまでの流れにフォーカスした内容になっています。
:::

## クラウド環境にコードを適用する迄のフロー
Terraformのコードを準備するところからコードの内容を反映する迄の一連の流れをフローにしました。

![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/f6739318-f37b-5a33-3edd-2df69f536711.png)


## 作業手順

### コード準備
Terraformのコードを用意します。

※今回使用するコードは以下になります。
[ec2_create_code](https://github.com/masato930/ec2_create_code)

こちらのコードで構築するAWSの構成は以下になります。
(AmazonLinux2にSSH接続をすることを目的に作成したコードになります。)

![Terraform-構成図.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/17df9d6f-696a-7947-0480-812a7666ca32.png)

### ワークスペース初期化
Terraform構成ファイルを含む作業ディレクトリを初期化するために以下コマンドを実行します。

```zsh:コマンド
terraform init
```

こちらのコマンドは、以下の場合に実行します。(何度でも実行可能)

- 新しいTerraformの設定を作成する場合
- GitHub等のバージョン管理ツールからTerraformのコードをcloneする場合

実行例は以下になります。

```zsh:実行例
% terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.22.0

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.
%
```

### フォーマットを整える
Terraformの設定ファイルのフォーマットを整えるために以下のコマンドを実行します。

```zsh:コマンド
terraform fmt
```

こちらのコマンドを実行すると、コードを綺麗にして読みやすくすることができます。

以下のように乱れているTerraformのコードがあるとします。

```terraform:terraform fmt実行前
resource "aws_key_pair" "keypair" {
  key_name   =      "${var.project}-${var.environment}-keypeir"
  public_key       =    file("./src/id_test_key.pub")

  tags = {
    Name    =      "${var.project}-${var.environment}-keypair"
    Project    = var.project
    Env     =     var.environment
  }
}
```

`terraform fmt`を実行すると、以下のように自動的にフォーマットしてくれます。

```terraform:terraform fmt実行後
resource "aws_key_pair" "keypair" {
  key_name   = "${var.project}-${var.environment}-keypeir"
  public_key = file("./src/id_test_key.pub")

  tags = {
    Name    = "${var.project}-${var.environment}-keypair"
    Project = var.project
    Env     = var.environment
  }
}
```

### 構文チェック
Terraformのコードの構文チェックを実施するために、以下のコマンドを実行します。

```zsh:コマンド
terraform validate
```

構文チェックに成功すると、以下のように表示されます。

```zsh:実行例
% terraform validate
Success! The configuration is valid.

%
```

構文チェックに失敗すると、以下のように表示されます。

```zsh:実行例
$ terraform validate
╷
│ Error: Reference to undeclared input variable
│ 
│   on ec2.tf line 9, in resource "aws_key_pair" "keypair":
│    9:     Name    = "${var.project}-${var.enviroent}-keypair"
│ 
│ An input variable with the name "enviroent" has not been declared. Did you mean "environment"?
╵
$
```

### クラウド環境適用前の確認
Terraformのコードをクラウド環境に適用する前に以下のコマンドを実行することで、インフラ構成の変更点を事前に確認することができます。

```zsh:コマンド
terraform plan
```

```zsh:実行例
% 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.server will be created
  + resource "aws_instance" "server" {
      + ami                                  = "ami-02c3627b04781eada"
      + arn                                  = (known after apply)
〜〜〜長いので省略〜〜〜
```


### クラウド環境への適用
最後に以下のコマンドを実行することで、Terraformのコードをクラウド環境に適用します。

```zsh:コマンド
terraform apply
```

```zsh:実行例
% 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.server will be created
  + resource "aws_instance" "server" {

〜〜〜省略〜〜〜

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  ← applyを実行する場合は「yes」、実行しない場合は「No」を入力

aws_key_pair.keypair: Creating...
aws_vpc.vpc: Creating...
aws_key_pair.keypair: Creation complete after 0s [id=Test-dev-keypeir]
〜〜〜省略〜〜〜

aws_route_table_association.public_rt: Creation complete after 0s [id=rtbassoc-0dcfc3f95cf89bd84]
aws_instance.server: Still creating... [10s elapsed]
aws_instance.server: Still creating... [20s elapsed]
aws_instance.server: Still creating... [30s elapsed]
aws_instance.server: Creation complete after 32s [id=i-052a91631cc5274c0]

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.
%
```

## 参考
- [Command: init](https://www.terraform.io/cli/commands/init)
- [Command: fmt](https://www.terraform.io/cli/commands/fmt)
- [Command: validate](https://www.terraform.io/cli/commands/validate)
- [Command: plan](https://www.terraform.io/cli/commands/plan)
- [Command: apply](https://www.terraform.io/cli/commands/apply)