ansible 〜つなぐ〜

# ansible 〜つなぐ〜

インベントリファイル(今回は`hosts.yml`で統一します)、`ansible.cfg`、`ssh_config`を駆使し、様々な状況でansibleをつなぎます。
繋いだ後は好きにしてください。

# 接続の確認に用いたコマンド

```
ansible -m ping all -i hosts.yml
```

allとはansibleが認識したホストが自動的に入れられるグループです。
その名の通り全ホストが対象になります。


# 初級
## 普通につなぐ

* `hosts.yml`

```
all:
  hosts:
    server1:
      ansible_host: 192.168.122.100
      ansible_user: vagrant
      ansible_ssh_private_key_file: ~/.ssh/id_rsa
    
```

ansibleは基本公開鍵認証でログインします。

「pingなのにログイン？？？」

って思うと思います。私は思いました。
`-vvv`オプションを使うと実行したコマンド等がダラダラ表示され、
`ansible -m ping all -vvv`とするとわかりますが、
`ansible -m ping` は `ping`を実行しているのではなく、`ssh`でログインを試行し、
ログイン成功した場合`SUCCESS`と帰ってきます。

## パスワード認証でつなぐ

* `hosts.yml`

```
all:
  hosts:
    server1:
      ansible_host: 192.168.122.100
      ansible_user: vagrant
      ansible_pass: vagrant
    
```

`ansible_pass`を設定した場合、パスワード認証でログインを試行します。
ただファイルにパスワードを直で書くのは少し気が引けますね

## パスワード認証でつなぐ`ask_pass`

* `hosts.yml`

```
all:
  hosts:
    server1:
      ansible_host: 192.168.122.100
      ansible_user: vagrant
```

* `ansible.cfg`

```
[defaults]
ask_pass = True
```

`ansible.cfg`内で`ask_pass`の値を`True`に設定することで、
ansibleコマンド実行前にパスワードの入力が促されます。

``` console
$ ansible -m ping all
SSH password: 
server1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

`ansible.cfg`に記述せず、コマンド実行時に`--ask-pass`オプションを付けることでも同様です。

``` console
$ ansible -m ping all --ask-pass
SSH password: 
server1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
```

# 中級

## `locahost`につなぐ

* `hosts.yml`

```
all:
  hosts:
    server1:
      ansible_connection: local
```

`ansible_connection`の値に`local`を設定すると`localhost`にアクセスします。
この時`ssh`接続は行いませんので、`ansible_user`や`ansible_ssh_pass`の設定は必要ありません。

## `ssh_config`を使ってつなぐ

`ssh_config`ファイルは`ssh`接続を行うときの設定ファイルです。
[ドキュメント](https://man.openbsd.org/ssh_config.5)
これ自体は`OpenSSH`の設定ファイルなのですが、`ansible`と組み合わせると非常に便利になります。

* `hosts.yml`

```
all:
  hosts:
    server1: {}
```

* `ansible.cfg`

```
[ssh_connection]
ssh_args = -F ssh_config
```

* `ssh_config`

```
Host server1
  HostName 192.168.122.100
  User vagrant
  Port 22
  PasswordAuthentication no
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes
```

`ansible.cfg`で`ansible`が`ssh`接続を行う際のオプションを追加しています。
接続情報をすべて`ssh_config`に記載してしまったので`hosts.yml`では何も設定していません。

# 上級

## 踏み台サーバーを経由してつなぐ

`ssh_config`の`ProxyCommand`を利用すると踏み台サーバーを経由したアクセスが可能になります。
`ansible`というより`OpenSSH`のお話ですね。
今回の構成は以下

```
[ansible] --> [server1(踏み台)] --> [server2(目的のサーバー)]
```

* `hosts.yml`

```
all:
  hosts:
    server1: {}
    server1: {}
```

* `ansible.cfg`

```
[ssh_connection]
ssh_args = -F ssh_config
```

* `ssh_config`

```
Host server1
  HostName 192.168.122.100
  User vagrant
  Port 22
  PasswordAuthentication no
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes

Host server2
  HostName 192.168.122.101
  User vagrant
  Port 22
  PasswordAuthentication no
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes
  ProxyCommand ssh -F ssh_config -W %h:%p server1
```

`ssh_config`内の`ProxyCommand`の設定を記述するだけですね。
`ProxyCommand`を設定するとターゲットになるホストに`ssh`接続を行う前に、 指定されたコマンドを実行します。
そして別のホストに`ssh`コネクションをはってから`ssh`接続を行うようになります。

## ポートフォーディングを利用してつなぐ

踏み台サーバーを経由しポートフォーディングで`ssh`接続を行います。
これも`ansible`というより`OpenSSH`のお話ですね。
今回の構成は以下

```
[ansible] --> [server1(踏み台)] --> [server2(目的のサーバー)]
```

server2の22番ポートをlocalhostの10022番ポートにつなぎます。

```
ssh -F ssh_config -f -N -L 10022:server2:22 server1
```

これで`localhost`の10022番にアクセスするとserver2の22番ポートにフォーディングされます。
あとは`localhost`の10022番にssh接続するだけでおっけーです。

* `hosts.yml`

```
all:
  hosts:
    server1: {}
    server1: {}
```

* `ansible.cfg`

```
[ssh_connection]
ssh_args = -F ssh_config
```

* `ssh_config`

```
Host server1
  HostName 192.168.122.100
  User vagrant
  Port 22
  PasswordAuthentication no
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes

Host server2
  HostName 127.0.0.1
  User vagrant
  Port 10022
  PasswordAuthentication no
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes
```


# おわり

他にも違うパターンでのつなぎ方&解決策を見つけ次第追記していきたいです。

アイデアある方コメントでいただければ幸いです。