Ansible Playbookを3分でマスターしよう

# 基本
基本的に、ホストマシンのコントローラーノードからリモートマシンのターゲットノードへジョブを実行します。
AnsibleはPuppetなどと違いエージェントを必要としません。なにかっていうと、ターゲットマシンへのインストールは必要ない。
その代わりでもないのですが、ターゲットにワークディレクトリ`.ansible`を作り、そこでローカルスクリプトを走らせることもできます。

## 前提条件（Prerequisite）
AnsibleはデフォルトのSSHメソッドを用いて、コントローラーノードからターゲットノード上でタスクを実行します。この設定はホストマシン上の`~/ansible/ansible.cfg`に記載されています。
前提条件として、すべてのターゲットノードにSSHがインストールされSSHデーモンが動作していること、また、コントローラーノードにおいて、ターゲットノードの認証情報がインベントリファイル`~/ansible/hosts`に適切に記載されていること。ただ、秘密鍵がある場合は、別途それをとってくる必要がある。
- 動作確認は次のコマンドを使います`ansible all -m ping`

```~/ansible/hosts  [Path for host file.]
[targetnode]
{{target_node_ip}} ansible_user={{target_ssh_user}} ansible_password={{target_ssh_password}}
```

```ansible.cfg
[defaults]
inventory = ~/ansible/hosts
host_key_checking = False
```

- jinja2を使用する場合はインストールしてください。`pip install jinja2`

## Ansible Playbook Script 
PlaybookはYAML構文（Yet Another Markup Language）で記述されます。

**Play（プレイ）** : プレイを実行するターゲットノードを定義します。各プレイのコンテキストディレクトリは分けられる場合があります（例えば、タスクや他のファイルをフォルダー内に配置できる）。例として、Jinjaテンプレートがあります。

**Tasks（タスク）** : 実行するタスクの順序を定義します。

**Template（テンプレート - タスク内で使用する名前）** : タスクのテンプレートを定義します。ansibleのモジュールを使用したプログラミングが可能です。

eg.a) タスクの戻り値を登録(register)することで、後続のタスクでその登録された戻り値を呼び出して使用することができます。また、jinja2を使いtemplateの管理（ターゲット毎に使い分けなど）ができます。

```sample_playbook.yml
---
- name: Sample Playbook
  hosts: localhost
  vars:
    date_time: "{{ ansible_date_time.iso8601 }}"
    hostname: "{{ inventory_hostname }}"
  tasks:
    - include_tasks: sample_task.yml  

    - name: Debug file details
      stat:
        path: /home/user/hello_world.txt
      register: file_stat 
      
    - name: Debug file owner, creation time
      debug:
        msg: |
          File Owner: {{ file_stat.stat.pw_name }}
          File Creation Time: {{ file_stat.stat.created | to_datetime('%s') }}
# unnecesary debug          
#    - name: Cat the content of the generated file
#      slurp:
#        src: /home/user/hello_world.txt
#      register: file_content
#    
#    - name: Display the content of the file
#      debug:
#        msg: "{{ file_content.content | b64decode }}"
```

```hello_world.j2
Hello, world!! It's {{date_time}}. 
This file was generated by {{hostname}}.
```

```sample_task.yml
---
- name: Generate a file using a template
  template:
    src: hello_world.j2
    dest: /home/user/hello_world.txt
```
*サンプルはこちら

## PLAY RECAP

非常にシンプルで、左端の列がターゲットノードを示します。結果の種類ごとの合計がその後に続きます。

Playbookが各タスクを処理する方法はプログラム可能です。一部のタスクを条件つけてスキップ(**skipped**)させることもでき、エラーを無視(**ignored**)するようにプログラムすることも可能です。

### 具体的な例

- 実際に重要なパラメータは`failed=`のみです。`ok=`、`changed=`、`failed=`、`skipped=`、`rescued=`、`ignored=`の合計が実行された全タスクの合計と一致します。
Playbookがリトライするたびに`failed=`以外の値は変動する可能性があります。もし一致しない場合、Playbook自体にプログラマーの意図しない動作があると認めることができバグの可能性も考慮する必要があります。
    
- `unreachable=`はタスクがまったく開始されなかったことを意味します。たとえば、コントローラーノード内にファイルやパラメータが不足している場合、または正しい権限が付与されていない際に見られます。
    
- `skipped=` `rescued=`  `ignored=` は、プレイが特定の　`failed=` 結果を回避するようにプログラムされている場合に発生します。例えば、タスクに`ignore_errors : true` が設定されている場合、タスクが失敗しても `ignored=` として表示されます。
    
## 公式ドキュメンテーション：
[![](https://ci3.googleusercontent.com/meips/ADKq_NboAy85b2FEyZmLMjm0R1bhYRPfISwic2uDhXnuO7kkEdSLOul1eGHDV8vudyFhrD_xu6kB2SKj4EE9aAgAyJ5CX6MBOAedQxbcoL_PrpHoXipo4bKw6ex9cL0EfcVafJySuIMcw04=s0-d-e1-ft#https://docs.ansible.com/ansible/latest/_static/images/Ansible-Mark-RGB_Black.png)
Ansible playbooks — Ansible Community Documentation](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html)

# 既知の問題（Known issues）

- タスク用テンプレートに依存関係の問題が発生する可能性があります（PythonパッケージやLinuxパッケージなど、例：rsync）
    
- ターゲットノードとコントローラーノード間で文字エンコードを自動変換するような魔法のような仕組みはありません。同様に、リターンコード（CRLFとLF）の扱いにも注意が必要です。特に、jinja2を扱いプレイブック内のパラメータを`{{dude_set_your_own_variable}}`のように設定されている場合には注意が必要です。
- Pythonが独自のシンタックスのせいでコンソールが読みづらかったりする。Raw Strings（生文字列）とリテラル文字列の扱い方には注意しましょう。
    - 例として、CRは`\r`, LFは`\n`, そしてタブスペースは`\t`と表現されます。