LoginSignup
4
2

localhostでsshをポートフォワードしたサーバとの synchronize が失敗する [解決]

Last updated at Posted at 2015-05-03

概要

やりたいこと

  • ローカルの ~/ansible/work/ にチェックアウトした myapp のソースコードを、サーバの /var/ma2saka/myapp に転送したい
  • サーバは vagrant でローカルに立ててる Cent OS 6.5
  • もともとスクリプトは AWS サーバ用に書いていて動作しているもの

先に解決策

ポート番号が違ってもホスト名部分が一緒だと誤動作する。

インベントリファイルで直接IP書かずに、host1 ansible_ssh_host=127.0.0.1 みたいに指定してホスト名称部分がかぶらないようにするとよい。

失敗してたパターン

書いた定義

main.yml
- name: sync source code
  synchronize:> 
    dest=/var/ma2saka/myapp
    src=/Users/ma2saka/ansible/work/myapp/ 
    recursive=yes
    links=yes
    rsync_opts="--exclude='.git'"

インベントリには

inventory.ini
[dev]
127.0.0.1

[dev:vars]
ansible_ssh_user=vagrant
ansible_ssh_port=2222

vagrant で立てたサーバがローカルの 2222 で待ち受けてる。

以下のようにしてあらかじめ公開鍵は登録している。

ssh-add -D
ssh-add ~/.ssh/id_rsa
ssh-copy-id -p 2222 vagrant@127.0.0.1

エラーになる

TASK: [deploy | sync source code] *********************************************
failed: [127.0.0.1 -> 127.0.0.1] => {"cmd": "rsync --delay-updates -FF --compress --archive --rsh 'ssh  -S none -o StrictHostKeyChecking=no -o Port=2222' --exclude='.git' --out-format='<<CHANGED>>%i %n%L' \"/Users/ma2saka/ansible/work/myapp/\" \"/var/ma2saka/myapp\"", "failed": true, "rc": 23}
msg: rsync: change_dir "/Users/ma2saka/ansible/work/myapp/" failed: No such file or directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1039) [sender=3.0.6]


FATAL: all hosts have already failed -- aborting

いや、msg: rsync: change_dir "/Users/ma2saka/ansible/work/myapp/" failed: No such file or directory (2)とか言われてもさ。あるからねそのディレクトリ。どう見てもさ。

brew で入れてる 1.8.2 だからかと疑って pip で入れなおしてみるもアカン

1.9.1 でも特に変化なし。

amazonとか別のサーバだとうまくいく

inventory.ini
[dev]
myapp1.amazon.example.com
myapp2.amazon.example.com
myapp3.amazon.example.com

[dev:vars]
ansible_ssh_user=ec2-user
ansible_ssh_port=22

問題なく期待通り動作する。

127.0.0.1 に /etc/hosts で別名つけたら動作した

127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost
127.0.0.1 this.is.it
inventory.ini
[dev]
this.is.it

[dev:vars]
ansible_ssh_user=vagrant
ansible_ssh_port=2222

これで実行すると。

 .. 略 ..

TASK: [deploy | sync source code] *********************************************
changed: [this.is.it -> 127.0.0.1]

 .. 略 ..

動くし・・・。
期待通り動くのでこれはこれでいいんだけど釈然としないものが残るな。

ホスト名を localhost にするとそもそも繋がらない

IP指定してやるのがダメなら localhost だとどうよと思ったら、

TASK: [deploy | sync source code] *********************************************
failed: [localhost -> 127.0.0.1] => {"cmd": "rsync --delay-updates -FF --compress --archive --rsh 'ssh  -S none -o StrictHostKeyChecking=no -o Port=2222' --exclude='.git' --out-format='<<CHANGED>>%i %n%L' \"/Users/ma2saka/ansible/work/myapp/\" \"/var/ma2saka/myapp\"", "failed": true, "rc": 12}
msg: ssh: connect to host localhost port 2222: Connection refused
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(600) [sender=3.0.6]

えーーー。

つまり実際のところ、ホストの「名前」が問題なわけ? と遅ればせながら気がつく。

ansible_ssh_host の設定で解決

ひっかかっていたのはまさにこの現象でした。

ローカルホストでポートフォワードしているホストに ansible で接続する場合、インベントリファイルで適当な別名を付与するのがよいやり方のようです。

[dev]
# lvh.me とか this.is.it とか書かなくていい
host1 ansible_ssh_host=127.0.0.1

[dev:vars]
ansible_ssh_user=vagrant
ansible_ssh_port=2222

だいたい synchronize モジュールのコードとか実行時に転送されてるスクリプトも確認したので挙動は理解したけど、これは罠だなー。だいたいエラーメッセージが不親切すぎる。という愚痴をいいつつ。解決したので気分よし。

反省

-vvvv してよく見ると、「そのスクリプトがどこで実行されてるか」がわかるんですね。127.0.0.1 を書いて失敗してたとき、実際にスクリプトはリモートサーバで実行されていたんです。それなのに source の指定はローカルマシンの相対パスが書かれているからディレクトリが見つからない。

というところに気がつけば、これ特定モジュールのバグじゃなくて ansible のホスト名解決ロジックの側だろうとすぐ察せられたはずなのですが、見当違いのところをトレースしていて時間を使ってしまいました。なかなか難しいものです。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2