LESSON 30分

HCL構文とリソース定義

ストーリー

「TerraformではHCL -- HashiCorp Configuration Languageという 独自の言語でインフラを定義する」

木村先輩がエディタに .tf ファイルを開いた。

「JSONやYAMLとは違う書き味だが、人間が読みやすいように 設計されている。慣れれば、AWSコンソールで10分かかる操作が 10行のコードで書けるようになるぞ」


HCLの基本構文

ブロック構文

HCLはブロックベースの構文を持ちます。

hcl
# ブロックの基本形
block_type "label1" "label2" {
  argument1 = "value1"
  argument2 = 42
  argument3 = true

  nested_block {
    nested_arg = "nested_value"
  }
}

データ型

説明
string"hello"文字列
number42, 3.14数値
booltrue, false真偽値
list["a", "b", "c"]配列
map{ key = "value" }キーバリューマップ
nullnull値なし

文字列補間

hcl
# 変数の参照
name = "webapp-${var.environment}"

# 複数行文字列(ヒアドキュメント)
user_data = <<-EOF
  #!/bin/bash
  echo "Hello from ${var.instance_name}"
  yum update -y
EOF

リソース(resource)

リソースはTerraformで管理するインフラの最小単位です。

基本構文

hcl
resource "リソースタイプ" "リソース名" {
  # 引数
}

# 例: EC2インスタンス
resource "aws_instance" "web" {
  ami           = "ami-0abcdef1234567890"
  instance_type = "t3.micro"

  tags = {
    Name = "WebServer"
  }
}

リソースタイプの命名規則

aws_instance
 │    │
 │    └── リソースの種類(instance = EC2インスタンス)
 └────── プロバイダ名(aws = AWS)

aws_s3_bucket          → AWSのS3バケット
aws_vpc                → AWSのVPC
aws_security_group     → AWSのセキュリティグループ
aws_iam_role           → AWSのIAMロール

よく使うAWSリソース

VPC

hcl
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main-vpc"
  }
}

サブネット

hcl
resource "aws_subnet" "public_a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-a"
  }
}

セキュリティグループ

hcl
resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group for web servers"
  vpc_id      = aws_vpc.main.id

  ingress {
    description = "HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "HTTPS"
    from_port   = 443
    to_port     = 443
    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"]
  }

  tags = {
    Name = "web-sg"
  }
}

EC2インスタンス

hcl
resource "aws_instance" "web" {
  ami                    = "ami-0abcdef1234567890"
  instance_type          = "t3.micro"
  subnet_id              = aws_subnet.public_a.id
  vpc_security_group_ids = [aws_security_group.web.id]

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
  EOF

  tags = {
    Name = "web-server"
  }
}

リソース間の参照

リソース間で値を参照するには リソースタイプ.リソース名.属性 の形式を使います。

hcl
# VPC の ID を参照
resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id          # ← aws_vpc.main の id を参照
  cidr_block = "10.0.1.0/24"
}

# セキュリティグループの ID を参照
resource "aws_instance" "web" {
  vpc_security_group_ids = [aws_security_group.web.id]   # ← SG の id を参照
  subnet_id              = aws_subnet.public.id          # ← サブネットの id を参照
}
リソース間の依存関係(自動解決)

  aws_vpc.main
       │
       ├── aws_subnet.public (vpc_id を参照)
       │        │
       │        └── aws_instance.web (subnet_id を参照)
       │
       └── aws_security_group.web (vpc_id を参照)
                │
                └── aws_instance.web (vpc_security_group_ids を参照)

Terraform が自動的に依存関係を解析し、正しい順序で作成する

データソース(data)

既存のリソースの情報を取得するにはデータソースを使います。

hcl
# 最新の Amazon Linux 2023 AMI を取得
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

# データソースの値を使用
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id    # ← data.で参照
  instance_type = "t3.micro"
}

よく使うデータソース

データソース用途
aws_amiAMI の検索
aws_availability_zones利用可能な AZ の取得
aws_caller_identity現在の AWS アカウント情報
aws_region現在のリージョン情報
aws_vpc既存 VPC の情報取得

出力(output)

リソースの情報を出力するには output ブロックを使います。

hcl
output "instance_public_ip" {
  description = "EC2インスタンスのパブリックIP"
  value       = aws_instance.web.public_ip
}

output "vpc_id" {
  description = "VPC ID"
  value       = aws_vpc.main.id
}

output "web_url" {
  description = "WebサーバーのURL"
  value       = "http://${aws_instance.web.public_ip}"
}
bash
# apply 後に出力される
Outputs:

instance_public_ip = "54.123.45.67"
vpc_id = "vpc-0abc123def456"
web_url = "http://54.123.45.67"

まとめ

ポイント内容
HCL構文ブロックベース、文字列補間、複数のデータ型
resourceインフラリソースの定義(aws_instance, aws_vpc等)
参照リソースタイプ.リソース名.属性 で値を参照
data既存リソースの情報取得
outputリソース情報の出力

チェックリスト

  • HCLの基本構文(ブロック、データ型、文字列補間)を書ける
  • resource ブロックでAWSリソースを定義できる
  • リソース間の参照方法を理解した
  • data ブロックで既存リソースの情報を取得できる
  • output ブロックで値を出力できる

次のステップへ

次のセクションでは、プロバイダとState管理について学びます。 Terraformが「現在のインフラ状態」をどのように追跡しているのかを理解しましょう。


推定読了時間: 30分