SSHのMultiplexingによって発生するAnsibleの問題
OpenSSHの問題なのかAnsibleの問題なのか、あるいは自分の書いているPlaybookの問題なのか、原因は不明だがSSHのMultiplexingが有効になっているとshellモジュールの標準出力が取得できない場合があるという問題にあたった。
検証version
- CentOS 7.5
- OpenSSH 7.4
- Ansible 2.7
Ansibleの使用するSSHオプション
Ansibleが使用しているSSHのオプションを確認する。
$ ansible all -i localhost, -m ping -vvv
略
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s 略
略
-o ControlMaster=auto -o ControlPersist=60s
のオプションによって60秒間Multiplexingのマスター接続が維持される。
つまり、AnsibleはデフォルトでSSHのMultiplexingを使っている。今回遭遇した問題はどこでも起こる可能性がある。
Playbookの概要
問題が発生したroleの内容は以下の通り。
略
- name: exec aws ec2 describe-instances
delegate_to: localhost
check_mode: no
shell: |
aws ec2 describe-instances --filters "Name=tag:Name,Values={{ inventory_hostname }}" "Name=instance-state-name, Values=running" --query "Reservations[0].Instances[0].PrivateIpAddress" |
sed 's/"//g'
environment: "{{ aws.environment }}"
register: host_ip
略
このroleのどこかのタイミングでSSHのMultiplexingが使われることが、ps -ef | grep ssh
でわかった。[mux]
という文字列が見つかる。
$ ps -ef | grep ssh
略
ssh: /home/user/.ansible/cp/ansible-ssh-localhost-22-user [mux]
略
Multiplexing中に標準出力が取得できない
ControlPersist
で指定されている時間内にもう一度Ansibleを実行すると、先に記載したaws ec2 describe-instances
の標準出力が取得できないことがあった。取得できない確率は10台くらいのサーバに実行して1, 2台ほど。
ControlPersist
で指定されている時間を過ぎてから、あるいはMultiplexingで接続されているSSHプロセスをkillしてからAnsibleを実行すると、この問題は発生しない。
Ansibleのパフォーマンスを上げるために-o ControlPersist=1800s
を設定したところ、Multiplexingが維持される時間が長くなり、この問題の発生確率が格段に上がって発見することができた。
$ tail -3 ansible.cfg
[ssh_connection]
pipeline=True
ssh_args=-C -o ControlMaster=auto -o ControlPersist=1800s
この設定はDocumentに書かれている通りの内容である。
In particular, users may wish to raise the ControlPersist time to encourage performance. A value of 30 minutes may be appropriate.
Multiplexingを無効にする
Ansibleは60秒間という短い時間ではあるもののデフォルトでMultiplexingを使っており、上記問題が発生しうる。根本原因がわからなかったので、安全のためMultiplexingは無効化した。
$ tail -3 ansible.cfg
[ssh_connection]
pipeline=True
ssh_args=-o ControlMaster=no
※ついでに-C
オプションも消したが、これは今回の問題には関係ない。Playbook内で大きなデータをリモートサーバに送信しないため、圧縮オプションが有効になっていてもCPUを食うだけで性能向上に期待できないから消しただけだ。