0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Terraform】SSM踏み台EC2のTerraformファイル構成と役割

Last updated at Posted at 2025-12-27

はじめに

前回の記事では、「SSHを前提としない踏み台EC2」をどう設計するかにフォーカスしました。

本記事ではその続きとして、設計で分離した責務が、Terraform上でどのファイルに現れるのかを確認します。

Terraformの構文解説が目的ではありません。

  • なぜ provider.tf が分離されているのか
  • なぜ main.tf にすべてを書かないのか
  • outputs.tf は誰のための情報なのか

こうした「設計とコードの対応関係」を読み解いていきます。

今回のファイル構成

terraform-aws-sample
├── provider.tf
├── main.tf
├── variables.tf
└── outputs.tf

この構成は、Terraformのベストプラクティスというより、 設計上の責務を意図的に分離した結果です。
以下では、それぞれのファイルが「何を責任として持っているか」に注目して見ていきます。

provider.tf:設計の前提条件を固定する

provider.tf は、 「この設計がどの世界で成立するか」 を定義するファイルです。

provider.tf
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

provider.tf の設計上の役割

  • AWSを操作対象とすること
  • TerraformとProviderのバージョン前提
  • どのリージョンで成立する設計か

これらはリソース設計以前の前提条件です。
もしリージョンやプロバイダが変われば、 同じEC2・同じIAM Roleでも結果は変わります。
そのため provider.tf は、 設計の土台をコードとして固定する責務を持っています。

variables.tf:設計上「変えていいもの」を明示する

variables.tf は、 Terraformコード内で使用する入力変数を定義するファイルです。

variables.tf
# リージョン指定
variable "aws_region" {
  description = "AWS region"
  type        = string
  default     = "ap-northeast-1"
}

# EC2のインスタンスタイプを指定
variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

# EC2のNameタグに使う値を指定
variable "instance_name" {
  description = "EC2 Name tag"
  type        = string
  default     = "ssm-bastion"
}

variables.tf の設計上の役割

重要なのは、すべてを変数にしていない点です。

  • インスタンスタイプ → 変えていい
  • Nameタグ → 変えていい
  • 接続方式(SSM) → 変えていない

variables.tf は、 設計上「調整可能な部分」だけを表に出す役割を持っています。
逆に言えば、変数になっていない要素は、 この構成において「触るべきでない前提条件」です。

main.tf:設計を成立させる最小構成を定義する

main.tf には、この構成が成立するために最低限必要なリソースのみを定義しています。

main.tf
# 既存の default VPC を取得するための data ブロック
data "aws_vpc" "default" {
  default = true
}

# IAM Role(SSM用)作成
resource "aws_iam_role" "ssm_role" {
  name = "ssm-bastion-role"

  # EC2 がこの Role を引き受けられるようにする設定
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
      Action = "sts:AssumeRole"
    }]
  })
}

# SSM用ポリシーのアタッチ
resource "aws_iam_role_policy_attachment" "ssm" {
  role       = aws_iam_role.ssm_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

# Instance Profile作成
resource "aws_iam_instance_profile" "ssm" {
  name = "ssm-bastion-profile"
  role = aws_iam_role.ssm_role.name
}

# 踏み台EC2専用の Security Group作成
resource "aws_security_group" "bastion_sg" {
  name        = "bastion-ssm-sg"
  description = "Security group for SSM bastion"
  vpc_id      = data.aws_vpc.default.id

  # egress(アウトバウンドのみ許可)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "bastion-ssm-sg"
  }
}

# AMI(Amazon Linux 2023)を取得
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

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

# EC2 Instance 作成
resource "aws_instance" "bastion" {
  ami                  = data.aws_ami.amazon_linux.id
  instance_type        = var.instance_type

  # IAM Role を付与
  iam_instance_profile = aws_iam_instance_profile.ssm.name

  # Security Group の指定
  vpc_security_group_ids = [
    aws_security_group.bastion_sg.id
  ]

  # Nameタグ設定
  tags = {
    Name = var.instance_name
  }
}

main.tf の設計上の役割

このファイルにあるリソースは、

  • 1つでも欠けると SSM 接続が成立しない
  • これ以上増やすと「踏み台」の責務を超える

という意味で、設計上の最小構成です。
Security Group にインバウンドルールが存在しない点も、 意図的な設計判断です。
接続可否は IAM に委ね、 ネットワークは「到達経路を作らない」ことで制御しています。

outputs.tf:Terraformの外との境界を定義する

outputs.tf は、Terraformで作成した情報を Terraformの外へ安全に渡すためのファイルです。

outputs.tf
# EC2 Instance ID を出力
output "instance_id" {
  description = "EC2 Instance ID"
  value       = aws_instance.bastion.id
}

# EC2 Name タグを出力
output "instance_name" {
  description = "EC2 Name tag"
  value       = aws_instance.bastion.tags["Name"]
}

# AWSリージョンを出力
output "aws_region" {
  description = "AWS Region"
  value       = var.aws_region
}

outputs.tf の設計上の役割

outputs.tf は、

  • AWS CLI
  • スクリプト
  • 運用者

といったTerraformの外にいる存在との境界です。
特に instance_id は、SSM接続時に必須となります。

aws ssm start-session --target <instance-id>

Terraformの state に閉じたままにせず、 必要な情報だけを明示的に外へ出すことが重要です。

まとめ

本記事では、SSM踏み台EC2の構成を通して、 設計上の責務が Terraform のファイル分割にどう現れるかを見てきました。

  • provider.tf:設計の前提条件を固定
  • variables.tf:変えていい設計要素の明示
  • main.tf:成立に必要な最小構成
  • outputs.tf:Terraform外との境界

Terraformを単なる作成ツールとしてではなく、 設計をそのまま状態として管理するツールとして使う感覚を掴めれば、 IaCの理解は一段深まります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?