Vagrant上でubuntuに入れたansibleからcentOSへ接続したメモ

ubuntuにansibleを入れて、CentOSへ接続を行う。

## 開発環境

* Windows 10
* Vagrant 2.1.5
* Virtualbox 5.2.18
* ubuntu 18.0.4
* ansible2.5
* CentOS 7.5


[この時点のソース](https://github.com/hibohiboo/develop/tree/cd099ec71ea326750f4345e55c5de37540b999d2/tutorial/lesson/ansible/)

## フォルダ構成

全体の構成。
nsibleを入れたコントロールサーバと設定を行うターゲットサーバをディレクトリを分けて作成した。

```
.
├── controll
│   ├── Vagrantfile
│   ├── bin
│   ├── provision
│   └── provision_targets
└── targets
    └── Vagrantfile
```

controllフォルダ以下を詳しく。
provisionディレクトリにはコントローラサーバのプロビジョニングで使う設定を書いている。
provison_targetディレクトリにはターゲットとなるサーバへ行う設定を書く。

```
vagrant@vagrant:/vagrant$ tree .
.
├── bin
│   ├── controll
│   │   ├── add-publickey.sh
│   │   └── ansible.sh
│   └── run.sh
├── provision
│   ├── bash
│   │   └── install_ansible.sh
│   ├── logs
│   │   └── ansible.log
│   └── playbooks
│       ├── inventory
│       │   └── hosts
│       ├── roles
│       │   └── ssh
│       │       ├── tasks
│       │       │   ├── check_install.yml
│       │       │   ├── configure.yml
│       │       │   ├── generate_key.yml
│       │       │   ├── install.yml
│       │       │   └── main.yml
│       │       └── vars
│       │           └── main.yml
│       └── site.yml
├── provision_targets
│   ├── inventory
│   │   └── inventory.ini
│   ├── logs
│   └── test.yml
└── Vagrantfile
```


## 手順

### 仮想環境の立ち上げ
まずはそれぞれの仮想環境を立ち上げておく

```
cd controll && vagrant up
cd targets && vagrant up
```

### 鍵の登録

コントロールサーバで作成した公開鍵をターゲットサーバに登録する

```
./controll/bin/run.sh add-publickey
```

### ansibleの実行

コントロールサーバからターゲットサーバへ設定を行う。
今回は接続のテストとしてipアドレスの表示を行う

```
./controll/bin/run.sh ansible
```

## ハマったポイントについてのメモ

expectモジュールを使用するが、pexpectはansibleの動く環境ではなく、ansibleが設定をしに行く環境に必要となる。
venvにpexpectをインストールするのではなく、ローカルにインストールする。

```yml:controll/provision/bash/install_ansible.sh
#!/bin/bash

curl -kL "https://bootstrap.pypa.io/get-pip.py" | sudo python
cd $HOME

# ansible expectモジュールが使えるようにする(ansibleの仮想環境ではなくローカルに必要)
sudo pip install pexpect

# pythonの仮想環境起動
virtualenv venv
source $HOME/venv/bin/activate

# ansibleインストール
pip install ansible
ansible --version
```


blockでwith_itemsは使えないので、includeでまとまった処理は繰り返す。
includeするファイルの中で変数名がitemではわかりにくいので、loop_varで変数名を変更する。

```yml:controll/provision/playbooks/roles/ssh/tasks/install.yml
---
- include: roles/ssh/tasks/generate_key.yml
  with_items: "{{targets_keyname}}"
  loop_control:
    loop_var: keyname
```


expectモジュールのresponsesには正規表現を書くので -()[]\?*.等にエスケープが必要

```yml:controll/provision/playbooks/roles/ssh/tasks/generate_key.yml
---
# 秘密鍵の存在チェック
- name: check private key
  command:
    test -f /home/vagrant/.ssh/{{keyname}}
  register:
    result_test_private_key
  failed_when: result_test_private_key.rc not in [0, 1]
  changed_when: false

# パスフレーズなしの秘密鍵と公開鍵のセットを作成。
- name: generate private key
  become: true
  become_user: vagrant
  expect:
    command: "ssh-keygen -t rsa"
    timeout: 10
    responses:
      'Enter file in which to save the key \(\/home\/vagrant\/\.ssh\/id_rsa\): ': "/home/vagrant/.ssh/{{keyname}}"
      'Enter passphrase \(empty for no passphrase\): ': ''
      'Enter same passphrase again: ': ''
  when:
    result_test_private_key.rc != 0
```

sshpassを使ってターゲットのcentosに公開鍵を登録する。

```controll/bin/controll/add-publickey.sh
sshpass -p vagrant ssh-copy-id -o StrictHostKeyChecking=no -i /home/vagrant/.ssh/id_rsa_web.pub 192.168.74.60
```

`vagrant ssh-config`でsshの設定をできるようにするためにsshに使用するポートを固定する。
これをしないと、ubuntuのvagrantと競合してランダムにsshポートを使ってしまうため、
[快適にssh][*3]できなくなってしまう。

```ruby:targets/Vagnraitfle
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-7.5"

  config.vm.provider "virtualbox" do |vm|
    vm.memory = 2048
  end

  config.vm.define "web_server_1" do |server|
    server.vm.network "private_network", ip: "192.168.74.60"
    server.vm.network "forwarded_port", guest: 22, host: 12223, id: "ssh"
  end
  
  config.vm.define "db_server_1" do |server|
    server.vm.network "private_network", ip: "192.168.7.25"
    server.vm.network "forwarded_port", guest: 22, host: 12230, id: "ssh"
  end
end
```

## 参考

[ansible expect][*1]
[公開鍵を使う][*2]
[Vagrant ssh-configでvagrant sshを快適にする][*3]
[初めてAnsible][*4]

[*1]:https://qiita.com/nyk0401/items/f0fdbdbadf61e1217dec
[*2]:https://qiita.com/t_732_twit/items/2303a0c3f27c288382c5
[*3]:https://qiita.com/Sanche/items/43d615beef05cd9417e2
[*4]:https://qiita.com/amagumo0207/items/26ebfec2f076db6b7c3f