4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

cloud-init × Ansible - VM作成時にAnsibleを自動実行しよう

Last updated at Posted at 2025-12-13

こちらはAnsible Advent Calendar 2025 14日目の記事です。

クラウドやハイパーバイザーで作成した仮想マシンの初期構成を自動化する際、cloud-initを利用するケースが多くあります。

cloud-initではバージョン22.3からAnsibleモジュールが公式に提供されており、cloud-initの処理の中でAnsibleを実行できるようになりました。

cloud-initだけでも十分ですが、Ansibleを呼び出すことで次の利点があります。

  • 高度な構成管理: Ansibleの豊富な機能により、複雑な構成を簡潔に定義できる
  • 再利用性: 既存のPlaybookやロールをそのまま活用できる
  • 構成の一貫性: cloud-initを利用できない環境でも同じPlaybookを使用することで、構成管理を統一できる

Ansible Playbookの準備

今回の検証で使用するPlaybookを作成します。

サンプルコードはGitHubで公開していますので、そのまま利用できます。
https://github.com/yamause/ansible-advent-calendar-2025/blob/main/playbooks/site.yml

このPlaybookでは次のことを行います。

  • cowsayパッケージのインストール
  • cowsayコマンドの実行
  • /tmp/advent_message.txt に実行結果を保存
# site.yml
---
- name: Ansible Advent Calendar 2025 Day 14 - cloud-init example playbook
  hosts: localhost
  connection: local
  gather_facts: false
  tasks:
    - name: Install cowsay package
      ansible.builtin.package:
        name: cowsay
        state: present

    - name: Display the Advent Calendar message using cowsay
      ansible.builtin.command: /usr/games/cowsay -f tux "Happy Holidays from Ansible Advent Calendar 2025!"
      register: cowsay_output
      changed_when: false

    - name: Create a Advent Calendar message file
      ansible.builtin.copy:
        dest: /tmp/advent_message.txt
        content: "{{ cowsay_output.stdout }}"
        mode: '0644'

cloud-configを書いてみよう

これが今回のサンプルコンフィグの全体です。詳細を見ていきましょう。

#cloud-config
package_update: true
package_upgrade: true
packages:
  - git

ansible:
  install_method: pip
  package_name: ansible-core
  setup_controller:
    repositories:
      - source: https://github.com/yamause/ansible-advent-calendar-2025.git
        path: /root/ansible-advent-calendar-2025
    run_ansible:
      - playbook_name: site.yml
        playbook_dir: /root/ansible-advent-calendar-2025/playbooks

GitHubからAnsible Playbookをダウンロードするため、事前にgitをインストールします。

package_update: true
package_upgrade: true
packages:
  - git

install_method はAnsibleをインストールする方法を distro または pip から選択します。

distroを選択すると、aptなどのパッケージ管理ツールを使ってインストールします。

pipを選択した場合、run_userの指定有無で動作が異なります。ユーザーを指定した場合はそのユーザーの環境にインストールし、指定しない場合はシステム全体のPython環境にインストールします。

ansible:
  install_method: pip
  package_name: ansible-core
  # run_user: ansible-user

setup_controller.repositoriesでは、Ansible Playbookを格納しているリポジトリの情報を記述します。setup_controllerはPlaybookの実行環境をセットアップする設定で、GitリポジトリからPlaybookをダウンロードし、このホスト上でansible-playbookコマンドを実行します。

  • source: リモートリポジトリのURLを指定する
  • path: リポジトリをクローンするディレクトリパスを指定する。既存のパスを指定するとエラーになるため、まだ存在しないパスを指定すること
ansible:
  #...
  setup_controller:
    repositories:
      - source: https://github.com/yamause/ansible-advent-calendar-2025.git
        path: /root/ansible-advent-calendar-2025

setup_controller.run_ansibleでは、実行するPlaybookと実行ディレクトリを指定します。

  • playbook_name: 実行するPlaybookのファイル名を指定する。
  • playbook_dir: Playbookが格納されているディレクトリパスを指定する。
ansible:
  #...
  setup_controller:
    #...
    run_ansible:
      - playbook_name: site.yml
        playbook_dir: /root/ansible-advent-calendar-2025/playbooks

実際に動かしてみよう

今回はAWSのEC2を利用して実行してみましょう。

UbuntuのAMIを利用して仮想マシンを作成します。

なお、Amazon Linux 2023でも試しましたが、cloud-initのバージョンが22.2であり、Ansibleモジュールが実装されていませんでした。

高度な詳細のトグルを開き、画面下部のユーザーデータ - オプションへ先ほどのcloud-configを貼り付けるか、ファイルからアップロードしてください。

仮想マシンを起動すると、自動的にcloud-initが実行されます。

ansible_cloudinit_aws.png

実行結果を確認しよう

先ほど作成した仮想マシンにログインします。

cloud-init statusコマンドで現在の実行状況を確認できます。status: doneと表示されていれば、実行が完了しています。

$ cloud-init status
status: done

Playbookで定義したファイルが無事に作成されています!

実行に失敗した場合は、以下のログファイルで詳細を確認できます。

# cloud-initの実行ログ(エラーが発生していた場合はここで確認できる)
$ sudo cat /var/log/cloud-init.log

# cloud-initの出力ログ
$ sudo cat /var/log/cloud-init-output.log
$ cat /tmp/advent_message.txt
 ____________________________________
/ Happy Holidays from Ansible Advent \
\ Calendar 2025!                     /
 ------------------------------------
   \
    \
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/

実践的な活用Tips

ここからは運用するにあたってよく遭遇する疑問にお答えします。

Ansible Galaxyからコレクションやロールをインストールしたい

標準外のコレクションを利用する場合は、事前にインストールが必要です。
以下の例では、依存するコレクションとnewrelicのロールをAnsible Galaxyからインストールしています。

ansible:
  #...
  galaxy:
    actions:
      - ['ansible-galaxy', 'collection', 'install', 'ansible.utils', 'ansible.windows']
      - ['ansible-galaxy', 'role', 'install', 'newrelic.newrelic_install']

Ansibleの実行オプションを指定したい

ansible-playbookの実行オプションは、run_ansible配下で指定できます。

ansible:
  #...
  setup_controller:
    #...
    run_ansible:
      - playbook_name: production.yml
        playbook_dir: /root/myapp/playbooks/
        vault_password_file: /root/.vault_pass.txt
        inventory: /root/myapp/inventory/
        limit: "webservers"

ソースコードを見ると、run_ansibleに指定したキーと値がそのまま実行オプションとしてコマンドに渡されることがわかります。そのため、cloud-init公式ドキュメントに記載されていないオプションも指定可能です。

def ansible_controller(cfg: dict, ansible: AnsiblePull):
    for repository in cfg.get("repositories", []):
        ansible.do_as(
            ["git", "clone", repository["source"], repository["path"]]
        )
    for args in cfg.get("run_ansible", []):
        playbook_dir = args.pop("playbook_dir")
        playbook_name = args.pop("playbook_name")
        command = [
            "ansible-playbook",
            playbook_name,
            *[f"--{key}={value}" for key, value in filter_args(args).items()],
        ]
        ansible.do_as(command, cwd=playbook_dir)

GitHub. canonical/cloud-init. cc_ansible.py

GitHubリポジトリに認証が必要な場合

リポジトリを非公開(PrivateまたはInternal)にしている場合、ダウンロード時に認証が必要です。

GitHubの場合、Personal Access Token(PAT)をURLに埋め込むことで認証できます。
リポジトリの読み取り権限があれば十分なので、PATを発行する際は必要最小限の権限を設定してください。

ただし、この方法ではcloud-init.logにURLとともにPATが記録されてしまう点に注意が必要です。

ansible:
  #...
  setup_controller:
    repositories:
      - source: https://x-access-token:<your_token>@github.com/yamause/ansible-advent-calendar-2025.git
        path: /root/ansible-advent-calendar-2025

ログに認証情報を記録したくない場合は、事前にGitの設定に認証情報を登録する方法があります。
ただし、この方法でもcloud-configや.git-credentialsに平文で保存されるため、取り扱いには十分注意してください。

ほかにいい方法があれば教えてください!

#cloud-config
write_files:
  # PlaybookをGitHubからダウンロードするためにgitの認証情報を保存したファイルを作成します。
  - path: /root/.git-credentials
    owner: root:root
    permissions: '0600'
    content: |
      https://x-access-token:<your_token>@github.com

  # Gitの認証情報ヘルパーを設定するためのファイルを作成します。
  - path: /root/.gitconfig
    content: |
      [credential]
              helper = store
    permissions: '0644'
    owner: root:root

あとがき

私は自宅で運用しているProxmox VEの構成管理をTerraformで行っています。それとあわせてcloud-initからAnsibleを呼び出すことで、VMの作成から初期設定までを完全に自動化しています。

terraform applyを実行するだけですべての設定が完了するため、構築手順を意識する必要がなく非常に快適です。この記事が皆様のインフラ自動化のヒントになれば幸いです。

参考

GitHub. canonical/cloud-init
Cloud-init documentation

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?