用 Ansible 管理 Windows

嗯~Ansible 很好用
所以很希望也可以用在 Windows 上~

開始

  1. 首先要參考 Ansible Windows Support 的文件
  2. 確認 Windows 本身的 Powershell 版本要在 3.0 以上 (沒有的話,就可以下載這個 upgrade_to_ps3.ps1 來執行)
  3. 設定 winrm - 執行 setup.ps1
    1. Windows 7/2008R2 版本還要先安裝 http://support.microsoft.com/kb/2842230
    2. Windows 8.1/2012 以後版本已經安裝了 .Net 4.0,所以不需要特別作什麼事情

測試

因為想在本機測試,所以用 Vagrant 來測試

  1. 我這次用的是 win2012-r2 的 box
  2. 很簡單的用 vagrant init opentable/win-2012r2-standard-amd64-nocm; vagrant up --provider virtualbox 就可以啟動了
  3. 當然,需要進入 Windows 裡面去設定 winrm,參考上面的步驟,但是我懶得手動下載後才執行,所以我用了 chocolatey 的技巧,直接下載後執行。開啟 Powershell 視窗,執行下面指令就可以:
    1
    iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1'))
  4. 執行完畢之後,我本來以為可以直接用 Vagrant 的 provision 功能,結果碰壁了~

問題一

1
$ ansible default -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory -m win_ping -vvvv
2
default | FAILED! => {
3
    "failed": true,
4
    "msg": "ERROR! ssl: 500 WinRMTransport. [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)"
5
}

原本以為直接用 Vagrant 產生的 inventory 檔案就可以執行,所以先用 win_ping 指令測試一下
結果就出現了上面的錯誤
找了一下資料以及對照 Vagrant 產生的 vagrant_ansible_inventory 檔案,才發現他產生出來的檔案是這樣:

1
# Generated by Vagrant
2
3
default ansible_connection=winrm ansible_ssh_host=127.0.0.1 ansible_ssh_port=55985 ansible_ssh_user='vagrant' ansible_ssh_pass='vagrant'

麻煩的是,產生出來的 ansible_ssh_port 走的是 http port
內部啟動 winrm 會有兩個 port,對應 http/https。分別是 5985/5986
virtualbox 會幫忙 mapping 這兩個 port,分別對應 55985/55986
但是 ansible 需要走 https,所以就出現了上面的錯誤訊息

改法就是自己產生一個 inventory 檔案 (你不能改 .vagrant 下面產生出來的檔案,因為每次執行 vagrant provision 都會重新產生)

1
[windows]
2
default ansible_connection=winrm ansible_ssh_host=127.0.0.1 ansible_ssh_port=55986 ansible_ssh_user='vagrant' ansible_ssh_pass='vagrant'

問題二

1
$ ansible windows -i hosts -m win_ping -vvvv
2
default | FAILED! => {
3
    "failed": true,
4
    "msg": "ERROR! ssl: 500 WinRMTransport. [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)"
5
}

本來以為改完後,一切幸福美滿~ 結果一執行就給我拋另外一個錯誤
不過這個錯誤看起來就是 SSL 憑證問題!靠!這怎麼改???

我前兩天升級了 Ansible 2.0,所以我還在想說是不是因為這個原因

果不其然,找到了這篇文章: Packer – Vagrant – Ansible – Windows (WinRMTransport Error)
Ansible 也有一個 Issue 在解釋這個問題
改法就是,在現在的目錄下,建立一個 callback_plugins 目錄。然後建立一個 fix_ssl.py 檔案:

1
import ssl
2
if hasattr(ssl, '_create_default_https_context') and hasattr(ssl, '_create_unverified_context'):
3
    ssl._create_default_https_context = ssl._create_unverified_context
4
5
class CallbackModule(object):
6
    pass

根據這段程式碼英文的意思,我猜測就是忽略自簽章的 SSL 憑證驗證~因為我在 .Net 幹過一樣的事情~

所以這次執行就成功了~

1
$ ansible windows -i hosts -m win_ping -vvvv
2
default | SUCCESS => {
3
    "changed": false,
4
    "invocation": {
5
        "module_name": "win_ping"
6
    },
7
    "ping": "pong"
8
}

結語

以上是我碰到的兩個問題,還好網路都有找到解法~
所以之後應該只需要參考 Windows Modules 試試看用法,應該之後就可以拿來管理 Windows 了~

不過可能還是要注意下面的事情:

  • 注意自己安裝的 Ansible 版本,我目前測試的版本是 2.0,所以我不知道 1.x 版本是不是沒有我遇到的問題
  • 注意 winrm 設定,因為我這次測試是用 Vagrant box,所以是直接用 Port forwarding 做到。
    如果是實機,就得自己去找 winrm 的 port
  • 之後如果要在實機測試的話,可能還要另外注意帳號密碼問題