AnsibleからAzureを操作してみた その3 ~Dynamic Inventory & パッケージ・アップデート編~

こんにちは。株式会社リアルグローブの廣川です。

先週の現地時間7/28にはサンフランシスコでAnsibleFestがありましたね。特に初公開の大きな発表は無かったようですが、それに合わせてAnsible 2.1.1.0 の正式版がリリースされました!Azureモジュール的には全体的に改修が入り、かなりの不具合が修正されました(自分も一箇所地味なバグフィックスをしております)。ただし、必要なAzureライブラリのバージョンが上がったので、

の様に新しいバージョンをインストールしてあげましょう!

さて、本題のAzureセットアップですがいよいよ最終回、Azure上のVM情報を取得してAnsibleに操作をさせていきましょう!

Azure Resource Manager用Dynamic Inventory

元々、Ansibleには外部システム(各種IaaSやサービス検出/モニタリング・システムなど)から動的にホスト情報を取得するための Dynamic Inventory という仕組みが用意されており、Azure Resource Manager(ARM)上のVM情報もこのDynamic Inventory経由で取ってくることになります。

Dynamic Inventoryスクリプトのダウンロード

ARM用のDunamic Inventoryは既に公式で提供されているので、以下の様にダウンロードしましょう。

ちなみに上記では(将来的にDynamic Inventoryの仕様が変わっても良い様に)記事執筆時点のバージョンを指定していますが、最新版はこちらからダウンロード可能です。

Dynamic Inventoryは実行可能なスクリプトである必要があるので、以下の様にダウンロードした azure_rm.py に実行権限を付与しましょう。

Dynamic Inventoryの動作確認

実際に azure_rm.py からAzure上のVM情報が取得できるか、確認してみましょう。第一回で取り扱ったAnsibleからAzureへの接続準備さえ出来ていれば、以下の様にVM情報を取得することができるはずです。

上記を実行すると、現在Azure上のVM情報がJSONで出力されます。なお、–pretty オプションは人が見やすい様にJSONをインデントして出力してくれるオプションです。

第二回のチュートリアル通りTestingAnsibleグループにWindows VMを作った場合の例は下の様になります(IPアドレスやSubscriptionIDは個別に異なる値が入ります)。

JSONを一見しただけだと分かりづらいですが、よく見ていくと ansiblewinvm01 と言う名前のVMに、

  • _meta.hostvars 内にVMの状態やイメージ、ネットワークの情報が格納
  • 以下のグループに所属している
    • azure(Azure上のマシンであることを表すグループ、値は固定)
    • testingansible(リソースグループ名)
    • japaneast(ロケーション)
    • ansiblewinvm0101(ネットワーク・セキュリティ・グループ名)
    • ansible-target(VMに付けられたタグ名)
    • ansible-target_true(タグ名と値を で繋いだもの)

と言った情報がことがわかります。

Dynamic Inventory用設定項目

Dynamic Inventoryに対しても、どの様にグループ分けするか、どのVM情報を取得するかといった項目を設定することが可能です。この設定は環境変数にセットするか、もしくは azure_rm.ini と言う名前のINIファイルに記述することができます。ここではより汎用性の高い、環境変数での設定例を見ていきます。

グループ分け設定項目

以下の項目のデフォルト値は全て yes。無効化したい場合は no を設定する。

  • AZURE_GROUP_BY_RESOURCE_GROUP
    • VMを所属するリソースグループ名でグルーピングする。
  • AZURE_GROUP_BY_LOCATION
    • VMを存在するロケーションでグルーピングする。
  • AZURE_GROUP_BY_SECURITY_GROUP
    • VMをネットワーク・セキュリティ・グループ名でグルーピングする。
  • AZURE_GROUP_BY_TAG
    • VMに設定されたタグ名でグルーピングする。

対象の絞り込み

  • AZURE_LOCATIONS
    • VMの存在するロケーションで絞り込み
  • AZURE_RESOURCE_GROUPS
    • 情報を取得するリソースグループ名をカンマ区切りで絞り込み
  • AZURE_TAGS
    • カンマ区切りで指定されたタグのついたVM情報だけを取得
    • タグ名:値 の形式で値も含めた絞り込みも可能

その他

  • AZURE_INCLUDE_POWERSTATE
    • VMの起動状態を取得するかどうか。デフォルトは yes
    • no にするとVM情報取得にかかる時間をある程度短縮できる。

VMアップデート用Playbook

それでは、このDynamic Inventory経由で取得した情報を用いてVMにログインし、インストール済みパッケージをアップデートする為のPlaybookを作ってみましょう。Playbookのファイル名は update_azure_vm.yml としておきます。

1. OSの判定

Azure上のVMのOSタイプは大きくWindows系とLinux系に分けられます。WindowsにはWinRM、LinuxにはSSHと、そもそも接続方法から異なりますので、事前にOSの判定をしてあげましょう。

上記のPlayを実行する事で、VMをOS毎にグループ分けする事ができます。これは上であげたDynamic Inventoryからの情報取得例を見ると分かるように、os_disk.operating_system_type 変数内にVMイメージのOSタイプ(Windows もしくは Linux)が格納されているためです。

2. Windows VMのパッケージ・アップデート

group_vars/azure.yml の用意

まず、azureグループ用の変数ファイル group_vars/azure.yml を用意して、以下の様にSSL証明書のチェックを無効化しましょう。これをしないとPython 2.7.9 以降で自己署名証明書で運用するWinRMへの接続が証明書エラーで通らなくなってしまいます。

Windown Update から更新をインストール

update_azure_vm.yml のOS判定Playの下に、以下のようなPlayを追加しましょう。

実行しているタスクの中身としては、

  1. リブート待機状態の場合はWindows Updateが実行できないので事前にリブート
    •  win_reboot モジュールは Ansible 2.1で追加された新モジュール
      • 既存の wait_for モジュールを使ったリスタートだとAzure環境上のWinRMの停止・再起動を正確に判定できないため、win_reboot がベターな選択
    • ansible_reboot_pending 変数が使えるのは、現在開発中のAnsible 2.2から
      • Ansible 2.1系の場合、エラーにはならないが実際にリブートされることはない
  2. apt モジュールを使って更新を適用。
    • category_names 引数には更新範囲を以下の中からリストで指定可能。
      • Application
      • Connectors
      • CriticalUpdates
      • DefinitionUpdates
      • DeveloperKits
      • FeaturePacks
      • Guidance
      • SecurityUpdates
      • ServicePacks
      • Tools
      • UpdateRollups
      • Updates
    • デフォルト値は [CriticalUpdates, SecurityUpdates, UpdateRollups]
  3. win_updates の実行結果を見て、再起動が必要であれば win_reboot を用いて再起動を実施

のようになっています。Playbookの実行

上記のPlaybookが完成すれば、あとは今まで通り ansible-playbook コマンドから簡単に実行できます。

  • -i で Dynamic Inventory スクリプト azure_rm.py を指定
  • -u でログイン・ユーザー名を指定
  • -k を指定して、ログイン・パスワードの入力プロンプトを表示
    • プロンプトには SSH password: と表示されますが、WinRMにも対応しています

これで Windows マシンのアップデートが簡単にAnsibleから自動実行できるようになりました!このようにアップデートからOS再起動処理と起動待機までを非常にシンプルに実現できるのはAnsibleの大きな美点の一つといって良いでしょう。

3. Linux VMのパッケージ・アップデート

もちろん Linux に対してだってWindowsと同じようにアップデートの自動化が可能です。ここでは yumRedHat系Linuxのパッケージ・マネージャ)apt(Debian系Linuxのパッケージ・マネージャ)に対応したLinuxでのパッケージ・アップデートの例を紹介します。なお、Linuxではライブラリ更新後にOS再起動が必要となる場面は多くないため、ここではOS再起動処理は省いています。

OSのディストリビューションを見て動作を切り分ける方法もありますが、Ansibleがデフォルトで取得するマシン情報の中には、そのマシンで使われているパッケージ・マネージャ名がそのまま入る ansible_pkg_mgr という変数(ファクト)が用意されていますので、それを使ってみましょう。

  1. パッケージ・マネージャが apt である時のためのブロックを用意
    1. aptitude を apt モジュールからインストール
      • Ansibleからインストール済みパッケージをまとめて更新するには aptitude が必須
    2. apt モジュールを使ってセーフ・アップグレードを実施
      • safe 以外には full(既存パッケージのアンインストールも実施)dist(カーネルを含んだアップデートを実施、カーネル更新反映にはOS再起動が必要) が指定可能
  2. パッケージ・マネージャが yum だった場合は、yum モジュールからインストール済み全パッケージを最新にする
    • name にワイルドカード(*)を指定することで、全パッケージを更新対象にすることが可能
    • state を latest に設定し、パッケージを最新版にしている

Playbookの実行は、Windowsの場合とほぼ同様で

のようになります。Windowsの時と比べて増えている -K オプションは become(sudo)パスワードをプロンプトから入力するためのものです。なお、Azureのデフォルト設定では、ログイン・パスワードとbecomeパスワードは共にVM作成時に指定した管理者パスワードになります。

【補足】特定パッケージのアップデート

上記ではインストール済みパッケージ全てのアップデートを実施していますが、もちろん特定パッケージのみをアップデートすることも可能です。

apt の場合であれば、dpkg-query コマンドを使ってインストール済みパッケージ名を取り出し、それを apt モジュールに渡すことができます。

の様にして、特定のインストール済みパッケージのみを最新に保つことが可能です。上記の様にワイルドカードも指定可能ですので、関連パッケージも含めたアップグレードが可能となっています。

yum でも同様に rpm コマンド経由でインストール済みパッケージの一覧を取得してから yum モジュールに渡すことで特定パッケージのアップグレードが可能です。

上記は libssl* や openssl* といった値を直書きしておりますが、この部分をリストを使って変数化してしまえば、任意のパッケージを自動アップグレードしてくれるPlaybookの完成です。

常に最新に保つ必要があるパッケージであれば、Playbookの実行を cron などでスケジューリングしてしまえばセキュリティ・アップデートの完全自動化まで可能になってしまいます。便利ですね!

これで今回のシリーズは終了ですが AnsibleのAzure Resource Manager対応はまだ出来たばかりで引き続きアクティブに開発が進められています。今後も皆さんの Ansible on Azure 活用のための情報を発信していきます!それでは、お読みいただいた皆さん、どうもありがとうございました。

Share on LinkedIn
LINEで送る
Pocket

realglobe Inc.