背景

業務で必要なansibleをマスターしたい。

ansibleとは

ansibleとは、Infrastructure as Codeを実現するための構成管理ツールである。 例えば、middlewareをデプロイする際に、ある程度の複雑さでのデプロイを可能にするツールである。

ansibleの特徴

  • 可読性を意識した設定ファイル
    • 柔軟性がないとも言える
  • 豊富なモジュール群
    • これは柔軟性の高い(=可読性が低い)ことの裏返しだと思う
  • 冪等性の担保
    • 何度ファイルを実行しても、対象の結果は変わらない
  • agentlessなツール
    • ローカルホストで実行し、sshで各サーバにログインして設定をする。構成管理をしたいサーバに別途ソフトを導入する必要などはない。

用途が似たツールにterraformがある。それとの違いに関してはまた今度としよう。

ansibleのアーキテクチャ

  • ansiblでは、コマンドを実行する「コントロールノード」と処理の対象となる「ターゲットノード」に分かれる。設定ファイルに書かれたモジュールをコントロールノード側でPythonのコードに変換し、sftpでターゲットノードに転送し、そこでPythonコードを実行する流れになっている。そのため、コントロールノード、ターゲットノードのどちらにもPythonがインストールされている必要がある。

ansibleの用語

  • インベントリ:ターゲットノードの一覧が書かれた設定ファイルである。ターゲットノードをグループ化することも可能である。
  • プレイブック:実行するモジュールが書かれた設定ファイルである。
  • モジュール:「ファイルの転送」や「サービスの起動、停止」などの処理の単位。Ansible側で用意されたモジュールを使って構成管理をする。(では、逆にansibleのモジュールにない設定を反映させたい場合にはどうするのか?ーー>自分でモジュールを開発することもできる)
  • プラグイン:Ansibleの基本機能を拡張してくれる。モジュールはタスクとして実行されるが、プラグインは、Ansible コアを拡張してくれる感じです。
  • コレクション:

ansibleのインストール方法

apt install ansible-core

インストールを確認

ray@delta:~$ ansible-playbook --version
ansible-playbook [core 2.12.0]
  config file = None
  configured module search path = ['/home/ray/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ray/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.10.12 (main, Jul 29 2024, 16:56:48) [GCC 11.4.0]
  jinja version = 3.0.3
  libyaml = True

設定ファイル

~/.ansible/ansible.cfg配下におくといいです。このファイルに以下の設定を書き込みましょう

ray@delta:~/.ansible/effective_ansible$ cat ~/.ansible/ansible.cfg 
[defaults]

fork = 15
log_path= $HOME/.ansible/ansible.log
host_key_checking = false
gathering = smart

動作確認

  1. コントロールノードから指定のノードにpingを飛ばすだけです。だから、ansible-playbookコマンドではないのです。
ray@delta:~/.ansible/effective_ansible$ ansible -i inventory.ini zeta.ingenboy.local -m ansible.builtin.ping
zeta.ingenboy.local | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
  1. コントロールノードからターゲットノードにファイルを転送するコマンドです。
ray@delta:~/effective_ansible$ ansible -i inventory.ini zeta.ingenboy.local -m ansible.builtin.file \
> -a 'path=$HOME/test.txt state=touch mode=0644'
zeta.ingenboy.local | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "dest": "/home/ray/test.txt",
    "gid": 1001,
    "group": "ray",
    "mode": "0644",
    "owner": "ray",
    "size": 0,
    "state": "file",
    "uid": 1001
}

はい、確認しに行きましたが、実際に作られていました。すごいですね。

3章の内容をまとめる。

ホスト変数とグループ変数ね。 インベントリファイルに書くんだよね。 こんな感じで

[group1]
server.hogehoge.com password=hogehoge

[group1:vars]
http_port=8080

みたいな感じで、上は各ホストごとに書くのでホスト変数といいます。 一方で、下はgroup1のグループ全体に対してかかってくるので、group変数といいます。いいですね。

ところで、実はグループ変数とホスト変数は別ファイルに分割することもできるんですね。うちのチームがまさにそうやって管理しているのですが。

グループ変数をファイル分割する方法

group_varsというディレクトリを作っておきます。deploy.ymlと同じ階層ですね。そして、group_vars/group_name/vars.yaml って感じで、group_nameに相当するところを実行したいインベントリのグループ名にするといいよ。

ホスト変数をファイル分割する方法

小技というか、知っておいたほうがいいもの

-i

インベントリの指定。これは基本 inventory/group みたいな感じで。

-l オプション

ホスト、ホストグループをさらにlimitするオプション。 うちのチームでは

-l '!group_to_exclude'

で除外サーバを抜くときに使うことが多いです。