What Ansible can do for you

    Our use case:

    First, let’s talk about the deployment architecture we actually want to have.Please keep in mind that this is just an example of how to use Ansible connectors, which I think will help you set up your own deployment.

    The following figure shows:

    • A machine that can initiate a deployment
    • Machines to be deployed
    • How they are connected


    The idea here is to be able to administrate the deployment of all hosts from the same tool (Ansible) and the same var files (Ansible inventory).

    The tricky part

    The tricky part here is that, as of today, Windows and Linux remain two very different OSs, with a lot of specificities. In particular :

    • They traditionally use different remote access protocols
      • Linux: SSH
      • Windows: PSRP / WinRM
    • They are not structured the same way, therefore Ansible module made for Linux-like OSs are generally not compatible with Windows
    • They do not offer the same command line interpreters as a workaround when no Ansible module exists to implement your use case
      • Linux: Bash, Zsh, etc
      • Windows: PowerShell

    How we can solve this : Ansible connectors

    Our problem here is that we need to tell Ansible :

    • To connect to Linux using the SSH protocol
    • To connect to Windows using the PSRP protocol (PowerShell Remoting Protocol)

    Well, Ansible has a mechanism to deal with heterogeneous targets connections: Ansible connectors.Connectors are libraries, often written in Python, that Ansible will use to establish a connection to the target host.The best part here is that Ansible handles the choice of the connector as well as the per-host configuration of a connector with its inventory. This means that you can use all of the power that Ansible gives you to customize the Ansible connector to use for a host or a group of hosts.

    In our case we will use the following connectors:

    Note: For windows hosts, we could also use the WinRM Ansible connector. In this case, I chose the PSRP connector instead because it offers the possibility to use a SOCKS5 proxy, which is really helpful to manage Windows hosts that are located behind a bastion.

    Network considerations

    Since the machine that will use Ansible need access to all targets, you need to ensure its ability to establish :

    • Connections to Linux machines with SSH
    • Connections to Windows machines with PSRP over WinRM

    If you have to go through a bastion host located between your deployment machines and your targets, you can use for example:

    In both case, and whatever your tunneling / proxying implementation is, you will have to carefully configure your network to accept the appropriate traffic:

    • Between the deployment machine and the bastion
    • Between the bastion and the target

    And this configuration may differ on Linux and Windows hosts.

    Connect Ansible to both Windows and Linux hosts

    We will use the following inventory.yaml file: 

    And we will create the following files and directories:

    Set up Linux targets

    Add the following variables to the ./group_vars/connector-linux.yaml

    Set up Windows targets

    Add the following variables to the ./group_vars/connector-windows.yaml

    Note 1: Here we use WinRM basic authentication without message encryption because it is the easiest to set up for an example. But for production environments, it’s highly recommended to use stronger authentication mechanisms such as Kerberos.

    Note 2: The user and password params are in the classic configuration file because it’s easier to show in this article, but it’s highly recommended to store them in an ansible-vault file instead.

    Launch a test command on both kinds of targets

    First of all, you can check that all your targets were defined as required, with the following command:

    $ ansible-inventory -i hosts.yaml --list

    If your inventory is to big for this output to be useful, you can also display variables host by host:

    $ ansible-inventory -i hosts.yaml --host vm-linux-1

    And since the output will be in json, you can use jq to quickly filter it to get the information you want.

    Then, to check usability of Linux targets:

    $ ansible -i hosts.yaml -l vm-linux-1 -m ping

    And for Windows targets:

    $ ansible -i hosts.yaml -l vm-windows-1 -m win_ping

    Note 1: the ping and win_ping Ansible modules check that the target is reachable, and that it will be able to handle Ansible actions (e.g. meaning on Linux targets that it checks the availability of Python). So it’s not a network ping (as would be performed by Linux ping command for example), it really is an Ansible-like implementation of a ping.

    Note 2: As you can see, because Linux and Windows are different, they require different implementations of the ping Ansible module, hence the use of “ping” and “win_ping” in the commande above.

    Writing a playbook

    Now that you can manage connections to both Linux and Windows targets, you will want to perform actions on them.Although you can put all of the actions in the same playbook, regardless of the OS of the target, I think that in most cases it’s easier to put Windows and Linux tasks in separate playbooks.

    For Linux targets, you can use:

    • Classic Ansible modules, like “file”, or “template”
    • Custom actions using the shell and command modules

    And for Windows targets, you can use:

    • Ansible modules that have the “win_” prefix, like “win_template”
    • DSC configurations using the Ansible win_dsc module
    • Custom actions using the win_shell module

    It’s quite simple.

    If you know how to deal with both Linux and Windows configuration, then you should easily succeed in using Ansible to configure both kinds of hosts.

    Going further with connectors

    In this article, we used two specific Ansible connectors: SSH and PSRP.But you can use the following command to list all connectors that are available in your environment:

    $ ansible-doc -t connection -l

    If I run this command on my computer, I find out that I have as many as 26 available connectors: Local, chroot, lxc, lxd, Docker, buildah, podman, netconf, …This means that Ansible can help you in many heterogeneous deployment scenarios.But each time you use a different connector, don’t forget to check what Ansible modules are applicable to the targeted environment. (E.g. netconf_config module for netconf connector).

    We saw in this article that you can quickly configure Ansible to deploy and configure different kinds of targets (e.g. Linux and Windows targets) through the use of connectors that let you customize both the protocols and authentication methods.