DEV Community

Droid Ek
Droid Ek

Posted on

Azure Multi-Platform Infrastructure Cluster Automation & Deployment Guide


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
  • 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

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Launch an RDP session into your Windows Server target instance (20.121.185.86) using administrative credentials (azureadmin).
  2. Open the Start menu, type PowerShell, right-click it, and select Run as Administrator.
  3. 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
Enter fullscreen mode Exit fullscreen mode
  1. 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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Expected Return Payload:

HTTP/1.1 200 OK
Server: nginx/1.31.3
Content-Type: text/html
Content-Length: 766
Connection: keep-alive
Enter fullscreen mode Exit fullscreen mode

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)