Terraformを始めよう【インフラエンジニアへの道1日目】

## 背景（読まなくてもいい）
普段はデータエンジニアをしています。（データ加工をチミチミチミチミしています…。）
スキルアップについて考えたときにデータサイエンス領域よりは、インフラサイドに関心が高いので、「インフラエンジニアへの道」と題してインフラエンジニアがやってそうなかっこいいことを学んでいきます。
### 出来るようになりたいこと
* TerraformでAWSの環境（VPC, EC2, ALB, RDS）を構築 する
* Docker + Kubernetesでフルスタックのアプリをデプロイ する
* GitHub ActionsやArgoCDを使ってCI/CDパイプラインを構築 する
* 監視ツール（Grafana, Prometheus）を使ってダッシュボードを作る
* 障害シナリオを作ってSLOを考えたり、カオスエンジニアリングのテストをする

## この記事内での目標
* まずはTerraformを使ってみる。具体的には、TerraformからEC2インスタンスを作って破壊します。
この過程で、Terraformのファイルの作成方法、Terraformの基本的なコマンド（`terraform init`、`terraform plan`、`terraform apply`、`terraform destroy`）を理解していきます。

### 環境
* OS: Windows 10 (WSLを使用)
* WSLバージョン: Ubuntu 20.04
* tfファイルはVSCodeで記述

### 参考文献
https://amzn.asia/d/admqFPN

## 1. （下準備）AWSにTerraform用のユーザを作成
1. AWSのコンソールからIAMを開いてユーザを作成。
Step1：ユーザーの詳細を指定
    ユーザー名：terraform
Step2：許可を設定
    ポリシーを直接アタッチする：`AdministratorAccess`を付与
Step3：確認して作成

2. アクセスキーを作成
作ったユーザー（terraform）を選択し、「セキュリティ認証情報」タブを開く
→アクセスキーを作成
    > コマンドラインインターフェイス (CLI)
    このアクセスキーを使用して、AWS CLI から AWS アカウントへのアクセスを有効化しようとしています。

これを選択して作成します。csvをダウンロードしておきます。

## 2. tfenvを使ってTerraformをインストール
### tfenvを使うといいこと
Terraformは活発に開発が進められているため、構築中や運用中にバージョンが上がってしまうことがあります。そのため`tfenv`というバージョンマネージャを使ってバージョンを切り替えられるようにしておくと便利です。
実際のプロジェクトで複数人でTerraformを使用する場合、担当者同士でバージョンを揃えてTerraformを利用するのが望ましいです。Terraformのstate情報には最後に ```apply``` したTerraformの ```version``` が書き込まれており、一度適用したバージョンを使っているとより新しいバージョンでしか適用できなくなります。複数人で異なるTerraformのバージョンを使っていると古い人だけ```apply``` できない、ということが発生します。
また、個人で複数プロジェクトを担当する場合においてもバージョン管理は重要になります。例えば、新しいプロジェクトで最新Terraformを利用していく形にすると、プロジェクトごとに異なるバージョンのTerraformを保持しなければなりません。Terraformは基本的に後方互換を有していますが、メジャーバージョンアップで基本構文が大きく変わるケースもあります。そういった課題があるので、プロジェクトごとにならんかの形でTerraformのバージョンを明記し、Terraform自体も任意のタイミングでバージョンを切り替えてオペレーションしていく必要があります。

### 手順
1. tfenvをインストール
    ``` sh
    git clone https://github.com/tfutils/tfenv.git ~/.tfenv
    echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc
    source ~/.bashrc
    ```
2. Terraformの最新バージョンをインストール
    ``` sh
    tfenv install latest
    ```
エラーが出ました。
```sh
    Not instructed to use Local PGP (/home/saki/.tfenv/use-{gpgv,gnupg}) & No keybase install found, skipping OpenPGP signature verification
    /home/saki/.tfenv/libexec/tfenv-install: line 287: unzip: command not found
    Tarball unzip failed
```
tfenvがTerraformのインストールを試みる際に、unzipコマンドが見つからなかったことが原因です。unzipは必要なツールなので、インストールする必要があります。
```sh
    sudo apt update
    sudo apt install unzip
```
これでunzipがインストールされます。もう一度Terraformをインストールしてみます。
インストールしたバージョンを確認します。
```sh
    terraform -v
    Terraform v1.11.3
    on linux_amd64
```

## 3️. AWS CLIのインストール
1. 必要な依存パッケージをインストール
    ```sh
    sudo apt update
    sudo apt install unzip curl
    ```
2. AWS CLIのインストール
    ```sh
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    ```
3. ダウンロードしたZIPファイルを解凍
    ```sh
    unzip awscliv2.zip
    ```
4. 解凍したディレクトリに移動しインストールを実行
    ```sh
    sudo ./aws/install
    ```
5. インストール確認
    ```sh
    aws --version
    ```
    正常にインストールされている場合、以下のような出力が得られる
    ```
    aws-cli/2.5.0 Python/3.8.8 Linux/5.4.0-77-generic exe/x86_64.ubuntu.20
    ```
6. AWS CLIの設定
    ```sh
    aws configure --profile terraform
    ```
    先ほど作ってダウンロードしたアクセスキーとシークレットアクセスキーの入力を求められるので入力します。


## 4. Terraformを使ってEC2を立ち上げてみる
手順
1. 作業用ディレクトリの作成
    ```sh
    mkdir ~/aws-ec2-terraform
    cd ~/aws-ec2-terraform
    ```
2. Terraform構成ファイルの作成
作業用ディレクトリ内に必要なTerraform構成ファイルを作成します。
    * terraform.tf：基本的な設定やプロバイダー情報を定義する。
    * provider.tf：AWS Provider情報を記述する
    * ec2.tf：EC2インスタンスの情報を定義するファイル

    ```tf:terraform.tf
    terraform {
     required_providers {
        aws = {
            source = "hashicorp/aws"
            version = ">= 3.0"
            }
        } 
    }
    ```
    ```tf:provider.tf
    provider "aws" {
      region = "ap-northeast-1"  # 東京リージョン
      profile = "terraform"
    
      default_tags {
        tags = {
          Managed = "terraform"
        }
      }
    }
    ```
    ```ec2.tf
    resource "aws_instance" "example" {
      ami           = "ami-00561c77487da40c1"  # Amazon Linux 2 AMI
      instance_type = "t2.micro"  # t2.micro（無料枠対象）
    
      tags = {
        Name = "tf_demo"
      }
    }
    ```
    
3. Terraformの初期化
ここで書いているtfファイルに問題があるとエラーがいっぱいでます。
    ```sh
    terraform init
    ```
    
4. インフラ計画を実行
このコマンドは、設定ファイルに基づいてリソースを作成するための計画を表示します。```plan```は、いわゆるドライインに相当するもので、構成ファイルと実リソースの差分から環境にどのような影響を与えるのか調べることができます。チェックするのみで、実環境には影響を与えません。
    ```sh
    terraform plan
    ```
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/42b10c10-d462-4a75-b8cc-3d6efe7e25ff.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/410700bd-c445-42f2-8e99-daa1b94a1d34.png)

5. インフラの適用
想定通りの状態になっていれば、```terraform apply```を実行します。```apply```は```plan```の内容を環境に反映させます。実リソースに影響を与えるため、実行前に確認ダイアログが表示されます。
    ```sh
    terraform apply
    ```
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/e2fc9e32-6a7e-4237-813a-d0852eb0a099.png)
これでリソースが作成されたようです。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/8bf8cf72-bc3a-460f-96b5-6cd3f78bc86d.png)
    AWSコンソールで確認してみます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/581ea63b-f350-4add-b2d6-d24284ff1e9f.png)
    名前にtf_demoとつけたEC2インスタンスが作成されています。
    ```terraform show```というコマンドでも確認できます。
```sh
terraform show
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/5f355e72-17e4-4a5d-a578-d6d3f1d45de0.png)

## 5.環境の削除
作ってみるだけなので一旦環境を削除します。まずは　planで削除対象を確認します。
```sh
terraform plan -destroy
```
```destroy```は非常に強力なコマンドで、Terraform管理化にあるリソースを全て削除します。意図しない環境で実行しないように気をつけます。
```sh
terraform destroy
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/42e2fffa-5927-43fc-9ac3-ed3b52b6f648.png)

コンソールからもインスタンスが終了していることを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734886/6e13744d-d91f-408d-b319-152456f8e5e9.png)

## まとめ
今回は、Terraformを使ってAWS上でEC2インスタンスを作成し、そのインスタンスを破壊するという基本的な操作を学びました。これにより、インフラリソースの作成から破壊までの流れを実践的に理解することができました。Terraformを使うことで、コードとしてインフラを管理できるメリットを実感できました。
今後は、さらに複雑なリソースの管理や、実際のシステムに適用できるスクリプトの作成に進んでいきます。今回はインスタンスを立ててすぐに削除で何もすることができなかったので、次回は、SessionManagerを使ってEC2インスタンスに接続し、Webサーバとして機能するようにEC2インスタンスを設定します。また、セキュリティグループを作成と適用を行い、より実践的な環境を構築していく予定です。
引き続き、このシリーズを通じてインフラエンジニアリングの知識を深めていきます。