インストールを自動化する Ansible を Windows にインストールする

<img width="70%" alt="Ansible Log Example" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/1603cf4b-f819-be27-a633-5dde09ac15d2.jpeg"/>


## 概要

Ansible は、Linux サーバーに各種ソフトウェアやファイルをインストールする作業を自動化するソフトウェアです。

しかし、Ansible 自体を Windows にインストールするインストーラーは提供されていません。また、Windows ユーザーが Ansible を試す方法は、ネットを探してもほとんど見つかりません。

そこで、Ansible が入った仮想マシン(VM) を Windows にインストールする手順を Windows のリセット状態から1つ1つ丁寧に紹介したいと思います。なお、途中で Vagrant 用プロジェクトをダウンロードする手順があります。インストール手順をなるべく自動化するために使っています。

自動化できるようになると、ハードウェアやネットワークの知識がない人でも VM に入ったサービスを使うことや物理サーバーを増やすことができるようになり、分業することができるようになります。


## 対象システム

あらかじめ用意する必要があるのは、以下のとおりです。

- Windows 10 21H1 64bit （多少古いバージョンでもよい）

以下の手順でインストールするソフトウェアは、以下のとおりです。
すべてのバージョンは、執筆時点の最新版です。
この記事が古くなったら、以下で説明する手順では失敗するかもしれませんがご了承ください。

- ホストOS（Windows）
    - Visual Studio Code 1.59.1
    - VirtualBox 6.1.26
    - Vagrant 2.2.18（コードで VirtualBox の VM を自動的に作るソフトウェア）
    - Ansible Local プロビジョナー（Ansible をインストールおよび実行をする Vagrant のプラグイン）
    - Vagrant や Ansible の設定ファイル
    - Git 2.33.0.2 （bash および SSH 関連のコマンドを使うため）

- コントロール ノード (VirtualBox の VM。名前は control)
    - CentOS7
    - Ansible
    - Ansible の設定ファイル（ホストOSと共有）

- マネージド ノード (VirtualBox の VM。名前は node1)
    - CentOS7
    - Ansible でインストールするソフトウェアやファイル

Windows で Visual Studio Code を開きつつ、Ansible を Linux で動かすために、
ホストOS と コントロール ノード を分けています。
ただし、この構成でなければ Ansible が使えないというわけではありません。
ホストOS は mac でもできると思いますが試していません。

物理サーバーにインストールする方法については本記事の対象外です。
最後の参考サイトを参照してください。


## Ansible とは

Ansible をよく知らない方のために、Ansible とは何かを説明します。
インストールするだけなら読み飛ばしていただいても構いません。

Ansible は、Linux サーバーに各種ソフトウェアやファイルをインストールする作業を
自動化することを目的にしたソフトウェアです。
インストールする処理を Ansible の Playbook ファイルのタスクに書きます。
Playbook ファイルは YAML 形式で書きますが、
他のスクリプトと同様に上から下へタスクを実行します。

タスクの実行は、コントロール ノード から SSH でログインした
マネージド ノード の中で行われます。 SSH でログインすることさえできれば
Ansible で様々なタスクを実行できるのですが、SSH でログインできるように
する設定は Ansible とは別に行う必要があります。

タスクには マネージド ノード の中で実行するコマンドに相当する
モジュールを指定します。
RPM パッケージをインストールするモジュールや
ファイルをリモートコピーするモジュールなど
非常に多くのモジュールが用意されています。
シェルのコマンドを直接実行するモジュールもあるため、
とりあえずシェルのコマンドで Playbook を作り、
後で適切なモジュールに置き換えると効率的に開発できるでしょう。

インストール済みのソフトウェアに関するタスクはスキップします。
このため、インストール済みの状態から再びインストールするとエラーになる
インストーラーを使っても Ansible はエラーになりません。
インストールしていない状態でもインストール済みの状態でも、
Ansible を実行した後はインストール済みの状態で正常終了します。
このように前提条件が異なっていても結果が同じになる性質を冪等性と呼び、
Ansible のタスクに指定できるモジュールのほとんどは冪等性を持っています。

ただし、シェルのコマンドを直接実行するモジュールを使うと、
そのタスクは冪等性を持っていない可能性があります。
後で直接コマンドを実行しないモジュールに置き換えるか適切な条件を設定すれば、
冪等性を持った Playbook にすることができます。

## Vagrant とは

Vagrant をよく知らない方のために、Vagrant とは何かを説明します。
インストールするだけなら読み飛ばしていただいても構いません。

Vagrant は VirtualBox や VMWare player などの仮想マシン(VM)
を扱うソフトウェアに対して、コードで操作することで、
自動的に VM を作るソフトウェアです。

コードで操作できるようになると VM の構成情報
（VM の数、メモリーサイズ、IPアドレスなど）はコードの中に入ります。
コードをコピーすることで VM の構成の全体または一部を再利用することや、
Git などでバージョン管理することができるようになります。

VM は物理的なハードウェアの中に作ることができる仮想的なハードウェアです。
本番で別の物理サーバーで動かすシステムを開発をするときに使います。
システムの構成要素に、ネットワークから来たリクエストに応答するサーバーがあるときに
必要になります。

VM を Docker コンテナーに置き換えて開発や運用をすることもできますが、
Vagrant は VM だけを扱います。
Docker を使う場合、Vagrant のコードや Ansible の全部または一部コードは、
Dockerfile や docker-compose.yml に置き換わります。

Vagrant には Ansible Local プロビジョナーのプラグインがあります。
Ansible の Playbook を実行する Vagrant のコードを書くと、
Ansible Local プロビジョナーが自動的に VM に Ansible をインストールして
Playbook を実行します。
本書の方法ではダミーの Playbook を実行することで、
Ansible を自動的にインストールしています。


## インストール手順

手順は多いですが、とくに前提とする知識や考慮すべきことはないので、
そのまま進めていくことができます。

言葉による説明が読みにくい場合は、
本書の最後に書いてある構造化文書による手順書を参照しながら進めていくこともできます。


### VirtualBox をインストールします

[https://www.virtualbox.org/](https://www.virtualbox.org/)
をブラウザーで開き、Download VirtualBox 6.1 ボタンを押し、
Windows hosts をクリックするとダウンロードが始まります。
ダウンロードしたファイルを開いてインストールします。

<img width="50%" alt="VirtualBox インストール ページ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/1e73fbd6-a2f7-824c-8918-408983bd7060.jpeg"/>

インストール オプションはデフォルトで構いません。

ドライバーをインストールするか聞かれたときはインストールすることを選びます。

後に書かれた手順の途中で VM が起動できない問題が発生したときは、次の点について具体的な方法をネットで検索してください。

- お使いの PC（ホストOS）の BIOS に仮想化（Virtualization）の機能をオンまたはオフを
    選ぶ項目がある場合、オンに設定する必要があります
- Hyper-V は無効にする必要があります


### Vagrant をインストールします

[https://www.vagrantup.com/downloads.html](https://www.vagrantup.com/downloads.html)
をブラウザーで開き、Windows タブの 64-bit をクリックするとダウンロードが始まります。
ダウンロードしたファイルを開いてインストールします。

<img width="50%" alt="Vagrant インストール ページ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/126f2aba-d23f-44fe-042d-d510e8bce5c6.jpeg"/>

インストール オプションはデフォルトで構いません。

インストールが完了したら PC を再起動します。


### Git for Windows をインストールします

[https://git-scm.com/](https://git-scm.com/)
をブラウザーで開き、Downloads for Windows ボタンを押すとダウンロードが始まります。
ダウンロードしたファイルを開いてインストールします。

<img width="50%" alt="Git インストール ページ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/5b16a064-3127-e2d4-7cf5-971ac5a01b35.jpeg"/>

インストールするときは、9回 Next を押すと表示される
Configuring the line ending conversions
を
Checkout as-is, commit as-is
に設定することをお勧めします。

他のインストール オプションはデフォルトで構いません。


### Visual Studio Code をインストールします

[https://code.visualstudio.com/](https://code.visualstudio.com/)
をブラウザーで開き、ダウンロードして、実行します。

<img width="50%" alt="Visual Studio Code インストール ページ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/e7a40934-b319-1513-5be3-8980a961aa64.jpeg"/>

インストール オプションはすべてデフォルトで構いません。

インストールが完了したら、Visual Studio Code を起動して
タスクバーにピン止めすることをオススメします。


### Visual Studio Code の端末が使うシェルを bash に変更します

Visual Studio Code のメニュー Terminal >> New Terminal
で端末を開き、＋の右の↓ をクリックして表示されるメニューの
Select Default Profile を選び、Git bash を選びます。

<img width="50%" alt="Visual Studio Code の Select Default Profile メニュー" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/22cf735f-0e02-d83c-17fe-133965bb022e.jpeg"/>

PowerShell を使っている既存の端末は、ゴミ箱 ボタンを押して閉じます。

後で使う code コマンドを使えるようにするため、
Visual Studio Code を一度終了して、再起動します。


### ホストOSがプロキシがあるLANにいるとき、プロキシの設定をします

もし、社内などプロキシがあるLANにいるときは、プロキシの設定をします。
設定に必要な プロキシ サーバー の URL はネットワーク管理者などにお問い合わせください。
家庭内などプロキシがないときは、この設定は不要です。

Visual Studio Code のメニュー Terminal >> New Terminal
で端末(bash)を開き、下記のコマンドを入力します。

```shell
echo  ${http_proxy}
```

もし、プロキシサーバーの URL が表示されたら下記の手順は不要です。

下記のコマンドの一部を、所属している LAN の プロキシ サーバー の URL に変更して実行します。

```shell
echo  "export   http_proxy=\"http://__ProxyDomain__:__ProxyPortNum__\"" >> ~/.bashrc
echo  "export  https_proxy=\"http://__ProxyDomain__:__ProxyPortNum__\"" >> ~/.bashrc
echo  "export  no_proxy=\"localhost,127.0.0.1,control,node1\"" >> ~/.bashrc
```

変更箇所：

    `http://__ProxyDomain__:__ProxyPortNum__`

変更後の例：

    `http://proxy.example.com:8080`

または

    `http://10.100.100.100:8080`

上記コマンドを実行したら、bash を開きなおします。

下記の警告は無視できます。

    WARNING: Found ~/.bashrc but no ~/.bash_profile, ~/.bash_login or ~/.profile.


### vbguest プラグインをインストールします

vbguest プラグインは Vagrant から Ansible Local プロビジョナーを
インストールおよび実行をする Vagrant のプラグインです。

端末(bash)で下記のコマンドを入力します。
もし、端末が開いていない時は、
Visual Studio Code のメニュー Terminal >> New Terminal
で開きます。

```shell
vagrant plugin install vagrant-vbguest
```


### プロジェクト フォルダーをダウンロードして開きます

VM を作り、Ansible 自体をインストールする Vagrant プロジェクトをダウンロードします。
このプロジェクトには、Vagrant のコードと Ansible のシンプルな Playbook を含みます。

端末(bash)で下記のコマンドを入力します。

```shell
cd ~/Desktop
git clone https://github.com/Takakiriy/multi_vm_ansible.git
```

端末(bash)で下記のコマンドを入力します。

```shell
code ~/Desktop/multi_vm_ansible
```

もし、code コマンドが見つからない場合は、Visual Studio Code を再起動してください。

Visual Studio Code 内で上記のコマンドを入力したら、
コマンドを入力した Visual Studio Code を閉じます。

新しく開いた Visual Studio Code の Terminal >> New Terminal メニューを
選びます。


#### プロジェクトに含まれる主なファイル

| ファイル名 | 内容 |
| --------- | ---- |
| playbook-0.yml     | Ansible をインストールするためのダミー Playbook |
| playbook.yml       | Ansible が実行する内容。サンプルとして、マネージド ノード にファイルを作成するタスクが入っています |
| run_playbook.sh    | Ansible の Playbook を実行します |
| upload_SSH_keys.sh | コントロール ノード から マネージド ノード に SSH 接続できるようにします |
| Vagrantfile        | Vagrant が作成する VM の内容 |


### 仮想マシンを作って起動します

端末(bash)で下記のコマンドを入力します。
このコマンドは、Vagrantfile の内容に従って VM を作ります。

```shell
vagrant up
```

初回は約 10分かかります。
コントロール ノード に Ansible Local プロビジョナーをインストールするために、
何も処理しない playbook-0.yml ファイルを実行します。

Vagrant プロジェクトがあるフォルダーは、
VM の /vagrant/ フォルダーと共有します。

実行ログの例:

```
Unmounting Virtualbox Guest Additions ISO from: /mnt
==> control: Checking for guest additions in VM...
==> control: Configuring and enabling network interfaces...
==> control: Mounting shared folders...
    control: /vagrant => C:/Users/user1/Desktop/multi_vm_ansible
==> control: Running provisioner: ansible_local...
    control: Installing Ansible...
    control: Running ansible-playbook...

PLAY [control] *****************************************************************

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

TASK [dummy] *******************************************************************
ok: [control] => {
    "msg": "Ansible ready"
}

PLAY RECAP *********************************************************************
control                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```


### Visual Studio Code から SSH で VM にログインできるように設定します

Visual Studio Code の拡張機能 ボタンを押して、Remote Development 拡張機能
をインストールします。

<img width="35%" alt="Remote Development 拡張機能" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/7cf27884-c98d-abfa-6fe5-22f9dd3b0af7.jpeg"/>

Remote Development のビューで REMOTE EXPLORER のプルダウンから
SSH Targets を選びます。

<img width="30%" alt="REMOTE EXPLORER の SSH Targets" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/f2aef37c-ab55-08a6-3119-acf8e4e905b8.jpeg"/>

端末(bash)で下記のコマンドを入力します。

```shell
vagrant ssh-config
```

SSH の接続に必要な設定が表示されるのでコピーします。
コピー先は、下記のコマンドで開くファイルです。
既存の別のサーバーの設定があるときは消さないでください。

```shell
code ~/.ssh/config
```

Remote Development のビューにカーソルを合わせて、
右上に表示される リロード ボタン を押します。

<img width="40%" alt="REMOTE EXPLORER の Reload" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/0eee8ebb-e6bb-cde9-6825-873a99f5313f.jpeg"/>

表示された control にマウスカーソルを合わせると
フォルダーのボタンが表示されるのでそれをクリックします。

<img width="40%" alt="REMOTE EXPLORER の Folder" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/fb2edf29-486a-0dad-5aae-83e194e8791a.jpeg"/>

新しい Visual Studio Code のウィンドウが開きます。
そのウィンドウは、control に SSH でリモート接続した Visual Studio Code です。
初めて接続するときは、プラットフォームを聞かれるので Linux を選びます。

<img width="50%" alt="REMOTE EXPLORER の Linux" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427559/c0c7f0a3-c1ca-12b7-2acd-270c1303b652.jpeg"/>

control の Visual Studio Code で、
File >> Open Folder ... メニューを選び、
/vagrant/ フォルダーを開きます。

再び新しい Visual Studio Code のウィンドウが開きます。
今まで開いていた control の Visual Studio Code は閉じます。
新しいウィンドウは、control ノードの /vagrant/ フォルダーを開いた
Visual Studio Code です。
そのウィンドウで Terminal >> New Terminal メニューを選び、
シェルを開けることを確認します。
このシェルは、SSH で接続されたシェルです。

    [vagrant@localhost vagrant]$

と表示されます。

開けたら Visual Studio Code を閉じます。


### コントロール ノード から マネージド ノードに SSH 接続できるようにします

ホストOS の Visual Studio Code の端末(bash)で下記のコマンドを入力します。

```shell
./upload_SSH_keys.sh
```

途中でこのサーバーに接続して良いか聞かれたときは yes を入力します。

シェルスクリプト upload_SSH_keys.sh は、
SSH の接続に必要な各種設定と接続テストをしています。

- コントロール ノード に秘密鍵をコピーします
- その公開鍵を マネージド ノード にコピーします
- ホスト名を登録します
- コントロール ノード から マネージド ノードに SSH 接続できることをテストします

実行の様子:

```
$ ./upload_SSH_keys.sh

~/.ssh/known_hosts
cat: /c/Users/user1/.ssh/known_hosts: No such file or directory

# test connection and set known_host @control
The authenticity of host '[localhost]:2259 ([127.0.0.1]:2259)' can't be established.
ED25519 key fingerprint is SHA256:OyAt+LkHfQOnkxDEJ2JhI+MTWKvOgg9ou/l2C21ltIs.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2259' (ED25519) to the list of known hosts.
connected to (@control)

# test connection and set known_host @node1
The authenticity of host '[localhost]:2251 ([127.0.0.1]:2251)' can't be established.
ED25519 key fingerprint is SHA256:Ndr0xuMRTa6a9OKa15VI3HmQtCFwty81RDeadb/ibhw.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2251' (ED25519) to the list of known hosts.
connected to (@node1)

# make private key @control
private_key                                                           100% 1706   603.4KB/s   00:00
-rw-r--r--. 1 vagrant vagrant 1706 Aug 29 04:13 /home/vagrant/.ssh/id_rsa

# chmod private key @control
-rw-------. 1 vagrant vagrant 1706 Aug 29 04:13 /home/vagrant/.ssh/id_rsa

# add host name @control
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.33.51  node1

# get public key @host
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCymXRpjm0PZfc2CHSi+Ilelm2BSfwigfXIWRleNPH66y+y46B8tENLDtwlVlMcv/p55HOelg+VwJ4P3udX80VABGWRKW/+VvEaZU5rdeCU82q95WyZOfV2WUwtwtEV81lcpKIsigDp1leR1eWmp8xucGbjLiZJ1i3WDCjgb7cYq49CIUpETHRdLqPFnsKOram3wRUOhD93kxVDma6d73E1b9XxoOm72EU2K0lQpejcjZuS/hZ8PCgca1kzM8wq6L6StOYlOugm/rorZDOMIXXEQddj2FUl27ORqCZn5b6YQr7ludd72AJE3ARVkRwRQGlm0Yasc8zqK99tph+jErF9 vagrant

# set authorized_keys @node1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsdsticBkUTm3ndmUuu1bdxuyw5guXo7FmpjwWoa1lGIX4pIBtSh+2VfcpEnShT4rl1mxRjHDXJT6lNqIW7BYMHeC61GLafKVkrQeXkwEpiQBvx2gYd6gO/zkrNAd6JwI13D/iNqxHKohylDI1A64DsBSHgZS8QV1BYWJSAl5iUxct2aA04jq0+LKU4WteQcZjCU03TTIYKYzXfQ8OhvUd7JNJvI3IUgpkolJz8keidKZdmfNmNzrjGhu51KdDZnn0iMfOe8rAgwzdKcRnYIbP4m9oBifZeFecWeuHFLOUP6hbNn+MRao8h/s07drlQNXkhUnZqwV8PgnT35gz6eOB vagrant
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCymXRpjm0PZfc2CHSi+Ilelm2BSfwigfXIWRleNPH66y+y46B8tENLDtwlVlMcv/p55HOelg+VwJ4P3udX80VABGWRKW/+VvEaZU5rdeCU82q95WyZOfV2WUwtwtEV81lcpKIsigDp1leR1eWmp8xucGbjLiZJ1i3WDCjgb7cYq49CIUpETHRdLqPFnsKOram3wRUOhD93kxVDma6d73E1b9XxoOm72EU2K0lQpejcjZuS/hZ8PCgca1kzM8wq6L6StOYlOugm/rorZDOMIXXEQddj2FUl27ORqCZn5b6YQr7ludd72AJE3ARVkRwRQGlm0Yasc8zqK99tph+jErF9 vagrant

# test connection and set known_host @control
Warning: Permanently added 'node1,192.168.33.51' (ECDSA) to the list of known hosts.
control connected to node1

$
```


### ホストOS から SSH 経由で コントロール ノード の Ansible を実行します

ホストOS の Visual Studio Code の端末(bash)で下記のコマンドを入力します。

```shell
./run_playbook.sh
```

playbook.yml に書かれたすべてのタスクを実行します。
付属の playbook.yml は マネージド ノード node1 に ~/tmp_visiting_card ファイルを作るだけですが、
通常の playbook.yml はインストールを行ます。

実行の様子:

```
$ ./run_playbook.sh
Using /etc/ansible/ansible.cfg as config file

PLAY [node1] *******************************************************************

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

TASK [make visiting card] ******************************************************
--- before
+++ after
@@ -1,6 +1,6 @@
 {
-    "atime": 1630211877.1403475,
-    "mtime": 1630211877.1403475,
+    "atime": 1630211959.23235,
+    "mtime": 1630211959.23235,
     "path": "tmp_visiting_card",
-    "state": "file"
+    "state": "touch"
 }

changed: [node1] => {"changed": true, "dest": "tmp_visiting_card", "gid": 1000, "group": "vagrant", "mode": "0664", "owner": "vagrant", "secontext": "unconfined_u:object_r:user_home_t:s0", "size": 0, "state": "file", "uid": 1000}

PLAY RECAP *********************************************************************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```


## バックアップ・リストア手順

Ansible がインストールできたら、その状態の VM をバックアップするとよいでしょう。
バックアップがあれば、開発する Playbook が正しく動作するようになるまで
VM をリストアしてやりなおすことができます。
また、正常に動くタスクがある程度増えたときも VM をバックアップするとよいでしょう。


### VM をバックアップします

SSH 接続している Visual Studio Code を閉じます。

VirtualBox マネージャーを開いて、Ctrl キーを押しながら VM を複数選択し、
右クリックして、閉じる >> 電源オフ を選びます。

下記のフォルダーをバックアップにコピーします。

- 各 VM のフォルダー (~/VirtualBox VMs/____)
- Vagrant プロジェクトの .vagrant フォルダー


### VM を削除します

VirtualBox マネージャーを開いて、Ctrl キーを押しながら VM を複数選択し、
右クリックして、除去 >> すべてのファイルを削除 を選びます。


### VM をバックアップからリストアします

下記のフォルダーを削除して、バックアップからコピーします。

- 各 VM のフォルダー (~/VirtualBox VMs/____)
- Vagrant プロジェクトの .vagrant フォルダー

もし、VirtualBox マネージャーに VM が表示されていないときは、
VirtualBox マネージャー >> 仮想マシン >> 追加 で復帰します。


## 起動手順

### コントロール ノード の電源を入れます

ホストOS の Vagrant プロジェクトのフォルダーを Visual Studio Code で開き、
端末(bash)で下記のコマンドを入力します。

```shell
control_only=1  vagrant up
```

control_only=1 の環境変数の設定によって、コントロール ノード (@control) だけ Vagrant から起動します

- control_only=1 は、このプロジェクトの Vagrantfile が定義した固有の設定です
- コントロール ノード だけを対象にすることで、
    コントロール ノード の起動の完了を待たずに、マネージド ノードの起動を始めることができます
- 先に VirtualBox マネージャーから起動した VM は共有フォルダーが使えなくなります


### マネージド ノード の電源を入れます

VirtualBox マネージャーを開いて、VM (@node1) を右クリックして、起動 >> ヘッドレス起動 を選びます。

もし、複数の マネージド ノード があるときは、Ctrl キーを押しながら VM を複数選択してから
起動します。


## デバッグ手順

Ansible を実行した Playbook のうち、問題が発生した1つのタスクだけ実行することで、
効率よくデバッグができます。

1つのタスクだけ実行するときは、コントロール ノード に SSH でログインする必要があります。


### Visual Studio Code で コントロール ノード を開きます

リモートのフォルダーを Visual Studio Code で開く（ログインする）ときは、
リモートではないフォルダーと同様に、最近開いたフォルダーから選ぶことで開くことができます。
下記のいずれかの方法があります。

- Windows のタスクバーの VSCode を右クリック >> __Folder__ [SSH:__Server__]
- 任意の Visual Studio Code >> File >> Open Recent >> __Folder__ [SSH:__Server__] 

初めてリモートのフォルダーを開いたときのように、
Remote Development のビューから開くこともできます。

Visual Studio Code でログインすると、
リモートのファイルを Visual Studio Code の テキスト エディター
で編集できるようになります。


### 1つの Ansible のタスクだけ実行します

コントロール ノード にログインしたら、
Ansible が使う インベントリー ファイル のパスを ANSIBLE_INVENTORY
環境変数に設定します。

    export ANSIBLE_INVENTORY="/tmp/vagrant-ansible/inventory/vagrant_ansible_local_inventory"

Vagrant の Ansible Local プロビジョナーを使っているので、
Ansible の インベントリー ファイル は自動的に VM 内に作られます。
のちに本番に使う物理サーバーに対して Ansible を使うときは、
別途 インベントリー ファイル を用意する必要があります。

1つの Ansible のタスクだけ実行するには、下記のコマンドを実行します。
ただし、実行するタスク名は編集してください。
make visiting card は playbook.yml に書かれたタスク名です。

    ansible-playbook  playbook.yml  --diff  -v  --step  --start-at-task "make visiting card"

上記に書かれていませんが、よく使うオプションは以下のものがあります。

- --check: チェックだけ行い、タスクの実行は行ません (dry run)。本番では必ず行ってください
- --limit "__HostName__": 対象のサーバーを指定または制限します
- -vvv: 最も詳細に状況を表示します。-v オプションの代わりに指定します

--step オプションを指定しているので、サーバーの情報収集する直前と、タスクを実行する直前に
それを実行するかどうかを聞かれます。
サーバーの情報収集は毎回行うので、
1つのタスクだけ実行するときは、y を 2回入力します。
そして次のタスクの実行をするかどうかを聞かれるので、Ctrl + C キーを押して終了します。
最後のタスクを実行したときは Ctrl + C は不要です。

実行の様子:

```
$ ansible-playbook  playbook.yml  --diff  -v  --step  --start-at-task "make visiting card"
Using /etc/ansible/ansible.cfg as config file

PLAY [node1] ****************************************************************************
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: y

Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: ******************************

TASK [Gathering Facts] ******************************************************************
ok: [node1]
Perform task: TASK: make visiting card (N)o/(y)es/(c)ontinue: y

Perform task: TASK: make visiting card (N)o/(y)es/(c)ontinue: ***************************

TASK [make visiting card] ***************************************************************
--- before
+++ after
@@ -1,6 +1,6 @@
 {
-    "atime": 1630211959.231837,
-    "mtime": 1630211959.231837,
+    "atime": 1630214387.011351,
+    "mtime": 1630214387.011351,
     "path": "tmp_visiting_card",
-    "state": "file"
+    "state": "touch"
 }

changed: [node1] => {"changed": true, "dest": "tmp_visiting_card", "gid": 1000, "group": "vagrant", "mode": "0664", "owner": "vagrant", "secontext": "unconfined_u:object_r:user_home_t:s0", "size": 0, "state": "file", "uid": 1000}

PLAY RECAP ******************************************************************************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
```


## マネージド ノード を増やすとき

Vagrantfile の Managed node の部分をコピー＆ペーストして、
IP アドレスをポート番号を調整して、vagrant up を実行すると
サーバー（＝ノード）を増やすことができます。
Vagrant にも冪等性があるため、増えたノードだけ作ります。

ホストOS から マネージド ノード への SSH 接続や
コントロール ノード から マネージド ノード への SSH 接続の設定も行います。


## 導入効果

Ansible が使えるようになると、ソフトウェアのインストールに苦労することが
最初の1回だけになり、クリーンな状態の Linux に戻すことに抵抗がなくなります。
様々なソフトウェアがインストールされていると、多くのソフトウェアの動作を疑って
しまいますが、そのような不安要素から開放されるでしょう。
また、新しく配属された人が開発環境を構築するためのドキュメントが不要になり、
構築にかかる日数も大幅に短縮されるでしょう。


## 付録）構造化文書による手順書

Windows で Ansible が入った VM をインストールする手順です。

```yaml
VirtualBox をインストールします:
    - https://www.virtualbox.org/ >> Download VirtualBox X.X >> Windows hosts
    - ダウンロードしたファイル（例：VirtualBox-6.1.22-144080-Win.exe）を開きます
    - インストール オプションはデフォルトを使用
    - ドライバーはインストールします
Vagrant をインストールします:
    - https://www.vagrantup.com/downloads.html >> Windows（タブ）>> 64-bit
    - ダウンロードしたファイル（例：vagrant_2.2.16_x86_64.msi）を開きます
    - インストール オプションはデフォルトを使用
    - PC を再起動します
Git for Windows をインストールします:
    - https://git-scm.com/ >> Download for Windows（右下）
    - ダウンロードしたファイル（例：Git-2.33.0.2-64-bit.exe）を開く
    - Next を9回押す
    - Configuring the line ending conversions: Checkout as-is, commit as-is
    - 他のインストール オプションはデフォルトを使用
Visual Studio Code をインストールします:
    - https://code.visualstudio.com/
    - ダウンロードしたファイル（例：VSCodeUserSetup-x64-1.50.1.exe）を開きます
    - インストール オプションはデフォルトを使用
    - Git bash シェルをデフォルトで開くようにします:
        VSCode >> Terminal >> New Terminal >> ＋の右の↓（シェルの右上）>>
        Select Default Profile >> Git bash >> ゴミ箱 ボタン（シェルの右上）
    - （推奨）VSCode (Visual Studio Code をタスクバーにピン止めします:
    - （推奨）Ctrl + S キーを押したときに全てのファイルを保存するように設定します: |
        VSCode >> File >> Preferences >> Keyboard Shortcuts >> save all （と入力） >>
            File: Save All （をダブルクリック） >> Ctrl + S キー >> Enter キー
ホストOSがプロキシがあるLANにいるとき:
    Git bash の環境変数 http_proxy などにプロキシのアドレスを設定します:
        #// 下記で定義する環境変数名は Linux でよく使われます
        #// http://__ProxyDomain__:__ProxyPortNum__ の例： http://10.100.100.100:8080
        (@host) bash:
            - echo  ${http_proxy}  #// 表示されたら以降の手順は不要です
            - echo  "export   http_proxy=\"http://__ProxyDomain__:__ProxyPortNum__\"" >> ~/.bashrc
            - echo  "export  https_proxy=\"http://__ProxyDomain__:__ProxyPortNum__\"" >> ~/.bashrc
            - echo  "export  no_proxy=\"localhost,127.0.0.1,control,node1\"" >> ~/.bashrc
        bash を開きなおします:
            下記の警告は無視できます: |
                WARNING: Found ~/.bashrc but no ~/.bash_profile, ~/.bash_login or ~/.profile.
vbguest プラグインをインストールします:  #// Ansible Local と Vagrant を接続するプラグインです
    (@host) Git bash:  #// VSCode >> Terminal >> New Terminal
        - vagrant plugin install vagrant-vbguest
プロジェクト フォルダーをダウンロードします:
    (@host) Git bash:
        - cd ~/Desktop
        - git clone https://github.com/Takakiriy/multi_vm_ansible.git
Visual Studio Code で プロジェクト フォルダーを開きます:
    (@host) Git bash:
        - code ~/Desktop/multi_vm_ansible
    #// VSCode 内で上記のコマンドを入力したら、コマンドを入力した VSCode を閉じます
Git bash シェルを開きます:
    (@host) VSCode >> Terminal >> New Terminal
仮想マシンを作って起動します:
    (@host) Git bash:
        - cd  __Project__  #// 不要の場合あり。以後も同様
        - vagrant up  #// 初回は約 10分。内部で Ansible Local による Playbook も動きます
            #// Vagrant プロジェクトがあるフォルダーは、VM の /vagrant/ フォルダーと共有します。
SSH で仮想マシンにログインできるように設定します（VSCode用）:
    VSCode の Remote Development 拡張機能をインストールします:
        インストールします:
            (@host) VSCode >> 拡張機能 ボタン（左） >> Remote Development
        SSH Targets を表示します:
            メニュー: (@host) VSCode >> Remote Explorer（アイコン：左）
            REMOTE EXPLORER（上）: SSH Targets
    SSH の設定を VSCode に追加します:
        (@host) VSCode Git bash:
            - vagrant ssh-config  #// SSH の接続に必要な設定が表示されます
            - code ~/.ssh/config  #// vagrant ssh-config の出力を最後に貼り付けます
    Visual Studio Code で SSH 接続します:
        vagrant / フォルダーが表示されているか確認します:
            (@host) VSCode >> Remote Explorer（左のアイコン）>> control >> vagrant /
        vagrant / フォルダーが表示されていない場合:
            SSH 接続します:
                control（の右のフォルダー）ボタン
            (@control) platform: Linux
                #// 接続できない時は、vagrant ssh-config を再実行してください
            SSH 接続した Visual Studio Code でフォルダーを開きます:
                (@control) VSCode >> File >> Open Folder ... >> /vagrant/
        vagrant / フォルダーが表示されている場合:
            (@host) vagrant / フォルダー（の右のフォルダー）ボタン
        シェルを開けることを確認します:
            (@control) VSCode >> Terminal >> New Terminal
                #// [vagrant@localhost vagrant]$ と表示されます
                #// 次回プロジェクトを開いたときにシェルが開いた状態になります
        開けたら Visual Studio Code を閉じます:
        Remote Explorer で開いたフォルダーを表示させます:
            (@host) VSCode >> Remote Explorer（左のアイコン）>> Reflesh ボタン（右上）
        次回からログインするときの操作:
            - (@host) タスクバーの VSCode を右クリック >> __Folder__ [SSH:__Server__]  #// または
            - (@host) VSCode >> File >> Open Recent >> __Folder__ [SSH:__Server__]  #// または
            - (@host) VSCode >> Remote Explorer ボタン（左）>> REMOTE EXPLORER= SSH Targets >> __Server__ >> __Folder__
        以上を @node1 についても行ます:
ansible_local がインストールされた VM から他の VM に SSH 接続できるようにします:
    (@host) Git bash:
        ./upload_SSH_keys.sh
SSH 経由で Ansible playbook を実行します:
    (@host) Git bash:
        ./run_playbook.sh
作成したすべての VM の電源を切ります:
    VirtualBox マネージャー >> __ProjectFolderName___control____ などを選択して右クリック >>
        閉じる >> 電源オフ
（必要なら）.vagrant フォルダーと VM のフォルダーをバックアップします:
    VM のフォルダー:
    .vagrant フォルダー:  #// VM の情報を持っています
VM の電源を入れます:  #// VM の電源を入れてホストOS と SSH 接続できるようにします
    #// 現在の VM が電源オフの状態でも中断の状態（ホストOSをシャットダウンした後の状態）でも同じ手順です
    VSCode でホストOS の Vagrant プロジェクトを開きます:
        タスクバーの VSCode を右クリック >> __Project__
    VirtualBox マネージャーに VM が表示されていない場合:
        VirtualBox マネージャー >> 仮想マシン >> 追加
    vagrant を起動します:
        (@host) Git bash:
            control_only=1  vagrant up
        #// 下記のサーバーも同時に起動できます:
        #// control_only=1 は、この Vagrantfile 固有の設定です
        #// 先に VirtualBox マネージャーで起動した VM は共有フォルダーが使えません
        #// control サーバー以外は vagrant up では起動しません。後で並列起動して早くするためです
    control サーバー以外を VirtualBox から起動します:
        VirtualBox マネージャー >> __ProjectFolderName___node1____ などをまとめて選択して右クリック >>
            起動 >> ヘッドレス起動
１つのタスクだけ実行します:
    --step オプションと --start-at-task オプションを使います:
        (@control) bash:
            - export ANSIBLE_INVENTORY="/tmp/vagrant-ansible/inventory/vagrant_ansible_local_inventory"
            - ansible-playbook  playbook.yml  --diff  -v  --step  --start-at-task "__TaskName__"
    よく使うオプション:
        --limit "__HostName__": 対象のサーバーを指定または制限します
        -vvv: 最も詳細に状況を表示します
        --check: チェックだけ行い、タスクの実行は行ません (dry run)
```

## 参考サイト

- Ansible の Vagrant ガイド  https://docs.ansible.com/ansible/2.9_ja/scenario_guides/guide_vagrant.html
- Vagrant の Amsible Local プロビジョナー  https://www.vagrantup.com/docs/provisioning/ansible_local
- Ansible Playbook の作り方（サンプルの表示が崩れています）  https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks.html
- Ansible Playbook の作り方（英語版）  https://docs.ansible.com/ansible/2.9/user_guide/playbooks.html
- ansible-playbook コマンドのオプション  https://docs.ansible.com/ansible/2.9_ja/cli/ansible-playbook.html
- Ansible のモジュールのカタログ  https://docs.ansible.com/ansible/2.9_ja/modules/modules_by_category.html
- （物理サーバーなど、Vagrant を使わない）Ansible のインストール  https://docs.ansible.com/ansible/2.9_ja/installation_guide/intro_installation.html