title: "Azure Multi-Platform Infrastructure Cluster Automation & Deployment Guide"
published: false
tags: ansible, azure, devops, automation
This repository contains the complete configuration management architecture and deployment runbooks for orchestrating a heterogeneous, cross-platform infrastructure environment via Ansible Core 2.17.14.
The pipeline automates the teardown of conflicting runtime contexts, maps local file parameters dynamically into Linux containers using Jinja2 templates, and uses WinRM over HTTPS to provision web server features on Windows targets via native system managers.
1. Cloud Architecture Specifications
This automation pipeline explicitly targets a multi-platform compute matrix provisioned across separate distinct virtual machine resources in Microsoft Azure:
Core Infrastructure Nodes
-
Ansible Control Node VM: Ubuntu 22.04 LTS (Acting as execution host running Python 3.10 and
pywinrm) -
Linux Managed Target VM: Ubuntu 22.04 LTS (Running Docker engine for containerized services)
-
Internal Private IP:
10.0.1.5 -
External Public IP:
20.124.121.94
-
Internal Private IP:
-
Windows Managed Target VM: Windows Server 2022 Datacenter (Running native IIS features)
-
Internal Private IP:
10.0.1.7 -
External Public IP:
20.121.185.86
-
Internal Private IP:
2. Inbound Azure Network Security Group (NSG) Verification
Before triggering the automation engine, the Azure Network Security Groups matching the resource group (Ansible-Project-RG) must allow inbound packets through the following port boundaries.
Ensure these rules are assigned exactly as shown inside the Azure Portal:
| Priority | Rule Name | Port | Protocol | Action | Inbound Workflow Purpose |
|---|---|---|---|---|---|
| 1000 | default-allow-ssh |
22 | TCP | Allow | SSH remote management access to control node and Linux targets |
| 1002 | open-port-5986 |
5986 | TCP | Allow | Secured WinRM over HTTPS orchestration transport tunnel |
| 1005 | open-port-80 |
80 | Any / TCP | Allow | Public HTTP frontend ingress for Nginx & IIS web platforms |
CLI Firewall Enforcement
If inbound rules are missing or need to be force-propagated across the Azure fabric via the Cloud Shell CLI, execute:
az vm open-port --resource-group Ansible-Project-RG --name "Docker-Manage-node" --port 80 --priority 1005
az vm open-port --resource-group Ansible-Project-RG --name "win-manage-node" --port 80 --priority 1006
3. Directory Structure & Source Code Configuration
The following file hierarchy must reside within the ~/ansible-lab workspace directory on the Ansible Control Node:
~/ansible-lab/
├── hosts.ini
├── index.html.j2
└── site.yml
File 1: Host Inventory Setup (hosts.ini)
Create this file to define the connection strings, target access credentials, and WinRM endpoint attributes:
[docker_nodes]
docker-target ansible_host=20.124.121.94 ansible_user=azureuser
[windows_nodes]
windows-target ansible_host=20.121.185.86
[windows_nodes:vars]
ansible_user=azureadmin
ansible_password=YourSecurePasswordHere
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
ansible_winrm_transport=ntlm
File 2: Dynamic Jinja2 Dashboard Template (index.html.j2)
Create this file to capture runtime facts dynamically evaluated during execution and pass them through Nginx:
<!DOCTYPE html>
<html>
<head>
<title>Automated Dev Cluster</title>
<style>
body { font-family: Arial, sans-serif; background: #2c3e50; color: white; text-align: center; padding-top: 50px; }
.card { background: #34495e; max-width: 600px; margin: 0 auto; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); }
h1 { color: #1abc9c; }
</style>
</head>
<body>
<div class="card">
<h1>Ansible Automation Success!</h1>
<p><strong>Target Hostname:</strong> {{ ansible_hostname }}</p>
<p><strong>Private IP:</strong> {{ ansible_default_ipv4.address }}</p>
<p><strong>OS Distribution:</strong> {{ ansible_distribution }} {{ ansible_distribution_version }}</p>
<p><strong>Deployment Timestamp:</strong> {{ ansible_date_time.iso8601 }}</p>
</div>
</body>
</html>
File 3: Unified Master Deployment Infrastructure Playbook (site.yml)
Create this file to handle cleanup routines, directory permissions, container initialization with storage volume bindings, and native Windows features activation:
---
# ==========================================
# CONFIGURATION FOR THE LINUX DOCKER NODE
# ==========================================
- name: Advanced Linux Container Deployment with Custom Site
hosts: docker_nodes
become: true
tasks:
- name: Remove the old conflicting Nginx container
community.docker.docker_container:
name: my-nginx
state: absent
- name: Create local directory structure for custom web content
file:
path: /opt/nginx/html
state: directory
mode: '0755'
- name: Parse dynamic Jinja2 web template into HTML target
template:
src: index.html.j2
dest: /opt/nginx/html/index.html
mode: '0644'
- name: Ensure universal read access permissions across opt path
file:
path: /opt/nginx/html/index.html
mode: '0755'
- name: Run Nginx Container mounting the custom dynamic volume
community.docker.docker_container:
name: prod-nginx
image: nginx:latest
state: started
restart_policy: always
ports:
- "80:80"
volumes:
- /opt/nginx/html:/usr/share/nginx/html:ro
# ==========================================
# CONFIGURATION FOR THE WINDOWS MANAGED NODE
# ==========================================
- name: Advanced Windows Server Infrastructure Provisioning
hosts: windows_nodes
tasks:
- name: Install IIS Web Server Role using Windows Features
ansible.windows.win_feature:
name: Web-Server
state: present
include_management_tools: yes
- name: Ensure the IIS Web Service is explicitly started and active
ansible.windows.win_service:
name: w3svc
state: started
start_mode: auto
- name: Overwrite default IIS page with automated telemetry text
ansible.windows.win_copy:
content: "<h1>Ansible Active Management Cluster Node</h1><p>Windows Target Environment Operational via WinRM.</p>"
dest: C:\inetpub\wwwroot\iisstart.htm
4. Windows Node WinRM Bootstrapping Sequence
Because native Windows configurations block automated third-party orchestration traffic out of the box, you must bootstrap the secure WinRM port listener on the server node manually before running playbooks:
- Launch an RDP session into your Windows Server target instance (
20.121.185.86) using administrative credentials (azureadmin). - Open the Start menu, type PowerShell, right-click it, and select Run as Administrator.
- Run this complete command block to download and execute the official remoting script wrapper:
# Define the remote setup script endpoint target
$url = "https://raw.githubusercontent.com/ansible/ansible-documentation/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
# Download the configuration framework asset
Invoke-WebRequest -Uri $url -OutFile ConfigureRemotingForAnsible.ps1
# Run the remoting setup utility to generate SSL paths and alter firewall rules
.\ConfigureRemotingForAnsible.ps1
- Verify that the terminal window outputs active metrics showing that the HTTPS listener is explicitly open and configured on port
5986.
5. Automation Execution Steps
Log back into your Ansible Control Node via SSH, access the lab directory, and execute the configuration steps:
# Move into the working workspace directory
cd ~/ansible-lab
# Install the Python WinRM wrapper module to communicate with the Windows target
python3 -m pip install pywinrm
# Fire off the unified multi-platform orchestration script execution loop
ansible-playbook -i hosts.ini site.yml
6. Post-Deployment Troubleshooting & Verification
If the terminal recap shows failed=0 but your web browser displays connection errors, run these targeted commands on the control node to isolate the root cause:
Validating Docker Port Mapping Engine
Confirm that the running container has explicitly mapped external port 80 to internal port 80:
ansible docker_nodes -i hosts.ini -m shell -a "sudo docker ps"
Expected Output: The PORTS column output string must read exactly 0.0.0.0:80->80/tcp.
Direct Network Layer Loop Verification
Bypass browser proxy rules and caching issues by sending a direct HTTP header query to the internal network target interface:
curl -I http://10.0.1.5
Expected Return Payload:
HTTP/1.1 200 OK
Server: nginx/1.31.3
Content-Type: text/html
Content-Length: 766
Connection: keep-alive
Browser Access Notes
Modern web browsers often automatically force URL extensions from standard HTTP to encrypted HTTPS paths (https://20.124.121.94). Because these nodes are explicitly listening on port 80, an automatic HTTPS redirect will trigger an immediate Connection Timed Out error.
To view the live running dashboards externally, you must load the addresses inside a clean Incognito/Private Browser Window and type out the complete http:// prefix explicitly:
-
Linux App Dashboard:
http://20.124.121.94 -
Windows IIS Server Web:
http://20.121.185.86

Top comments (0)