terraformについて

### そもそもterraformって何

AWS（Amazon Web Services）においてTerraformを使用すると、AWSの各種リソースをコードで管理し、プロビジョニングや変更を自動化できます。以下に、AWSでのTerraform利用について詳しく説明します。

1. AWSプロバイダの設定：
    - AWS認証情報（アクセスキーとシークレットキー）をTerraformに設定
    - 使用するAWSリージョンを指定
2. リソース定義（.tfファイル）：
    - Terraform用の構成ファイル（HCL言語またはJSON形式）で、AWSリソースを宣言的に記述
    - 例：VPC、サブネット、セキュリティグループ、EC2インスタンス、RDSデータベースなど
3. terraform init：
    - Terraformの初期化コマンド
    - 必要なプロバイダプラグインのダウンロードと、バックエンドの初期化を実行
4. terraform plan：
    - 現在の構成と、Terraformコードで定義された構成の差分を確認
    - 実行計画を表示し、変更内容を事前に把握できる
5. terraform apply：
    - Terraformコードに基づいて、AWSリソースの作成、更新、削除を実行
    - 変更内容を適用し、インフラの状態をコードに合わせる
6. terraform destroy：
    - Terraformで管理されているAWSリソースを削除
    - インフラのクリーンアップや、一時的な環境の破棄に使用
7. ステートファイル（terraform.tfstate）：
    - Terraformで管理されているリソースの状態を記録するファイル
    - 各リソースのIDや属性値などの情報を保持
    - S3バケットなどのバックエンドに保存し、チーム間で共有可能

AWSの多様なサービスに対応した豊富なリソース定義が利用できるため、Terraformは、AWS環境のインフラ管理において強力なツールとなっています。コードによるインフラ管理により、インフラの可視化、バージョン管理、再現性の向上が図れます。また、AWSの各サービスと連携し、整合性のあるインフラ構築を実現できます。

- AWSプロバイダの設定ってどうやるの
    
    `~/.aws/credentials` に書いてあるものを使う
    

- リソース定義 (.tfファイル) ってどうやるの
    
    Terraformでリソースを定義するには、Terraform構成ファイル（通常は拡張子が`.tf`のファイル）を使用します。以下に、よく使われるAWSリソースの定義例を示します。
    
    VPCの定義：
    
    ```bash
    resource "aws_vpc" "main" {
      cidr_block = "10.0.0.0/16"
      
      tags = {
        Name = "my-vpc"
      }
    }
    ```
    
    サブネットの定義：
    
    ```bash
    resource "aws_subnet" "public_subnet" {
      vpc_id     = aws_vpc.main.id
      cidr_block = "10.0.1.0/24"
      
      tags = {
        Name = "public-subnet"
      }
    }
    ```
    
    セキュリティグループの定義：
    
    ```bash
    resource "aws_security_group" "allow_ssh" {
      name        = "allow_ssh"
      description = "Allow SSH inbound traffic"
      vpc_id      = aws_vpc.main.id
      
      ingress {
        from_port   = 22
        to_port     = 22
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    ```
    
    EC2インスタンスの定義：
    
    ```bash
    resource "aws_instance" "web_server" {
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t2.micro"
      subnet_id     = aws_subnet.public_subnet.id
      
      tags = {
        Name = "web-server"
      }
    }
    ```
    
    RDSデータベースの定義：
    
    ```bash
    resource "aws_db_instance" "mysql" {
      engine            = "mysql"
      engine_version    = "5.7"
      instance_class    = "db.t2.micro"
      name              = "mydb"
      username          = "admin"
      password          = "password123"
      parameter_group_name = "default.mysql5.7"
    }
    ```
    
    これらの例では、`resource`ブロックを使用して各AWSリソースを定義しています。`resource`ブロックには、リソースのタイプ（例：`aws_vpc`、`aws_subnet`など）と、リソースに付ける名前（例：`main`、`public_subnet`など）を指定します。
    
    リソースブロック内では、そのリソースに固有の設定を行います。例えば、VPCではCIDRブロック、サブネットではVPC IDとCIDRブロック、EC2インスタンスではAMI、インスタンスタイプ、サブネットIDなどを指定します。
    
    また、`tags`ブロックを使用して、リソースにタグを付けることができます。タグは、リソースを識別したり、管理したりするのに役立ちます。
    
    これらのTerraform構成ファイルを作成したら、`terraform init`、`terraform plan`、`terraform apply`のコマンドを順番に実行することで、定義したリソースがAWS上にプロビジョニングされます。
    

- terraform initって何
    
    `terraform init`は、Terraformを使用する前に必ず実行する必要があるコマンドです。このコマンドは、Terraformの初期化処理を行います。
    
    1. バックエンドの初期化：
        - Terraformのステート（状態）ファイルを保存するバックエンドを初期化します。
        - バックエンドには、ローカルファイルシステム、S3、Terraformクラウドなどを指定できます。
    2. プロバイダプラグインのダウンロード：
        - Terraformコードで使用されているプロバイダ（AWS、Azure、GCPなど）のプラグインをダウンロードします。
        - プラグインは、Terraformがクラウドリソースを管理するために必要です。
    3. モジュールの初期化：
        - Terraformコードで使用されているモジュール（他の.tfファイルから呼び出されるリソース定義）を初期化します。
        - モジュールの初期化には、モジュールのソースコードのダウンロードが含まれます。
    4. 依存関係の解決：
        - Terraformコードの依存関係を解決します。
        - 依存関係には、プロバイダやモジュールのバージョン指定などが含まれます。
    
    `terraform init`コマンドを実行すると、カレントディレクトリに`.terraform`ディレクトリが作成されます。このディレクトリには、ダウンロードしたプロバイダプラグインやモジュールのコードが格納されます。
    
    以下は、`terraform init`コマンドの実行例です：
    
    ```bash
    $ terraform init
    
    Initializing the backend...
    
    Initializing provider plugins...
    - Finding latest version of hashicorp/aws...
    - Installing hashicorp/aws v3.37.0...
    - Installed hashicorp/aws v3.37.0 (signed by HashiCorp)
    
    Terraform has been successfully initialized!
    ```
    
    `terraform init`は、Terraformプロジェクトを新しく作成したとき、プロバイダやモジュールを追加・変更したとき、バックエンドの設定を変更したときなどに実行する必要があります。これにより、Terraformが正しく動作するために必要な準備が整います。
    

- すでにリソースがaws上にある場合、terraform initするとどうなるの
    
    すでにAWS上にリソースが存在する状態で`terraform init`を実行した場合、Terraformはそれらの既存リソースを認識せず、新しいリソースを作成しようとします。これにより、リソースの重複や競合が発生する可能性があります。
    
    このような状況を適切に処理するには、以下のようなアプローチを取ることができます：
    
    1. 既存リソースをTerraformの管理下に置く（インポート）：
        - `terraform import`コマンドを使用して、既存のリソースをTerraformのステートファイルにインポートします。
        - インポートされたリソースは、Terraformコードで定義されているものと同じ設定である必要があります。
        - インポート後、`terraform plan`を実行して、インポートされたリソースとTerraformコードの定義が一致していることを確認します。
    2. 既存リソースとTerraformコードの定義を一致させる：
        - 既存リソースの設定を確認し、Terraformコードでそれらの設定を正確に再現します。
        - 必要に応じて、既存リソースの設定を変更して、Terraformコードの定義と一致させます。
    3. 既存リソースを削除し、Terraformで新しいリソースを作成する：
        - これは、既存リソースが不要な場合や、設定が大きく異なる場合に適しています。
        - 既存リソースを手動で削除した後、`terraform apply`を実行して新しいリソースを作成します｡
    4. データソースを使用して既存リソースを参照する：
        - Terraformのデータソース機能を使用して、既存リソースの情報を取得します。
        - データソースで取得した情報を使用して、他のリソースを設定することができます。
        - この方法は、既存リソースを直接管理する必要がない場合に便利です。
    
    既存リソースがある状態でTerraformを使用する場合は、慎重に計画を立てる必要があります。既存リソースとTerraformコードの定義が一致していることを確認し、必要に応じてインポートや設定の調整を行ってください。
    
    また、本番環境で作業する前に、テスト環境やステージング環境で変更の影響を確認することを強くお勧めします。これにより、既存リソースへの意図しない変更や破壊的な操作を防ぐことができます。
    

- terraform planって何
    
    `terraform plan`は、Terraformの実行計画を表示するコマンドです。このコマンドは、現在のTerraformコードと実際のインフラの状態を比較し、変更が必要なリソースを特定します。
    
    `terraform plan`コマンドが行う主な処理は以下の通りです：
    
    1. 現在の状態の読み込み：
        - Terraformのステートファイル（`terraform.tfstate`）から現在のインフラの状態を読み込みます。
        - ステートファイルには、Terraformで管理されているリソースの情報が含まれています。
    2. Terraformコードの読み込み：
        - カレントディレクトリにある`.tf`ファイルを読み込み、定義されているリソースを解析します。
    3. 差分の計算：
        - 現在のインフラの状態とTerraformコードの定義を比較し、変更が必要なリソースを特定します。
        - 追加、変更、削除が必要なリソースが表示されます。
    4. 実行計画の表示：
        - 特定された変更内容を実行計画として表示します。
        - 実行計画には、各リソースに対して行われる変更の詳細が含まれます。
        - 変更は、`+`（追加）、``（削除）、`~`（変更）の記号で示されます。
    
    以下は、`terraform plan`コマンドの実行例です：
    
    ```bash
    $ terraform plan
    
    Terraform will perform the following actions:
    
      # aws_instance.example will be created
      + resource "aws_instance" "example" {
          + ami           = "ami-0c55b159cbfafe1f0"
          + instance_type = "t2.micro"
          + tags          = {
              + "Name" = "example-instance"
            }
          # (other attributes omitted for brevity)
        }
    
    Plan: 1 to add, 0 to change, 0 to destroy.
    ```
    
    この例では、`terraform plan`が1つの新しいAWS EC2インスタンスを作成することを示しています。インスタンスのAMI、インスタンスタイプ、タグなどの詳細が表示されます。
    
    `terraform plan`は、実際にインフラに変更を加えるわけではありません。それは、変更内容のプレビューを提供し、適用前に確認できるようにするためのものです。`terraform plan`の出力を確認し、意図した変更であることを確認してから、`terraform apply`コマンドを使用して実際の変更を適用します。
    
    また、`terraform plan`コマンドには、`-out`オプションを使用して実行計画を保存することもできます。これにより、後で`terraform apply`コマンドで保存された計画を適用することができます。
    
    - terraform planはリモート先に特に変化は与えないという認識で大丈夫？
        
        `terraform plan`コマンドは、実際のインフラに変更を加えるのではなく、現在のTerraformコードとインフラの状態を比較して、変更予定の内容を表示するだけです。
        
        `terraform plan`の主な目的は以下の通りです：
        
        1. 変更内容の確認：
            - `terraform plan`は、Terraformコードを適用した場合の変更内容を事前に確認するために使用されます。
            - これにより、意図しない変更や潜在的な問題を特定することができます。
        2. コードレビューの促進：
            - `terraform plan`の出力は、他のチームメンバーがコードレビューを行う際に役立ちます。
            - 変更内容を事前に確認することで、コードの品質と安全性を向上させることができます。
        3. 自動化パイプラインでの使用：
            - `terraform plan`は、CI/CDパイプラインの一部として使用されることがあります。
            - 変更内容を自動的に検証し、問題がある場合はパイプラインを停止するためです。
        
        `terraform plan`は、リモートのインフラに対して読み取り専用の操作を行います。APIを通じて現在の状態を取得しますが、変更は加えません。したがって、`terraform plan`を実行しても、実際のリソースに影響はありません。
        
        ただし、`terraform plan`を実行する前に、`terraform init`コマンドを実行して、必要なプロバイダプラグインやモジュールを初期化しておく必要があります。
        
        実際にインフラに変更を加えるには、`terraform apply`コマンドを使用します。`terraform apply`は、`terraform plan`で表示された変更内容を適用し、リソースの作成、更新、削除を行います。
        
    

- terraform applyって何
    
    `terraform apply`は、Terraformコードで定義された構成をインフラに適用するコマンドです。このコマンドは、`terraform plan`で表示された変更内容を実際のリソースに反映します。
    
    `terraform apply`コマンドが行う主な処理は以下の通りです：
    
    1. 実行計画の作成または読み込み：
        - デフォルトでは、`terraform apply`は適用前に実行計画を作成します。
        - `terraform plan`で事前に作成された実行計画がある場合は、その計画を読み込みます。
    2. 変更内容の確認：
        - `terraform apply`は、適用される変更内容を表示し、ユーザーに確認を求めます。
        - ユーザーは、変更を確認し、処理を続行するか、キャンセルするかを選択できます。
    3. リソースの作成、更新、削除：
        - ユーザーが変更を承認すると、`terraform apply`は実行計画に基づいてリソースを作成、更新、削除します。
        - Terraformは、必要な順序でリソースを処理し、依存関係を解決します。
    4. ステートファイルの更新：
        - 変更が適用された後、Terraformはステートファイル（`terraform.tfstate`）を更新します。
        - ステートファイルは、現在のインフラの状態を記録し、次回の実行時に使用されます。
    
    以下は、`terraform apply`コマンドの実行例です：
    
    ```bash
    $ terraform apply
    
    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
    
      # aws_instance.example will be created
      + resource "aws_instance" "example" {
          + ami           = "ami-0c55b159cbfafe1f0"
          + instance_type = "t2.micro"
          + tags          = {
              + "Name" = "example-instance"
            }
          # (other attributes omitted for brevity)
        }
    
    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.example: Creating...
    aws_instance.example: Still creating... [10s elapsed]
    aws_instance.example: Creation complete after 15s [id=i-1234567890abcdef0]
    
    Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
    ```
    
    - 実行計画って何
        
        実行計画（Execution Plan）は、Terraformが実際にインフラに適用する変更内容を示したものです。これは、現在のインフラの状態とTerraformコードで定義された desired state（望ましい状態）の差分を表しています。
        
        `terraform plan`コマンドを実行すると、実行計画が生成されます。実行計画には以下の情報が含まれます：
        
        1. リソースの作成、更新、削除：
            - `+`記号は、新しいリソースが作成されることを示します。
            - ``記号は、既存のリソースが削除されることを示します。
            - `~`記号は、既存のリソースが更新されることを示します。
        2. リソースの属性：
            - 実行計画には、各リソースの属性値が表示されます。
            - 新しく作成されるリソースの場合は、すべての属性が表示されます。
            - 更新されるリソースの場合は、変更される属性のみが表示されます。
        3. 変更の概要：
            - 実行計画の最後には、変更の概要が表示されます。
            - 概要には、追加、変更、削除されるリソースの数が示されます。
        
        実行計画は、以下のような目的で使用されます：
        
        1. 変更内容の確認：
            - 実行計画を確認することで、Terraformが意図した変更を行うことを確認できます。
            - 予期しない変更や潜在的な問題を特定することができます。
        2. コードレビュー：
            - 実行計画は、Terraformコードのレビューに役立ちます。
            - レビュアーは、実行計画を確認して、変更内容が適切であるかどうかを判断できます。
        3. 変更の承認：
            - 実行計画は、変更管理プロセスの一部として使用されることがあります。
            - 変更を適用する前に、関係者が実行計画をレビューし、承認することができます。
        
        実行計画は、`terraform apply`コマンドで適用される前に表示されます。これにより、ユーザーは変更内容を確認し、処理を続行するかキャンセルするかを選択できます。
        
        また、`terraform plan`コマンドに`-out`オプションを指定することで、実行計画をファイルに保存することもできます。保存された実行計画は、後で`terraform apply`コマンドで使用できます。これにより、実行計画の作成と適用を分離し、変更管理プロセスに組み込むことができます。
        
        実行計画は、Terraformを使用する上で重要な役割を果たします。これにより、変更内容を事前に確認し、インフラの予期しない変更を防ぐことができます。
        

- terraform importって何
    
    `terraform import`は、既存のリソースをTerraformの管理下に置くためのコマンドです。これにより、Terraformで管理されていない既存のインフラリソースを、Terraformの状態（state）に取り込むことができます。
    
    既存のリソースをTerraformにインポートする主な目的は以下の通りです：
    
    1. 既存インフラのTerraform管理：
        - Terraformを導入する前に作成されたリソースを、Terraformで管理できるようにします。
        - インポートにより、既存リソースをTerraformのコードとステートに合わせることができます。
    2. 部分的なTerraform管理：
        - インフラの一部をTerraformで管理する場合に、既存リソースをインポートすることができます。
        - これにより、Terraformで管理されるリソースと、他の方法で管理されるリソースを混在させることができます。
    
    `terraform import`コマンドの基本的な構文は以下の通りです：
    
    ```bash
    terraform import [resource_type].[resource_name] [resource_id]
    ```
    
    - `resource_type`：インポートするリソースのタイプ（例：`aws_instance`）。
    - `resource_name`：Terraformコードで使用するリソースの名前。
    - `resource_id`：インポートするリソースの一意の識別子（例：EC2インスタンスのID）。
    
    例えば、既存のAWS EC2インスタンスをTerraformにインポートする場合は、以下のようなコマンドを実行します：
    
    ```bash
    terraform import aws_instance.example i-1234567890abcdef0
    ```
    
    このコマンドは、IDが`i-1234567890abcdef0`のEC2インスタンスを、Terraformコードの`aws_instance.example`リソースとしてインポートします。
    
    インポート後は、Terraformコードを書く必要があります。インポートされたリソースの設定をコードで再現し、desired stateを定義します。これにより、インポートされたリソースをTerraformで管理できるようになります。
    
    ただし、すべてのリソースタイプがインポートをサポートしているわけではありません。また、リソースによっては、インポート時に追加の設定が必要な場合もあります。
    
    `terraform import`は、既存のインフラをTerraformに移行する際に便利なコマンドです。ただし、インポートするリソースの設定を十分に理解し、Terraformコードでそれらを正確に再現する必要があります。インポート後は、`terraform plan`と`terraform apply`を実行して、インポートされたリソースがTerraformで正しく管理されていることを確認してください。
    

- ec2って何
    
    EC2（Amazon Elastic Compute Cloud）は、Amazon Web Services（AWS）が提供するクラウドコンピューティングサービスの1つです。EC2を使用すると、スケーラブルな仮想サーバー（インスタンス）をクラウド上に起動し、管理することができます。
    
    EC2の主な特徴は以下の通りです：
    
    1. 仮想マシン：
        - EC2インスタンスは、仮想化された環境で動作する仮想マシンです。
        - さまざまなオペレーティングシステム（Linux、Windows、macOSなど）を選択できます。
    2. スケーラビリティ：
        - 必要に応じてインスタンスの数を増減できます。
        - 負荷に応じて自動的にスケールアップ・ダウンすることもできます（Auto Scaling）。
    3. インスタンスタイプ：
        - EC2には、さまざまなインスタンスタイプ（t2、c5、m5、g4dnなど）があります。
        - インスタンスタイプごとに、CPU、メモリ、ストレージ、ネットワーク性能が異なります。
    4. ストレージオプション：
        - EC2インスタンスには、複数のストレージオプションがあります。
        - EBS（Elastic Block Store）：永続的なブロックレベルのストレージ。
        - インスタンスストア：一時的な高速ストレージ。
    5. ネットワーク：
        - EC2インスタンスは、VPC（Virtual Private Cloud）内で起動されます。
        - セキュリティグループを使用して、インスタンスへのネットワークアクセスを制御できます。
    6. セキュリティ：
        - IAM（Identity and Access Management）を使用して、EC2インスタンスへのアクセス権限を管理できます。
        - キーペアを使用して、インスタンスへのSSHアクセスを認証できます。
    7. 料金モデル：
        - EC2は従量課金制です。使用した分だけ料金が発生します。
        - オンデマンドインスタンス、リザーブドインスタンス、スポットインスタンスなど、さまざまな料金オプションがあります。
    
    EC2は、ウェブアプリケーション、バッチ処理、データ分析、機械学習など、さまざまな用途で使用されています。スケーラビリティ、柔軟性、コスト効率性から、多くの企業や開発者に利用されています。
    
    Terraformを使用すると、EC2インスタンスのプロビジョニングと管理を自動化できます。Terraformコードでインスタンスの設定を定義し、`terraform apply`コマンドでインスタンスを起動できます。これにより、インフラのコード化と一貫した管理が可能になります。
    

- terraformを実際に使ってみた例
    
    
    以下は、TerraformでAWS EC2インスタンスを起動する簡単な例です。
    
    まず、Terraformコードを記述します（例：`main.tf`）：
    
    ```bash
    provider "aws" {
      region = "us-west-2"
    }
    
    resource "aws_instance" "example" {
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t2.micro"
      key_name      = "my-key-pair"
    
      tags = {
        Name = "example-instance"
      }
    }
    ```
    
    このコードは、AWS providerを設定し、`us-west-2`リージョンを指定しています。`aws_instance`リソースを使用して、EC2インスタンスを定義しています。AMI ID、インスタンスタイプ、キーペア名、タグを指定しています。
    
    次に、`terraform init`コマンドを実行して、Terraformを初期化します：
    
    ```bash
    $ terraform init
    ```
    
    このコマンドにより、AWS providerプラグインがダウンロードされ、初期化されます。
    
    `terraform plan`コマンドを実行して、実行計画を確認します：
    
    ```bash
    $ terraform plan
    ```
    
    このコマンドにより、Terraformが作成する予定のリソースが表示されます。EC2インスタンスが作成されることを確認してください。
    
    `terraform apply`コマンドを実行して、インフラに変更を適用します：
    
    ```bash
    $ terraform apply
    ```
    
    確認メッセージが表示されたら、`yes`と入力して適用を承認します。Terraformが、指定されたEC2インスタンスを起動します。
    
    1. AWSマネジメントコンソールで、EC2ダッシュボードに移動し、インスタンスが正常に起動していることを確認します。
    2. 後片付けとして、`terraform destroy`コマンドを実行して、作成したリソースを削除します：
    
    ```bash
    $ terraform destroy
    ```
    
    確認メッセージが表示されたら、`yes`と入力して削除を承認します。Terraformが、作成したEC2インスタンスを終了し、関連リソースを削除します。
    
    この例では、非常に基本的なEC2インスタンスの起動を示しました。実際のシナリオでは、セキュリティグループ、ネットワーク設定、ストレージ、ユーザーデータなどの追加設定が必要になることがあります。
    
    Terraformを使用することで、インフラのコード化、バージョン管理、再現性の向上、コラボレーションの促進などのメリットがあります。このシンプルな例をベースに、より複雑なインフラ構成を構築していくことができます。