【小ネタ】Ansibleでyum updateするときはBackgroundオプションをつけると良いという話

2015.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。

複数台のサーバーにyum updateする時には、各サーバー1台ずつにsshでログインしてコマンドを実行するのではなく、ansibleを使って実行することが推奨されます。これは実施した作業内容や作業ログをログとして残すのが容易なためです。

ただ、yum updateのように時間がかかる処理をansibleから行ってしまうと、タイムアウトが発生して処理が中断してしまいrpmの不整合が発生するという残念な事態になってしまいます。

今回はそんな残念な事態を回避するための子ネタをお送りしたいと思います。

ansibleでのタイムアウト

ansibleはsshを用いてサーバーへコマンドを送り、その処理結果を待って成否を判定します。この際コマンドの実行に時間がかかるとsshがタイムアウトしてしまい、処理途中でコマンドが強制終了してしまうことになります。

たとえばAmazon LinuxでAMIバージョン2013.09から一気に2015.03までyum updateしようとすると、大量のパッケージがアップデートされるため10分近くかかります(m3.largeでも)。なお不幸にもyum updateがタイムアウトで失敗してしまった場合には、リカバリはほぼ不可能と考えた方が良いようです。私が遭遇した状況では sudo yum-complete-transaction しても不整合パッケージのチェックが無限ループして終わりませんでした。

Backgroundオプション(-B)

処理に時間がかかる場合にはBackgroupdオプションを付けましょう。-B n (sec)で指定が可能です。

       -B NUM, --background=NUM
           Run commands in the background, killing the task after NUM
           seconds.

たとえばyum updateをバックグラウンドで実行し、10分後に処理を中断する場合には下記コマンドになります。

$ ansible all -i hosts -B 600 -m shell -a "yum update -y" -s
もしくは
$ ansible all -i hosts -B 600 -m yum -a "name=* state=latest" -s

これによりyum updateはバックグラウンドで実行され、その後は定期的にコマンドが完了したかを問い合わせるため、sshによるタイムアウトが発生しにくくなります。また10分(600秒)経過したバックグラウンドタスクはKILLされます。

まとめ

ansibleは複数サーバーで同じコマンドを実行するときにも大変便利に使えますが、時間がかかる処理の時はsshタイムアウトが発生しないように気をつけましょう。

またサーバーへ変更作業するするときには作業前にAMIやEBSスナップショットなどを取得し、仮に作業が失敗してもリストアができる準備をしておくことを決して忘れないでください!AWSなら簡単にバックアップとれます。壊れてからでは遅いですよ〜