>開発>Ansible>[Ansible]Ansibleの基礎「動作を確認するまで」

以前、Ansibleを使おうと思って、本を読んだり調べたりしてメモっていたので、それをまとめておく。

Ansibleのテスト開発環境

今回のAnsibleのテスト開発環境は、Virtual Boxを利用する。Virtual Box上にUbuntu DesktopをインストールしてAnsibleを実行する。

構成バージョン
Virtual BoxVersion 7.0
UbuntuUbuntu 24.04.2 LTS
Ansibleの開発環境

Virtual Boxで2つの仮想環境を構築し、片方をコントロールノード、もう片方をターゲットノードとし、ユーザー名を”vboxuser”で共通させる。また、この2つの仮想環境を同じ内部ネットワーク内に設定する。

IPアドレスサブネットマスク
コントロールノード172.168.0.1255.255.255.0
ターゲットノード172.168.0.2255.255.255.0

VIrtual Boxのメニューから[Settings]を選択し、[Network]の中のAdapter2を有効にする。”Internal Network”をアタッチして[OK]すると、内部ネットワーク用のアダプターが有効になる。

Ubuntu DesktopならSettingsアプリケーションから先ほど有効にしたアダプターのIPアドレスを簡単に設定できる。

※CLIの場合は、”\etc\network\interface”などでIPアドレスを指定できたはず?

Ansibleの基本情報

Ansibleでは、操作する側の端末をコントロールノード、コントロールノードに管理される側の端末をターゲットノードに区別される。また、Ansibleの実行方法には、Ad-hocとPlaybookがある。Ad-hocは単体のコマンドやAnsibleモジュールを実行し、Playbookはyml形式などのファイルで実行する。サーバー構築する手順をplaybookにまとめて実行することで、自動化し、簡単に構築できるだけでなく、構築内容をファイルで管理できる。AnsibleはPythonで実行されるのでPythonの実行環境が必要となる。基本的にUbuntuインストールしたらPythonが入っているので特に気にする必要はないが、自身の開発環境に合わせてPythonのバージョンやPATHを変えたりする。

Ansibleをインストール

Ansibleのインストールはパッケージマネージャ、またはPythonでインストールできる。

パッケージマネージャでのインストール

$ sudo apt update
$ sudo apt install software-properties-common
$ sudo apt-add-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible

インストールとバージョンの確認する。

$ ansible --version

Pythonでのインストール

Pythonのパッケージマネージャ(pip)を利用する場合は、virtualenvを利用するのがいい。virtualenvはPythonの仮想実行環境で、一般ユーザー権限でのAnsibleの操作や異なるバージョンのAnsibleを試すことができる。同一のPythonバージョンで異なる仮想環境を管理し、用途に応じてPython環境を切りけることもできる。よって、同一バージョン内でもライブラリから異なる環境を作ることができる。Pythonのバージョンを切り替えるツールではなく、同一Python内で異なるPythonライブラリの利用環境を切り替えるためのツールと考えた方がよい。

virtualenvをインストールする。

$ sudo apt install python3-virtualenv

仮想環境を作成する。仮想環境名は任意。

$ virtualenv [仮想環境名]

仮想環境をアクティベートする。

$ source [仮想環境名]/bin/activate

アクティベートしたら、仮想環境内のpipを最新のバージョンにアップデートし、Ansibleをインストールする。

$ pip install --upgrade pip
$ pip install ansible

インストールできたら”ansible”コマンドが利用できるようになるので、バージョンの確認でもしてみよう。

$ ansible --version

設定ファイルについて

Ansibleの設定ファイル(ansible.cfg)は、置く場所によって読込まれる優先順位が変わる。pipやソースコードからインストールした場合は、設定ファイルは存在しない。一般ユーザーでAnsibleを利用する場合は、コマンド実行者の意図に合わせて柔軟に設定できるよう、ホームディレクトリに配置することが推奨される。

読み込まれる順番

  1. 環境変数にファイルパスを設定
  2. カレントディレクトリに存在する設定
  3. ホームディレクトリに存在する設定
  4. /etc/ansible/ansible.cfg

設定ファイルの設定値

パラメーターデフォルト値内容
forks5ターゲットノードの並列処理を行うプロセス数を設定。大きすぎるとCPUやネットワーク負荷に繋がる。
log_pathansible実行コマンドログの配置場所を設定。Ansibleの実行ユーザーがログファイルへのアクセス権限を持っているか要確認。
host_key_checkingTrueターゲットノードにSSH接続する際の公開鍵のフィンガープリントチェックを行う。
gatheringimplictターゲットノードの詳細情報に関する設定。 – implict キャッシュが無視され、常に情報収集が行われる。 – explicit キャッシュを利用し、情報収集が行われない。 – smart 新規に接続した時のみ情報収集を行い、キャッシュがある場合は情報収集を行わない。
gather_subsetallターゲットノードの詳細情報取得を制限できる。 – all 全ての情報を収集 – network 最小限の情報とネットワーク情報を収集 – hardware ハードウェア情報を収集 – virtual 最小限の情報と仮想マシンに関する情報を収集
transportsmartターゲットノードの接続方法の設定 – smart OpenSSHがControlPersist機能対応自はOpenSSH接続を行い、未対応であれば、Pythonモジュールのparamikoを利用して接続を行う。 – paramiko PythonのSSH機能で、アクションの度に各ホストに再接続を行う。 – local SSHを利用せず、直接ローカルホストに接続を行う。

ansibleコマンド

プレイブックを使わずに直接モジュールを指定するコマンド。

ansibleコマンドを試してみる

実際にVirtual Boxのテスト開発環境を使って、コマンドを送ってみる。今回はターゲットノードではなく、コントロールノード自身にコマンドを送る。従って、”localhost”を宛にコマンドを送る。

先ず、”inventory.ini”というイベントリファイルを生成し、下記のように宛先を”localhost”にして、”test_server”と命名する。

[test_servers]
localhost

pingの実行

localhost宛にpingコマンド実行する。

$ ansible -i inventory.ini test_servers -m ping -c local

下記がレスポンス。”SUCCESS”となっており、”ping”: “pong”となっているので、pingが通ったことが確認できた。

$ localhost | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

ファイル生成

ホームディレクトリにテキストファイル生成する。

$ ansible -i inventory.ini test_servers -m file -c local -a 'path=$HOME/test.txt state=touch mode=0644'

下記がレスポンス。CHANGEDとなっているのでファイルが生成できたはず。

$ localhost | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "dest": "/home/vboxuser/test.txt",
    "gid": 1000,
    "group": "vboxuser",
    "mode": "0644",
    "owner": "vboxuser",
    "size": 0,
    "state": "file",
    "uid": 1000
}

ファイル(test.txt)が生成されていることを確認する。”test.txt”が表示されていればOK。

$ ls /home/[User]

ファイル削除

確認できたら削除する。

$ ansible -i inventory.ini test_servers -m file -c local -a 'path=$HOME/test.txt state=absent'

CHANGEDとなっているのでファイルが削除できているはず。

$ localhost | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "path": "/home/vboxuser/test.txt",
    "state": "absent"
}

確認すると削除されている。

$ ls /home/[User]

ansibleコマンドでのファイル操作は、引数を変えることでファイルの更新や削除操作等もできるため、複数のターゲットノードに一度でオペレーションを行うときに効果的。ansibleコマンドでは、root権限の必要なオペレーションも実行可能。

ユーザー追加

OSのユーザー管理にはuserモジュールを利用する。

引数内容
userユーザー名指定
groups所属グループ指定
appendgourpsで指定したグループ以外を叙階しないかを指定
commentユーザーの詳細を指定
userモジュールの引数

root権限が必要な場合は”-b(become)オプション”を利用し、”-Kオプション”でBECOMEパスワードを指定する。これらのオプションを利用するためには、事前にターゲットノード側で実行者がsudo権限を持っている必要がある。

$ ansible -i inventory.ini test_servers -c local -m user -K -b -a 'user=user01 groups="vboxsf" append=yes comment="Test User01"'

下記がレスポンス。CHANGEDが返ってきているのでユーザーが追加できたようだ。

$ localhost | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "comment": "Test User01",
    "create_home": true,
    "group": 1001,
    "groups": "vboxsf",
    "home": "/home/user01",
    "name": "user01",
    "shell": "/bin/sh",
    "state": "present",
    "system": false,
    "uid": 1001
}

ユーザーが追加されているか確認する。下記のように表示されていればユーザーが追加できている。

$ cat /etc/passwd | grep user01
user01:x:1001:1001:Test User01:/home/user01:/bin/sh

ユーザー削除

ユーザーを確認したら削除する。

$ ansible -i inventory.ini test_servers -m user -c local -K -b -a 'user=user01 groups="vboxsf" append=yes comment="Test User01"'

下記はレスポンス。”SUCCESS”が返ってきたので削除できた。

$ localhost | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": true,
    "changed": false,
    "comment": "Test User01",
    "group": 1001,
    "groups": "vboxsf",
    "home": "/home/user01",
    "move_home": false,
    "name": "user01",
    "shell": "/bin/sh",
    "state": "present",
    "uid": 1001
}

ansible-playbookコマンド

playbookの種類

PLAY

ターゲットノードグループごとに行うタスクのまとめりを示す。複数のPLAYでも実行可。

TASK

個々のタスクは全てのターゲットノードで処理が行われる。タスク数分モジュールを実行している。標準出力はansibleコマンドのように全て表示されるわけでなく、タスクの結果のみ表示される。

PLAY RECAP

ansible-playbookコマンドでは、全てのPLAY実行後に最終的な実行結果が表示される。実行結果の内容は下記の通り。

実行結果ステータス内容
ok成功すでに定義された状態になっているため処理を実行せず
changed成功タスクで指定したステータスと行っているため変更した
skip成功タスクの実行条件に当てはまらなかったため処理を実行せず
unreachable失敗ターゲットノードに接続できない
failed失敗タスクを実行した結果、エラーが発生し定義された状態にならなかった

ansible-playbookコマンドを試してみる

ansible-playbookコマンドを実行するには、まずイベントリとプレイブックを作成する。

ターゲットノート側の準備

ここからは、ターゲットノード相手にコマンドを実行していくので、コントロールノードと同じユーザー”vboxuser”をターゲットノード側で作成する。既に作成されていれば問題ない。

$ sudo adduser vboxuser

vboxuserにsudoを許可。

$ sudo gpasswd -a vboxuser sudo

許可されたか確認。”vboxuser”が表示されていれば許可されている。

$ sudo cat /etc/group | grep vboxuser

“vboxuse”に切り替える。

$ sudo su vboxuser

ssh用のディレクトリを生成。”.ssh”がなければ、sshのキー生成コマンドで自動的に生成される。パスフレーズはあってもなくてもいい。

$ ssh-keygen

後は、コントロールノード側からターゲットノード側にsshが通るようにすればAnsibleを使ってターゲットノードを操作できるようになる。

$ ssh vboxuser@172.168.0.1

playbookを生成し実行(コントロールノード側)

“inventory.ini”(イベントリファイル)を生成、既にあれば編集し、下記のように宛先をターゲットノードにする。

[test_servers]
172.168.0.1 #ターゲットノードのIPアドレス

ターゲットノードでディレクトリの生成とファイルをコピーを行う簡単なplaybookを作って実行してみる。ymlファイルなので、書き方は簡単、尚且つ可読性が高く、初めての人でも下記のplaybookが何をしようとしているのかがわかる。

---
- hosts: test_servers
  tasks:
  - name: create directory
    file:
       path: /home/vboxuser/tmp
       state: directory
       owner: vboxuser
       mode: 0755

  - name: copy file
    copy:
       src: /etc/hosts
       dest: /home/vboxuser/tmp/hosts
       owner: vboxuser
       mode: 0644

下記コマンドで実行できる。

$ ansible-playbook -K -i inventory.ini test_playbook.yml

下記のようなレスポンスが返ってくれば問題ない。

$ PLAY [test_servers] ***********************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [172.168.0.1]

TASK [create directory] *******************************************************************
changed: [172.168.0.1]

TASK [copy file] **************************************************************************
changed: [172.168.0.1]

PLAY RECAP ********************************************************************************
172.168.0.1                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

コントロールノード側のユーザーディレクトリに”tmp”というディレクトリが生成され、そのディレクトリ内にコントロールノード側のhostsファイルがコピーされているはず。

$ ls
tmp
$ cd tmp
$ ls
hosts

sshキーにパスフレーズが設定されている場合

sshキーにパスフレーズが設定されている場合は、”–ask-pass”を付けてパスフレーズを入力する。

$ ansible-playbook -K -i inventory.ini test_playbook.yml --ask-pass

“sshpass”がインストールされていない場合は”FAILED”し、下記のようなメッセージが返ってくる。これは”sshpass”インストールするだけで解決できる。

$ PLAY [test_servers] ***********************************************************************

TASK [Gathering Facts] ********************************************************************
fatal: [172.168.0.1]: FAILED! => {"msg": "to use the 'ssh' connection type with passwords or pkcs11_provider, you must install the sshpass program"}

PLAY RECAP ********************************************************************************
172.168.0.1                : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

“sshpass”をインストールする。

$ sudo apt install sshpass

再度実行し、パスフレーズを入力すれば問題なく動作するはず。

$ ansible-playbook -K -i inventory.ini test_playbook.yml --ask-pass
$ PLAY [test_servers] ***********************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [172.168.0.1]

TASK [create directory] *******************************************************************
changed: [172.168.0.1]

TASK [copy file] **************************************************************************
changed: [172.168.0.1]

PLAY RECAP ********************************************************************************
172.168.0.1                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

これでとりあえずplaybookが使えるところまで確認できた。後は、構築したい内容によってplaybookを記述するだけ。また、暇があればイベントリやplaybookについてメモしたことをまとめて投稿しようと思う。

ansible

記事を読んでいただきありがとうございました。

Page Top