AmazonインフラストラクチャのためのエピックTerraform AWSプロバイダー

Amazon Web Services (AWS)を管理し、使用する予定がある場合、Terraformを使用したAWSプロバイダは必須です。これにより、Amazon S3Elastic BeanstalkLambdaなど、AWSでサポートされている多くのリソースとやり取りすることができます。

この究極のガイドでは、AWSプロバイダについてのほぼすべてと、Terraformを使用してAmazonインフラストラクチャを管理する方法について、ステップバイステップで学ぶことができます。

さあ、始めましょう!

前提条件

このチュートリアルに従いたい場合は、以下の準備が必要です:

  • A code editor – Even though you can use any text editor to work with Terraform configuration files, you should have one that understands the HCL Terraform language. Try out Visual Studio (VS) Code.

Terraform AWSプロバイダーとは何ですか?

Terraformは、AWS、Google Cloud Platform(GCP)、Oracleなどのクラウドプロバイダーと対話するためにプラグインに依存しています。最も広く使用されているプロバイダーの1つはAWSプロバイダーです。このプロバイダーは、Amazon S3Elastic BeanstalkLambdaなど、AWSがサポートする多くのリソースと対話します。

Terraformは、適切な認証情報を使用してAWSプロバイダーと接続し、数十のAWSサービスを管理または展開/更新します。

AWSプロバイダーは、Terraformの設定ファイル内で宣言され、バージョン、エンドポイントURLやクラウドリージョンなどのさまざまなパラメーターが含まれています。

AWSプロバイダーの宣言

プロバイダーの名前を参照する必要がある場合は、ローカル名を定義する必要があります。ローカル名は、required_providers ブロック内で割り当てられたプロバイダーの名前です。プロバイダーを要求する際にローカル名が割り当てられ、モジュールごとに一意である必要があります。

required_providers を宣言する際に、Terraform 0.13以降のバージョンでは source パラメーターも宣言する必要があります。 source パラメーターは、Terraform が プラグイン をダウンロードできるソースアドレスを設定します。

ソースアドレスは、次の3つのパーツで構成されます:

  • ホスト名 – プロバイダーを配布するTerraformレジストリのホスト名です。デフォルトのホスト名は registry.terraform.io です。
  • 名前空間 – 指定されたレジストリ内の組織の名前空間です。
  • タイプ – タイプは、プロバイダーが管理するプラットフォームまたはシステムのために提供される短い名前であり、一意である必要があります。

以下に、ソースパラメーターの宣言構文が示されています。ソースアドレスの3つのパーツは、スラッシュ (/) で区切られています。

## <ホスト名>/]<名前空間>/<タイプ>

# ソースパラメータ構文の使用例

# Terraformがプラグインをダウンロードするためのソースの場所/アドレスを宣言する
# 公式のAWSプロバイダは、registry.terraform.ioレジストリのhashicorp名前空間に属しています。
# したがって、hashicorpのソースアドレスはhashicorp/awsです
source  = "hashicorp/aws"

以下のTerraform構成では、必要なプロバイダ名(aws)、ソースアドレス、AWSプロバイダのバージョンを宣言し、プロバイダのリージョンを構成します(us-east-2)。

# Terraform 0.13以降がインストールされている場合のプロバイダ要件の宣言
terraform {
  # プロバイダの要件は、ローカル名(aws)、ソースの場所、バージョン制約で構成されます。
  
  required_providers {
    aws = {     
      # Terraformがプラグインをダウンロードするためのソースの場所/アドレスを宣言する
      source  = "hashicorp/aws"
      # awsプロバイダのバージョンを3.0より大きくすることを宣言する
      version = "~> 3.0"  
    }
  }
}

# us-east-2リージョンでAWSプロバイダを構成する
provider "aws" {
  region = "us-east-2"
}

AWSアカウントのハードコードされた認証情報での認証

今、AWSプロバイダを宣言する方法の基本的な理解ができたので、AWSアカウントの認証方法を説明します。

AWSプロバイダーを認証する方法はいくつかあります。環境変数を宣言したり、名前付きプロファイルに資格情報を格納したりすることができます。しかし、AWSアカウントに認証する最も迅速な方法は、AWSプロバイダー内で資格情報をハードコーディングすることです。

ハードコーディングされた資格情報は漏洩の危険性があるため推奨されませんが、Terraform構成でハードコーディングされた資格情報を宣言して、AWSリソースを迅速にテストすることはできます。しかし、後で環境変数を宣言することで、AWSアカウントをより良い方法で認証する方法を学ぶことができます。

以下の構成では、ローカル名(aws)とプロバイダーリージョン(us-east-2)が宣言されています。AWSプロバイダーブロックも、AWSアカウントを認証するためのアクセスキーとシークレットキーを宣言しています。

# AWSプロバイダーをawsという名前で宣言
provider "aws" {
  # プロバイダーリージョンを宣言
  region = "us-east-2"
  # アクセスキーとシークレットキーを宣言
  access_key = "access-key"
  secret_key = "secret-key"
}

環境変数を宣言して資格情報を保護する

静的な資格情報をハードコーディングしてAWSクラウドサービスをTerraformで認証する方法を学びました。しかし、ハードコーディングは安全ではなく、コードを迅速にテストするためのテスト環境でのみ推奨されます。

別の方法で資格情報を安全に保護することはできますか?はい、環境変数として宣言することで、宣言することができる数に制限はありません。環境変数は、値がTerraformの設定ファイルの外部で設定され、名前/値のペアで構成される変数です。

以下のexportコマンドのシリーズを実行して、各環境変数をエクスポートしてください。環境変数をエクスポートすることで、プログラム全体で使用可能になります。また、Terraformが実行されるまで有効です。

# 変数 AWS_ACCESS_KEY_ID をエクスポート
export AWS_ACCESS_KEY_ID="access-key"
# 変数 AWS_SECRET_ACCESS_KEY をエクスポート
export AWS_SECRET_ACCESS_KEY="secret-key"
# 変数 AWS_DEFAULT_REGION をエクスポート
export AWS_DEFAULT_REGION="us-east-2"

名前付きプロファイルに複数の資格情報を保存する

ハードコードや環境変数として資格情報を宣言することで、AWSアカウントの認証が1つずつ行えます。しかし、必要な場合に複数の資格情報を保存して使用するにはどうすればよいでしょうか?名前付きプロファイルに資格情報を保存することが最適なオプションです。

以下のコードは、アクセスキーとシークレットキーを含む名前付きプロファイル(Myprofile)を作成します。

名前付きプロファイルのデフォルトの場所は、LinuxとmacOSでは$HOME/.aws/credentials/Myprofile、Windowsでは%USERPROFILE%\.aws\credentials\Myprofileです。Myprofileの部分は、実際の名前付きプロファイルの名前に置き換えてください。

# 名前付きプロファイル 'Myprofile' を作成します
[Myprofile]
aws_access_key_id = AKIAVWOJMI5836154yRW31
aws_secret_accesss_key = vIaGmx2bJCAK90hQbpNhPV2k5wlW7JsVrP1bm9Ft

~/.aws/credentials に名前付きプロファイルを作成した後、profile 属性を使用して Terraform 構成でそのプロファイルを参照できます。以下では、Myprofile という名前のプロファイルを参照しています。

# us-east-2 リージョンで 'aws' という名前の AWS プロバイダを構成する
provider "aws" {
  region = "us-east-2"
  # 名前付きプロファイル (Myprofile) を宣言する
  profile = "Myprofile"
}

AWS プロバイダで Assume Role を宣言する

Terraform を実行する前にハードコードされた資格情報を宣言することで、AWS プロバイダを構成する方法を学びました。しかし、実行時に資格情報を宣言したい場合があります。そのような場合は、AssumeRole API が必要です。AssumeRole は、アクセスキー ID、秘密アクセスキー、および セキュリティトークン を含む一時的な資格情報を提供します。これらの資格情報を使用して AWS に接続できます。

以下のコードは、provider という名前のプロバイダと、ロール名とセッション名を含む assume_role を宣言しています。AssumeRole アクセスを構成するには、どのエンティティがそれを引き受け、それが付与する特権を指定する IAM ロールを定義する必要があります。

# AWSプロバイダーの名前を'aws'と宣言します。
provider "aws" {
  # AssumeRoleを宣言します。
  assume_role {
		# リソース名を宣言します。
    # role_arnは、前提とするIAMロールのAmazonリソース名(ARN)です。
    # ARNは、AWSアカウント内のすべてのリソースに対して整列された一意の番号です。
    role_arn     = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
    # セッション名を宣言します。
    session_name = "SESSION_NAME"
  }
}

AWSプロバイダーの複数宣言

これまでに、単一のリージョンで機能するTerraformでAWSプロバイダーを宣言して構成する方法を学びました。しかし、複数のクラウドリージョンでインフラストラクチャやAWSサービスを管理する必要がある場合はどうでしょうか?その場合、キーワードaliasを宣言する必要があります。

エイリアスは、同じプロバイダーの複数の構成を定義し、リソースまたはモジュールごとに使用する構成を選択したり、複数のリージョンをサポートしたりできます。

以下のコードは、デフォルトのAWSプロバイダーを名前がawsで、regionus-east-2に設定された状態で宣言し、その後、同じ名前の追加のAWSプロバイダーを宣言しますが、宣言されたaliaswestで、regionus-west-2に設定されています。

alias を宣言すると、デフォルトでは us-east-2 リージョンにリソースを作成することができます。また、プロバイダー aws.west を選択すると、要件に応じて us-west-2 リージョンにリソースを作成することもできます。

# aws. で始まるデフォルトのプロバイダー構成リソース
provider "aws" {
  # 'aws' という名前の AWS プロバイダーに us-east-2 リージョンを宣言
  region = "us-east-2" 
}

# west リージョンの追加のプロバイダー構成
# リソースは aws.west として参照できる
provider "aws" {
  alias  = "west"
  # 'west' という別名で参照される AWS プロバイダーに us-west-2 リージョンを宣言
  region = "us-west-2"
}

# 追加のプロバイダーを使用して west リージョンでリソースを宣言
resource "aws_instance" "west-region" {
  # プロバイダーを aws.west として宣言
  # aws.west は 'aws' という名前の AWS プロバイダーから参照され、別名は 'west'
  provider = aws.west
}

# デフォルトのプロバイダーを使用してリソースを宣言
resource "aws_instance" "east-region" 
}

AWS プロバイダーのエンドポイント構成のカスタマイズ

エンドポイント構成のカスタマイズは、AWS Snowball のようなデフォルトではない AWS サービスエンドポイントに接続したり、ローカルテストを実行したりする場合に便利です。

Terraform AWSプロバイダーを構成して、カスタマイズされたエンドポイントを使用します。以下に示すように、プロバイダーのブロック内でendpoints構成ブロックを宣言することで行います。

以下の構成では、AWS S3サービスにローカルポート4572でアクセスでき、まるでAWSアカウント上のAWS S3サービスにアクセスしているかのようです。同様に、構成を使用するとdynamodbをローカルでポート4569でアクセスできます。 DynamoDBは、シームレスなスケーラビリティで高速なパフォーマンスを提供するNoSQLデータベースサービスです。

Terraform AWSプロバイダーが許可するカスタマイズされたエンドポイントのリストを確認してください。

# AWSプロバイダー 'aws'の宣言
provider "aws" {
  # エンドポイントの宣言
  endpoints { 
    # localhostのポート4569でdynamodbを宣言する
    dynamodb = "<http://localhost:4569>"  
    # localhostのポート4572でS3を宣言する
    s3 = "<http://localhost:4572>"  
  }
}

タグの追加

以前、AWSプロバイダーがリージョン、ソース場所などの構成で宣言される方法を学びました。しかし、リソースをよりよく管理するために、プロバイダーレベルでタグを追加する必要があります。

タグは、ユーザーが定義したキーと値で構成されるラベルです。AWSアカウントでの課金、所有権、自動化、アクセス制御など、さまざまなユースケースを確認する必要がある場合に役立ちます。

個々のリソースにタグを追加する代わりに、プロバイダーレベルでリソースにタグを追加する方法を学びましょう。

以下のコードは、default_tags内で定義されたタグを持つAWSプロバイダーを構成します。プロバイダー内でタグを追加する利点は、このプロバイダーでリソースを作成すると、指定したタグが自動的に追加されることです。

# AWSプロバイダー 'aws'の構成
provider "aws" {
  # プロバイダーレベルでデフォルトのタグ「Environment」と「Owner」を追加
  default_tags {
    # タグの値を宣言
    tags = {
      Environment = "Production"
      Owner       = "shanky"
    }
  }
}
# 'aws_vpc'リソースの作成、Name=MyVPCのタグ付き
resource "aws_vpc" "myinstance" {
  tags = {
    Name = "MyVPC"
  }
}

タグを無視

プロバイダーレベルでタグを有効にすると、環境全体にわたってタグを適用できます。ただし、EC2インスタンスにデフォルトのタグを追加したくない場合など、タグを無視する必要がある場合もあります。詳細は以下のコードをご覧ください。

以下のコードは、プロバイダー内で定義されたignore_tagsを使用してAWSプロバイダーを構成します。ignoreタグを使用する利点は、特定のリソースにデフォルトのタグを追加したくない場合や、AWSアカウントの他のリソースに適用したい場合です。

以下のコードでは、awsプロバイダを使用してリソースを作成すると、すべてのリソースはLastScannedおよびkubernetes.ioのタグを無視します。

# AWSプロバイダの構成
provider "aws" {
	# AWSプロバイダ(aws)の下のすべてのリソースでタグキーの接頭辞とキーを無視する
  ignore_tags {
    key_prefixes = ["kubernetes.io"]
  }
  ignore_tags {
    keys = ["LastScanned"]
  }
}

AWS S3バケットの作成

これまでに、AWSプロバイダを宣言して設定する方法についてすべて学びました。ただし、AWSプロバイダを宣言するだけでは何も行われません。AWSリソースの管理、例えばAWS S3バケットのプロビジョニングやEc2インスタンスの削除などが必要です。では、AWS S3バケットを作成する方法を学びましょう!

1. ~/terraform-s3-demoという名前のフォルダを作成し、そのフォルダに作業ディレクトリを変更(cd)します。 ~/terraform-s3-demoフォルダには、Terraformが作成する構成ファイルと関連するすべてのファイルが含まれます。

mkdir ~/terraform-s3-demo
cd ~/terraform-s3-demo

2. お気に入りのコードエディタに以下の構成をコピーして貼り付け、main.tfとして保存します。保存先は~/terraform-s3-demoディレクトリです。

main.tfファイルは、いくつかの必要なリソースを作成します:

  • プロバイダの要件:要件には、ローカル名、ソースの場所、およびバージョン制約が含まれます。
  • 暗号化キー: Amazon S3の暗号化キーは、S3バケットを支援し、すべての新しいオブジェクトがバケットに保存される際に暗号化されます。暗号化キーはTerraformでaws_kms_keyを使用して作成されます。
  • AWSプロバイダの設定: プロバイダ名(aws)とリージョンus-east-2を宣言します。
  • Bucket: このTerraformモジュールはterraformdemobucketという名前のバケットを作成します。このバケットはforce_destroyフラグを含むため、Terraformでは破棄できません。

バージョニング: Amazon S3のバージョニングは、同じバケツ内でオブジェクトの複数のバージョンを保持することを意味します

# AWSプロバイダ(aws)の設定
provider "aws" {
# すべてのリソースに対してプロバイダawsの下でtag key_prefixesとkeysを無視します。 
  ignore_tags {
    key_prefixes = ["kubernetes.io/"]
  }
  ignore_tags {
    keys = ["LastScanned"]
  }
}

# プロバイダの要件を宣言する
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

# リージョンを'us-east-2'に設定したAWSプロバイダ(aws)の設定
provider "aws" {
  region = "us-east-2"
}

# バケットへのアクセスの許可
resource "aws_s3_bucket_public_access_block" "publicaccess" {
  bucket = aws_s3_bucket.demobucket.id
  block_public_acls = false
  block_public_policy = false
}

# バケットオブジェクトを暗号化する暗号化キーの作成
resource "aws_kms_key" "mykey" {
  deletion_window_in_days = "20"
}

# terraformdemobucketという名前のバケットの作成
resource "aws_s3_bucket" "demobucket" {
  bucket = terraformdemobucket
  force_destroy = false
  server_side_encryption_configuration {
    rule {
        apply_server_side_encryption_by_default {
        kms_master_key_id = aws_kms_key.mykey.arn
        sse_algorithm = "aws:kms"
      }
    }
  }
  # 同じバケット内のオブジェクトの複数のバージョンを保持する
  versioning {
    enabled = true
  }
}

3. 以下のコマンドを実行して、~\\terraform-s3-demo ディレクトリに移動し、Terraform を初期化します。Terraform はリソースと連携するために必要なプラグインとプロバイダを初期化します。

Terraform は通常、terraform initterraform planterraform apply の 3 つのコマンドを順番に使用します。

cd ~\terraform-s3-demo       # ~\terraform-s3-demo ディレクトリに変更
terraform init               # Terraform を初期化
terraform plan               # 構成の構文が正しいことを確認
terraform apply -auto-approve # AWS S3 バケットをプロビジョニング

AWS EC2 インスタンスと IAM ユーザーの作成

前のセクションでは、AWS プロバイダを使用して Terraform で単一のオブジェクト (AWS S3 バケット) を作成する方法を学びました。しかし実際には、AWS プロバイダを使用して同じ種類の複数のオブジェクトを作成することができます。

1. ~/terraform-ec2-iam-demo という名前のフォルダを作成し、そのフォルダに移動します

2. お気に入りのコードエディタを開き、以下の設定をコピーして貼り付け、ファイルをmain.tfとして~/terraform-ec2-iam-demoディレクトリに保存してください。

以下のコードは、ec21aec21aという2つのEC2インスタンスを作成し、t2.microt2.mediumインスタンスタイプを持ち、さらに4つの異なる名前のIAMユーザーを作成します。コードで宣言されているamiは、Amazon Machine Image(AMI)であり、OSのタイプ、インストールするソフトウェアなど、インスタンスを起動するために必要な情報を提供します。

Amazon EC2コンソールを使用してLinux AMIsを見つけることができます

# インスタンスを t2.micro と t2.medium の instance_type で作成
resource "aws_instance" "my-machine" {
# AMI を宣言
  ami = "ami-0a91cd140a1fc148a"
  for_each  = {
      key1 = "t2.micro"
	    key2 = "t2.medium"
   }
  instance_type  = each.value
	key_name       = each.key
    tags =  {
	   Name  = each.value
	}
}
# IAM ユーザーを四つの異なる名前で作成
resource "aws_iam_user" "accounts" {
  for_each = toset( ["Account1", "Account2", "Account3", "Account4"] )
  name     = each.key
}

3. 次に、別のファイルを作成し、以下のコードをコピーして貼り付け、ファイル名をvars.tfにして、~/terraform-ec2-iam-demoディレクトリに保存してください。

以下のコードは、main.tfファイルで参照されるすべての変数を宣言しています。Terraformコードを実行した後、tag_ec2変数にec21aec21bの値がmain.tfファイルで定義された2つのEC2インスタンスに割り当てられます。

variable "tag_ec2" {
  type = list(string)
  default = ["ec21a","ec21b"]
}

4. 別のTerraform構成ファイルをoutput.tfとして~/terraform-ec2-iam-demoディレクトリに作成し、次に以下のコードをoutput.tfファイルにコピーして貼り付けます。

terraform applyコマンドの成功した実行後、コマンドの出力の末尾に${aws_instance.my-machine.*.id}${aws_iam_user.accounts.*.name}の値が表示されます。

以下のコードは、Terraformにmain.tf構成ファイルで定義されたaws_instanceおよびaws_iam_userリソースを参照するように指示しています。

output "aws_instance" {
   value = "${aws_instance.my-machine.*.id}"
}
output "aws_iam_user" {
   value = "${aws_iam_user.accounts.*.name}"
}

5.  ~/terraform-ec2-iam-demo ディレクトリに、provider.tfという名前の追加の構成ファイルを作成し、以下のコードをprovider.tfファイルに貼り付けます。以下のprovider.tfは、Terraform AWSプロバイダーを定義しています。これにより、Terraformは前の手順で定義したすべてのAWSリソースとやり取りする方法を知ることができます。

provider "aws" {
   region = "us-east-2"
 }

6. 今、~/terraform-ec2-iam-demoフォルダに必要なすべてのファイルが含まれていることを、treeコマンドを実行して確認します。

Showing all the Terraform configuration files required

7. Terraformを初期化し、AWS EC2インスタンスとIAMユーザーを作成するために、以下のコマンドを順番に実行します。

terraform init
terraform plan
terraform apply
Terraform apply command executed successfully.

最後に、AWS管理コンソールに移動し、AWS EC2サービスとIAMコンソールに移動します。

次のスクリーンショットでは、EC2インスタンスとIAMユーザーが存在することを確認できます。

Verifying the two EC2 instances that got created using Terraform
Verifying the four IAM users that got created using Terraform

結論

この究極のガイドを参照することで、AWSプロバイダーの宣言からTerraform内でのAWSプロバイダーの実行までの知識を得ることができました。また、AWSプロバイダーがさまざまな方法で安全に資格情報を宣言する方法も学びました。

今後、AWSプロバイダーとTerraformを使用して管理するAWSサービスは何ですか?

Source:
https://adamtheautomator.com/terraform-aws/