「Ansible」カテゴリーアーカイブ

Vagrant+Ansibleのデバッグ方法

VagrantとAnsibleを使っていると、たびたびエラーになります。

そのデバッグに役立ったことを紹介します。

Vagrantの場合

Vagrantでプロビジョニングをしてエラーになったときは、次のようにします。

VAGRANT_LOG=info vagrant provision

を実行する。

エラーになると次のような表示が確認できる。

ERROR vagrant: The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.

調べてみるとログの上の方にこんな情報がありました。

 INFO interface: info: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)
 INFO interface: info: ==> default: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)

apt-getのエラーのようで、vagrant sshでゲストOSにログインしてapt-getしてみても原因はつかめず。もう1度vagrant provisionしてみると成功しました。一時的にエラーになっただけのようでした。

Ansible単独の場合

AnsibleはSSHで接続できていないと動きません。そのためSSHのチェックが重要になります。
まず、次のコマンドで接続を確かめます。

ansible -vvvv all -m ping

を実行してみる。

表示色が濃い青色で読めないときは、ANSIBLE_NOCOLOR=1をつけます。

ANSIBLE_NOCOLOR=1 ansible -vvvv all -m ping

ログのポイントは次のところです。ESTABLISH SSH CONNECTION FOR USERでssh接続のユーザー名が間違っていないか。

SSH:EXEC sshのところで、この場合sshから192.168.33.10までがsshのコマンドラインになります。とりあえずこのIPアドレスまでをコピーしてペーストして単独で接続できるか見てみます。

<192.168.33.10> ESTABLISH SSH CONNECTION FOR USER: ubuntu
<192.168.33.10> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile=".vagrant/machines/default/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ubuntu -o ConnectTimeout=10 -o ControlPath=/tmp 192.168.33.10 '/bin/sh -c '"'"'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1496030041.85-156969875839371/ /home/ubuntu/.ansible/tmp/ansible-tmp-1496030041.85-156969875839371/ping.py && sleep 0'"'"''

sshからIPアドレスまでの部分だけをコピーペーストで新しく張り付けて実行してみます。

ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o 'IdentityFile=".vagrant/machines/default/virtualbox/private_key"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=ubuntu -o ConnectTimeout=10 -o ControlPath=/tmp 192.168.33.10

これで接続できているかまず確認しましょう。

sshで接続できていれば、問題の切り分けができます。あとはpythonのスクリプトが実行できているかどうかです。

MSYS2でansibleを使うときの訂正とpythonのvirtualenvとvenv

MSYS2でansibleを使うときは32bit版ではなくて、インストールするパッケージがmsysのpythonであることが必要でした。
以前の記事を訂正しました。

pythonのバージョンを管理する、python3のvenvやpython2のvirutalenvも、msys用のpythonだと動きますがMinGW用のpythonだと動きません。

スタートメニューのMSYS2 MinGW 32-bitや、MSYS2 MinGW 64-bitのコンソールでは、MinGW用のpythonがインストールしてあるとそちらが優先的に実行されてしまうので注意してください。

msys用のpythonはpipが用意されていませんので、get-pip.pyをcurlでインストールします。

python2の場合、pipでvirtualenvをインストールします。そのうえで-m virtualenvでモジュールを指定して実行します。適当な名前myvenvを指定すると、myvenv/bin/以下にpythonやpipがコピーされます。activateをbashに読み込ませると開発環境が変わります。

カッコつきで(myvenv)のように表示されるとOKです。

deactivateで元に戻ります。

$ pacman -S python2

$ curl -kL https://bootstrap.pypa.io/get-pip.py | python2
$ pip install virtualenv

$ mkdir test
$ cd test
$ python2 -m virtualenv myvenv
$ source myvenv/bin/activate

(myvenv)

$ deactivate

python3をpython2と同居させる場合、pipコマンドをpython2のようにインストールすると、/usr/bin/pipが上書きされてしまいます。
そのため、venvというモジュールを使ってローカルのフォルダにpip関係のモジュールを入れて隔離したほうがいいです。

python2は、virtualenvをpipでインストールしないといけないので、グローバルにインストールするしかないです。

適当な名前myvenvを指定してpython3 -m venvを実行するとpython3の実行ファイルとpipがコピーされて使えるようになります。

$ pacman -S python

$ mkdir python3test
$ cd python3test
$ python3 -m venv myvenv
$ source myvenv/bin/activate

(myvenv)

$ deactivate

python2とpython3でpipをインストールすると、pipは後にインストールしたほうになります。先にインストールした方は、pip2もしくはpip3で指定しないといけないです。

混在するのはよくないので、pipはpython2のみでインストールし、python3は-m venvで仮想環境を作ったときに自動でインストールされるpipを使うのがよいです。

MSYS2のAnsibleを使ってVagrantでプロビジョニング

VagrantでゲストOSをセットアップするには、次の3通りがあります。

  1. Vagrantfileの中ではプロビジョニングを使わず、ゲストOSを立ち上げるだけにして、ansible単独でゲストOSを操作する方法
  2. Vagrantfileの中でconfig.vm.provision 'ansible_local'として、Vagrantのansible_localというプロビジョニングを使う方法
  3. Vagrantfileの中でconfig.vm.provision 'ansible'として、Vagrantのプロビジョニングを使う方法

今回は、3番目のVagrantのansibleプロビジョニングを使ってゲストOSをセットアップします。

AnsibleもVagrantも、ansibleプロビジョニングをWindowsホストではサポートしていないのでその点はご了承ください。

前回までに、MSYS2上でAnsibleが動くことがわかりました。

まず、これまでのように、ホストからansible-playbookでゲストOSが操作できることを確認します。

これで素直にVagrantのプロビジョニングのなかでansibleが使えるかというと、エラーが出て使えません。

そこで、Cygwinでの動作例を参考に次のようにしました。

ansble-play.batという次のようなファイルを作ってPATHの通ったところに置きます。

@echo off

REM MSYS2のインストール場所
set MSYS=C:\msys32

REM bash.exeからansible-playbookを起動します
set SH=%MSYS%\usr\bin\bash.exe

"%SH%" -c "/usr/bin/ansible-playbook %*"

これで、Vagrantからansible-playbookを呼び出すことができます。

Vagrantfileは次の通りです。ゲストOSはubuntu/xenial64にしたのですが、このイメージはpythonが含まれていません。そのため、shellプロビジョニングを使ってインストールしました。このとき、aptのソースファイルを書き換えて少し速くインストールするようにしました。

ansibleプロビジョニングでは、Playbookをsite.yml、コンフィグレーションファイルにansible.cfg、インベントリファイルにhostsを指定しました。

Vagrantfile

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/xenial64"

  config.vm.network "private_network", ip: "192.168.33.10"
  
  config.vm.provision "shell", inline: <<-SHELL
		# aptのソースファイルを書き換え
    sed -i s%archive.ubuntu.com/ubuntu%ftp.jaist.ac.jp/pub/Linux/ubuntu/%g /etc/apt/sources.list
    apt-get update
    apt-get -y install python aptitude
  SHELL

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "site.yml"
    ansible.config_file = "ansible.cfg"
    ansible.inventory_path = "hosts"
    ansible.limit = 'all'
  end
end

次にansible.cfgファイルです。vagrant ssh-configで表示される結果をもとに作ります。Userをremote_userに、IdentityFileをprivate_key_fileにします。

control_pathの設定は、CygwinやMSYS2を使ったときにエラーになるのを回避するためです。こちらの情報をもとにしました。

ansible.cfg

[defaults]
inventory = hosts
remote_user = ubuntu
host_key_checking = False
private_key_file = .vagrant/machines/default/virtualbox/private_key


[ssh_connection]
# for Cygwin, MSYS2
control_path = /tmp

インベントリファイルは、次の通りです。vagrantsというグループで、ubuntu01という名前にしました。IPアドレスはVagrantfileと合わせます。これが違っていてよくSSHのエラーになりました。

hosts

[vagrants]
ubuntu01 ansible_host=192.168.33.10

最後はPlaybookです。Apache2をインストールすることにしました。

vagrantsというグループにubuntuでアクセスします。aptでapache2の最新版ををインストールしてbecome: trueでスーパーユーザーで行います。

site.yml

---
- hosts: vagrants
  user: ubuntu
  tasks:
    - name: install packages Apache2
      apt: name=apache2 update_cache=yes
      become: true

4つのファイルがそろえば、vagrant upでサーバーが設定され、http://192.168.33.10/にアクセスするとApache2の画面を見ることができます。
使ってみて、VagrantのAnsibleプロビジョニングはVagrantと一緒に使うときは便利ですが、Ansible単独で設定したほうが自由度はあるのかなという感じがしました。

Vagrantで、ansible_localを使ってみる

VagrantでゲストOSをセットアップするには、次の3通りがあります。

  1. Vagrantfileの中ではプロビジョニングを使わず、ゲストOSを立ち上げるだけにして、ansible単独でゲストOSを操作する方法
  2. Vagrantfileの中でconfig.vm.provision 'ansible_local'として、Vagrantのansible_localというプロビジョニングを使う方法
  3. Vagrantfileの中でconfig.vm.provision 'ansible'として、Vagrantのプロビジョニングを使う方法

このうち、今回はansible_localを使う方法を試してみます。

Vagrantのプロビジョニングでansible_localを使う場合には、ホストOSにはansibleをインストールしてある必要はありません。

ゲストOSにansibleが自動的にインストールされ、そこでansible-playbookが実行されます。

ポイントは2つあります。1つは、Vagrantfileでprovisionにansible_localを設定します。2つめは、Playbookでconnection: localを使うことです。

ansible_localを指定すると、ゲストOSにansibleが自動的にインストールされます。

実際の例は以下の通りです。

Vagrantfileは次の通りです。プライベートアドレスに192.168.33.10を指定して、provisionにansible_localを指定します。Playbookにsite.ymlを指定し、インベントリファイルにhostsを指定しています。

Vagrantfile

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/xenial64"

  config.vm.network "private_network", ip: "192.168.33.10"
  
  config.vm.provision "ansible_local" do |ansible|
    ansible.playbook = "site.yml"
    ansible.inventory_path = "hosts"
    ansible.limit = 'all'
  end
end

インベントリファイルは次の通りです。vagrantsというグループにubuntu01というホスト名のサーバーがあり、アドレスは192.168.33.10としています。

hosts

[vagrants]
ubuntu01 ansible_host=192.168.33.10

Playbookは次の通りです。vagrantsというグループに、connection: localという設定で、ubuntuというユーザーにログインします。そこで、Apache2をインストールしています。

site.yml

---
- hosts: vagrants
  connection: local
  user: ubuntu
  tasks:
    - name: install packages Apache2
      apt: name=apache2 update_cache=yes
      become: yes

connection: localがないと、次のようなエラーになります。

TASK [Gathering Facts] *********************************************************
fatal: [ubuntu01]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Host key verification failed.\r\n", "unreachable": true}
        to retry, use: --limit @/vagrant/site.retry

connection: localを使わないと、ゲストOSにansibleをインストールしてあるのに、わざわざ自分自身にsshでログインしてplaybookを実行しようとします。そのとき、SSHのエラーになります。

ansible_localを使うと、ansibleは自動的にインストールしてくれますので簡単ですね。

AnsibleにはGitによる管理が必須です

Ansibleを使って構成管理をしだすと、少し設定を変更しては試してみることが増えます。特に、AnsibleやDockerを学ぶ際には繰り返すことが多いです。Vagrantを使っていると特に設定して試してみてという試行錯誤が簡単なので、変更が多くなります。

そうすると、ここを変更したいけど、後でまた必要になるからコメントアウトしておこうとかしたくなります。

また、少しづつ変えると何のために変更したのか後で見直すとよくわからないということになります。

そこで有効になるのがGitです。

Gitで設定ファイルを管理すると、とりあえず今の状態を保存しておこうということが簡単にできます。また、動かなくなった時でも簡単に元に戻せます。

あれ、このプログラム以前は動いたはずだけど、なんで動かないのだろうとよくあるのではないでしょうか。また、Gitでとりあえず保存はしておいて、過去のコードが役に立ったというような経験がありませんか。そのとき初めてGitの良さがわかるようになります。

Git無しではなんか不安、になれば十分使いこなしているといえましょう。

別に、Git中毒になれと言っているわけではないです。時々でもいいからコメント付きで保存しておくと、いざという時役に立ちます。

サーバーの構成管理がファイルでできるようになっていることが大きいです。ファイルを保存してきさえすれば、以前の状態のサーバーを簡単に作り出すことができます。

幸いにして、Git使っているけどなんでいいのかわからない、なんて場合もあると思います。そういう場合は、作業記録を残しておくことに意義を見出しましょう。

Ansibleで開発しようと思ったらとりあえずgit init。できた!、動いた!と思ったらとりあえずgit comit。これを習慣にしておくといいです。

AnsibleのインベントリファイルはLinuxのhostsファイルとは違う

インベントリファイルはhostsという名前になっていることが多いです。

Ansibleを使い始めた時、Linuxの/etc/hostsファイルと一緒なのかと思っていました。

よく紹介されている例でも、IPアドレスが直書きされています。

それでも動くのですが、調べていくうち/etc/hostsファイルとは違うことがわかってきました。

インベントリファイルは、ホストの名前とその設定を書く場所です。

よくある例では、

[default]
192.168.33.10

と書かれています。これは、defaultグループに192,168.33.10でアクセスできるホストがあるという設定です。

でも、次のような書き方もあります。

host01 ansible_host=192.168.33.10

[webservers]
host02 ansible_host=192.168.33.20

このインベントリファイルの意味は、host01はグループに属していません。IPアドレスは、192.168.33.10です。webserversというグループにhost02という名前のマシンがあって、そのIPアドレスが192.168.33.20という意味です。

どうもインベントリファイルは、/etc/hostsファイルとは違って名前を設定するファイルのようです。

Ansibleのtutorialを見てみると、Getting Startedでは、

192.0.2.50
aserver.example.org
bserver.example.org

このように直書きしたものもありますが、Inventoryの説明では、

mail.example.com

[webservers]
foo.example.com
bar.example.com

[dbservers]
one.example.com
two.example.com
three.example.com

このようにすべて、名前で設定されています。

また、IPアドレスだけでなくいろいろな設定を書くことができます。

ansible_connectionで接続方法が設定できたり、ansible_userで接続時のユーザー名を設定できたりします。

foo.example.com ansible_host=192.168.33.10 ansible_connection=local ansible_user=foo

:varsという拡張子をつけることでグループを一括して設定を書くことができます。

[webservers]
foo.example.com
bar.examble.com

[webservers:vars]
ansible_connection=local
ansible_ssh_private_key_file=/home/example/.ssh/aws.pem

AnsibleのインベントリファイルはLinuxのhostsファイルとは違うという話でした。

AnsibleでゲストOSをセットアップする

前々回でAnsibleをインストールし、前回でVagrantで作ったゲストOSにSSHで接続できることがわかりました。Ansibleを使う環境は整ったので、Ansible単独でゲストOSをセットアップします。

手順はまず、Vagrantでサーバーを用意します。次に、Ansibleの設定をansible.cfgにして、扱うサーバーの設定を書いたhostsという名前のインベントリファイルを用意して動作確認をします。それが出来たら、Playbookを作成して実行してみます。

なお、Windows上のAnsibleの設定ではこちらのCygwinの情報を参考にしました。

Vagrantfileファイル

用意したサーバーは、次のようなVagrantfileで作りました。

Vagrantfile

VAGRANTFILE_API_VERSION = &quot;2&quot;

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = &quot;ubuntu/xenial64&quot;

  config.vm.define 'ubuntu01' do |host|
    host.vm.hostname = 'ubuntu01'
    host.vm.network &quot;private_network&quot;, ip: &quot;192.168.33.10&quot;
  end

  config.vm.provision 'shell', inline: &lt;&lt;-SCRIPT
    # aptのソースファイルを書き換え
    sed -i s%archive.ubuntu.com/ubuntu%ftp.jaist.ac.jp/pub/Linux/ubuntu/%g /etc/apt/sources.list
    apt-get update
    apt-get -y install python aptitude
  SCRIPT

end

ゲストOSには、ubuntu/xenial64を選びました。ubuntu01という名前にして、IPアドレスは、192.168.33.10にしました。

ubuntu/xenial64にはPythonがインストールされていません。Ansibleは、PythonのコードをゲストOSに送り込んで実行します。そのため、あらかじめPythonをインストールしていおきます。ダウウンロードの時間を短縮するために、aptのソースファイルを編集してあります。

ansible.cfgファイル

次に、Ansibleの設定をするansible.cfgを作ります。vagrant ssh-configの結果をもとに次のようなファイルを作りました。

ansible.cfg

[defaults]
inventory = hosts
remote_user = ubuntu
host_key_checking = False
private_key_file = C:/msys32/home/kazu/ansible/intro/.vagrant/machines/ubuntu01/virtualbox/private_key

[ssh_connection]
# for Cygwin, MSYS2
control_path = /tmp

インベントリファイル名は、hostsにします。remote_userとprivate_key_fileは、vagrant ssh-configで表示されるユーザー名UserとプライベートキーIdentityFileの場所を設定します。

host_key_checking = Falseは、ゲストOSを作ったり壊したりしたときに公開鍵が変わってしまうのですが、それをチェックしないという意味です。

MSYS2やCygwinでansibleを動かすときのポイントは、control_path = /tmpをansible.cfgに設定することです。これがないとエラーになります。
こんなエラーが出ます。

ubuntu01 | UNREACHABLE! =&gt; {
    &quot;changed&quot;: false,
    &quot;msg&quot;: &quot;Failed to connect to the host via ssh: mm_send_fd: sendmsg(2): Connection reset by peer\r\nmux_client_request_session: send fds failed\r\n&quot;,
    &quot;unreachable&quot;: true
}

hostsファイル

次に、hostsという名前のインベントリファイルを作ります。

hosts

[webservers]
ubuntu01 ansible_host=192.168.33.10

webserversというグループに、ubuntu01という名前のサーバーを作り、そのIPアドレスは192.168.33.10です。これは、Vagrantと合わせます。

Ansibleで使うhostsファイルのホスト名(この場合はubuntu01)は、Vagrantで使うVagrantfileのhost.vm.nameで指定する名前とは無関係です。もっとも、同じにしておいた方が間違わなくて済むのでいいです。

動作確認

ファイルが出来たら、ansibleに続けて、すべてのマシン(all)にpingを打ってサーバーからの返事を見ます。-m pingというのはpingモジュールを使ってpingを打つという意味です。

ansible all -m ping

こういう返事が返ってくれば成功です。

ubuntu01 | SUCCESS =&gt; {
    &quot;changed&quot;: false,
    &quot;ping&quot;: &quot;pong&quot;
}

Playbookの実行

あとは、Playbookを作って実行するだけです。

Playbookは、インデントが重要なのでタブが入っているとエラーになります。気をつけましょう。

ここでは、site.ymlという名前のPlaybookを作りました。

hostsに実行するサーバー名を指定して、userにログインするユーザー名を入れます。tasksとして、Apache2をインストールします。nameには、このタスクのコメントをいれ、aptというモジュールを使ってapache2をインストールされた状態にします。このとき、スーパーユーザーで行います。

site.yml

---
- hosts: ubuntu01
  user: ubuntu
  tasks:
    - name: install Apache2
      apt: name=apache2 state=installed
      become: true

ansible-playbookの次にsite.ymlを指定して実行してみます。

ansible-playbook site.yml

これで、Apache2がインストールできたら成功です。

実際に、http://192.168.33.10/ にブラウザでアクセスするとApacheの画面が見れると思います。

Ansibleの使い方は、Ansible構成管理入門を参考にさせてもらいました。ありがとうございます。

VagrantでAnsibleを使うのはSSHの理解がカギ

VagrantでAnsibleを使うのは、SSHを使ってリモートホストを操作します。なので、SSHがつながらないと話になりません。

SSHのしくみ

SSHの接続には秘密鍵と公開鍵の2つを使います。

公開鍵は、秘密鍵から作ることができます。

クライアント側とサーバー側の双方で秘密鍵と公開鍵があります。このうち公開鍵をお互いに送って保管することで通信ができます。

サーバーに接続してみて.sshディレクトリにあるauthorized_keysが保管場所。自分のホームディレクトリの.sshディレクトリの中のknown_hostsというファイルが保管場所です。

接続される側(サーバー側)で使われるのがauthorized_keysで、接続する側(クライアント側)で使われるのがknown_hostsです。

SSHクライアントで接続しようとしている場合、まずパスワードで接続してクライアント側の公開鍵をサーバー側に送ります。接続されるサーバー側は、authorized_keysという中にクライアント側の公開鍵をいれます。

そのあとで、サーバー側からサーバー側の公開鍵をクライアント側に送ります。これをクライアント側でknown_hostsに登録することで鍵認証で通信する準備が整います。これは、初めてsshで接続しようとしたときに警告が出てyesと答えると自動でやってくれます。

一度設定が済むと、

ssh -i <秘密鍵> <リモートホスト名>

で接続できます。

Vagrantの場合

Vagrantで作ったゲストOSにSSHを使ってパスワードでログイン

まずは、ゲストOSにパスワードでログインしてみます。

まず、vagrant ssh-configでVagrantが使っているsshの設定を見てみます。

$ vagrant ssh-config

Host default
  HostName 127.0.0.1
  User ubuntu
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/msys32/home/vagrant/vm/ubuntu16.04/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

HostNameが接続時に設定するホスト、Userがユーザー名、Portがポート番号です。-pでポート番号を指定して、ユーザー名とホスト名を@マークで区切って指定します。

$ ssh -p 2222 ubuntu@127.0.0.1

The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
ECDSA key fingerprint is SHA256:h8pe0EpC3I5ocDrZ7PGUxjYMIs2Wh8lIsXG0R/C3S5A.
Are you sure you want to continue connecting (yes/no)?

なにやら表示が出ます。これは、サーバー側の公開鍵をホームディレクトリの.ssh/known_hostsに登録してもいいかという意味です。

yesと答えると、パスワードを聞かれます。

ubuntu@127.0.0.1's password:

Vagrantでubuntu/xenail64をゲストに使ったときは、ゲストのパスワードは、C:\ユーザー\自分の名前\.vagrant.dのなかのVagrantfileの中に書かれています。

ubuntu/xenial64の場合は以下のところです。

C:\Users\(your name)\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64\20170423.0.0\virtualbox\Vagrantfile

これでログインできると思います。

公開鍵認証を使う場合

Vagrantの場合は、ホームディレクトリの.vagrant\machines\(host名)\virtualboxというフォルダの中にprivate_keyがつくられています。これを使って、ゲストOSに接続しています。
Vagrantが最初にvagrant upしたとき、ホストの公開鍵をコピーしてゲストOSのAuthorized_keysに登録しています。これで、パスワードなしでも鍵を使ってログインできるようになっています。

このauthorized_keysを確認してみます。

$ vagrant ssh

で接続して

(remote host) $ cat .ssh/authorized_keys

で、なかを見ると、

ssh-rsa AAAAB3NzaC----すごく長い------CBnRropmyAxL vagrant

みたいにssh-rsaで始まりvagrantで終わっているのがVagrantが送ったクライアント側の公開鍵です。

(remote host) $ exit

でログアウトします。

実際にsshを使って手動で接続してみようと思います。

まず、vagrant ssh-configでVagrantが使っているsshの設定を見てみます。

$ vagrant ssh-config

Host default
  HostName 127.0.0.1
  User ubuntu
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/msys32/home/vagrant/vm/ubuntu16.04/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

HostNameが接続時に設定するホスト、Userがユーザー名、Portがポート番号、IdentityFileが接続時に使う秘密鍵です。

sshで-iで秘密鍵を、-pでポート番号を、ホストの前に@マークで名前を指定して接続してみます。

$ ssh -i .vagrant/machines/default/virtualbox/private_key -p 2222 ubuntu@127.0.0.1

最初に接続したときは、ゲストOS(接続先)の公開鍵が登録されていないため、次のような警告が出ます。

The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
ECDSA key fingerprint is SHA256:+lHBujro5WLFzsFfFSFTQzWS/E35OvSwdr8t8OO/AFo.
Are you sure you want to continue connecting (yes/no)? 

yesと入力しリターンキーを押すとパスワードなしでログインしたと思います。この確認は2度目から出ません。

(remote host)$ exit

でログアウトして、自分のホームディレクトリの.ssh/known_hostsを確認してみます。

$ cat ~/.ssh/known_hosts

[127.0.0.1]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE1rZpVqvH1jYQ2lEjm0zc0LORZh7aIH61qIS0msMbBvA0W1s+NTgiftffhTcnON903vw/pWt9tqNhR69wNJsI8=

ホスト127.0.0.1ポート番号2222としてリモートホストの公開鍵が登録されています。

なお、vagrant destroyしたあと、vagrant upでゲストOSを作り直し、sshで接続しようとすると、次のようなエラーになります。

$ ssh -i .vagrant/machines/default/virtualbox/private_key  -p 2222 ubuntu@127.0.0.1

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:h8pe0EpC3I5ocDrZ7PGUxjYMIs2Wh8lIsXG0R/C3S5A.
Please contact your system administrator.
Add correct host key in /home/vagrant/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/vagrant/.ssh/known_hosts:3
ECDSA host key for [127.0.0.1]:2222 has changed and you have requested strict checking.
Host key verification failed.

これは、ゲストOSを作り直して公開鍵が変わってしまったために、ホームディレクトリで保存しているゲストOSの公開鍵と違っているためです。

このときは、エディタで~/.ssh/known_hostsの[127.0.0.1]:2222の行を削除すると接続することができます。

このようにvagrant ssh-configで確認した設定値を使って、sshで接続することができます。

AnsibleをMSYS2で使う

前回、VagrantとDockerで環境構築をしたので、Ansibleを使ってみることにしました。

Vagrantで作ったゲストOSに対してAnsibleで環境設定をするには、大きく分けると次の3つの方法があります。

  1. Vagrantfileの中ではプロビジョニングを使わず、ゲストOSを立ち上げるだけにして、ansible単独でゲストOSを操作する方法
  2. Vagrantfileの中でconfig.vm.provision 'ansible_local'として、Vagrantのansible_localというプロビジョニングを使う方法
  3. Vagrantfileの中でconfig.vm.provision 'ansible'として、Vagrantのプロビジョニングを使う方法

1番の方法は、WindowsホストではAnsibleからサポートされていません。

2番の方法は、AnsibleをゲストOSにインストールして、ゲストOS内でAnsibleを動かします。よって、Windowsホストでも使えます。

3番の方法は、WindowsホストではVagrantからは公式にはサポートされていません。そもそも1番の方法でansibleコマンドが動かないと、Vagrantでは動きようがありません。

このように、Windowsをホストにする場合、ansible_localしか方法はないのかと思いました。

実際、MSYS2のpipでパッケージを入れてみても、ansibleコマンドはエラーが出て動きません。

でも、Cygwinで動かしている人がいて、何とかならないかなとやってみることにしました。

最近はMSYS2をメインに使っています。そこでMSYS2で検索してみると、Ansibleを動かした人がいました。

[ansible] MSYS2 で ansible を使えるようにする手順

この通りやったらansibleが動き出しました。ありがとうございます。

ポイントは、32bitバージョンのMSYS2(msys2-i686-20161025.exe)を使うことです。64bitバージョンでは動きませんでした。

(2017/05/31)訂正
MSYS2のバージョンが問題ではなかったです。インストールするパッケージがmsysのpython2である必要がありました。

pacman -S python2

です。mingw-w64-x86_64-python2とかではだめでした。スタートメニューから起動するコンソールがMSYS2 MinGW 64bitやMSYS2 MinGW 32bitだと、MinGWのpythonがインストールしてある時はそちらが優先的に使われてしまうので気をつけてください。

インストールが終わったら、SSHでゲストOSにアクセスできることを確認して、ansibleが使えるようになります。

次回は、SSHについて書きます。