Ansible解禁して一発目はこれ、と決めていたので、WindowsUpdateをやってみたお話を書きます。
Ansible関連の実践記事一覧はこちら。
Ansible自動化の実践記事一覧 - てんこ
目的
Windowsのセットアップや運用で必ず通る、アップデートをAnsibleで実施する方法を理解するため
環境
共通
下記のホストはすべてVirtual Box上の仮想マシンで実施。
Ansible側
Pythonのサポートの話は認識はしてますが、とりあえず手元にあった環境で実験。
Ansibleのインストールは、まずはyumで導入しました。
ansible.cfgについては、-vを付けた時の出力形式が好みだったので、以下の設定だけ実施しています。
stdout_callback = unixy
両方とも、評価版でISOから手動でポチポチとインストール。
接続方法
今回は、実績も文献も多いWinRMを選択しています。
Ansible側
セットアップは以下のサイト(以下公式ガイド)を参照しながら実施。
Windows Remote Management — Ansible Documentation
WinRMのPython用のモジュールの導入
公式ガイド通り、pipにてpywinrmをインストール。
pip install "pywinrm>=0.3.0"
関連モジュールがいろいろと入りましたが、モジュールそのものはpywinrm-0.3.0が入りました。
インベントリの定義
過去のもくもく会や書籍などの情報から、インベントリはシンプルに、というのは理解していますが、まず動かしたかったのでインベントリに認証情報などを入力。
[win_2016]
192.168.10.233
[win_2012]
192.168.10.248
[windows:children]
win_2016
win_2012
[windows:vars]
ansible_user=Administrator
ansible_password=P@ssw0rd
ansible_connection=winrm
ansible_winrm_transport=basic
ansible_winrm_server_cert_validation=ignore
実際には、最後の1行(cert_validation)は後から付け足しました。
この手順通りに実行した場合、操作対象のWindowsには自己証明書が導入されるのですが、そのままだと接続のときに証明書の確認エラーで弾かれてしまいました。(以下ログ)
Gathering Facts...
192.168.10.233 unreachable: {
"changed": false,
"msg": "basic: HTTPSConnectionPool(host='192.168.10.233', port=5986): Max retries exceeded with url: /wsman (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:618)'),))",
"unreachable": true
}
そのため、もう一度公式ガイドを確認したら、cert_validationについて、しっかり書いてありました。ちゃんと読め自分。
インストール時のパラメータ
基本的に、Administratorのパスワードをインベントリに合わせたくらいです。
WinRMの設定
公式ガイドに、PowerShellでセットアップできる方法が記載があったため、そのまま実施。
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS C:\Users\Administrator>
PS C:\Users\Administrator> $url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
PS C:\Users\Administrator> $file = "$env:temp\ConfigureRemotingForAnsible.ps1"
PS C:\Users\Administrator>
PS C:\Users\Administrator> (New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
PS C:\Users\Administrator> powershell.exe -ExecutionPolicy ByPass -File $file
Self-signed SSL certificate generated; thumbprint: 804F14E0FFED613185E8049AEF5AB79E578DC775
wxf : http://schemas.xmlsoap.org/ws/2004/09/transfer
a : http://schemas.xmlsoap.org/ws/2004/08/addressing
w : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
lang : ja-JP
Address : http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
ReferenceParameters : ReferenceParameters
OK
設定されているかどうかの確認
こちらも、公式ガイドにあったとおりのコマンドでListenerの状態を確認。(ログはWin2016側のもの)
PS C:\Users\Administrator> winrm enumerate winrm/config/Listener
Listener
Address = *
Transport = HTTP
Port = 5985
Hostname
Enabled = true
URLPrefix = wsman
CertificateThumbprint
ListeningOn = 127.0.0.1, 192.168.10.233, ::1, 2001:0:348b:fb58:28d8:154a:3f57:f516, fe80::28d8:154a:3f57:f516%4, fe8
0::e572:d2e2:836a:bafe%3
Listener
Address = *
Transport = HTTPS
Port = 5986
Hostname = WIN-KPFBQSB4964
Enabled = true
URLPrefix = wsman
CertificateThumbprint = 804F14E0FFED613185E8049AEF5AB79E578DC775
ListeningOn = 127.0.0.1, 192.168.10.233, ::1, 2001:0:348b:fb58:28d8:154a:3f57:f516, fe80::28d8:154a:3f57:f516%4, fe8
0::e572:d2e2:836a:bafe%3
よくあるハマりで、Windows Firewallの設定があるなあと思ってそちらも確認してみたのですが、自動で接続許可設定が入っていました。(Win2016/Win2012いずれも)
行き届いている…
またPowerShellの中身そのものは確認しておきたいところです。
両方完了後の疎通試験
win_pingモジュールを使いました。
もくもく会では、sshでの疎通試験だったなあと思いつつ、WinRMではどうやってやるんだ?と思い、Windowsのモジュール一覧を確認していたら、win_pingなるものがあるのを見つけました。
モジュール一覧から、目的のもの見つけ出すのは楽しいですね。
win_ping.yaml
---
- name: Windows WinRM Ansible
hosts: windows
gather_facts: no
tasks:
- name: ping
win_ping:
実行結果
ping...
192.168.10.233 ok
192.168.10.248 ok
まだやってる最中ですが、Win2012/Win2016いずれも1回は成功しました。
こんな感じのPlaybookにしています。
---
- name: Windows WinRM Ansible
hosts: windows
- name: Do Windows Update
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
- UpdateRollups
state: installed
register: update_result
- name: debug
debug:
var: update_result
verbosity: 0
- name: reboot if needed
win_reboot:
when: update_result.reboot_required
最初はwin_updatesの中でリブートという流れにしていたんですが、初回Update後のリブート→再起動後のパッチ適用でreboot_timeoutの初期値1200秒を超えてしまい、最終結果がfailedになることがわかりました。
Timeout値を長くしようか悩んだ挙句、まずは結果の出力を優先し、アップデートを切り離すことに。
やってみて
とっかかりこそ苦労したものの、2台目のホスト(Windows2012 R2)のセットアップはとても簡単でした。
今まで業務でPoC環境作るのに手動でぽちぽちやってたのがウソみたいです。
まずは取り急ぎ動かしてみただけなので、実運用を考えた場合に修正すべき点はたくさんあると思いますが、便利さが実感できただけでもとても満足できました。
今後もこんな風に、小さな成功体験を積み上げていきたいと思います。
ただ、動かしている最中に、どの程度作業が進行しているのかがわからないのが、ドキドキしてしまいます。(%表示とかが出ないので)
この辺は何かうまい方法があるのか、また探してみたいなと思います。
追伸
(現在、Win2012の2回目で絶賛ハマり中です…)
Do Windows Update...
192.168.10.248 failed: {
"changed": false,
"filtered_updates": {},
"msg": "Failed to search for updates: \"1\" 個の引数を指定して \"Search\" を呼び出し中に例外が発生しました: \"HRESULT からの例外:0x80072EFE\"",
"updates": {}
}
追伸の追伸
上記エラーは2回試して2回とも発生しました。
大型アップデートとかの初期処理がログイン後に走るのかな?と思ってコンソールでログインしてみましたが、特に動きはなく。
ただ、その後何もいじらずに再度WindowsaUpdateのPlaybook走らせてみたら、問題なく動きました。
ログインが功を奏したのか、時間が解決したのか、一体何なんだ…
またログなど確認して原因分かれば調べてみたいと思います。