回到:Ansible系列文章
各位讀者,請您:由於Ansible使用Jinja2模板,它的模板語法{% raw %} {{}} {% endraw %}和{% raw %} {%%} {% endraw %}和博客系統的模板使用的符號一樣,在渲染時會產生衝突,儘管我盡我努力地花了大量時間做了調整,但無法保證已經全部都調整。因此,如果各位閱讀時發現一些明顯的詭異的錯誤(比如像這樣的空的
行內代碼),請一定要回復我修正這些渲染錯誤。
15.意外之喜:Ansible管理Windows主機
15.1 Ansible如何管理Windows
Ansible能管理Linux類系統,它是Agentless的,只要在Linux端安裝好Ansible,並指定連接到目標的連接類型(例如ssh),就可以將操作指令發送到目標節點上執行。
但Ansible還能管理Windows系統。可使用三種方式進行管理:
- (1).Windows 10或Windows Server 2016上安裝WSL(Windows Subsystem for Linux),如果是早於該版本的Windows系統,可安裝Cygwin模擬Linux環境。然後啓動sshd服務,便可讓Ansible進行管理
- (2).Windows上開啓WinRM(Windows Remote Management)連接方式,出於安全考慮,Windows默認禁用了WinRM。只要開啓了WinRM,Ansible指定WinRM連接方式便可以管理Windows
- (3).Ansible 2.8中增加了基於Win32-Openssh的ssh連接方式,目前還處於測試階段
讓Ansible通過WSL基於ssh連接的方式管理Windows系統是非常受限的,Windows不像Linux,Linux通過配置文件完成配置,而Windows通過註冊表的方式配置程序,所以通過WSL上只能做一些基本操作,比如文件類操作。這樣失去了很多Windows自身的能力,比如域、活動目錄類的管理。
所以,需要讓Ansible基於WinRM連接方式去管理Windows是比較可取的,可管理的對象、功能也更爲豐富。
本文不會介紹如何在Windows 10/Windows Server 2016上開啓WSL以及如何讓Ansible通過WSL去管理Windows,本文要介紹的是基於WinRM連接方式管理Windows。
15.2 Ansible管理Windows前的設置
對於Ansible端來說,唯一需要做的就是安裝Python的winrm包:
pip3 install "pywinrm>=0.3.0"
對於Windows端來說,要讓Ansible管理Windows,要求Windows端:
- (1).PowerShell 3.0+
- (2). .NET 4.0+
所以,默認支持的Windows系統包括:
- (1).Windows 7 SP1, 8, 10
- (2).Windows Server 2008 SP2, 2008 R2 SP1, 2012, 2012 R2, 2016, 2019
如果是更古老的系統,要求額外安裝PowerShell 3.0+以及.NET 4.0+。
另外,.NET 4.0有很多漏洞,所以要麼安裝更高版本的.NET,要麼打補丁;PowerShell 3.0下的WinRM也有漏洞,所以要麼打補丁,要麼使用更高版本的PowerShell。
然後就可以開啓WinRM了。Ansible官方提供了一個自動化配置的powershell腳本。可先以管理員身份打開PowerShell,按如下方式下載並執行powershell腳本:
$ansibleconfigurl = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$ansibleconfig = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($ansibleconfigurl, $ansibleconfig)
powershell.exe -ExecutionPolicy ByPass -File $ansibleconfig
配置好後,winrm將默認以HTTPS的方式監聽在5986端口上。
> netstat -an | Select-String -Pattern '5986'
TCP 0.0.0.0:5986 0.0.0.0:0 LISTENING
TCP [::]:5986 [::]:0 LISTENING
爲方便演示,這裏在Windows上再創建一個新用戶junmajinlong,密碼爲123456,並加入管理員組(Administrators):
New-LocalUser -name "junmajinlong" `
-Password (ConvertTo-SecureString -String '123456' -AsPlainText -Force) `
-AccountNeverExpires -PasswordNeverExpires
Add-LocalGroupMember -Group "Administrators" -Member "junmajinlong"
配置好Windows端後,可以先測試下Ansible是否能連接到Windows。
如果哪裏失敗了,可參考官方手冊:https://docs.ansible.com/ansible/latest/user_guide/windows_setup.html。
15.3 測試能否成功管理Windows
Ansible連接目標節點時,默認使用SSH連接,且默認使用執行Ansible操作的用戶名連接目標節點。
對Linux來說這些都可以採用默認值,但是對Windows來說,這顯然是行不通的,所以需要顯式指定Ansible連接Windows時的用戶名、密碼、端口、winrm連接類型等。
例如,對於IP爲192.168.200.14的Windows來說,如果用戶名爲junmajinlong,密碼爲123456,那麼可以配置如下inventory信息:
[windows]
192.168.200.14 ansible_user=junmajinlong
[windows:vars]
ansible_password="123456"
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
關於上述Inventory配置,需要注意幾點:
- (1).對於自籤CA,
ansible_winrm_server_cert_validation
必須設置爲ignore - (2).密碼不應直接寫在inventory中,而是採用Vault加密的方式或者使用
-k, --ask-pass
選項由用戶手動輸入 - (3).如果是域用戶,那麼
ansible_user
的格式爲:USERNAME@domain_name
然後找個ping模塊測試是否能成功執行。
$ ansible -i win_host all -m win_ping
192.168.200.14 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ansible中的Windows相關模塊,全部都以win_
開頭,比如ping模塊對應於win_ping
。在此列出了Ansible所提供的所有管理Windows的模塊:https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html。
比如用Ansible管理Windows來創建一個本地用戶並加入Administrators組:
---
- name: manage win user
hosts: windows
gather_facts: no
tasks:
- name: create new user named "junma"
win_user:
name: junma
password: 123456
state: present
groups_action: add
groups: Administrators
password_never_expires: yes
15.4 Ansible執行PowerShell、CMD命令
執行powershell命令和cmd命令非常簡單,只需使用win_shell
模塊即可。該模塊默認使用的powershell,如果要使用cmd,明確指明executable: cmd
即可。
例如:
- name: create a dir use powershell
win_shell: New-Item -Path C:\testfile -ItemType Directory
- name: create a dir use cmd
win_shell: mkdir C:\testfilecmd
args:
executable: cmd
15.5 創建域控制器
假設現在Windows Server已經開啓了WinRM,目前的IP地址是192.168.200.75,使用的是默認管理員administrator。接下來將從0到1將其創建成域控制器(DC, Domain Controller)。
如下是dc節點的inventory配置:
[dc_controller]
192.168.200.75
[dc_controller:vars]
ansible_user=administrator
ansible_password="123456"
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
如下是playbook文件內容,相關解釋在註釋中:
- name: install first domain controller
hosts: dc_controller
gather_facts: no
tasks:
# 按需修改主機名,這裏改爲dc1,修改主機名可能要求重啓
- name: set dc hostname
win_hostname:
name: "dc1"
register: res
- name: Reboot
win_reboot:
when: res.reboot_required
# 等待重啓完成
- name: Wait dc to become reachable
wait_for_connection:
timeout: 900
# 安裝Active Direcotry相關功能
- name: install ad
win_feature: >
name=AD-Domain-Services
include_management_tools=yes
include_sub_features=yes
state=present
register: result
# 創建域控制器,要求重啓
# safe_mode_password參數指定域控制器的恢復密碼
- name: install domain
win_domain: >
dns_domain_name="junmajinlong.com"
safe_mode_password='P@ssword1!'
register: ad
- name: reboot server
win_reboot:
msg: "Installing AD. Rebooting..."
pre_reboot_delay: 3
when: ad.changed
# 等待重啓結束後重連
- name: Wait dc to become reachable
wait_for_connection:
timeout: 900
# 設置域控制器的DNS指向自己
- name: set dc dns pointer to self
win_dns_client:
adapter_names: "*"
ipv4_addresses:
- "{{inventory_hostname}}"
執行完上面的playbook後,將創建一個junmajinlong.com
的域環境。
另外,上面示例中是將所有屬性直接硬編碼在playbook中,合理的做法應該是將其定義爲inventory變量或普通變量,然後在playbook中引用。
15.6 將主機加入域
比如將本文之前操作過的192.168.200.14這個Win10主機加入域環境。
inventory部分如下:
[windows]
192.168.200.14 ansible_user=junmajinlong
[windows:vars]
ansible_password='123456'
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
要將一個節點加入域,需要修改其DNS指向域控制器。
playbook內容如下:
- name: add win 10 to domain junmajinlong.com
hosts: windows
gather_facts: no
tasks:
- name: configure DNS pointer to Domain Controller
win_dns_client:
adapter_names: "*"
ipv4_addresses:
- 192.168.200.75
- name: set dc hostname
win_hostname:
name: "win10"
register: res
- name: Reboot
win_reboot:
when: res.reboot_required
- name: join to domain
win_domain_membership:
dns_domain_name: junmajinlong.com
domain_admin_user: [email protected]
domain_admin_password: 123456
state: domain
register: domain_state
- name: Reboot after joining
win_reboot:
msg: "Joining Domain.Rebooting..."
pre_reboot_delay: 3
when: domain_state.reboot_required
關於Ansible管理Windows就介紹這麼多,個人用的較少,而且個人覺得Ansible管理Windows更多的時候需要藉助於PowerShell命令或PowerShell腳本。