自分もそのひとりであったのだが、ControlMasterやpipeliningといった機能を使って高速化に成功した。 本ブログでは、その効果の実験を行ったので参考にしてください。
1. はじめに
仕事や趣味での開発などでAnsibleを使うことが多いのだが、
その実行速度があまりでないことに不満をもっていて、どうしたら早くできるか考えていました。
調べると、ControlMasterを利用してSSHのコネクションを再利用するとか、pipelineの機能を利用する方法などが見つかった。
しかし、それによってどのくらいの効果については記述もないし、仕組みもよくわかっていなかったので、仕組みの理解と実行速度の実験をした。
もう少し余談をすると、
ControlMasterを有効にすれば早くなることは前から知っていたが、
最近MacをEl Capitanに変えてから「なんか最近Ansibleはやいな〜」とか思っていて、
「OpenSSHのバージョンもあがったし、まさか。。。」と思って今にいきついている。
ControlMasterについて
OpenSSH は、1 つの接続で複数のセッションを共有する(束ねる)「コントロール マスター」と呼ばれる機能を持っています。コントロールマスターを使用すると、 リモートホストに接続する最初のセッションは制御用のセッション(マスターセッショ ンと呼ばれます)として利用され、制御用のソケットを作成します。セッションを 共有する SSH クライアントは、この制御用のソケットを通じてリモートホストと 接続し通信を行います。
出典:「OpenSSH実践入門」
上記のように、1つの接続で複数のセッションを共有するため、
Ansibleのようにタスク実行ごとにSSH接続するような場合には大きな効果を得ることができる。
Pipeliningについて
Pipelining機能の説明の前に、軽くAnsibleの実行までの流れを説明する。
Ansibleは対象サーバにSSHログインしたあと実行するタスクのモジュールをファイルとして転送しそれを実行する。
Pipelining機能をなしの状態だと、このファイル転送とファイルの削除を1タスクごとに行う。
ansibleを-vvvv
オプションをつけて実行するとわかるが、
4行目でファイルのPUT
(転送)を、5行目の最後の方にrm -rf
でディレクトリ・ファイルの削除を行っている。
<192.168.33.100> ESTABLISH CONNECTION FOR USER: deploy
<192.168.33.100> REMOTE_MODULE command ls -l /root
<192.168.33.100> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=300s -o ControlPath="/Users/xxxxx/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=user -o ConnectTimeout=10 192.168.33.100 /bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321 && echo $HOME/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321'
<192.168.33.100> PUT /var/folders/7_/d_dwdlcx1m95mn_846x30xb40000gn/T/tmpc8amAw TO /home/user/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321/command
<192.168.33.100> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=300s -o ControlPath="/Users/xxxxx/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=user -o ConnectTimeout=10 192.168.33.100 /bin/sh -c 'sudo -k && sudo -E -S -p "[sudo via ansible, key=koibtlgpbiprbaihcqxiqgcnnreofxuo] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-koibtlgpbiprbaihcqxiqgcnnreofxuo; LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 /usr/bin/python /home/user/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321/command; rm -rf /home/user/.ansible/tmp/ansible-tmp-1448959936.93-272271942952321/ >/dev/null 2>&1'"'"''
Pipiliningの機能を有効にすると、タスク実行ごとのモジュールファイルの転送と削除をしなくなる。
そのため、実効速度があがるのです。
下記はPipeliningを有効にした際の出力。SSHでタスクを実行しているだけなのがわかる。
<192.168.33.100> ESTABLISH CONNECTION FOR USER: deploy
<192.168.33.100> REMOTE_MODULE command ls -l /root
<192.168.33.100> EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=300s -o ControlPath="/Users/xxxxx/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=deploy -o ConnectTimeout=10 192.168.33.100 /bin/sh -c 'sudo -k && sudo -E -S -p "[sudo via ansible, key=kjtoopnjepksibiitumqfycsoldadiws] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-kjtoopnjepksibiitumqfycsoldadiws; LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 /usr/bin/python'"'"''
Configuration file — Ansible Documentation
2. 実験方法
下記の3パターンでどれだけ実行速度に差があるか確認してみた。
- ① ControlMaster: 無効 & pipeline: 無効
- ② ControlMaster: 有効 & pipeline: 無効
- ③ ControlMaster: 有効 & pipeline: 有効
実行環境
- クライアント
- ハードウェア:MacBook Air (13-inch, Mid 2012)
- プロセッサ:1.8 GHz Intel Core i5
- メモリ:4 GB 1600 MHz DDR3
- OS:El Capitan
- OpenSSH:OpenSSH_6.9p1, LibreSSL 2.1.7
- サーバ
実行タスク
ネットワーク環境やタスクの実行時間に左右されないように、
ls -l /
を実行するタスクを300個用意した。
設定
ansible.cfgを下記のように書いてためした。
① ControlMaster: 無効 & pipeline: 無効
[defaults]
transport = ssh
[ssh_connection]
pipeline = false
ssh_args = -o ControlMaster=no
② ControlMaster: 有効 & pipeline: 無効
[defaults]
transport = ssh
[ssh_connection]
pipeline = false
ssh_args = -o ControlMaster=auto -o ControlPersist=300s
③ ControlMaster: 有効 & pipeline: 有効
[defaults]
transport = ssh
[ssh_connection]
pipeline = true
ssh_args = -o ControlMaster=auto -o ControlPersist=300s
実行コマンド
実行時間を図るために、下記のようにコマンドを実行した。
$ date; ansible-playbook site.yml ; date
※ansible-playbookコマンドは環境に合わせてオプションとかつけてください。
3. 結果
ControlMaster | Pipelining | 実行時間 |
---|---|---|
✕ | ✕ | 6分38秒 |
◯ | ✕ | 1分31秒 |
◯ | ◯ | 52秒 |
結果は明らかでした。
実際の環境ではタスクの実行時間などがあるため、この数字のように6倍はやくなるとかそういうことではないが、
リモートホストへの接続回数が多くなればなるほど大きな差が生まれそうです。
4. まとめ
ControlMasterとpipeliningがどのような仕組みの機能で、 どのように速度に影響してくるのか理解できただろうか。仕組みがわかると、どのような場面での高速化に役立つか理解できるようになる。みなさんの利用中の環境に合わせて是非使ってAnsible Lifeを快適にしましょう。
また新しいAnsible情報はこちらの書籍がおすすめ。