Infrastructure as Codeの導入を検討するエンジニアなら、一度はこの疑問にぶつかるはずです。
どちらもIaCを実現するツールですが、設計思想も得意領域もまったく異なります。「なんとなく流行っているから」という理由で選ぶと、現場で使い物にならない構成になってしまいます。
この記事では、TerraformとAnsibleの違いを設計思想レベルから整理し、「どの場面でどちらを選ぶべきか」の判断軸を実務目線で解説します。CI/CD連携の具体的な手順や、現場でよくある連携の失敗パターンも取り上げます。
この記事のポイント
・TerraformはインフラのプロビジョニングにAnsibleは設定管理に向く
・「宣言型」と「手続き型」の設計思想の違いが選定の核心になる
・現場では両ツールを役割分担させて併用するのが主流
・迷ったときはリソースの「作成/削除」ならTerraform、「設定/変更」ならAnsibleが目安
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
TerraformとAnsibleはどう違うのか
まず根本的な設計思想の違いを押さえましょう。Terraformは「宣言型」のプロビジョニングツールです。「どういう状態にしたいか」をコードで定義すると、現在の状態と比較して必要な操作を自動で判断して実行します。
Ansibleは「手続き型」の構成管理ツールです。「どういう操作をするか」を順番に記述します。べき等性(何度実行しても同じ結果になること)を意識した書き方ができますが、基本的には「このタスクをこの順番で実行する」という記述スタイルです。
この違いを具体例で見てみましょう。
Terraformでは、EC2インスタンスを1台作りたい場合、次のように書きます。
# Terraform: 「この状態を作れ」と宣言する resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" tags = { Name = "web-server" } }
# Ansible: 「この操作を実行しろ」と手順を書く - name: Install Nginx hosts: webservers tasks: - name: Install nginx yum: name: nginx state: present - name: Start nginx service: name: nginx state: started enabled: yes
もう一点、重要な違いがあります。エージェントレス設計かどうかです。
・Terraform:TerraformはローカルのPC(またはCI/CDサーバー)からAPIを叩いて操作します。対象サーバーに何かをインストールする必要はありません
・Ansible:AnsibleもSSH経由でエージェントレスに動作します。ただし対象サーバーにSSHでアクセスできる必要があります
Terraformは主にクラウドプロバイダー(AWS/Azure/GCP等)のAPIを呼び出してリソースを作成・管理するのに特化しており、Ansibleはサーバーにログインして設定変更・パッケージ管理・ファイル配置を行うのに特化しています。
2つの役割を一言で整理するとこうなります。
・Terraform:インフラの「存在」を宣言する(クラウドAPIに「このリソースを作れ/消せ」と命令する)
・Ansible:サーバーの「状態」を適用する(SSHで「このソフトウェアを入れろ/この設定にしろ」と実行する)
この切り分けが頭に入ると、「これはどちらに書くべきか」という現場での迷いが大幅に減ります。
なお、Terraformにも
remote-execプロビジョナーというサーバー内コマンドを実行する仕組みがあります。しかし公式ドキュメントでも「最終手段」と位置づけられており、terraform destroy時のクリーンアップが保証されず、再apply時にべき等性が崩れることがあります。「Terraformでできるから全部Terraformに書く」という発想が後から設計の混乱を招く典型例です。Terraformの得意領域:インフラのプロビジョニング
TerraformはHashiCorp社が開発したオープンソースのIaCツールです。AWSのEC2やRDS、Google CloudのCompute Engine、AzureのVirtual Machinesなど、複数クラウドのリソースをまとめて管理できる点が強みです。1. クラウドリソースの作成・変更・削除
Terraformが最も輝くのは、クラウドリソースの生成から廃棄までのライフサイクル管理です。実際の業務でよく使うシナリオを挙げます。
・VPC・サブネット・セキュリティグループの設計:ネットワーク構成をコードで定義し、環境ごとに複製する
・EC2インスタンス・ELBのセット構築:Webサーバーとロードバランサーをまとめて作成する
・RDS・ElastiCache等のマネージドサービス:設定パラメータをコードで管理して再現性を確保する
・IAMロール・ポリシーの定義:権限設計をコードで管理してドリフト(手動変更による乖離)を防ぐ
Terraformの
terraform plan コマンドは、実行前に「何が作られ、何が変更され、何が削除されるか」を表示します。これによって本番環境への意図しない変更を事前に防げます。# terraform plan の実行例(実際の出力イメージ) $ terraform plan Terraform will perform the following actions: # aws_instance.web will be created + resource "aws_instance" "web" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t3.micro" ... } Plan: 1 to add, 0 to change, 0 to destroy.
2. 状態管理(tfstate)による差分検出
Terraformはterraform.tfstate というファイルで「現在のインフラの状態」を記録しています。次回 terraform plan を実行するとき、このstateファイルとクラウドの実際の状態を突き合わせて差分を計算します。この仕組みにより、「コードを変更したとき、実際に何が変わるか」を明示できます。手動でインフラを変更してしまった場合も、Terraformがそのドリフトを検出してくれます。
チームで使う場合は、tfstateをS3などのリモートバックエンドに保存して共有するのが標準的な運用です。
3. モジュールによる構成の再利用
Terraformはモジュール機能を使うと、共通の構成をテンプレート化して再利用できます。たとえば「本番環境」「ステージング環境」「開発環境」で同じ構成を変数だけ変えてデプロイするような使い方が効率的にできます。Ansibleの得意領域:構成管理と設定自動化
AnsibleはRed Hat社(現IBM)が買収したオープンソースの構成管理ツールです。エージェントレスでSSH経由で動作し、YAMLで書いたPlaybookで操作を記述します。1. サーバーへのミドルウェアインストールと設定
Ansibleが真価を発揮するのは、すでに存在するサーバーに対してソフトウェアのインストールや設定変更を行う作業です。典型的なユースケースを挙げます。
・Nginx/Apache の設定ファイル配置:設定ファイルをテンプレート化して複数台に配布する
・パッケージの一括インストール:yum/apt/dnf経由でパッケージを管理する
・cronジョブの設定:定期実行ジョブを複数サーバーに一括設定する
・セキュリティパッチ適用:脆弱性対応でパッケージをアップデートする
・ユーザー・グループ管理:アカウントの作成/削除を自動化する
2. Playbookによる手順の記述と再実行
Ansibleのコアはプレイブック(Playbook)です。YAMLで書かれた手順書を実行するイメージで、IT部門の新人でも読みやすいのが特徴です。以下はNginxをインストールして設定ファイルを配置するPlaybookの例です(RHEL 9.4 / Ansible 2.16)。
# webserver.yml --- - name: Webサーバー構成を適用する hosts: webservers become: yes tasks: - name: Nginxをインストールする ansible.builtin.dnf: name: nginx state: present - name: Nginx設定ファイルを配置する ansible.builtin.template: src: templates/nginx.conf.j2 dest: /etc/nginx/nginx.conf owner: root group: root mode: '0644' notify: reload nginx - name: Nginxを起動し自動起動を有効にする ansible.builtin.systemd: name: nginx state: started enabled: yes handlers: - name: reload nginx ansible.builtin.systemd: name: nginx state: reloaded
$ ansible-playbook -i inventory.ini webserver.yml PLAY [Webサーバー構成を適用する] *** TASK [Gathering Facts] ********* ok: [10.0.1.45] TASK [Nginxをインストールする] *** changed: [10.0.1.45] TASK [Nginx設定ファイルを配置する] *** changed: [10.0.1.45] TASK [Nginxを起動し自動起動を有効にする] *** changed: [10.0.1.45] PLAY RECAP ********************* 10.0.1.45 : ok=3 changed=3 unreachable=0 failed=0
3. Role分割による大規模構成管理
Ansibleはロール(Role)という機能で、タスクを機能単位に分割・整理できます。「webserver」「database」「monitoring」といったロールを定義して組み合わせることで、複雑な構成でも管理しやすい状態を保てます。IaCツール選定の判断軸:何を基準に選ぶか
「結局どっちを使えばいいの?」という問いへの答えは、「何をしたいか」によって変わります。Terraform・Ansible 選定チェック
「クラウドでVMやネットワークを作りたい」→ Terraform
「作ったサーバーにNginxを設定したい」→ Ansible
「複数の環境を同じ構成で量産したい」→ Terraform(モジュール)
「OSのパッチを複数台に一括適用したい」→ Ansible
「インフラの状態変化を検出・修正したい」→ Terraform(plan/apply)
「設定変更をCIから自動実行したい」→ どちらも可能
| 観点 | Terraform | Ansible |
|---|---|---|
| 主な用途 | インフラリソースの作成・削除 | サーバー内の設定・ソフトウェア管理 |
| 設計思想 | 宣言型(あるべき状態を定義) | 手続き型(操作手順を記述) |
| 対象レイヤー | クラウドAPI・インフラレイヤー | OS・ミドルウェアレイヤー |
| 状態管理 | tfstateで明示的に管理 | 都度実行してべき等性で担保 |
| 学習曲線 | HCL記法の習得が必要 | YAMLで書けるため比較的入りやすい |
| マルチクラウド | プロバイダー機能で対応 | SSHが通れば基本対応可能 |
| コミュニティ | Terraform Registry | Ansible Galaxy |
詳細な振り分け基準:何をどちらのツールで管理するか
「実際にこれはどちらに書くべきか」と迷う場面に向けて、より具体的な振り分け基準を示します。| Terraformで管理する(インフラ層) | Ansibleで管理する(OS・ミドルウェア層) |
|---|---|
| EC2・VPC・サブネット・セキュリティグループ | OS初期設定・パッケージインストール |
| RDS・ElastiCache・S3バケット | Nginx / Apache / MySQL の設定ファイル |
| IAMロール・ポリシー・インスタンスプロファイル | アプリケーションのデプロイとサービス管理 |
| Route53レコード・ACM証明書・ALB | cronjob・sudoers・ログローテーション設定 |
| CloudWatch・SNS・Lambda関数 | ユーザー・グループ・SSH公開鍵の配布 |
・AWSマネジメントコンソールで操作するか、SSH接続後にサーバー内で操作するか?
コンソールで行う操作(セキュリティグループの追加、RDSの作成など)はTerraformの管轄です。SSH後にサーバー内で行う操作(dnf install、systemctl、設定ファイルの編集)はAnsibleの管轄です。
・terraform destroyで消えてよいか?
Terraformで管理するということは、destroy時に削除対象になります。永続データ(RDS・S3)をdestroy対象にしたくない場合はlifecycle設定が必要です。Ansibleで管理するものは、インフラが再作成されれば再適用するだけです。
・リソースの「作成/存在」を扱うか、「設定/状態」を扱うか?
リソース自体の作成・削除はTerraformです。すでに存在するリソース上の設定変更はAnsibleです。
「Terraformだけで全部できるのでは?」という疑問が浮かびます。確かにTerraformにもリモートプロビジョナー(
remote-exec)でサーバー内コマンドを実行する機能はあります。しかし公式ドキュメントでもこれは「最終手段」として位置づけられており、OS内の設定管理には向きません。Terraformはあくまでクラウドリソースの生成・削除のために設計されています。逆に「Ansibleだけでクラウドリソースも管理できるのでは?」という疑問もあります。Ansibleにもクラウドモジュール(
amazon.aws等)はあります。しかし、tfstateのような状態管理機能がないため、現在のインフラ状態と定義の差分を検出する機能はTerraformに劣ります。クラウドリソースの大規模管理はTerraformに任せるのが現場のベストプラクティスです。
>> Terraform実践セミナーの詳細はこちら
併用パターン:TerraformとAnsibleを組み合わせる
現場では、TerraformとAnsibleを組み合わせて使うのが最も現実的な選択です。それぞれの得意領域を活かして役割分担します。1. 典型的な役割分担パターン
最も多い構成は「Terraformでインフラを作ってAnsibleで設定する」という2段階アプローチです。# フェーズ1: TerraformでAWSリソースを作成 terraform apply # → EC2インスタンス、VPC、セキュリティグループ等が作成される # フェーズ2: AnsibleでEC2の内部を設定 ansible-playbook -i aws_ec2.yml site.yml # → Nginx インストール、設定ファイル配置、起動設定
terraform output -json を使った動的インベントリ生成です。# main.tf: EC2のIPアドレスをOutputsに定義する output "web_server_ip" { value = aws_instance.web.private_ip } # Terraform applyでIPアドレスを確認する $ terraform output -raw web_server_ip 10.0.1.45 # シェルスクリプトでAnsibleインベントリを自動生成する(generate-inventory.sh) #!/bin/bash WEB_IP=$(terraform output -raw web_server_ip) cat > inventory.ini << INVENTORY_EOF [webservers] ${WEB_IP} ansible_user=ec2-user ansible_ssh_private_key_file=~/.ssh/mycompany-key.pem [webservers:vars] ansible_ssh_common_args='-o StrictHostKeyChecking=no' INVENTORY_EOF echo "インベントリ生成完了: ${WEB_IP}"
$ ansible-playbook -i inventory.ini webserver.yml PLAY [Webサーバー構成を適用する] *** TASK [Nginxをインストールする] *** changed: [10.0.1.45] TASK [Nginx設定ファイルを配置する] *** changed: [10.0.1.45] TASK [Nginxを起動し自動起動を有効にする] *** changed: [10.0.1.45] PLAY RECAP ************* 10.0.1.45 : ok=3 changed=3 unreachable=0 failed=0
2. CI/CDパイプラインへの組み込み
GitHub ActionsなどのCI/CDパイプラインでは、Terraform applyの完了後にAnsible playbookを実行する設計が標準的です。重要な原則は「順序の厳守」です。Ansibleが実行される時点でTerraformのapplyが完了していなければ、接続先IPが存在せずパイプラインが失敗します。# .github/workflows/deploy.yml(抜粋) jobs: terraform: name: Terraform Apply runs-on: ubuntu-latest outputs: web_ip: ${{ steps.tf-output.outputs.web_ip }} steps: - uses: actions/checkout@v4 - name: Terraform Apply run: | terraform init terraform apply -auto-approve - name: Terraform Outputを取得する id: tf-output run: | echo "web_ip=$(terraform output -raw web_server_ip)" >> $GITHUB_OUTPUT ansible: name: Ansible Playbook runs-on: ubuntu-latest needs: terraform # terraformジョブの完了を必須にする steps: - uses: actions/checkout@v4 - name: インベントリを生成する run: | echo "[webservers]" > inventory.ini echo "${{ needs.terraform.outputs.web_ip }} ansible_user=ec2-user" >> inventory.ini - name: Ansible Playbookを実行する run: | ansible-playbook -i inventory.ini webserver.yml
needs: terraform によりTerraformジョブの成功を必須条件にしています。outputs 経由でIPアドレスをAnsibleジョブへ引き渡すことで、インベントリ生成スクリプトを介さずにジョブ間でデータを共有できます。この分業体制にすることで、インフラの変更はTerraformのPRで管理し、アプリケーション設定の変更はAnsibleのPlaybookで管理するという明確な責任分離ができます。
3. 連携時の注意点と失敗パターン
TerraformとAnsibleを組み合わせる現場で頻発する失敗パターンを3つ取り上げます。いずれも「どちらのツールで管理するか」の判断が曖昧なために起きます。【失敗1】TerraformのprovisionerでNginxをインストールしようとする
Terraformの
remote-exec プロビジョナーでサーバーにパッケージをインストールするコードを書いてしまうケースです。# 要注意: provisionerでパッケージインストール(非推奨パターン) resource "aws_instance" "web" { ami = data.aws_ami.rhel9.id instance_type = "t3.medium" provisioner "remote-exec" { inline = [ "sudo dnf install -y nginx", "sudo systemctl enable nginx", ] } }
terraform plan ではprovisionerの変更が検出できず、差分確認が機能しません。最後に、SSHの接続タイムアウトで terraform apply が途中失敗する事故が頻発します。対処法は明確です。provisionerは使わず、インフラ構築後にAnsibleを別ステップで実行してください。【失敗2】AnsibleからAWSのセキュリティグループを変更する
Ansibleの
amazon.aws.ec2_security_group モジュールでセキュリティグループを変更するケースです。Terraformでも同じセキュリティグループを管理していると、次回の terraform plan で差分が検出され、Terraform側に上書きされます。同じリソースを2つのツールで管理することはドリフトの原因になります。AWSリソースはTerraformに一本化し、AnsibleからAWSリソースを操作するモジュールは使わないのが鉄則です。【失敗3】terraform destroy後にAnsibleの再適用を忘れる
EC2インスタンスを
terraform destroy で削除すると、Ansibleで適用したNginxの設定も消えます。インフラ再構築後にAnsibleを実行しないまま運用を再開してしまう事故です。以下のように手順を明示しておくと防げます。# destroy後の安全な再構築手順 $ terraform destroy -target=aws_instance.web # → EC2インスタンスが削除される $ terraform apply # → EC2インスタンスが再作成される $ ./generate-inventory.sh # → 新しいIPアドレスでインベントリを再生成 $ ansible-playbook -i inventory.ini webserver.yml # → Ansibleで構成を再適用する(この手順を省くと設定なしのサーバーが稼働し続ける)
4. Pulumi・CDKとの比較でTerraformを選ぶ理由
近年はPulumi(Python/TypeScript等の汎用言語でインフラ定義)やAWS CDK(TypeScript/Python等でAWSリソースを定義)も注目されています。これらとTerraformを比較するポイントとしては次が挙げられます。・マルチクラウド対応:TerraformはAWS/Azure/GCPを同一ツールで管理できる。PulumiもマルチクラウドだがCDKはAWS専用
・HCLの習得コスト:TerraformのHCLはDSL(ドメイン固有言語)のため学習が必要だが、慣れるとシンプル
・エコシステムの成熟度:Terraform Registryには豊富なプロバイダー・モジュールが揃っており、現場での採用実績が最も多い
よくある質問と落とし穴
Q1. AnsibleにはPlaybookがあるのに、なぜTerraformが必要なの?
Ansibleのクラウドモジュールでもリソースは作れますが、状態管理がない点が大きな違いです。Terraformはterraform.tfstate で「今どういうリソースが存在するか」を追跡し、次回の terraform plan で差分を計算します。Ansibleにはこの仕組みがないため、「誰かが手動でリソースを変更した」ことを検出するのが難しくなります。Q2. TerraformとAnsibleのどちらから学べばいい?
クラウドインフラ構築を主眼に置くなら Terraform から。サーバー設定・ミドルウェア管理が中心なら Ansible から始めるのが実践的です。多くの現場ではどちらも使うため、最終的には両方の基礎を理解することを目指してください。Q3. Terraformでサーバー内の設定もやろうとしたが上手くいかない
Terraformのremote-exec プロビジョナーはデバッグが困難で、公式でも使用を推奨していません。「サーバー内の設定」はAnsibleに任せ、TerraformはAWSリソースの作成・削除に特化させるのが正解です。Q4. tfstateファイルをGitにコミットしてしまった
これは現場でよくある落とし穴です。tfstateにはクラウドリソースのIDや場合によっては機密情報が含まれるため、Gitには絶対にコミットしてはいけません。.gitignore に *.tfstate と *.tfstate.backup を追加し、S3等のリモートバックエンドで管理するのが正解です。Q5. Ansibleの実行が途中で失敗したが、どこまで適用されたかわからない
Ansibleのタスクは失敗した時点で停止します(ignore_errors: yes を設定しない限り)。どこまで適用されたかはAnsibleのRun Summaryを確認します。また、タスクはべき等性を持つように書いておけば、再実行しても問題ありません。Q6. Ansibleのplaybookが「No hosts matched」で実行されない
インベントリファイルのホスト名またはIPアドレスと、playbook内のhosts: 指定が一致していない場合に発生します。ansible-playbook -i inventory.ini webserver.yml --list-hosts で対象ホストを事前確認できます。Terraform側でIPアドレスが変わった場合(destroy/recreateの後)もこのエラーが起きるため、インベントリの再生成が必要です。本記事のまとめ
TerraformとAnsibleの違いと選定判断軸を整理しました。| やりたいこと | 推奨ツール |
|---|---|
| クラウドリソース(EC2/VPC/RDS等)を作成する | Terraform |
| サーバーにNginx/Apacheを設定する | Ansible |
| 環境(本番/ステージング/開発)を量産する | Terraform(モジュール) |
| OSパッチを複数台に一括適用する | Ansible |
| インフラの変更内容を事前に確認する | Terraform(plan) |
| 設定ファイルを複数サーバーに配布する | Ansible |
| クラウド+OS設定を一気通貫で自動化する | Terraform + Ansible(併用) |
併用する場合の基本の型は「Terraform applyでリソースを作成 →
terraform output -json でIP情報を取得 → Ansibleインベントリを動的生成 → playbook実行」の4ステップです。CI/CDでこの順序を自動化することで、再現性のあるインフラ構築フローが実現できます。同じリソースを2つのツールで管理することだけは避けてください。ドリフトが発生し、どちらが正しい状態かわからなくなった時点で、IaC管理の価値が失われます。次のステップとして、Terraformのtfstate管理やAnsibleのRole設計といった「現場で崩れない構成管理」のスキルを深めていきましょう。
・Terraformのtfstate管理とS3バックエンド設定|チーム運用で壊さないための基礎
・AnsibleでAWS上にNginx・PHP・MariaDBを自動構築する実践手順
・Terraformのmoduleとfor_each・countで構成を再利用する設計パターン
・Terraform入門|Infrastructure as CodeでAWSインフラをコード化する基礎ハンズオン
>> Terraform実践セミナーの詳細はこちら
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 次のページへ:TerraformのHCL変数設計|variable・locals・output・data sourceで構成を整理する方法
- 前のページへ:Terraformのtfstate管理とS3バックエンド設定|チーム運用で壊さないための基礎
- この記事の属するカテゴリ:Terraformへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます