01 Dec 2015, 18:13

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

1. はじめに

Vim::Factoryの開発や、仕事などで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倍はやくなるとかそういうことではないが、
リモートホストへの接続回数が多くなればなるほど大きな差が生まれそうです。

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