AnsibleでWindows ServerにPowershellスクリプトを実行する

2015.03.06

渡辺です。今年の冬は暖かすぎて札幌は春の気配ですね。

AutoScaling時にAnsibleで環境構築を行うでは、Auto ScalingのLifecycle Hookを利用したAnsibleによる環境構築を紹介しました。 今回は対象がWindows Serverであった場合にAnsibleでスクリプトを実行する手順について紹介します。 これらを組み合わせればWindows ServerのAuto Scalingでもフル自動化の扉が開くでしょう!

AnsibleとWindowsリモート管理

基本的にAnsibleは、対象となるサーバにSSHでアクセスして処理(環境構築)を実行します。 Windows Serverでは、デフォルトでSSH接続ができないため、代替手段が必要になります。 代替手段として使われるのは、Windowsリモート管理(WinRM)です。 Windows ServerでWinRMが有効になっていることが、AnsibleでWindowsにアクセスする条件となります。

また、AnsibleでWindowsを操作する場合、Poweshell 3.0以上が必要となります。

詳細は、Ansible - Windows Supportを参照ください。

Windows Serverインスタンスの準備

はじめにWindows Serverのインスタンスを作成します。

Powershellのバージョン確認

現在、Windows Serverのバージョンとしては2012 R2が最新バージョンとなっていますが、2012, 2008 R2, 2008などを利用しなければならないケースもあるでしょう。 それぞれのバージョンでのPowershellのバージョンを確認してたところ、2012 R2ではPowershell 4.0、2012, 2008 R2, 2008ではPowershell 3.0となっています(サービスパック適用済みのため)。 よほど古いAMIから作成したWindow Serverでなければ大丈夫そうですが、確認は必要です。 もし、Powershellのバージョンが3.0未満の場合は3.0以上にアップデートしてください。

なお、Powershellのバージョンは以下のコマンドで確認出来ます。

PS > $PSVersionTable

WinRMのセットアップ

Ansibleで提供しているWinRMのセットアップスクリプトをダウンロードして実行すれば、WinRMが有効になります。

PS > Invoke-WebRequest /
   > -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 /
   > -OutFile ConfigureRemotingForAnsible.ps1
PS > powershell -ExecutionPolicy RemoteSigned .\ConfigureRemotingForAnsible.ps1

Windows Serverのバージョンによって表示されるメッセージは異なりますが、どのバージョンでも問題なく利用できました。

AnsibleからのPowershellスクリプトの実行

WindowsにAnsibleでアクセスするためには、通常のSSHではなくWinRMを利用します。 このため、Ansibleの他に追加のライブラリが必要です。 また、アクセス時にはAdministratorパスワードを利用します。

ここでは、別のAmazon LinuxのEC2インスタンスからAnsibleを実行することを想定していますが、ローカルのMacから実行する場合でも変わりません。 Ansibleはインストール済みとします。

pywinrmのインストール

AnsibleのWindowsモジュールが依存するPythonでWinRMを扱うライブラリpywinrmをpipでインストールします。

$ pip install pywinrm

Inventoryファイルの作成

適当なディレクトリにInventoryファイル(hosts)を作成します。

[windows]
ec2-54-178-xxx-xxx.ap-northeast-1.compute.amazonaws.com

winsowsというグループを作成し、Windows ServerのPublic DNSを設定しました。

group_varsファイルの作成

windowsグループのための変数ファイル(group_vars/windows.yml)を作成します。 SSH UserとSSH PasswordにはWindowsのログイン情報を記入してください。

sible_ssh_user: Administrator
ansible_ssh_pass: PASSWORD_FOR_ADMIN
ansible_ssh_port: 5986
ansible_connection: winrm

なお、複数のWindowsサーバにアクセスする場合、デフォルトではログインパスワードがサーバ毎に異なる点に注意してください。

セキュリティグループの設定

WinRMは5986ポートで通信を行うため、セキュリティグループの設定でAnsibleを実行するマシンからの5986ポートを許可します。

疎通確認

最低限の設定は完了したので、Windowsモジュールのwin_pingを利用して疎通確認します。

$ ansible windows -i hosts -m win_ping -vvv

疎通に失敗する場合は、セキュリティグループ(ポート)とWindowsパスワードを確認してみてください。 特にWindowsパスワードが間違っている場合にHTTPエラーのようなメッセージが表示されて混乱します。

Powershellスクリプトの実行

Playbook(playbool.yml)を用意してPowershellスクリプトを実行してみます。 Playbookでは、Powershellのスクリプトを対象のサーバで実行させます。

- hosts: windows
  gather_facts: false
  tasks:
  - name: output ec2-instance info to text file
    script: files/get-ec2-instance.ps1

Powershellスクリプト(files/get-ec2-instance.ps1)を配置します。

Get-EC2Instance -Region ap-northeast-1  | Out-File -FilePath C:/temp/ec2.txt

このスクリプトでは、AWS SDK for Powershellを利用し、EC2インスタンスの情報をファイルに出力しています。

実行してみましょう。

# ansible-playbook -i hosts playbook.yml

まとめ

Windows ServerにWinRMをセットアップすることで、AnsibleからPowershellスクリプトを流し込むことができます。 ファイルの転送を行ったりすることが難しいため、リソースは外部サーバからダウンロードするなど、工夫は必要となりますが、Poweshellでできる範囲であればWindows Serverを自由自在に操作できるでしょう。

とはいえ、簡単に検証した範囲では他のWinodows系モジュールの動作はまだ不安定なようです(Ansibel 1.8.4時点)。 サービスの起動や停止も可能なのですが、成功したり失敗したりと微妙な挙動でした。 Windowsサポートがはじまったのも最近のようですので今後の安定化が期待されます。