以前、Ansibleを使おうと思って、本を読んだり調べたりしてメモっていたので、それをまとめておく。
Ansibleのテスト開発環境
今回のAnsibleのテスト開発環境は、Virtual Boxを利用する。Virtual Box上にUbuntu DesktopをインストールしてAnsibleを実行する。
構成 | バージョン |
Virtual Box | Version 7.0 |
Ubuntu | Ubuntu 24.04.2 LTS |
Virtual Boxで2つの仮想環境を構築し、片方をコントロールノード、もう片方をターゲットノードとし、ユーザー名を”vboxuser”で共通させる。また、この2つの仮想環境を同じ内部ネットワーク内に設定する。
IPアドレス | サブネットマスク | |
コントロールノード | 172.168.0.1 | 255.255.255.0 |
ターゲットノード | 172.168.0.2 | 255.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ライブラリの利用環境を切り替えるためのツールと考えた方がよい。
$ 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を利用する場合は、コマンド実行者の意図に合わせて柔軟に設定できるよう、ホームディレクトリに配置することが推奨される。
読み込まれる順番
- 環境変数にファイルパスを設定
- カレントディレクトリに存在する設定
- ホームディレクトリに存在する設定
- /etc/ansible/ansible.cfg
設定ファイルの設定値
パラメーター | デフォルト値 | 内容 |
forks | 5 | ターゲットノードの並列処理を行うプロセス数を設定。大きすぎるとCPUやネットワーク負荷に繋がる。 |
log_path | – | ansible実行コマンドログの配置場所を設定。Ansibleの実行ユーザーがログファイルへのアクセス権限を持っているか要確認。 |
host_key_checking | True | ターゲットノードにSSH接続する際の公開鍵のフィンガープリントチェックを行う。 |
gathering | implict | ターゲットノードの詳細情報に関する設定。 – implict キャッシュが無視され、常に情報収集が行われる。 – explicit キャッシュを利用し、情報収集が行われない。 – smart 新規に接続した時のみ情報収集を行い、キャッシュがある場合は情報収集を行わない。 |
gather_subset | all | ターゲットノードの詳細情報取得を制限できる。 – all 全ての情報を収集 – network 最小限の情報とネットワーク情報を収集 – hardware ハードウェア情報を収集 – virtual 最小限の情報と仮想マシンに関する情報を収集 |
transport | smart | ターゲットノードの接続方法の設定 – 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 | 所属グループ指定 |
append | gourpsで指定したグループ以外を叙階しないかを指定 |
comment | ユーザーの詳細を指定 |
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についてメモしたことをまとめて投稿しようと思う。
記事を読んでいただきありがとうございました。