IaCとは?Terraformを軸にインフラのコード管理を理解する

目次

IaC(Infrastructure as Code)の基本

IaC(Infrastructure as Code)は、サーバーやネットワークなどのインフラ構成を、GUIやCLIの手作業ではなくコードで定義・管理する手法を指す。

IaCではこれらをすべてコードに落とし込むことで、Gitによるバージョン管理、プルリクエストでのレビュー、CI/CDによる自動適用が可能になる。

宣言的アプローチと命令的アプローチ

IaCツールには「宣言的」と「命令的」の2つのアプローチがある。

スクロールできます
項目宣言的命令的
記述内容「あるべき状態」を定義「手順」を記述
代表ツールTerraform, CloudFormationAnsible, シェルスクリプト
冪等性ツールが担保自分で担保する必要あり
状態管理ツールが現在の状態を追跡基本的に追跡しない

Terraformを例にすると、「EC2インスタンスが1台、t3.microで、このサブネットに存在する」と書く。Terraformは現在の状態と比較して、差分だけを適用する。すでに存在すれば何もしない。これが「宣言的」の意味であり、何度実行しても同じ結果になる冪等性が自然に得られる。

一方Ansibleは「このパッケージをインストールせよ」「このファイルを配置せよ」と手順を並べる。モジュール単位では冪等性があるが、全体の設計は書く側の責任になる。

IaCには3つのレイヤーがある

IaCを「Terraform = IaC」と理解してしまうケースは多いが、実際にはIaCがカバーする範囲はもっと広い。大きく3つのレイヤーに分かれ、それぞれ担当するツールが異なる。

アプリケーション層 コンテナイメージ、デプロイ定義、マニフェスト Dockerfile / Kubernetes Manifests / Helm OS・ミドルウェア層 パッケージ導入、ユーザー作成、設定ファイル配置 Ansible / Chef / Puppet / cloud-init インフラ層 VPC、サブネット、EC2、RDS、ロードバランサー Terraform / CloudFormation / Pulumi 上位層は下位層の上に構築される

インフラ層

VPC、サブネット、セキュリティグループ、EC2、RDS、ロードバランサーなど、クラウド上の「箱」にあたる部分。Terraformの主戦場はここだ。

resource "aws_instance" "web" {
  ami           = "ami-0abcdef1234567890"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id

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

この例では、EC2インスタンスを1台、t3.microで作成する。terraform applyを実行すれば、AWSのAPIが叩かれて実際にインスタンスが起動する。

OS・ミドルウェア層

EC2が立ち上がっても、中身は素のAMIのままだ。Nginxのインストール、設定ファイルの配置、ユーザーの作成といったOS内部の構成は、Ansibleなどが担当する。

- name: Install and start Nginx
  hosts: web_servers
  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present
    - name: Start Nginx
      service:
        name: nginx
        state: started
        enabled: true

Terraformでもprovisioner機能でシェルスクリプトを流すことは技術的には可能だが、公式ドキュメント自体が「provisionerは最後の手段」と明記しており、推奨されない。インフラ層はTerraform、OS層はAnsibleと分離するのが定石だ。

アプリケーション層

アプリケーションのビルド・デプロイ定義を管理するレイヤー。DockerfileやKubernetesのマニフェスト、Helmチャートがここに該当する。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    spec:
      containers:
        - name: web
          image: myapp:1.2.0
          ports:
            - containerPort: 80

各レイヤーのツールは独立して動作するが、相互に依存関係がある。Terraformで作ったEKSクラスターに対して、Helmチャートでアプリをデプロイする、という流れが典型的だ。

TerraformとAWS CloudFormationの比較

AWSを使うなら、Terraformの他にAWS純正のCloudFormationという選択肢がある。やっていることは「インフラをコードで定義して適用する」という点で同じだが、設計思想に違いがある。

スクロールできます
項目TerraformCloudFormation
対応クラウドAWS, Azure, GCP, その他多数AWSのみ
記述言語HCL(HashiCorp Configuration Language)JSON / YAML
状態管理tfstateファイルを自分で管理AWSが管理(不要)
新サービス対応プロバイダーの更新を待つAWS公式なので即対応が多い
学習コストHCLの習得が必要JSON/YAMLが書ければすぐ始められる
マルチクラウド同一言語で複数クラウドを扱える不可

Terraformの最大の強みはマルチクラウド対応だ。AWSとGCPを組み合わせた構成でも、同じHCLで一貫して管理できる。一方CloudFormationはtfstateの管理が不要で、AWSに閉じるプロジェクトであれば運用負荷が低い。

実務では「AWS専業ならCloudFormation、マルチクラウドや将来的な移行可能性があるならTerraform」という選び方が多い。ただし、近年はTerraformのエコシステムの広さからTerraformを第一選択にするチームが増えている。

ローカル環境で練習する方法

Terraform自体はローカルにインストールして使うCLIツールだ。ただしterraform applyでリソースを作るには、接続先のクラウドアカウントが必要になる。クラウドアカウントなしでも学習を進める方法はいくつかある。

LocalStackでAWSをエミュレートする

LocalStackは、AWSの主要サービスをローカルのDockerコンテナ上でエミュレートするツールだ。無料版(Community Edition)でもS3、Lambda、DynamoDB、SQS、SNSなどが使える。

# LocalStackの起動
docker run --rm -p 4566:4566 localstack/localstack

# Terraformから接続するためのprovider設定
provider "aws" {
  access_key = "test"
  secret_key = "test"
  region     = "ap-northeast-1"

  endpoints {
    s3       = "http://localhost:4566"
    dynamodb = "http://localhost:4566"
    lambda   = "http://localhost:4566"
  }

  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true
}

この設定でterraform applyを実行すると、AWSではなくLocalStackに対してリソースが作られる。料金は一切かからない。

注意点として、LocalStackのエミュレーションは完全ではない。IAMのポリシー評価やVPCのネットワーク挙動など、本物と異なる部分がある。HCLの文法やワークフロー(init → plan → apply → destroy)の学習には十分だが、本番設計の検証には向かない。

Docker Providerで手軽に試す

TerraformにはDocker用のプロバイダーがあり、ローカルのDockerコンテナをTerraformで管理できる。クラウドアカウントが一切不要で、Terraformの基本操作を体験するには最も手軽な方法だ。

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

resource "docker_image" "nginx" {
  name = "nginx:latest"
}

resource "docker_container" "web" {
  name  = "learn-terraform"
  image = docker_image.nginx.image_id
  ports {
    internal = 80
    external = 8080
  }
}

terraform applyすると実際にNginxコンテナが起動し、localhost:8080でアクセスできる。terraform destroyで消える。Terraformのライフサイクルを体感するには最適だ。

AWS Free Tierで本物に触る

学習目的であれば、AWSの無料利用枠(Free Tier)を使うのが最終的には一番効率がいい。EC2のt2.micro/t3.microが月750時間、S3が5GBまで無料で使える。

ただし注意点がある。

  • terraform destroyを忘れるとリソースが残り、課金される
  • NAT GatewayやElastic IPなど、Free Tier対象外のリソースを知らずに作ると課金される
  • AWS Budgetsでアラートを設定しておくこと

ローカルで練習したい AWSサービスを使う? No Docker Provider クラウドアカウント不要 Yes 課金OK? No LocalStack AWSエミュレーション(無料) Yes AWS Free Tier 本物のAWS(要アカウント)

HCLの文法とTerraformのワークフローを掴むだけならDocker Providerが最速。AWSリソースの定義を練習したいならLocalStack。実際のAWSの挙動まで確認したいならFree Tier。目的に応じて使い分けるのが効率的だ。

目次