Ansible、実行速度高速化の実験。ControlMasterとPipeliningについて

執筆日:

更新日:

Ansibleの実行速度に不満を持っている人は多いのではないだろうか。
自分もそのひとりであったのだが、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
  • サーバ
    • ハードウェア:Vagrantによる仮想環境。メモリ1GB。
    • OS: CentOS 7.0
    • ネットワーク:プライベートのIPアドレスをふっています

実行タスク

ネットワーク環境やタスクの実行時間に左右されないように、
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情報はこちらの書籍がおすすめ。

記事の内容に関連した相談、仕事依頼したい New

記事の内容やクラウドネイティブ技術に関する相談、仕事依頼を開始しました。
仕事依頼、相談をしてみる

フィードバック

本記事に対して、フィードバックあればこちらのフォームからご記入ください。
記事の内容にフィードバックしてみる

このエントリーをはてなブックマークに追加