Ansible
WindowsServer

AnsibleでWindows Server 2012を構成する

More than 1 year has passed since last update.


Ansible の Windows 対応について(ドキュメント抜粋)

2015/08/25に書いたものですが、部分的にアップデートをしています。

http://www.ansible.com/windows


  • Windowsホスト情報をゲット

  • MSIをインストール、アンインストール

  • Windowの機能を有効化・無効化

  • Windowsのサービスの管理(起動・停止)

  • ローカルユーザ・グループの作成・管理

  • ChocolateyパッケージマネージャによるWindowsパッケージの管理

  • Windowsアップデートの管理・インストール

  • リモートサイトからファイルを取得

  • PowerShellでスクリプトを書いても実行可

  • runas というWindowsのコマンドをサポートできるようになる


Linux/Unix の sudo , su のようなやつ(以下リファレンス)

Windowsのrunasコマンドで、一時的に他のユーザー権限でプログラムを実行する



  • PowerShell で Moduleを書くことができる


Ansible ユーザは、ファイルシステムのACLを管理、Windowsファイアウォール、ホスト名とドメインのメンバシップを管理等、多くのモジュールを書ている



  • Ansible Towerも対応


環境


  • OpenStack Kilo 上インスタンス

  • コントロールマシン


    • Ubuntu 14.04 x86_64



  • リモートマシン


    • Windows Server 2012 R2 Standard



2015-08-26 10-33-15.jpg


コントロールマシン 準備


Ansible インストール

$ sudo apt-get install software-properties-common

$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible

For Windows remote host
$ sudo apt-get install python-pip
$ sudo pip install https://github.com/diyan/pywinrm/archive/master.zip#egg=pywinrm
$ sudo apt-get install libkrb5-dev python-dev
$ sudo pip install kerberos


インベントリファイル(~ 1.9.x)

$ more hosts

[windows]
10.1.1.6
test.example.com

[windows:vars]
ansible_ssh_user=Administrator
ansible_ssh_pass=XXXXXXXXXXXX
ansible_ssh_port=5986
ansible_connection=winrm


インベントリファイル(2.x~)

$ more hosts

[windows]
10.1.1.6
test.example.com

[windows:vars]
ansible_user=Administrator
ansible_password=XXXXXXXXXXXX
ansible_port=5986
ansible_connection=winrm
# The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates:
ansible_winrm_server_cert_validation: ignore

パスワード指定のパラメータに注意!(ansible_ssh_pass => ansible_password)

ansible_password を ansible_pass など他の文字列にすると、下記のようなエラーがでます。

192.168.1.6 | UNREACHABLE! => {
"changed": false,
"msg": "ssl: auth method ssl requires a password",
"unreachable": true
}


Windows Server 2012 準備


  • 特別手を加えていない

  • PowerShell 3.0以上が必要だが、既に4.0が含まれている

2015-08-24 17-45-21.jpg


モジュール試行

上記環境で確認できたPlaybook例など示す。


モジュール (Stable Ansible v1.9.2)


copy


  • ファイルのコピー(ディレクトリも可能だが、それのみでないとだめ)

  • 1MBを越えると数分かかる

  • 3MB以上だと500エラーでる

  • 大きいファイルには向かないので、win_get_urlモジュールか、ファイルサーバを利用する


playbook

    - name: Copy a file

win_copy: src=hogefile.zip dest={{ mydir }}

v2.0.0 からは改良されており、大きなファイルも送れるようになっています。


win_feature

telnet クライアントを入れた例


playbook

    - name: Install Telnet Client

win_feature:
name: "Telnet-Client"
state: absent
restart: no
include_sub_features: no
include_management_tools: no


win_file


playbook

    - name: Create directory structure

win_file: path={{ mydir }}\testfolder state=directory


win_get_url

インターネット上のファイルをダウンロードする例


playbook

    - name: Get a file from web site

win_get_url:
url: 'http://sarah.secret.jp/worklog/wp-content/uploads/2015/03/pen8-300x209.jpg'
dest: '{{ mydir }}\test.jpg'


win_group


playbook

    - name: Create group

win_group:
name: hogefuga
description: Deploy Group
state: present


win_user


playbook

    - name: Add a user

win_user:
name: hogefuga
password: "eisaku@00"
groups: ["Users"]
state: present


win_msi

Vagrant をインストールした例


playbook

    - name: MSI Install

win_msi: path={{ mydir }}\vagrant_1.7.2.msi state=present


win_ping


playbook

    - name: Test ping

action: win_ping


win_service


playbook

    - name: Restart a service

win_service:
name: snmptrap
state: started


win_stat

以下の例では「win.ini」の情報を取得して、assert でチェック


playbook

    - name: Returns information about a Windows file

tags: stat_file
win_stat: path={{ mydir }}\win.ini
register: stat_file

- debug: var=stat_file

- name: Check stat_file result
tags: check_stat
assert:
that:
- "stat_file.stat.exists"
- "not stat_file.stat.isdir"
- "stat_file.stat.size > 0"
- "stat_file.stat.md5"



win_template


playbook

  vars:

mydir: C:\Users\Administrator\Desktop
ntp_srv_addr: 100.100.100.100
tasks:
- name: template
win_template: src=./ntp.conf.j2 dest={{ mydir }} backup=yes


win_updates


playbook

    - name: Update

win_updates:
category: critical # critical or security


"win_"が付かないモジュール


setup

$ ansible 10.1.1.6 -m setup

10.1.1.6 | success >> {
"ansible_facts": {
"ansible_distribution": "Microsoft Windows NT 6.3.9600.0",
"ansible_distribution_version": "6.3.9600.0",
"ansible_fqdn": "ansible-target-",
"ansible_hostname": "ANSIBLE-TARGET-",
"ansible_interfaces": [
{
"default_gateway": "10.1.1.254",
"dns_domain": "openstacklocal",
"interface_index": 12,
"interface_name": "Red Hat VirtIO Ethernet Adapter"
}
],
"ansible_ip_addresses": [
"10.1.1.6",
"fe80::69c3:3631:3bd:845a"
],
"ansible_os_family": "Windows",
"ansible_powershell_version": 4,
"ansible_system": "Win32NT",
"ansible_totalmem": 4294967296,
"ansible_winrm_certificate_expires": "2025-08-24 06:52:04"
},


slup

$ ansible 10.1.1.6 -m slurp -a src='C:\Users\Administrator\Desktop\win.ini'

10.1.1.6 | success >> {
"changed": false,
"content": "OyBmb3IgMTYtYml0IGFwcCBzdXBwb3J0DQo=",
"encoding": "base64"
}


playbook

    - name: slurp module

slurp:
src: '{{ mydir }}\win.ini'


fetch

リモートホストからデータをフェッチする

以下の例ではリモートホスト(Windows Server)上の ntp.conf.txt ファイルをコントロールマシンのplaybook実行カレントに「test/<windows server>/C:/Users/Administrator/Desktop/ntp.conf.txt」という形でフェッチされる


playbook

  vars:

mydir: C:\Users\Administrator\Desktop

- name: fetch module
fetch:
src: '{{ mydir }}\ntp.conf.txt'
dest: ./test



raw


  • リモートホスト上の個別のコマンドや.exe、PowerShellスクリプトを実行したい時


playbook

    - name: raw module

tags: raw
raw: ipconfig
register: ipconfig
- debug: var=ipconfig


script


  • 実行プログラムを転送した後、PowerShell のスクリプトを実行したい時


playbook

    - name: run test script

script: files/test_script.ps1


モジュール(Dev Ansible v2.0)


win_environment (v2.0)


playbook

- name: Set Environment

tags: env
win_environment:
state: present
name: TestVariable
value: "Test value"
level: machine


win_regedit (v2.0)


playbook

- name: Set Registry

tags: reg
win_regedit:
key: HKCU:\Software\MyCompany
value: hello
data: 1337
datatype: dword

2015-08-26 17-30-18.jpg


win_unzip (v2.0)


  • PowerShell Community Extensions (PSCX) Module が必要

  • zip 以外も展開可(bzip,gzなど)

  • 再帰的にアーカイブを展開可

  • 展開先のディレクトリがなければ作ってから展開

  • 展開後、不要なソースファイルを削除可

以下例の「presen.zip」は展開すると「presen\test.zip」となり、更にtest.zipを展開するとテキストファイルに展開される。つまり、通常全て展開すると下記のようになる。

presen

\__test.txt
\__test.zip

これを下記のように指定してPlaybookを実行(再帰的に展開)してみる。


playbook

- name: Unzip file

tags: unzip
win_unzip:
src: '{{ mydir }}\presen.zip'
dest: '{{ mydir }}\archive'
recurse: yes
rm: true
creates: '{{ mydir }}\archive'

結果は以下のようになった。再帰的に展開はされ、元のzipファイルは全て削除されているが、ちょっと直感的ではなかった。

archive

\presen #(この下は空)
\test.txt


モジュール (Ansible Docs)

以下は未評価


  • win_chocolatey (v1.9.2 extras) # Enterpriseとして使うか否か

  • win_dotnet_ngen (v2.0)

  • win_iis_virtualdirectory (v2.0)

  • win_iis_webapplication (v2.0)

  • win_iis_webapppool (v2.0)

  • win_iis_webbinding (v2.0)

  • win_iis_website (v2.0)

  • win_package (v2.0)

  • win_scheduled_task (v2.0)

  • win_webpicmd (v2.0)


おまけ


コンフィグファイルを設定

guest@ahost:~$ cp /etc/ansible/ansible.cfg ~/

guest@ahost:~$ sed -i -e 's/\/etc\/ansible\/hosts/\/home\/guest\/hosts/g'
guest@ahost:~$ export ANSIBLE_CONFIG=~/ansible.cfg


Chocolatey 対応


  • 1.9.2 のモジュールでうまくいっていない

# cd /usr/share/pyshared/ansible/modules/extras/windows/

# cp win_chocolatey.py org_win_chocolatey.py
# cp win_chocolatey.ps1 org_win_chocolatey.ps1

# curl https://raw.githubusercontent.com/ansible/ansible-modules-extras/devel/windows/win_chocolatey.ps1 -o ./win_chocolatey.ps1
# curl https://raw.githubusercontent.com/ansible/ansible-modules-extras/devel/windows/win_chocolatey.py -o ./win_chocolatey.py


Reminder: You Must Have a Linux Control Machine

Windows を管理するのはLinuxコントロールマシンであり、Windowsのコントロールマシンではない。

また、Cygwinはサポートされていない。


テストにおいて、Windows Server 2012 留意点

Ansibleがどうこうという意味ではなく、Windows Server 2012 はこうだったというメモ。


  • セキュリティが高い設定は相変わらずだが至極当然

  • ブラウザからデフォルト状態ではファイルダウンロードX

  • ファイアウォールも有効

  • 隠しファイルはデフォルト見えない


参考

http://docs.ansible.com/ansible/intro_windows.html

http://docs.ansible.com/ansible/list_of_windows_modules.html