Even though Ansible is known for managing Linux nodes using SSH, did you know that Ansible on Windows works just as well? Using Windows Remote Management (WinRM), Ansible on Windows can effectively manage all of your Windows nodes too!
Not a reader? Watch this related video tutorial!With Ansible on Windows, you can perform tasks like deploying patches, managing Windows servers, execute PowerShell scripts, and more.
In this tutorial, you’re going to learn how to set up your first Windows node to be managed with Ansible and see how to run commands and playbooks against it.
Prerequisites
If you’d like to follow along with the tutorial, please be sure you have the following before starting:
- An Ansible controller host – This tutorial will be using Ansible v2.9.18 on an Ubuntu 18.04.5 LTS machine with an IP address of 10.111.4.53. Note that Windows is not supported as a control node, only a managed node.
- Python installed on your Ansible controller host – This tutorial will be using Python v2, but v3 should work just as well.
- The pip package installed on the Ansible controller.
- A Windows 2012 R2 or greater computer for Ansible to manage – This tutorial will use two Windows Server 2012 R2 Standard machines as remote nodes with IP addresses of 52.242.251.213 and 10.111.4.106.
- A Windows workstation – This tutorial will perform some basic pre-configuration to the node that Windows will manage with Ansible and will require you to sitting at a Windows workstation.
- The Windows server to manage has PowerShell Remoting enabled
- A user account in the local Administrators group on the Windows computer. This tutorial will use an account called adminuser.
Setting up the WinRM listener on Windows
Before Ansible can communicate with a remote Windows node, it must be able to make a connection to it. It does this through the Microsoft protocol WinRM. WinRM is the same protocol that PowerShell Remoting uses to run remote commands from within PowerShell.
As of this writing, Ansible does support SSH as a management protocol, but it’s an experimental feature at this time.
For Ansible to use WinRM to communicate with the Windows node, you must configure WinRM. To do this, Ansible provides a PowerShell script that sets various WinRm options.
Although the PowerShell script that Red Hat provides to configure WinRM has been tested and is safe, you should read through it and understand, at a high level, what it’s doing.
Your first task will be to download the configuration script and run Ansible on the Windows node. To do that, assuming you already have PowerShell Remoting enabled on your target Windows computer and you’re at a Windows workstation:
Download the ConfigureRemotingForAnsible.ps1 PowerShell script to your local Windows computer. This tutorial will assume it’s saved in ~\Downloads.
Run the configuration script on the Windows node Ansible will manage using the Invoke-Command
command. The command below will run the command on the tutorial’s two demo machines and prompt you for the password for the local adminuser account on the Windows nodes.
Invoke-Command -ComputerName 52.242.251.213, 10.111.4.106 -FilePath '~\Downloads\ConfigureRemotingForAnsible.ps1' -Credential (Get-Credential -UserName adminuser)
By default, the configuration script will configure WinRM for basic HTTP authentication. If you’d like Ansible to use a more secure connection, learn How to Configure WinRM over HTTPS for Ansible.
Configuring the Controller of Ansible on Windows
Now that the Windows node is ready for Ansible, let’s now configure the Ansible controller to show Ansible how to communicate with it.
1. Connect to your Ansible controller host via SSH using your favorite SSH client.
2. Install the pywinrm Python module. The pywinrm Python module is required for Ansible on Windows to communicate to hosts via the WinRM protocol.
pip install pywinrm
3. Define the remote Windows nodes in an Ansible inventory file. An Ansible inventory is a collection of remote hosts defined in a file either by their hostname or IP address. Once defined, you can then target Ansible inventories with commands and playbooks, as you’ll soon see.
The default Ansible inventory file is located in the /etc/ansible/hosts directory.
The sample inventory file below is created a windows
host group that contains each Windows node. The tutorial is using a host group here to make it easier to target all Windows nodes (if you have more than one) at once later.
[windows]
54.242.251.213
10.111.4.106
4. Next, define a few required variables Ansible will use when connecting to the Windows hosts in the inventory file as a windows:vars
group.
[windows:vars]
ansible_user=localadmin ## the windows username for ansible to communicate
ansible_password=s3crect ## the windows password for ansible to communicate
ansible_connection=winrm ## The kind of connection which ansible will make with remote windows node
ansible_winrm_server_cert_validation=ignore ## ignore certificate validation because we'll just be using a self-signed certificate that comes with Ansible
5. Now, use the Ansible win_ping module to execute a simple connection test to the hosts inside of the windows
host group defined in step #3.
# windows is the host group
# -m tells Ansible to use the win_ping module
ansible windows -m win_ping
Once executed, you can see below that Ansible returns green text with a SUCCESS message indicating the successful ping attempt.
The output confirms that the Ansible controller host can communicate with the Windows remote host successfully over WinRM.
Running ad-hoc Commands on Windows Hosts
At this point, you’re all set for Ansible to begin controlling your Windows nodes. Let’s now test this out by running an ad-hoc command on the Windows nodes to change them. Ad-hoc commands are great when you need to run a simple command on nodes without first creating a playbook.
Let’s demonstrate ad-hoc commands by installing a Windows feature on the Windows nodes defined in the windows
host group in the inventory file. To do that, assuming you’re still SSHed into your Ansible controller node:
1. Instead of the win_ping module this time, call the win_feature module (-m
), passing it two arguments (-a
) of name
and state
indicating the name of the Windows feature and the state you desire it to be in.
# windows here is a group of hosts
# win_feature is the name of the module
# state=present means to install the package or service
ansible windows -m win_feature -a "name=Telnet-Client state=present"
When you run the above command, if all goes well, Ansible should connect to all of the nodes in the windows
host group and run the win_feature command on each checking for, and if not present, installing the Telnet-Client
Windows feature.
2. Ansible shows success, but to be sure, connect to the Windows nodes manually with PowerShell and verify the Telnet Client Windows feature is now installed. On your local Windows workstation, run Invoke-Command
to run the Get-WindowsFeature
PowerShell command on each Windows computer.
Invoke-Command -ComputerName 52.242.251.213, 10.111.4.106 -ScriptBlock { Get-WindowsFeature -Name 'Telnet-Service' } -Credential (Get-Credential -UserName adminuser)
At this point, you can run any Windows module you like as ad-hoc commands!
Creating and Running Ansible on Windows Playbooks
Once you’ve mastered the art of running ad-hoc commands on Windows managed nodes, your next task is to create and run playbooks.. An Ansible playbook combines commands into a single place and allows you to write complex logic to perform complex automation scenarios.
Running Remote Windows Commands with the win_command Module
Assuming you’re still connected to your Ansible controller host:
1. Create a folder under your home directory called ansible-windows-demo and change to it. This folder will hold your playbook.
mkdir ~/ansible-windows-demo
cd ~/ansible-windows-demo
2. Open your favorite text editor and create and save a file called ansible-windows.yml in the ~/ansible-windows-demo directory.
Ansible playbooks are written in YAML
3. Now, copy the below playbook into the ansible-windows.yml file to create a single task. This playbook will execute the netstat Windows command using the win_command Windows Ansible module on all hosts inside the windows
host group.
The win_command module executes commands on windows remote host. It doesn’t allow commands which include variables such as special characters, line breaker, greater than symbol, etc.
---
- name: Ansible win_command module example
hosts: windows # host group to run the module on
tasks:
- name: run an executable command on a remote Windows system
win_command: netstat -e # win_command is a Windows module.
4. Invoke the ansible-windows.yml playbook, which executes the task on the remote host by running the following command.
ansible-playbook ansible-windows.yml
If all went well, you should see output like below.
Running Remote PowerShell Commands with the win_shell Module
You created a playbook to run a remote cmd.exe command (netstat
) on Windows
managed nodes in the previous example. Let’s now up the ante a bit and run PowerShell commands using the win_shell module.
By default win_shell module runs on PowerShell on windows host
On your local Windows workstation:
1. First, open your favorite text editor on your local Windows workstation and create a sample PowerShell script and copy the following code into it, saving it as one.ps1. This tutorial will save the script to ~\one.ps1.
The below code creates a blank text file called test2.txt in the C:\temp directory.
Set-Content -Path C:\temp\test2.txt -Value ''
2. Copy the one.ps1 PowerShell script to your Windows managed nodes using your preferred method. This tutorial will assume you’ve copied the one.ps1 script to the C:\Temp folder on each Windows node.
3. Once the sample PowerShell script is one the Windows node(s), connect to your Ansible controller host and open your favorite text editor again. This time, create and save another playbook called ansible-windows-shell.yml in the same ~/ansible-windows-demo directory.
4. Copy and paste the following playbook into the ansible-windows-shell.yml file. This playbook will run two tasks to demonstrate the win_shell module. It invokes the PowerShell script just copied from step #2 and inserts the PowerShell code directly into the playbook to demonstrate the script isn’t needed at all.
To pass multiple lines of PowerShell code to the win_shell module, use the
|
pipe character.
---
- name: Ansible win_shell module example
remote_user: localadmin # local Windows user to connect with
hosts: windows # remote host group
tasks:
- name: Single line PowerShell # Running single command using win_shell module
win_shell: C:\temp\one.ps1
- name: Run multi-lined shell commands
win_shell: |
$text = ' Iam Author of ATA'
Set-Content -Path C:\temp\test3.txt -Value $text
5. Now, invoke the second playbook ansible-windows-shell.yml, which executes on the remote host but with PowerShell.
ansible-playbook ansible-windows-shell.yml
6. If necessary, on your local Windows workstation, verify the playbook executed the existing script and the PowerShell code in the playbook.
Invoke-Command -ComputerName 52.242.251.213, 10.111.4.106 -ScriptBlock { Test-Path -Path 'C:\Temp\test3.txt','C:\Temp\test2.txt' } -Credential (Get-Credential -UserName adminuser)
If the Ansible playbook ran successfully, PowerShell should return two True
statements indicating that the files now exist.
Conclusion
In this tutorial, you’ve learned how to set up your first Windows managed node in Ansible. Even though Ansible has traditionally been known as a Linux tool, it can easily be used for Windows also!
What playbooks and Windows modules will you start using to manage Windows with Ansible?