ホストWIndowsでVagrant + ansibleでLinuxをプロビジョニングしようとしたら盛大にハマった。

はじめに

vagrantのansible_local使って複数台のゲストOSをansibleでプロビジョニングしようとしたら盛大にはまった。

筆者環境

ちなみに自宅のMBPで同じことやってもちゃんと動いたので、 Windows特有の問題。

構成

複数台のVM立ち上げるのに、地道にプロビジョニングしていくと時間かかるので、 ansibleのコントロールVMを1個作って、そこからプロビジョニングするようにする。

絵書くとこんな感じ f:id:syogo0417:20180228173439p:plain

図には書いてないですが、ホストオンリーアダプタでホストOSとやり取りが可能で、 ゲストOSは同一のネットワークセグメントです。

コード

基本Vagrant公式のansible_localの下の方に書いてあるヤツ。

Ansible Local - Provisioning - Vagrant by HashiCorp

ソースの構成

/root

 Vagrantfile

 inventory

 docker.yml

 ansible.cfg

プロジェクトルートからフラットに並べてるだけ

Vagrantfile

Vagrant.configure("2") do |config|

  config.vm.box = "centos7.2"

  config.vm.define "node1" do |machine|
    machine.vm.network "private_network", ip: "172.17.177.21"
  end

  config.vm.define "node2" do |machine|
    machine.vm.network "private_network", ip: "172.17.177.22"
  end

  config.vm.define 'controller' do |machine|
    machine.vm.network "private_network", ip: "172.17.177.11"

    machine.vm.provision :ansible_local do |ansible|
      ansible.playbook       = "docker.yml"
      ansible.verbose        = true
      ansible.install        = true
      ansible.limit          = "all" # or only "nodes" group, etc.
      ansible.inventory_path = "inventory"
    end
  end

end

inventory

controller ansible_connection=local
node1      ansible_ssh_host=172.17.177.21 ansible_ssh_private_key_file=/home/vagrant/private_key.node1
node2      ansible_ssh_host=172.17.177.22 ansible_ssh_private_key_file=/home/vagrant/private_key.node2

[nodes]
node[1:2]

playbook

---
- name: install docker
  hosts: nodes
  become: true
  tasks:
  - name: create docker group
    group: name=docker
  - name: add a docker user
    user: name=docker password=docker123 group=docker state=present
  - name: install required packages
    yum: name={{ item }} state=present
    with_items:
      - yum-utils
      - device-mapper-persistent-data
      - lvm2
  - name: setup stable docker repository
    shell: "yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo"
    args:
      chdir: "/etc/yum.repos.d"
      creates: docker-ce.repo
  - name: install docker
    yum: name=docker-ce state=present
  - name: enable service docker
    systemd:
      name: docker
      enabled: yes
      state: started

ansible.cfg

[defaults]
host_key_checking = no

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes

実行する

vagrant up

provisionが動くと盛大にエラーになる。

実行エラー

PLAY [install docker] ********************************************************

TASK [Gathering Facts] *********************************************************
fatal: [node1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '172.17.177.21' (ECDSA) to the list of known hosts.\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\nPermissions 0777 for '/vagrant/.vagrant/machines/node1/virtualbox/private_key' are too open.\r\nIt is required that your private key files are NOT accessible by others.\r\nThis private key will be ignored.\r\nbad permissions: ignore key: /vagrant/.vagrant/machines/node1/virtualbox/private_key\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n", "unreachable": true}
        to retry, use: --limit @/vagrant/docker.retry

PLAY RECAP *********************************************************************
node1                      : ok=0    changed=0    unreachable=1    failed=0

Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.

エラーのざっくりした内容

sshで使用するkeyのパーミッションが悪くてsshが失敗している。 めんどくさいからホストOS上からフルコントロール付ける。

再チャレンジ

vagrant provision

これでいけるだろうと思ったら盛大にエラーが出る

実行エラー

==> controller: Running provisioner: ansible_local...
Vagrant has automatically selected the compatibility mode '2.0'
according to the Ansible version installed (2.4.2.0).

Alternatively, the compatibility mode can be specified in your Vagrantfile:
https://www.vagrantup.com/docs/provisioning/ansible_common.html#compatibility_mode
    controller: Running ansible-playbook...
cd /vagrant && PYTHONUNBUFFERED=1 ANSIBLE_NOCOLOR=true ansible-playbook --limit="all" --inventory-file=inventory -v docker.yml
Using /vagrant/ansible.cfg as config file

PLAY [install docker] ********************************************************

TASK [Gathering Facts] *********************************************************
fatal: [node1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '172.17.177.21' (ECDSA) to the list of known hosts.\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\nPermissions 0777 for '/vagrant/.vagrant/machines/node1/virtualbox/private_key' are too open.\r\nIt is required that your private key files are NOT accessible by others.\r\nThis private key will be ignored.\r\nbad permissions: ignore key: /vagrant/.vagrant/machines/node1/virtualbox/private_key\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n", "unreachable": true}
fatal: [node2]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '172.17.177.22' (ECDSA) to the list of known hosts.\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @\r\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\nPermissions 0777 for '/vagrant/.vagrant/machines/node2/virtualbox/private_key' are too open.\r\nIt is required that your private key files are NOT accessible by others.\r\nThis private key will be ignored.\r\nbad permissions: ignore key: /vagrant/.vagrant/machines/node2/virtualbox/private_key\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n", "unreachable": true}
        to retry, use: --limit @/vagrant/docker.retry

PLAY RECAP *********************************************************************
node1                      : ok=0    changed=0    unreachable=1    failed=0
node2                      : ok=0    changed=0    unreachable=1    failed=0

Ansible failed to complete successfully. Any error output should be

エラーのざっくりした内容

権限与えすぎなんだよ!って怒られてる。 ~/.ssh/known_hostに何かする場合、権限与えすぎてもダメということらしい。 (はじめて知った)

調べてみたら、 所有者以外の書込み権を設定してあるとだめとのこと。 Windows上から何したら600とかになるのか判らんから、とりあえずkeyファイルをコピーして権限を与えることに。

vagrant ssh controller
cp -p /vagrant/.vagrant/machines/node1/virtualbox/private_key private_key.node1
cp -p /vagrant/.vagrant/machines/node2/virtualbox/private_key private_key.node2
chmod 600 private_key*
exit
vagrant provision

(略) 最後まで動いて、各ゲストにログインしてdockerコマンド打ってもちゃんと入った。

教訓

ファイルシステムが違うものをマウントして、参照することの難しさを再認識したのであった。

まとめ

VagrantWindowsをホストOS)を使って、コントロールマシン経由で各VMをプロビジョニングしたい場合は、 private_keyをコントロールマシン上にコピーしてパーミッションを600に変更してあげると、 WindowsだのMacだのLinuxだのでエラーは起きない。 Vagrant使うときはGNU系の何かが使う処理をホスト側に置いたまま処理しない方が無用な問題を避けられるなーと感じた。

弊社はLaravel + Vagrantで開発環境を作るので、この辺の知見は仕事にも活かしたい。

私、k8sの環境を会社のPC内に作りたかっただけなのに、これだけで3日分の昼休みを浪費した。。つらい。