Ansible入門|インフラ自動化の基礎と初めての構成管理

サーバー管理の手間を劇的に削減したいエンジニアに向けて、Ansibleを使ったインフラ自動化の基礎を完全解説します。本記事では、AnsibleのインストールからPlaybook作成、実践的な構成管理手法まで、初心者でも理解できるように丁寧に解説します。

Ansibleでインフラ自…

Ansibleを使いこなすには、まず「エージェントレス」「YAML形式」「冪等性」という3つの基本概念を理解することが不可欠です。これらを押さえることで、他の自動化ツールとの違いやAnsibleの強みが明確になります。

エージェントレスで管理対象…

Ansibleは管理対象のサーバーにエージェントをインストールする必要がありません。SSH経由で直接コマンドを実行するため、管理対象のリソース消費が少なく、導入コストが低いのが特徴です。これは特に多数のサーバーを管理する場合に大きなメリットとなります。

YAML形式で直感的に記述…

AnsibleのPlaybookはYAML形式で記述されます。YAMLは人間にとって読みやすい構文で、インデントで階層構造を表現するため、構成管理のルールを簡潔に記述できます。JSON形式よりもはるかにメンテナンスしやすいのが特徴です。

冪等性で同じ操作を繰り返し…

Ansibleは冪等性(Idempotency)を重視した設計になっています。同じPlaybookを複数回実行しても、システムの状態が変わらないように設計されています。これにより、誤った操作によるシステム障害のリスクを最小限に抑えることができます。

Ansibleの導入環境を…

Ansibleを使い始めるには、まず実行環境を整える必要があります。ここでは、Ansibleを動作させるための基本的な環境構築手順を解説します。

Ansibleを実行するた…

Ansibleを実行するには、以下の環境が必要です。

  • Python 3.8以上(Ansible 2.10以降)
  • SSH接続が可能なLinux/Unix系OS
  • 管理対象サーバーへのSSHアクセス権限

Windows環境でAnsibleを実行する場合は、WSL(Windows Subsystem for Linux)を利用するか、専用のAnsible for Windowsを使用します。

Ansibleのインストー…

Ansibleのインストールは、Pythonのパッケージ管理ツールpipを使用するのが一般的です。以下のコマンドでインストールできます。

OSインストールコマンド備考
Ubuntu/Debiansudo apt update && sudo apt install -y ansible公式リポジトリからインストール
CentOS/RHELsudo yum install -y epel-release && sudo yum install -y ansibleEPELリポジトリ経由でインストール
macOSbrew install ansibleHomebrew経由でインストール
Windowspip install ansibleWSL経由で実行

インストール後、バージョンを確認して正しくインストールされたことを確認します。

ansible --version

出力例: ansible [core 2.15.1]

config file = /etc/ansible/ansible.cfg

configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']

ansible python module location = /usr/lib/python3/dist-packages/ansible

executable location = /usr/bin/ansible

python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]

Ansibleの基本的なデ…

Ansibleを効率的に使用するためには、プロジェクトごとにディレクトリ構成を整理することが重要です。一般的なAnsibleプロジェクトのディレクトリ構成は以下の通りです。

my_ansible_project/
├── ansible.cfg          # Ansible設定ファイル
├── inventory/           # インベントリファイル
│   ├── production       # 実行環境用インベントリ
│   ├── staging          # 検証環境用インベントリ
│   └── development      # 開発環境用インベントリ
├── group_vars/          # グループ変数
├── host_vars/           # ホスト変数
├── roles/               # ロールディレクトリ
│   ├── common/          # 共通ロール
│   ├── webserver/       # Webサーバーロール
│   └── database/        # データベースロール
├── playbooks/           # Playbookファイル
│   ├── site.yml         # メインPlaybook
│   └── webserver.yml    # Webサーバー専用Playbook
└── files/               # 静的ファイル
└── templates/           # テンプレートファイル

この構成により、プロジェクトの規模が大きくなっても、ファイルの整理と管理が容易になります。

インベントリファイルで管理…

Ansibleでサーバーを管理するには、まず管理対象のサーバーをインベントリファイルに定義する必要があります。インベントリファイルは、Ansibleが操作するサーバーの一覧とグループ化を定義するファイルです。

インベントリファイルの基本構文

インベントリファイルはINI形式またはYAML形式で記述できます。最も一般的なINI形式の例を以下に示します。

[webservers]
web1.example.com
web2.example.com

[dbservers]
db1.example.com
db2.example.com

[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsa

この例では、webserversグループとdbserversグループを定義し、各グループに属するサーバーを列挙しています。また、all:varsセクションで全てのサーバーに共通の変数を定義しています。

動的インベントリの活用

クラウド環境や大規模なインフラでは、サーバーのIPアドレスやホスト名が頻繁に変更されることがあります。このような環境では、静的なインベントリファイルではなく、動的インベントリを使用することで、常に最新のサーバー情報を取得できます。

AWS、Azure、GCPなどの主要なクラウドプロバイダーでは、公式の動的インベントリスクリプトが提供されています。例えば、AWS EC2用の動的インベントリスクリプトは以下のように使用します。

# 必要なPythonパッケージをインストール
pip install boto3

実行

./ec2.py --list

動的インベントリを使用することで、クラウド環境のサーバー情報を自動的に取得し、Ansibleで管理することができます。

インベントリ変数の活用

インベントリファイルでは、サーバーやグループに対して変数を定義することができます。これにより、同じPlaybookを異なる環境で実行する際に、環境ごとの設定を柔軟に切り替えることができます。

例えば、開発環境と本番環境で異なるポート番号を使用する場合、以下のように変数を定義します。

[webservers:vars]
http_port=8080

[webservers:children]
web_production
web_development

[web_production:vars]
http_port=80

[web_development:vars]
http_port=8000

このように、グループやサーバーごとに変数を定義することで、環境に応じた柔軟な設定が可能になります。

Playbookでタスクを…

AnsibleのPlaybookは、YAML形式で記述された自動化スクリプトです。Playbookには、実行するタスクや条件、変数などを定義し、Ansibleを使ってシステムを構成管理します。

Playbookの基本構造

Playbookは、1つ以上のPlayで構成されます。各Playには、実行対象のホストグループ、実行するタスク、使用する変数などを定義します。以下に基本的なPlaybookの例を示します。

---
- name: Configure web servers
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    docroot: /var/www/html

  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present
      when: ansible_os_family == 'Debian'

    - name: Install Apache (RedHat)
      yum:
        name: httpd
        state: present
      when: ansible_os_family == 'RedHat'

    - name: Configure Apache
      template:
        src: templates/httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: restart apache

  handlers:
    - name: restart apache
      service:
        name: apache2
        state: restarted
      when: ansible_os_family == 'Debian'

このPlaybookでは、webserversグループに属するサーバーにApacheをインストールし、設定ファイルを配置してApacheを再起動します。become: yesを指定することで、root権限でタスクを実行します。

モジュールを活用したタスク実行

Ansibleには、様々なモジュールが用意されており、これらを使用することで、システムの構成管理を効率的に行うことができます。以下に代表的なモジュールとその用途を示します。

カテゴリモジュール名用途使用例
パッケージ管理aptDebian系OSでのパッケージ管理apt: name=nginx state=present
パッケージ管理yumRedHat系OSでのパッケージ管理yum: name=httpd state=present
サービス管理serviceサービスの起動・停止・再起動service: name=nginx state=started
ファイル管理copyファイルのコピーcopy: src=files/index.html dest=/var/www/html/
ファイル管理templateテンプレートファイルのレンダリングと配置template: src=templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
コマンド実行command任意のコマンドを実行command: /usr/bin/apt-get update
ユーザー管理userユーザーの作成・削除・管理user: name=deploy state=present
グループ管理groupグループの作成・削除・管理group: name=developers state=present

これらのモジュールを組み合わせることで、複雑な構成管理を自動化することができます。

条件分岐とループ処理

AnsibleのPlaybookでは、条件分岐やループ処理を使用して、柔軟なタスク実行が可能です。以下に代表的な構文を示します。

条件分岐(when)

whenを使用することで、特定の条件が満たされた場合にのみタスクを実行することができます。

tasks:
  - name: Install Nginx on Debian
    apt:
      name: nginx
      state: present
    when: ansible_os_family == 'Debian'

  - name: Install Nginx on RedHat
    yum:
      name: nginx
      state: present
    when: ansible_os_family == 'RedHat'

ループ処理(loop)

loopを使用することで、同じタスクを複数のアイテムに対して実行することができます。

tasks:
  - name: Create users
    user:
      name: "{{ item }}"
      state: present
      groups: developers
    loop:
      - alice
      - bob
      - charlie

ブロック(block)

blockを使用することで、関連するタスクをグループ化し、エラー処理や条件付き実行を行うことができます。

tasks:
  - block:
      - name: Install required packages
        apt:
          name: "{{ item }}"
          state: present
        loop:
          - nginx
          - php
          - mysql-server

      - name: Configure Nginx
        template:
          src: templates/nginx.conf.j2
          dest: /etc/nginx/nginx.conf
    when: ansible_os_family == 'Debian'
    rescue:
      - name: Rollback changes
        command: /usr/bin/apt-get remove -y nginx php mysql-server

ロールで再利用可能な構成を…

Ansibleのロール機能を使用すると、再利用可能な構成をモジュール化することができます。ロールを使用することで、プロジェクト間で共通の構成を共有したり、複雑なPlaybookを整理することができます。

ロールの基本構造

ロールは、特定の機能やサービスを提供するための一連のタスク、変数、ファイル、テンプレートなどをまとめたものです。ロールの基本的なディレクトリ構成は以下の通りです。

roles/
└── webserver/
    ├── defaults/       # デフォルト変数
    │   └── main.yml
    ├── files/          # 静的ファイル
    │   └── index.html
    ├── handlers/       # ハンドラー
    │   └── main.yml
    ├── tasks/          # タスク
    │   └── main.yml
    ├── templates/      # テンプレートファイル
    │   └── nginx.conf.j2
    ├── tests/          # テスト用Playbook
    │   └── test.yml
    └── vars/           # 変数
        └── main.yml

各ディレクトリには、特定の目的を持つファイルが配置されます。例えば、tasks/main.ymlにはロールのメインタスクが、handlers/main.ymlにはロールのハンドラーが定義されます。

ロールの作成手順

ロールを作成するには、以下の手順に従います。

  1. ロールのディレクトリ構造を作成する
  2. 各ディレクトリに必要なファイルを配置する
  3. Playbookからロールを呼び出す

例えば、Webサーバーを構成するロールを作成する場合、以下のようになります。

# ロールのディレクトリ構造を作成
mkdir -p roles/webserver/{tasks,handlers,templates,files,defaults,vars,tests}

tasks/main.ymlにメインタスクを定義

cat > roles/webserver/tasks/main.yml << 'EOF' --- - name: Install Nginx apt: name: nginx state: present when: ansible_os_family == 'Debian' - name: Configure Nginx template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx - name: Deploy web content copy: src: index.html dest: /var/www/html/index.html EOF

handlers/main.ymlにハンドラーを定義

cat > roles/webserver/handlers/main.yml << 'EOF' --- - name: restart nginx service: name: nginx state: restarted EOF

templates/nginx.conf.j2にテンプレートを作成

cat > roles/webserver/templates/nginx.conf.j2 << 'EOF' server { listen 80; server_name {{ ansible_hostname }}; root /var/www/html; index index.html; location / { try_files $uri $uri/ =404; } } EOF

defaults/main.ymlにデフォルト変数を定義

cat > roles/webserver/defaults/main.yml << 'EOF' --- http_port: 80 EOF

これで、webserverロールが完成しました。このロールをPlaybookから呼び出すことで、Webサーバーを簡単に構成することができます。

ロールをPlaybookで…

作成したロールをPlaybookで使用するには、rolesセクションにロール名を指定します。以下に例を示します。

---
- name: Configure web servers
  hosts: webservers
  become: yes

  roles:
    - webserver

このPlaybookを実行すると、webserverロールが呼び出され、Webサーバーの構成が自動的に行われます。

Ansible Galax…

Ansible Galaxyは、Ansibleのロールやモジュールを共有・再利用するためのプラットフォームです。Ansible Galaxyを活用することで、既存のロールを利用して構成管理を迅速に行うことができます。

Ansible Galax…

Ansible Galaxyを使用するには、まずAnsible Galaxyにログインする必要があります。以下のコマンドでログインします。

ansible-galaxy login

ログイン後、以下のコマンドでロールを検索することができます。

ansible-galaxy search "nginx"

検索結果から、必要なロールをインストールします。例えば、geerlingguy.nginxロールをインストールするには、以下のコマンドを実行します。

ansible-galaxy install geerlingguy.nginx

インストールされたロールは、rolesディレクトリに配置されます。このロールをPlaybookで使用するには、以下のように指定します。

---
- name: Configure Nginx
  hosts: webservers
  become: yes

  roles:
    - geerlingguy.nginx

Ansible Galax…

Ansible Galaxyには、様々な用途に対応したロールが公開されています。以下に代表的なロールを紹介します。

ロール名用途GitHubスター数(2024年1月現在)
geerlingguy.apacheApache HTTP Serverの構成1,200+
geerlingguy.mysqlMySQLサーバーの構成1,100+
geerlingguy.postgresqlPostgreSQLサーバーの構成800+
geerlingguy.nodejsNode.jsのインストールと構成600+
geerlingguy.dockerDockerのインストールと構成1,500+
geerlingguy.gitGitのインストールと構成400+
geerlingguy.pipPython pipのインストールと構成300+

これらのロールを活用することで、構成管理の効率を大幅に向上させることができます。

Ansibleの実践的な活…

Ansibleを実際の業務で活用する際の具体的なシナリオを紹介します。これらのシナリオを参考に、自分の業務にAnsibleを適用してみましょう。

Webサーバーの一括デプロ…

Webサーバーを複数台管理する場合、Ansibleを使用することで、一括デプロイと構成管理を自動化することができます。以下に具体的なPlaybookの例を示します。

---
- name: Deploy and configure web servers
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    docroot: /var/www/html

  tasks:
    - name: Install required packages
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - php
        - php-fpm
        - php-mysql

    - name: Configure Nginx
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: restart nginx

    - name: Create document root
      file:
        path: "{{ docroot }}"
        state: directory
        mode: '0755'

    - name: Deploy web application
      copy:
        src: files/webapp/
        dest: "{{ docroot }}/"
        owner: www-data
        group: www-data
        mode: '0755'

    - name: Enable Nginx site
      file:
        src: /etc/nginx/sites-available/default
        dest: /etc/nginx/sites-enabled/default
        state: link
      notify: restart nginx

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

このPlaybookを実行することで、Webサーバーの一括デプロイと構成管理を自動化することができます。

データベースサーバーの構成管理

データベースサーバーを管理する場合も、Ansibleを使用することで、構成管理を自動化することができます。以下にMySQLサーバーの構成管理用Playbookの例を示します。

---
- name: Configure MySQL server
  hosts: dbservers
  become: yes
  vars:
    mysql_root_password: "secure_password"
    mysql_databases:
      - name: app_db
        encoding: utf8
        collation: utf8_general_ci
    mysql_users:
      - name: app_user
        host: "%"
        password: "user_password"
        priv: "app_db.*:ALL"

  tasks:
    - name: Install MySQL server
      apt:
        name: mysql-server
        state: present
      when: ansible_os_family == 'Debian'

    - name: Install MySQL server (RedHat)
      yum:
        name: mysql-server
        state: present
      when: ansible_os_family == 'RedHat'

    - name: Set MySQL root password
      mysql_user:
        name: root
        password: "{{ mysql_root_password }}"
        host_all: yes
        login_unix_socket: /var/run/mysqld/mysqld.sock

    - name: Create databases
      mysql_db:
        name: "{{ item.name }}"
        encoding: "{{ item.encoding }}"
        collation: "{{ item.collation }}"
        state: present
      loop: "{{ mysql_databases }}"

    - name: Create users
      mysql_user:
        name: "{{ item.name }}"
        host: "{{ item.host }}"
        password: "{{ item.password }}"
        priv: "{{ item.priv }}"
        state: present
      loop: "{{ mysql_users }}"
      no_log: true

このPlaybookを実行することで、MySQLサーバーの構成管理を自動化することができます。

CI/CDパイプラインへの…

AnsibleはCI/CDパイプラインに統合することで、デプロイメントの自動化を実現することができます。以下にGitHub Actionsを使用したCI/CDパイプラインの例を示します。

name: Ansible CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: Install Ansible
        run: pip install ansible

      - name: Run Playbook
        run: ansible-playbook -i inventory/production playbooks/site.yml
        env:
          ANSIBLE_HOST_KEY_CHECKING: False

このCI/CDパイプラインを使用することで、コードの変更を自動的に検知し、Ansible Playbookを実行して構成管理を自動化することができます。

Ansibleのベストプラ…

Ansibleを効果的に活用するためのベストプラクティスを紹介します。これらのベストプラクティスを実践することで、Ansibleの運用効率を向上させることができます。

Playbookの整理とモ…

Playbookを整理し、モジュール化することで、保守性と再利用性を向上させることができます。以下にベストプラクティスを示します。

  • ロールの活用:関連するタスクをロールにまとめ、再利用可能な構成を作成します。
  • 変数の整理:環境ごとの変数をgroup_varsやhost_varsに分離し、管理します。
  • タスクの分割:大きなPlaybookを小さなPlaybookに分割し、管理しやすくします。
  • テンプレートの活用:設定ファイルをテンプレート化し、動的な値を埋め込みます。

セキュリティのベストプラク…

Ansibleを使用する際には、セキュリティに注意することが重要です。以下にセキュリティのベストプラクティスを示します。

  • SSH鍵の管理:管理対象サーバーへのSSHアクセスには、鍵ベース認証を使用します。パスワード認証は無効にします。
  • 変数の暗号化:機密情報を含む変数は、Ansible Vaultを使用して暗号化します。
  • 最小権限の原則:Playbookの実行には、必要最小限の権限で実行します。becomeを使用する場合は、必要なタスクのみに限定します。
  • ネットワークセキュリティ:管理対象サーバーへのアクセスは、必要なポートのみに限定します。ファイアウォールを適切に設定します。

パフォーマンスの最適化

Ansibleの実行パフォーマンスを最適化することで、大規模なインフラの構成管理を効率的に行うことができます。以下にパフォーマンス最適化のベストプラクティスを示します。

  • 並列実行の活用:大量のサーバーを管理する場合は、並列実行(forks)を活用します。デフォルトのforksは5ですが、必要に応じて増やします。
  • キャッシュの活用:fact gatheringの結果をキャッシュすることで、Playbookの実行時間を短縮します。fact cachingを有効にします。
  • モジュールの選択:可能な限り、Ansibleの組み込みモジュールを使用します。カスタムモジュールよりも高速に実行されます。
  • 冗長なタスクの排除:冪等性を活かして、同じタスクを複数回実行しないようにします。

Ansibleのトラブルシ…

Ansibleを使用していると、様々な問題に遭遇することがあります。ここでは、一般的なトラブルシューティング手法を紹介します。

実行時のエラー対応

Ansibleの実行時にエラーが発生した場合は、以下の手順で対応します。

  1. エラーメッセージの確認:Ansibleの出力からエラーメッセージを確認し、原因を特定します。
  2. 詳細な出力の取得:-vvvオプションを使用して、詳細な出力を取得します。
  3. タスクのデバッグ:failed_whenやignore_errorsを使用して、タスクの実行を制御します。
  4. ローカルでのテスト:管理対象サーバーと同様の環境で、ローカルでタスクをテストします。

例えば、以下のようにタスクをデバッグします。

tasks:
  - name: Check disk space
    command: df -h
    register: disk_space
    changed_when: false

  - name: Debug disk space
    debug:
      var: disk_space

SSH接続のトラブルシュー…

SSH接続に関する問題が発生した場合は、以下の手順で対応します。

  1. SSH接続
    ABOUT ME
    たから
    サラリーマンをしながら開業して経営やってます。 今年、本業で独立・別事業を起業予定です。 ◆経験:IT講師/インフラエンジニア/PM/マネジメント/採用/運用・保守・構築・設計 ◆取得資格:CCNA/CCNP/LPIC-1/AZ-900/FE/サーティファイC言語 ◆サイドビジネス:アパレル事業/複数のWEBメディアを運営