【備忘録】Ansibleの仕組みを整理する

#本記事の目的
社内でのDevOps検証に合わせて、Ansibleの基礎知識を学び、アウトプットとして備忘録を記す。
本記事ではAnsibleのインベントリ、プレイブック、コンフィグの概念について説明する。

#インベントリ
###1. インベントリとは
- インベントリ：ターゲットノードをリストして記載するファイル。

###2. 接続情報
- コントロールノード：インベントリとプレイブックを使用して、処理の指示を出す。
- ターゲットノード：コントロールノードの指示を受けて、処理を実施する。インベントリで、IPアドレスまたはホスト名を記載する事で定義する。
    - グループ：同一の処理を実施するターゲットノード群。インベントリで、"[ ]"でグループ名を囲み、その下にターゲットノードを記載する事で定義する。
- インベントリ例

```txt:inventory
[web_servers]
apache-01
apache-02

[db_servers]
mysql-01
mysql-02
```

###3. 接続変数
- ターゲットノードへの接続を制御するための変数。インベントリでは、ターゲットノードの後ろに記載する事で定義できる。主な接続変数は以下の通り。

|  接続変数名 |  設定内容  |
| ---- | ---- |
|  ansible_connection  |  ターゲットノードへの接続方法。Linuxサーバに接続する場合は主に`ssh`、Windowsサーバに接続する場合は主に`winrm`の値を設定する。  |
|  ansible_host  |  ターゲットノードのホスト名及びエイリアス名。  |
|  ansible_port  |  ターゲットノードのリモート接続ポート。デフォルトは`22`。  |
|  ansible_user  |  ターゲットノードへのリモート接続で使用するユーザー名。  |
|  ansible_password  |  ターゲットノードへのリモート接続で使用するパスワード。  |

- インベントリ例

```txt:inventory
[web_servers]
apache-01 ansible_connection=ssh ansible_host=192.168.6.161 ansible_user=root ansible_password=Password
apache-02 ansible_connection=winrm ansible_host=192.168.6.162 ansible_user=administrator ansible_password=Password
```




#プレイブック

###1. プレイブックとは
- プレイブック：ターゲットノード側で実行したい処理の流れを記載するファイル。
- セクション：プレイブック内での処理のまとまり。
- ディレクティブ：セクション内で定義されるキー項目。


###2. 主要セクション/ディレクティブ
- Targetセクション：ターゲットノードを特定する。プレイブックでは接続ディレクティブで定義する。主な接続ディレクティブは以下の通り。

|  ディレクティブ名 |  設定内容  |
| ---- | ---- |
|  hosts  |  ターゲットノードの接続パターン。基本的にはインベントリファイルで定義したターゲットノード及びインベントリグループを指定する。 |
|  gather_facts  |  ターゲットノードでの情報取得の有無。`true`または`false`を指定する。 |

- Tasksセクション：処理を実行するセクション。プレイブックではtasksディレクティブで定義する。また、tasksディレクティブではモジュール(Ansibleの処理用コンポーネント)を使用する事ができる。主なモジュールは以下の通り。

|  モジュール名 |  設定内容  |
| ---- | ---- |
|  command  |  指定したコマンドを実施する。 |
|  script  |  指定したスクリプトを実施する。 |
|  yum/apt  |  `name`でパッケージ名を指定し、`state`で状態を指定する事で、指定したパッケージの状態を定義する。主にパッケージの導入/削除に用いられる。 |
|  service  |  `name`でサービス名を指定し、`state`で状態を指定する事で、指定したサービスの状態を定義する。主にサービスの起動/停止に用いられる。 |
|  lineinfile  |  `path`で指定されたファイル内で`line`で指定された文を検索し、存在しない場合は該当する文の書き換えまたは追記を実施する。 |


- Varsセクション：変数を設定する。プレイブックでは変数ディレクティブで定義する。主な変数ディレクティブは以下の通り。

|  ディレクティブ名 |  設定内容  |
| ---- | ---- |
|  vars  |  基本的な変数を定義する。Jinja2(Python用のテンプレートエンジン)を利用し、"{{}}"の記号を用いて定義する場合が多い。 |
|  var_files  |  変数情報を管理しているファイルを定義する。 |

- プレイブック例①

```yaml:playbook.yml
hosts: web_servers
gather_facts: true
tasks: 
  - name: Execute command 'date'
    command: date
  - name: Execute script on server
    script: test_script.sh
  - name: Execute script on server
    script: test_script.sh
  - name: Install httpd service
    yum:
      name: httpd
      state: installed
  - name: Start httpd service
    service:
      name: httpd
      state: started
```

- プレイブック例②

```yaml:playbook.yml
hosts: web_servers
vars:
  dns_server: 8.8.8.8
tasks:
  - name: Add DNS server to resolv.conf
    lineinfile:
      path: /etc/resolv.conf
      line: 'nameserver {{ dns_server }}'
```

###3. 特殊ディレクティブ
- whenディレクティブ：タスクに条件を指定して実行する(条件分岐)。tasksセクションのディレクティブとして指定する。複数条件を論理積で指定したい場合は`and`、論理和で指定したい場合は`or`を用いて、条件同士をつなげる。

- プレイブック例

```yaml:playbook.yml
hosts: db_servers
tasks:
  - name: Install Mysql on Debian
    apt: 
      name: mysql
      state: installed
    when: ansible_os_family == "Debian"
  - name: Install Mysql on RedHat
    yum: 
      name: mysql
      state: installed
    when: ansible_os_family == "RedHat"
```

- loopディレクティブ：タスクを繰り返し実行する(反復処理)。tasksセクションのディレクティブとして指定し、その中に{{ item }}という変数名を用いて繰り返し実行したい値を定義する。(なお、Ansibleバージョン2.4以前はLookupプラグイン`with_...`の使用が推奨されていたが、バージョン2.5以降はloopディレクティブの使用が推奨されている。)
- プレイブック例

```yaml:playbook.yml
hosts: db_servers
tasks:
  - name: Create users
    user: 
      name: "{{ item }}"
      state: presemt
    loop:
      - jeorge
      - mary
      - tom
```


###4. ロール
- ロール：プレイブックを分割するためのコンポーネント。ロールを利用する場合は、Ansibleが認識できる特定のディレクトリを作成し、ディレクトリ配下に`main.yml`を配置する必要がある。また、以下のディレクトリは必ず配置する必要がある。
    - tasksディレクトリ：Tasksセクションの内容を定義した`main.yml`を配置するディレクトリ。


#コンフィグ

###1.コンフィグとは
- コンフィグ：Ansibleの設定ファイル。Ansibleの処理におけるパラメーターを設定する。

###2.主要パラメーター
|  パラメーター名 |  設定内容  |
| ---- | ---- |
|  log_path  |  Ansible実行コマンドログの配置場所を設定する。  |
|  gathering  |  ターゲットノードの詳細情報取得に関する設定を行う。`implicit`の場合、常に情報収集を行う。`explicit`の場合、情報収集を行わない。`smart`の場合、新規の接続の際に情報収集を行い、既存の接続の際には情報収集を行わない。デフォルトは`implicit`。  |
|  forks  |  ターゲットノードの並列処理を行うプロセス数を設定する。デフォルトは`5`。  |

- コンフィグファイル例

```cfg:ansible.cfg
[defaults]
log_path = /var/log/ansible.log
gatherig = implicit
forks = 5
```
###3.優先順位
- コンフィグファイルは以下の順番で検索される。

|  優先順位 |  ファイルパス  |
| :----: | ---- |
|  ①  |  環境変数`ANSIBLE_CONFIG`で指定されたファイル |
|  ②  |  `./ansible.cfg`(カレントディレクトリに存在するファイル) |
|  ③  |  `~/.ansible.cfg`(ホームディレクトリに存在するファイル) |
|  ④  |  `/etc/ansible/ansible.cfg` |


#感想
今回はAnsibleの基本的な使い方のみをまとめたが、使用可能なディレクティブやモジュールの数が非常に多く、まとめるのに苦労した。
実際にAnsibleを使う場合はロールでプレイブックを分割する事が大半であるため、今後はAnsibleの検証を通じてロールを使いこなせるように理解を深めていきたい。



#参考文献
- 公式サイト：[Ansible Documentation](https://docs.ansible.com/)
- Kode Kloud：[Ansible Certification Preparation Course](https://kodekloud.com/)
- 書籍：[Ansible実践ガイド](https://www.amazon.co.jp/dp/B07YXYM94G/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)