記事検索

検索ワードを入力してください。
Sky Tech Blog
Terraformで​リソースを​ループ作成する​コツ:Security Groupと​EC2の​実践例

Terraformで​リソースを​ループ作成する​コツ:Security Groupと​EC2の​実践例

本記事では、Terraformを使用してインフラを効率的に管理するためのfor_eachの活用方法を解説します。Security GroupやEC2インスタンスの具体例を通じて、保守性の高いコードの実現方法や実践的なテクニックを紹介します。

はじめに

Terraformでインフラを管理していると、「Webサーバー用」「アプリケーション用」「データベース用」といった複数の類似リソースを作成する場面が頻繁に発生します。 従来の方法では、リソースごとに個別にコードを書く必要がありましたが、for_eachを使うことで効率的かつ保守性の高いコードが実現できます。

本記事では、Security GroupとEC2インスタンスを例に、実際の運用で役立つfor_eachのテクニックを解説します。

基本的な​for_eachの​使い方

for_eachを使うことで、mapやsetから複数のリソースを一度に作成できます。 以下は複数のSecurity Groupを作成する例です。

resource "aws_security_group" "main" {
  for_each = var.security_groups

  name        = each.key
  description = each.value.description
  vpc_id      = each.value.vpc_id

  tags = {
    Name = each.key
  }
}

設定ファイル(terraform.tfvars)では以下のように定義します。

security_groups = {
  "web-sg" = {
    description = "Security group for web servers"
    vpc_id      = "vpc-12345678"
  }
  "app-sg" = {
    description = "Security group for application servers"
    vpc_id      = "vpc-12345678"
  }
}

この方法により、新しいSecurity Groupが必要になった場合も、設定ファイルにエントリを追加するだけで対応できます。

EC2インスタンスと​Security Groupの​関連付け

作成したSecurity Groupを、同じくfor_eachで作成するEC2インスタンスに関連付けることができます。

resource "aws_instance" "main" {
  for_each = var.ec2_instances

  ami                    = each.value.ami
  instance_type          = each.value.instance_type
  vpc_security_group_ids = [
    for sg_key in each.value.vpc_security_group_ids : 
    aws_security_group.main[sg_key].id
  ]

  tags = {
    Name = each.key
  }
}

重要なポイントは、aws_security_group.main[sg_key].idの部分です。これにより、for_eachで作成したSecurity GroupのIDを動的に参照できます。

実践的な​コツ

基本的なfor_eachの使い方を理解したところで、実際の運用で役立つより高度なテクニックを見ていきましょう。

countと​for_eachの​使い分け

Terraform公式ドキュメント では以下のように説明されています:

"If your instances are almost identical, count is appropriate. If some of their arguments need distinct values that can't be directly derived from an integer, it's safer to use for_each."

実践的な判断基準:

  • count: 同じ設定のリソースを複数作成する場合(例:同一設定のEC2を3台)
  • for_each: 各リソースが異なる設定値を持つ場合(例:Web用、App用、DB用のSecurity Group)

for_eachを使うことで、リストの順序変更時にリソースが再作成されるリスクも回避できます。

条件付きリソース作成

実際の運用では、環境(開発・本番)によって異なるリソースを作成したい場合があります。 例えば、「本番環境でのみSSHアクセスを制限する」「開発環境では全ポートを開放する」といったケースです。 環境別セキュリティルールの適用

resource "aws_security_group_rule" "production_only" {
  for_each = { 
    for key, rule in var.security_group_rules : key => rule 
    if rule.environment == "production"
  }
  
  type              = each.value.type
  from_port         = each.value.from_port
  to_port           = each.value.to_port
  protocol          = each.value.protocol
  security_group_id = aws_security_group.main[each.value.security_group_id].id
  cidr_blocks       = each.value.cidr_blocks
}

この方法により、同一のコードベースで環境ごとに適切なセキュリティ設定を適用できます。

リソース間の​依存関係管理

複数のモジュールでリソースを管理する場合、作成したリソースを他のモジュールから参照する必要があります。 例えば、ネットワークモジュールで作成したSecurity GroupをEC2モジュールで使用するケースです。

outputを活用したモジュール間連携

# ネットワークモジュールのoutput
output "security_group_ids" {
  description = "Map of security group names to IDs"
  value = { 
    for key, sg in aws_security_group.main : key => sg.id 
  }
}
# EC2モジュールでの参照
resource "aws_instance" "main" {
  for_each = var.ec2_instances
  
  vpc_security_group_ids = [
    for sg_name in each.value.security_groups :
    var.security_group_ids[sg_name]
  ]
  # ... その他の設定
}

Terraform公式ドキュメント

では、モジュール間でのリソース参照にはoutputを使用することを推奨しています。 これにより、依存関係が明確になり、変更時の影響範囲を把握しやすくなります。

まとめ

for_eachを活用することで、以下のような保守性の高いTerraformコードが実現できます。

  • 意味のあるキー: リソース名で直接識別でき、デバッグや運用が容易
  • 柔軟な条件分岐: 環境や要件に応じたリソース作成が可能
  • 明確な依存関係: outputを通じたモジュール間の連携で、変更影響を最小化

新しいリソースが必要になった場合も、設定ファイルへの追加だけで対応でき、コードの重複を避けながらスケーラブルなインフラ管理が可能になります。 ぜひ実際のプロジェクトで活用してみてください。


\シェアをお願いします!/
  • X
  • Facebook
  • LINE
キャリア採用募集中!

入社後にスキルアップを目指す若手の方も、ご自身の経験を幅広いフィールドで生かしたいベテランの方も、お一人おひとりの経験に応じたキャリア採用を行っています。

Sky株式会社のソフトウェア開発や製品、採用に関するお問い合わせについては、下記のリンクをご確認ください。
お問い合わせ
ホーム