複数のサーバーを管理していると、「同じ設定を何度も手作業で繰り返すのは面倒…」「設定ミスが心配」と感じたことはありませんか?
10台、100台のサーバーに同じソフトウェアをインストールしたり、設定ファイルを配布したりするのは、手作業では現実的ではありませんよね。
実は、Ansibleはサーバーの構成管理を自動化して、インフラ運用を劇的に効率化できる強力なツールなんです。エージェント不要で、YAMLという読みやすい形式で設定を書けるのが大きな特徴ですよ。
この記事では、Ansibleの基礎知識から実践的な使い方まで、インフラ初心者の方にも分かりやすく解説していきます。
具体的な設定例をたくさん見ながら、サーバー管理の自動化を実現していきましょう!
Ansibleとは?その正体を知ろう

基本的な説明
Ansible(アンシブル) は、サーバーやネットワーク機器の構成管理を自動化するオープンソースツールです。
2012年にMichael DeHaan氏によって開発され、2015年にRed Hat社が買収しました。現在では、世界中のエンジニアに広く使われているインフラ自動化のデファクトスタンダードとなっています。
名前の由来は、SF小説に登場する「超光速通信装置」から来ているんです。遠く離れた場所とも瞬時に通信できる、という意味が込められているんですね。
構成管理ツールとは
構成管理ツールとは、サーバーやネットワーク機器の設定を自動化・標準化するためのソフトウェアです。
手作業の課題:
- 設定ミスが発生しやすい
- 作業に時間がかかる
- 設定内容を忘れる
- サーバーごとに設定が異なる
- 手順書のメンテナンスが大変
自動化のメリット:
- 人為的ミスの削減
- 作業時間の短縮
- 設定の標準化
- 再現性の確保
- ドキュメントとしても機能
Ansibleを使えば、これらの課題を一気に解決できるんです。
Ansibleが選ばれる理由
1. エージェントレス
管理対象サーバーに特別なソフトをインストールする必要がありません。SSHさえあれば動作します。
2. シンプルな記述
YAMLという人間が読みやすい形式で設定を書けます。プログラミング知識がなくても理解できますよ。
3. べき等性
何度実行しても同じ結果になるよう設計されています。安全に再実行できるんです。
4. 豊富なモジュール
パッケージ管理、ファイル操作、クラウドサービスなど、3,000以上のモジュールが用意されています。
5. 学習コストが低い
他の構成管理ツール(Chef、Puppetなど)と比べて、習得が比較的簡単です。
Ansibleの基本概念
コントロールノードとマネージドノード
Ansibleの構成は、シンプルな2層構造です。
コントロールノード(Control Node)
Ansibleをインストールして実行する管理サーバー。ここから操作を行います。
マネージドノード(Managed Node)
Ansibleで管理される対象サーバー。Ansibleのインストールは不要です。
構成イメージ:
[コントロールノード]
↓ SSH接続
[マネージドノード1]
[マネージドノード2]
[マネージドノード3]
一つのコントロールノードから、何百台ものマネージドノードを管理できます。
Inventory(インベントリ)
Inventoryは、管理対象サーバーのリストです。
どのサーバーにどんな設定を適用するか、ここで定義するんです。
例:
[webservers]
web1.example.com
web2.example.com
db1.example.com db2.example.com
グループ化することで、複数サーバーをまとめて管理できます。
Playbook(プレイブック)
Playbookは、実行する作業内容を記述したファイルです。
YAML形式で書かれていて、「このサーバーで、この作業を、この順番で実行する」という指示書のようなものですね。
例:
- name: Webサーバーのセットアップ
hosts: webservers
tasks:
- name: Nginxをインストール
apt:
name: nginx
state: present
これだけで、webserversグループの全サーバーにNginxがインストールされます。
Module(モジュール)
Moduleは、特定の作業を実行するための部品です。
ファイルをコピーする、パッケージをインストールする、サービスを起動する、など様々なモジュールが用意されています。
主要なモジュール:
- apt/yum:パッケージ管理
- copy:ファイルコピー
- template:テンプレート展開
- service:サービス管理
- user:ユーザー管理
- command/shell:コマンド実行
車輪の再発明をせず、用意されているモジュールを使うのが基本です。
Task(タスク)
Taskは、Playbookの中で実行される個々の作業単位です。
一つのモジュールを使った一つの操作が、一つのタスクになります。
Role(ロール)
Roleは、関連するタスクや設定をまとめた再利用可能な単位です。
「Webサーバー構築」「データベースセットアップ」など、役割ごとに分割して管理できるんです。
後で詳しく説明しますね。
Ansibleのインストール
前提条件
コントロールノード:
- Linux、macOS、BSD系OS(Windowsは非推奨)
- Python 3.8以上
マネージドノード:
- SSH接続が可能
- Python 2.7以上または3.5以上
- 特別なソフトウェアは不要
Ubuntu/Debianでのインストール
推奨方法:公式PPAを使用
# システムを更新
sudo apt update
sudo apt upgrade
# ソフトウェアプロパティをインストール
sudo apt install software-properties-common
# Ansible PPAを追加
sudo add-apt-repository --yes --update ppa:ansible/ansible
# Ansibleをインストール
sudo apt install ansible
バージョン確認:
ansible --version
CentOS/RHELでのインストール
# EPELリポジトリを有効化
sudo dnf install epel-release
# Ansibleをインストール
sudo dnf install ansible
# バージョン確認
ansible --version
pipでのインストール
Python環境がある場合:
# pipでインストール
pip install ansible
# または特定バージョン
pip install ansible==2.15.0
この方法なら、最新版がすぐに使えます。
macOSでのインストール
Homebrewを使用:
brew install ansible
これが最も簡単な方法ですね。
初期設定と動作確認
SSH鍵の設定
Ansibleは基本的にSSH経由で接続するので、パスワード認証ではなく鍵認証を設定しましょう。
SSH鍵の生成:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
公開鍵をマネージドノードに配布:
ssh-copy-id user@managed-node-ip
これで、パスワードなしでSSH接続できるようになります。
Inventoryファイルの作成
最初のInventoryファイルを作りましょう。
hosts.ini:
[test]
192.168.1.10 ansible_user=ubuntu
192.168.1.11 ansible_user=ubuntu
ansible_python_interpreter=/usr/bin/python3
ファイルの説明:
[test]:グループ名ansible_user:SSH接続に使うユーザーansible_python_interpreter:Pythonのパス
疎通確認
Ansibleが正しく動作するか確認します。
pingモジュールで確認:
ansible -i hosts.ini test -m ping
成功すると:
192.168.1.10 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.11 | SUCCESS => {
"changed": false,
"ping": "pong"
}
すべてのサーバーから “pong” が返ってくれば成功です!
アドホックコマンドを試す
アドホックコマンドは、Playbookを書かずに単発でコマンドを実行する方法です。
例:uptimeを確認
ansible -i hosts.ini test -a "uptime"
例:ディスク使用量を確認
ansible -i hosts.ini test -a "df -h"
簡単な確認作業に便利ですよ。
最初のPlaybookを書いてみよう

シンプルなPlaybookの例
Nginxをインストールして起動する、基本的なPlaybookを作りましょう。
nginx.yml:
---
- name: NginxをインストールしてWebサーバーを構築
hosts: webservers
become: yes
tasks:
- name: Nginxパッケージをインストール
apt:
name: nginx
state: present
update_cache: yes
- name: Nginxサービスを起動
service:
name: nginx
state: started
enabled: yes
- name: デフォルトのindex.htmlを配置
copy:
content: "<h1>Hello from Ansible!</h1>"
dest: /var/www/html/index.html
mode: '0644'
Inventoryファイル:
[webservers]
web1.example.com
web2.example.com
実行:
ansible-playbook -i hosts.ini nginx.yml
これだけで、複数のサーバーにWebサーバーが構築されます!
Playbookの構造を理解する
主要な要素:
name
何をするPlaybookなのか、説明を書きます。
hosts
どのグループのサーバーに実行するか指定します。
become
root権限で実行する場合は yes にします。
tasks
実行するタスクのリストです。
各タスクの構造:
name:タスクの説明- モジュール名(例:
apt、service) - モジュールのパラメータ
読みやすく、意図が分かりやすい構造ですよね。
変数の使い方
変数の定義
繰り返し使う値は、変数にすると管理しやすくなります。
Playbook内で定義:
---
- name: 変数を使った設定
hosts: webservers
become: yes
vars:
nginx_port: 8080
server_name: example.com
tasks:
- name: Nginxをインストール
apt:
name: nginx
state: present
- name: ポート番号を表示
debug:
msg: "Nginxは{{ nginx_port }}番ポートで起動します"
{{ 変数名 }} で変数を参照できます。
Inventory内の変数
ホスト変数:
[webservers]
web1.example.com http_port=80
web2.example.com http_port=8080
グループ変数:
[webservers:vars]
ansible_user=ubuntu
nginx_worker_processes=4
サーバーごと、グループごとに異なる値を設定できるんです。
変数ファイルの分離
変数が多い場合は、別ファイルに分けると管理しやすくなります。
vars/main.yml:
---
nginx_port: 80
nginx_user: www-data
ssl_certificate_path: /etc/ssl/certs/server.crt
Playbookから読み込み:
---
- name: 変数ファイルを使用
hosts: webservers
become: yes
vars_files:
- vars/main.yml
tasks:
- name: 設定を表示
debug:
msg: "Nginxポート: {{ nginx_port }}"
設定と処理を分離できて、見通しが良くなりますね。
テンプレートの活用
Jinja2テンプレート
Ansibleでは、Jinja2テンプレートを使って動的に設定ファイルを生成できます。
templates/nginx.conf.j2:
server {
listen {{ nginx_port }};
server_name {{ server_name }};
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Playbookでテンプレートを展開:
---
- name: Nginx設定ファイルをテンプレートから生成
hosts: webservers
become: yes
vars:
nginx_port: 80
server_name: example.com
tasks:
- name: Nginx設定ファイルを配置
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: '0644'
notify: Nginxを再起動
handlers:
- name: Nginxを再起動
service:
name: nginx
state: restarted
変数の値に応じて、サーバーごとに異なる設定ファイルが生成されます。
条件分岐
テンプレート内で条件分岐も使えます。
{% if enable_ssl %}
server {
listen 443 ssl;
ssl_certificate {{ ssl_cert_path }};
ssl_certificate_key {{ ssl_key_path }};
}
{% endif %}
柔軟な設定が可能になるんです。
Handlersの使い方
Handlersとは
Handlersは、特定の条件で実行されるタスクです。
設定ファイルが変更されたときだけサービスを再起動する、といった使い方ができます。
例:
---
- name: Handlersの例
hosts: webservers
become: yes
tasks:
- name: Nginx設定ファイルを更新
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
notify: Nginxを再起動
- name: index.htmlを更新
copy:
src: files/index.html
dest: /var/www/html/index.html
# このタスクではhandlerは呼ばれない
handlers:
- name: Nginxを再起動
service:
name: nginx
state: restarted
ポイント:
notifyでHandlerを呼び出す- Handlersはすべてのタスクが終わった後に実行される
- 複数回呼ばれても、実行は1回だけ
不要な再起動を避けられて、効率的なんです。
Roleで構成を整理する
Roleとは
Roleは、関連する設定をまとめた再利用可能な単位です。
複雑なPlaybookを、論理的な単位に分割して管理できます。
Roleの構造
標準的なディレクトリ構造:
roles/
nginx/
tasks/
main.yml
handlers/
main.yml
templates/
nginx.conf.j2
files/
index.html
vars/
main.yml
defaults/
main.yml
meta/
main.yml
各ディレクトリの役割:
- tasks:実行するタスク
- handlers:Handler定義
- templates:Jinja2テンプレート
- files:配布する静的ファイル
- vars:変数定義
- defaults:デフォルト変数
- meta:Roleの依存関係
Roleの作成
ディレクトリを作成:
mkdir -p roles/nginx/{tasks,handlers,templates,files,vars,defaults}
roles/nginx/tasks/main.yml:
---
- name: Nginxをインストール
apt:
name: nginx
state: present
- name: Nginx設定ファイルを配置
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Nginxを再起動
- name: Nginxを起動
service:
name: nginx
state: started
enabled: yes
roles/nginx/handlers/main.yml:
---
- name: Nginxを再起動
service:
name: nginx
state: restarted
roles/nginx/defaults/main.yml:
---
nginx_port: 80
nginx_worker_processes: auto
Roleの使用
site.yml:
---
- name: WebサーバーをRoleでセットアップ
hosts: webservers
become: yes
roles:
- nginx
たったこれだけで、nginxロールのすべての設定が適用されます。
複数のRoleを組み合わせ:
---
- name: フルスタックサーバー構築
hosts: appservers
become: yes
roles:
- common
- nginx
- php
- mysql
- application
Role単位で管理すると、再利用性が高まるんです。
実践的な使用例
例1:複数サーバーへのパッケージ一括インストール
playbook:
---
- name: 必要なパッケージをインストール
hosts: all
become: yes
vars:
packages:
- vim
- git
- curl
- htop
- tmux
tasks:
- name: パッケージをインストール
apt:
name: "{{ packages }}"
state: present
update_cache: yes
リスト形式で複数のパッケージを一度に指定できます。
例2:ユーザーとSSH鍵の管理
---
- name: ユーザー管理
hosts: all
become: yes
vars:
admin_users:
- name: alice
ssh_key: "ssh-rsa AAAAB3NzaC1..."
- name: bob
ssh_key: "ssh-rsa AAAAB3NzaC1..."
tasks:
- name: 管理者ユーザーを作成
user:
name: "{{ item.name }}"
groups: sudo
shell: /bin/bash
create_home: yes
loop: "{{ admin_users }}"
- name: SSH公開鍵を配置
authorized_key:
user: "{{ item.name }}"
key: "{{ item.ssh_key }}"
state: present
loop: "{{ admin_users }}"
複数のユーザーをループで一括作成できます。
例3:Dockerのインストールと設定
---
- name: Dockerをインストール
hosts: docker_hosts
become: yes
tasks:
- name: 古いバージョンを削除
apt:
name:
- docker
- docker-engine
- docker.io
state: absent
- name: 必要なパッケージをインストール
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
- name: Docker GPGキーを追加
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Dockerリポジトリを追加
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Docker CEをインストール
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
state: present
update_cache: yes
- name: ユーザーをdockerグループに追加
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
- name: Dockerサービスを起動
service:
name: docker
state: started
enabled: yes
複雑なセットアップも、一度書けば何度でも再利用できますね。
例4:Let’s Encrypt SSL証明書の取得
---
- name: Let's Encrypt証明書を取得
hosts: webservers
become: yes
vars:
domain: example.com
email: admin@example.com
tasks:
- name: certbotをインストール
apt:
name:
- certbot
- python3-certbot-nginx
state: present
- name: SSL証明書を取得
command: >
certbot --nginx
-d {{ domain }}
-m {{ email }}
--agree-tos
--non-interactive
args:
creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
- name: 自動更新のcronを設定
cron:
name: "Certbot renewal"
minute: "0"
hour: "3"
job: "certbot renew --quiet"
SSL証明書の取得から自動更新まで、完全自動化できます。
条件分岐とループ

whenによる条件分岐
OSによって処理を分ける:
---
- name: OS別のパッケージインストール
hosts: all
become: yes
tasks:
- name: Debianでパッケージをインストール
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Red Hatでパッケージをインストール
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
変数による条件分岐:
tasks:
- name: 本番環境でのみ実行
command: /opt/app/production-setup.sh
when: environment == "production"
loopによる繰り返し
リストをループ:
tasks:
- name: 複数のファイルをコピー
copy:
src: "{{ item }}"
dest: /etc/config/
loop:
- config1.conf
- config2.conf
- config3.conf
辞書をループ:
tasks:
- name: 複数のユーザーを作成
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop:
- { name: 'alice', uid: 1001 }
- { name: 'bob', uid: 1002 }
- { name: 'charlie', uid: 1003 }
繰り返し処理が簡潔に書けて便利です。
ベストプラクティス
1. べき等性を保つ
Playbookは何度実行しても同じ結果になるよう書きましょう。
良い例:
- name: ディレクトリを作成
file:
path: /opt/myapp
state: directory
既にディレクトリがあれば何もしない、なければ作成します。
悪い例:
- name: ディレクトリを作成
command: mkdir /opt/myapp
既にあるとエラーになってしまいます。
2. 適切な粒度でRoleを分割
良い分割:
- common(共通設定)
- nginx(Webサーバー)
- mysql(データベース)
- application(アプリケーション)
悪い分割:
- すべてを一つのRoleに詰め込む
- タスク一つごとにRoleを作る
適度な粒度が重要ですね。
3. 変数名に命名規則を使う
推奨:
nginx_port: 80
nginx_worker_processes: 4
mysql_root_password: "secret"
Role名をプレフィックスにすると、変数の衝突を避けられます。
4. secretsを安全に管理
パスワードなどの機密情報は、Ansible Vaultで暗号化しましょう。
暗号化:
ansible-vault encrypt vars/secrets.yml
使用:
ansible-playbook site.yml --ask-vault-pass
平文でパスワードを保存するのは危険です。
5. ドキュメントとしても読みやすく
- name: 分かりやすい説明をつける
apt:
name: nginx
state: present
# nameを省略しないこと
説明があれば、後で見返したときに理解しやすくなります。
6. テスト環境で検証
本番環境にいきなり適用せず、必ずテスト環境で検証しましょう。
- name: テスト環境での動作確認
hosts: staging
# ...
トラブルシューティング
問題1:SSH接続できない
症状:
fatal: [host]: UNREACHABLE!
確認事項:
手動でSSH接続できるか:
ssh user@host
Inventoryの設定確認:
[servers]
host ansible_user=ubuntu ansible_port=22
SSH鍵のパーミッション:
chmod 600 ~/.ssh/id_rsa
問題2:権限エラー
症状:
Permission denied
解決策:
become を使う:
- name: root権限が必要な操作
become: yes
tasks:
- ...
sudoパスワードを指定:
ansible-playbook site.yml --ask-become-pass
問題3:Playbookが冪等でない
症状:
実行するたびに「changed」になる
原因:commandやshellモジュールを使っている
解決策:
適切なモジュールを使う:
# 悪い例
- command: mkdir /opt/myapp
# 良い例
- file:
path: /opt/myapp
state: directory
creates/removesを使う:
- command: /opt/install.sh
args:
creates: /opt/myapp/installed
問題4:変数が展開されない
症状:{{ variable }} がそのまま出力される
原因:
YAMLの構文エラー
解決策:
クォートで囲む:
# エラー
- debug:
msg: {{ variable }}
# 正しい
- debug:
msg: "{{ variable }}"
行頭が変数の場合は必ずクォートが必要です。
デバッグ方法
verboseモード:
ansible-playbook site.yml -vvv
-vの数を増やすと、詳細な情報が出力されます。
デバッグモジュール:
- debug:
var: ansible_facts
変数の内容を確認できて便利ですよ。
チェックモード(Dry Run):
ansible-playbook site.yml --check
実際には実行せず、何が変更されるか確認できます。
Ansible Galaxyの活用
Ansible Galaxyとは
Ansible Galaxyは、コミュニティが作成したRoleを共有するプラットフォームです。
車輪の再発明をせず、既存のRoleを活用できるんです。
Roleの検索とインストール
Galaxyで検索:
https://galaxy.ansible.com/
インストール:
ansible-galaxy install geerlingguy.nginx
使用:
---
- name: Nginxをインストール
hosts: webservers
become: yes
roles:
- geerlingguy.nginx
高品質なRoleがたくさん公開されています。
requirements.ymlで管理
requirements.yml:
---
roles:
- name: geerlingguy.nginx
version: 3.1.4
- name: geerlingguy.mysql
version: 4.3.3
一括インストール:
ansible-galaxy install -r requirements.yml
依存関係を明示的に管理できて便利です。
まとめ
Ansibleは、サーバー構成管理を自動化する強力でシンプルなツールです。
この記事のポイント:
- Ansibleはエージェントレスの構成管理ツール
- YAMLで読みやすい設定を記述
- Inventoryで管理対象を定義
- Playbookで作業手順を記述
- Moduleで様々な操作を実行
- Roleで構成を整理して再利用
- べき等性で安全な実行を保証
- 変数とテンプレートで柔軟な設定
- Handlersで効率的なサービス管理
- Ansible Galaxyで既存Roleを活用
手作業でのサーバー管理から解放されて、効率的で確実なインフラ運用ができるようになります。
最初は小さなPlaybookから始めて、徐々に複雑な構成に挑戦していくのがおすすめです。
一度Ansibleを覚えてしまえば、10台でも100台でも、同じ手間でサーバー管理ができるようになりますよ。
さあ、あなたのインフラもAnsibleで自動化して、運用負荷を劇的に削減してみませんか?作業時間が大幅に短縮されるはずです!

コメント