AWSに戻る

Terraform

Terraformとは

Terraformは、HashiCorp社が開発したオープンソースのインフラストラクチャ as コード(IaC)ツールです。Terraformを使用すると、クラウドプロバイダー(AWS、Azure、GCPなど)やその他のサービスのインフラストラクチャをコードとして定義、プロビジョニング、管理することができます。Terraformは宣言的な構成ファイルを使用して、インフラストラクチャのあるべき状態を記述し、その状態に到達するために必要なアクションを自動的に計画して実行します。

Terraformの主な特徴

Terraformの仕組み

Terraformの基本的な仕組みは以下の通りです:

  1. 構成ファイルの作成: HCL(HashiCorp Configuration Language)またはJSON形式でインフラストラクチャリソースを定義します。
  2. 初期化: terraform initコマンドを実行して、必要なプロバイダープラグインをダウンロードし、バックエンドを設定します。
  3. 計画: terraform planコマンドを実行して、現在の状態と目標の状態の差分を確認します。
  4. 適用: terraform applyコマンドを実行して、計画された変更を実際のインフラストラクチャに適用します。
  5. 状態管理: Terraformは適用された変更を状態ファイル(通常はterraform.tfstate)に記録します。
  6. 破棄: 必要に応じてterraform destroyコマンドを実行して、作成したリソースを削除します。

Terraformのワークフロー

構成ファイル作成 → terraform init → terraform plan → terraform apply → インフラストラクチャ構築
                                                                      ↓
                                                terraform destroy → インフラストラクチャ削除
        

Terraformの構成ファイル

Terraformの構成ファイルは、通常.tf拡張子を持つファイルで、HCL(HashiCorp Configuration Language)またはJSONで記述されます。基本的な構成要素は以下の通りです:

要素 説明
プロバイダー 使用するクラウドプロバイダーやサービスを定義 provider "aws" { region = "us-west-2" }
リソース 作成または管理するインフラストラクチャリソース resource "aws_instance" "web" { ami = "ami-123456" }
データソース 既存のリソースからデータを取得 data "aws_ami" "ubuntu" { most_recent = true }
変数 構成で使用する入力変数 variable "instance_type" { default = "t2.micro" }
ローカル値 構成内で再利用する式や値 locals { common_tags = { Environment = "Dev" } }
出力値 他のモジュールや実行後に参照できる値 output "instance_ip" { value = aws_instance.web.public_ip }
モジュール 再利用可能なインフラストラクチャコンポーネント module "vpc" { source = "./modules/vpc" }
バックエンド 状態ファイルの保存場所と方法 terraform { backend "s3" { bucket = "mybucket" } }

Terraformの構成例

AWSでEC2インスタンスを作成する基本的な例

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

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"  # Amazon Linux 2 AMI
  instance_type = "t2.micro"
  
  tags = {
    Name = "example-instance"
  }
}

output "instance_id" {
  value = aws_instance.example.id
}

output "public_ip" {
  value = aws_instance.example.public_ip
}

変数とモジュールを使用した例

# variables.tf
variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-west-2"
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

variable "environment" {
  description = "Deployment environment"
  type        = string
  default     = "dev"
}

# main.tf
provider "aws" {
  region = var.region
}

module "vpc" {
  source = "./modules/vpc"
  
  environment = var.environment
  cidr_block  = "10.0.0.0/16"
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_type
  subnet_id     = module.vpc.public_subnet_id
  
  tags = {
    Name        = "web-server"
    Environment = var.environment
  }
}

# outputs.tf
output "vpc_id" {
  value = module.vpc.vpc_id
}

output "instance_id" {
  value = aws_instance.web.id
}

output "public_ip" {
  value = aws_instance.web.public_ip
}

AWSでのTerraformの使用方法

AWSでTerraformを使用するための基本的な手順は以下の通りです:

1. Terraformのインストール

macOSでのインストール(Homebrew使用)

brew install terraform

Linuxでのインストール

wget https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip
unzip terraform_1.5.7_linux_amd64.zip
sudo mv terraform /usr/local/bin/

Windowsでのインストール(Chocolatey使用)

choco install terraform

2. AWS認証情報の設定

AWS CLIを使用した認証情報の設定

aws configure

環境変数を使用した認証情報の設定

export AWS_ACCESS_KEY_ID="your_access_key"
export AWS_SECRET_ACCESS_KEY="your_secret_key"
export AWS_DEFAULT_REGION="us-west-2"

Terraform構成ファイルでの認証情報の設定(非推奨)

provider "aws" {
  region     = "us-west-2"
  access_key = "your_access_key"
  secret_key = "your_secret_key"
}

3. Terraformプロジェクトの初期化と実行

プロジェクトの初期化

terraform init

実行計画の作成

terraform plan

変更の適用

terraform apply

リソースの破棄

terraform destroy

AWSリソースの管理

Terraformを使用して管理できる主なAWSリソースの例:

コンピューティングリソース

EC2インスタンス

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  key_name      = "my-key"
  
  vpc_security_group_ids = [aws_security_group.web.id]
  subnet_id              = aws_subnet.public.id
  
  tags = {
    Name = "web-server"
  }
}

Auto Scaling Group

resource "aws_launch_configuration" "web" {
  name_prefix     = "web-"
  image_id        = "ami-0c55b159cbfafe1f0"
  instance_type   = "t2.micro"
  security_groups = [aws_security_group.web.id]
  
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "web" {
  name                 = "web-asg"
  launch_configuration = aws_launch_configuration.web.name
  min_size             = 2
  max_size             = 5
  desired_capacity     = 2
  vpc_zone_identifier  = [aws_subnet.public.id]
  
  tag {
    key                 = "Name"
    value               = "web-server"
    propagate_at_launch = true
  }
}

ネットワークリソース

VPC

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true
  
  tags = {
    Name = "main-vpc"
  }
}

サブネット

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-west-2a"
  map_public_ip_on_launch = true
  
  tags = {
    Name = "public-subnet"
  }
}

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-west-2b"
  
  tags = {
    Name = "private-subnet"
  }
}

セキュリティグループ

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Allow HTTP and SSH traffic"
  vpc_id      = aws_vpc.main.id
  
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

ストレージリソース

S3バケット

resource "aws_s3_bucket" "data" {
  bucket = "my-data-bucket"
  acl    = "private"
  
  versioning {
    enabled = true
  }
  
  tags = {
    Name = "data-bucket"
  }
}

RDSインスタンス

resource "aws_db_instance" "default" {
  allocated_storage    = 20
  storage_type         = "gp2"
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  name                 = "mydb"
  username             = "admin"
  password             = "password"
  parameter_group_name = "default.mysql5.7"
  skip_final_snapshot  = true
  
  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.default.name
}

Terraformの状態管理

Terraformは、作成したリソースの状態を状態ファイル(通常はterraform.tfstate)に保存します。この状態ファイルは、Terraformがリソースの現在の状態を追跡し、変更を計画するために使用されます。

リモート状態の設定

チーム開発やCI/CDパイプラインでは、状態ファイルをリモートで管理することが推奨されます。AWSでは、S3バケットとDynamoDBを使用して状態ファイルを管理することができます。

S3バックエンドの設定

terraform {
  backend "s3" {
    bucket         = "terraform-state-bucket"
    key            = "terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

状態ロック用のDynamoDBテーブルの作成

resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"
  
  attribute {
    name = "LockID"
    type = "S"
  }
}

状態の操作

状態の一覧表示

terraform state list

特定のリソースの状態を表示

terraform state show aws_instance.web

リソースを状態から削除

terraform state rm aws_instance.web

状態のインポート

terraform import aws_instance.web i-1234567890abcdef0

Terraformのモジュール

Terraformモジュールは、再利用可能なインフラストラクチャコンポーネントを作成するための仕組みです。モジュールを使用することで、コードの重複を減らし、ベストプラクティスを共有することができます。

モジュールの構造

modules/
  ├── vpc/
  │   ├── main.tf
  │   ├── variables.tf
  │   └── outputs.tf
  └── web-server/
      ├── main.tf
      ├── variables.tf
      └── outputs.tf

モジュールの作成と使用

VPCモジュールの例(modules/vpc/main.tf)

resource "aws_vpc" "this" {
  cidr_block           = var.cidr_block
  enable_dns_support   = true
  enable_dns_hostnames = true
  
  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
  }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.this.id
  cidr_block              = var.public_subnet_cidr
  availability_zone       = var.availability_zone
  map_public_ip_on_launch = true
  
  tags = {
    Name        = "${var.environment}-public-subnet"
    Environment = var.environment
  }
}

VPCモジュールの変数(modules/vpc/variables.tf)

variable "cidr_block" {
  description = "CIDR block for the VPC"
  type        = string
}

variable "public_subnet_cidr" {
  description = "CIDR block for the public subnet"
  type        = string
}

variable "availability_zone" {
  description = "Availability zone for the subnet"
  type        = string
}

variable "environment" {
  description = "Deployment environment"
  type        = string
}

VPCモジュールの出力(modules/vpc/outputs.tf)

output "vpc_id" {
  description = "The ID of the VPC"
  value       = aws_vpc.this.id
}

output "public_subnet_id" {
  description = "The ID of the public subnet"
  value       = aws_subnet.public.id
}

モジュールの使用(main.tf)

module "vpc" {
  source = "./modules/vpc"
  
  cidr_block         = "10.0.0.0/16"
  public_subnet_cidr = "10.0.1.0/24"
  availability_zone  = "us-west-2a"
  environment        = "dev"
}

module "web_server" {
  source = "./modules/web-server"
  
  vpc_id            = module.vpc.vpc_id
  subnet_id         = module.vpc.public_subnet_id
  instance_type     = "t2.micro"
  environment       = "dev"
}

Terraformのベストプラクティス

TerraformとCloudFormationの比較

TerraformとAWS CloudFormationは、どちらもインフラストラクチャ as コード(IaC)ツールですが、いくつかの重要な違いがあります。

特徴 Terraform CloudFormation
プロバイダー マルチクラウド(AWS、Azure、GCP、その他) AWSのみ
言語 HCL(HashiCorp Configuration Language) YAML/JSON
状態管理 状態ファイルを管理する必要あり AWSが管理
変更検出 計画フェーズ(terraform plan) ドリフト検出
リソースのサポート 多くのプロバイダーのリソースをサポート AWSリソースの包括的なサポート
モジュール化 Terraformモジュール ネスト化されたスタック
コミュニティ 幅広いオープンソースコミュニティ AWSコミュニティ
統合 多くのサードパーティツールとの統合 AWSサービスとの緊密な統合
学習曲線 中程度 比較的緩やか
ロールバック 手動(状態を使用) 自動(エラー時)

Terraformの制限事項

Terraformエンタープライズ(Terraform Cloud/Enterprise)

HashiCorpは、Terraformの商用版としてTerraform CloudとTerraform Enterpriseを提供しています。これらのサービスは、チームでのTerraformの使用を容易にするための追加機能を提供します。

主な機能

まとめ

Terraformは、AWSを含む多くのクラウドプロバイダーのインフラストラクチャをコードとして定義、プロビジョニング、管理するための強力なツールです。HCL(HashiCorp Configuration Language)を使用した宣言的な構文、多くのプロバイダーのサポート、モジュール化による再利用性など、多くの利点を提供します。

Terraformの主な利点は以下の通りです:

Terraformを効果的に活用するには、状態ファイルの適切な管理、モジュール化によるコードの再利用、変数の活用、セキュリティのベストプラクティスの適用などが重要です。また、プロジェクトの要件に応じて、CloudFormationなどの他のIaCツールと比較して、最適なツールを選択することも重要です。