Azure-Infrastruktur mit Polycrate: VMs, Resource Groups und Networking automatisiert
Fabian Peter 12 Minuten Lesezeit

Azure-Infrastruktur mit Polycrate: VMs, Resource Groups und Networking automatisiert

Azure-Infrastruktur automatisieren: VMs, Resource Groups und Networking mit Polycrate und Ansible

TL;DR

  • In diesem Beitrag bauen wir einen Polycrate-Workspace, der On-Premise-Server und Azure-VMs in einem gemeinsamen Inventory verwaltet – inklusive Resource Groups, VNet/Subnet und virtuellen Maschinen (Linux & Windows).
  • Azure-Ressourcen (Resource Group, VNet, VMs) werden über Ansible-Module aus azure.azcollection automatisiert bereitgestellt – sauber gekapselt in Polycrate-Blöcken, ohne lokale Python- oder Ansible-Installation.
  • Ein dynamisches Inventory-Playbook schreibt neu provisionierte Azure-VMs automatisch in die zentrale inventory.yml, sodass Sie direkt danach via polycrate ssh (Linux) bzw. WinRM (Windows) weiterkonfigurieren können.
  • Zusätzliche Blöcke kümmern sich um Backups/Artifacts in Azure Blob Storage und Kostenkontrolle über Stop/Start-Patterns für nicht-produktive VMs.
  • ayedo unterstützt Sie mit erprobten Polycrate-Workspaces und Azure-Bausteinen – von der ersten Demo bis hin zu unternehmensweiter Hybrid-Automatisierung.

Azure als Hybrid-Ziel für Polycrate

Viele Teams stehen irgendwo zwischen klassischem Rechenzentrum und Cloud: ein paar hundert Linux-Server On-Premise, ein Active Directory auf Windows Server, dazu einige Workloads in Azure. Genau hier spielt Polycrate seine Stärken aus:

  • Ein Workspace verwaltet On-Premise-Server und Azure-VMs gemeinsam.
  • Ansible läuft stets im Container – keine Konflikte mit lokalem Python, keine unterschiedlichen Versionen im Team.
  • Blöcke bringen Struktur in Ihre Automatisierung; jede Azure-Funktionalität (Netzwerk, VMs, Kosten, Backups) lebt in einem eigenen Block.

Die Azure-Anbindung nutzt die Ansible-Integration von Polycrate. Die Azure-Module (azure.azcollection) laufen innerhalb des Polycrate-Containers und sprechen die Azure-APIs direkt an (hosts: localhost, connection: local ist hier korrekt – es wird keine VM per SSH/WinRM angesprochen, sondern nur das Azure Control Plane).

Ein zentrales Ziel dieses Beitrags: Das dynamische Inventory. Neu erstellte Azure-VMs landen automatisch in inventory.yml im Workspace-Root – gemeinsam mit Ihren On-Premise-Hosts. Damit können Sie im nächsten Schritt direkt mit denselben Ansible-Rollen weiterarbeiten, die Sie heute bereits On-Premise nutzen.


Workspace-Struktur: On-Premise + Azure im gleichen Setup

Zunächst definieren wir einen minimalen Workspace mit On-Premise-Hosts und Azure-Blöcken.

# workspace.poly
name: acme-corp-automation
organization: acme

blocks:
  - name: azure-infra
    from: registry.acme-corp.com/acme/infra/azure-infra:0.1.0
    config:
      subscription_id: "00000000-0000-0000-0000-000000000000"
      location: "westeurope"
      resource_group: "rg-acme-hybrid"
      vnet_name: "vnet-acme-hybrid"
      address_prefix: "10.50.0.0/16"

  - name: azure-vms
    from: registry.acme-corp.com/acme/infra/azure-vms:0.1.0
    config:
      subscription_id: "00000000-0000-0000-0000-000000000000"
      location: "westeurope"
      resource_group: "rg-acme-hybrid"
      vnet_name: "vnet-acme-hybrid"
      subnet_name: "default"
      admin_username: "acmeadmin"

  - name: azure-cost-control
    from: registry.acme-corp.com/acme/infra/azure-cost-control:0.1.0
    config:
      subscription_id: "00000000-0000-0000-0000-000000000000"
      resource_group: "rg-acme-hybrid"
      tag_filter: "env=dev"

  - name: azure-backup
    from: registry.acme-corp.com/acme/infra/azure-backup:0.1.0
    config:
      subscription_id: "00000000-0000-0000-0000-000000000000"
      resource_group: "rg-acme-backup"
      storage_account: "acmehybridbackup"

Die Blöcke liegen nicht als lose blocks/<name>-Verzeichnisse im Workspace, sondern werden per from: aus einer OCI-Registry bezogen (registry.acme-corp.com/... ist ein fiktives Beispiel; in der Praxis nutzen Sie z. B. polycrate blocks pull … oder Ihre eigene Registry). from: enthält die vollständige Referenz inklusive Versions-Tag. In workspace.poly und block.poly gibt es kein Jinja2 – Pfade zu Dateien unter artifacts/secrets/ tragen Sie als literale Strings in der Block-config ein; das lokale Admin-Passwort für Azure-Windows-VMs gehört wie im Hybrid-Artikel in secrets.poly (Merge in block.config). Details: Konfiguration.

secrets.poly (Auszug, wird mit workspace.poly gemerged):

blocks:
  - name: azure-vms
    config:
      win_admin_password: "…"

Unser gemeinsames Inventory liegt im Workspace-Root als inventory.yml. Wie im Multi-Server-Artikel und im Hybrid-Artikel stehen alle Hosts einmal unter all.hosts; unter children ordnen wir sie den Gruppen onprem_linux, onprem_windows, azure_linux und azure_windows zu – damit nutzen Ansible und polycrate ssh dieselbe kanonische Hostliste. Zunächst tragen wir nur On-Premise-Server ein; die Azure-Gruppen bleiben leer, bis die Inventory-Action läuft:

# inventory.yml (Workspace-Root)
all:
  vars:
    ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
    ansible_python_interpreter: /usr/bin/python3

  hosts:
    server01.acme-corp.com:
      ansible_user: ubuntu
    dc01.acme-corp.com: {}

  children:
    onprem_linux:
      hosts:
        server01.acme-corp.com:
    onprem_windows:
      hosts:
        dc01.acme-corp.com:
      vars:
        ansible_connection: winrm
        ansible_winrm_transport: ntlm
        ansible_winrm_server_cert_validation: ignore
    azure_linux:
      hosts: {}
    azure_windows:
      hosts: {}
      vars:
        ansible_connection: winrm
        ansible_winrm_transport: ntlm
        ansible_winrm_server_cert_validation: ignore

Polycrate setzt ANSIBLE_INVENTORY automatisch auf dieses File. Weitere Details finden sich in den Best Practices.


Azure-Basis: Resource Group und Netzwerk als Block

Block-Definition für Azure-Infrastruktur

Der erste Block kümmert sich um Resource Group und Virtual Network.

# blocks/registry.acme-corp.com/acme/infra/azure-infra/block.poly
# name = from: ohne Tag (vollständiger Registry-Pfad)
name: registry.acme-corp.com/acme/infra/azure-infra
version: 0.1.0
kind: generic

config:
  azure_credentials_path: "artifacts/secrets/azure-credentials.json"
  subscription_id: ""
  location: "westeurope"
  resource_group: "rg-acme-hybrid"
  vnet_name: "vnet-acme-hybrid"
  address_prefix: "10.50.0.0/16"
  subnet_name: "default"
  subnet_prefix: "10.50.1.0/24"

actions:
  - name: provision
    driver: ansible
    playbook: provision.yml

Die Azure-Anmeldeinformationen (z. B. ein Service Principal im JSON-Format) liegen verschlüsselt im Workspace unter artifacts/secrets/azure-credentials.json. Die Verschlüsselung erfolgt mit age direkt in Polycrate – Details dazu unter Workspace-Verschlüsselung.

Ansible-Playbook für Resource Group und VNet

# …/azure-infra/provision.yml
- name: Azure Resource Group und Netzwerk provisionieren
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    azure_credentials_path: "{{ block.config.azure_credentials_path }}"
    subscription_id: "{{ block.config.subscription_id }}"
    location: "{{ block.config.location }}"
    resource_group: "{{ block.config.resource_group }}"
    vnet_name: "{{ block.config.vnet_name }}"
    address_prefix: "{{ block.config.address_prefix }}"
    subnet_name: "{{ block.config.subnet_name }}"
    subnet_prefix: "{{ block.config.subnet_prefix }}"

  pre_tasks:
    - name: Azure Anmeldeinformationen laden
      set_fact:
        azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"

  tasks:
    - name: Resource Group erstellen
      azure.azcollection.azure_rm_resourcegroup:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        name: "{{ resource_group }}"
        location: "{{ location }}"

    - name: Virtual Network erstellen
      azure.azcollection.azure_rm_virtualnetwork:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ vnet_name }}"
        address_prefixes:
          - "{{ address_prefix }}"

    - name: Subnet anlegen
      azure.azcollection.azure_rm_subnet:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ subnet_name }}"
        address_prefix: "{{ subnet_prefix }}"
        virtual_network_name: "{{ vnet_name }}"

Ausführung:

polycrate run azure-infra provision

Mit plain Ansible müssten Sie hier zuerst lokal die azure.azcollection installieren, Python-Versionen abstimmen und ansible.cfg passend konfigurieren. Mit Polycrate läuft dieses Playbook reproduzierbar im Container – inklusive der passenden Azure-Module.


Virtuelle Maschinen provisionieren: Linux und Windows

Block für Azure-VMs

# blocks/registry.acme-corp.com/acme/infra/azure-vms/block.poly
name: registry.acme-corp.com/acme/infra/azure-vms
version: 0.1.0
kind: generic

config:
  azure_credentials_path: "artifacts/secrets/azure-credentials.json"
  subscription_id: ""
  location: "westeurope"
  resource_group: "rg-acme-hybrid"
  vnet_name: "vnet-acme-hybrid"
  subnet_name: "default"
  admin_username: "acmeadmin"
  ssh_public_key_path: "artifacts/secrets/azure-ssh.pub"

actions:
  - name: provision
    driver: ansible
    playbook: provision.yml
  - name: inventory
    driver: ansible
    playbook: inventory.yml

Das Windows-Admin-Passwort für die VM-Erstellung kommt aus secrets.poly (siehe oben) und steht im Playbook nach dem Merge als block.config.win_admin_password zur Verfügung.

Playbook: VMs erstellen

# …/azure-vms/provision.yml
- name: Azure Linux- und Windows-VMs bereitstellen
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    azure_credentials_path: "{{ block.config.azure_credentials_path }}"
    subscription_id: "{{ block.config.subscription_id }}"
    location: "{{ block.config.location }}"
    resource_group: "{{ block.config.resource_group }}"
    vnet_name: "{{ block.config.vnet_name }}"
    subnet_name: "{{ block.config.subnet_name }}"
    admin_username: "{{ block.config.admin_username }}"
    ssh_public_key: "{{ lookup('file', block.config.ssh_public_key_path) }}"
    win_admin_password: "{{ block.config.win_admin_password }}"

    linux_vms:
      - name: "vm-ubuntu-01"
        size: "Standard_B2s"

    windows_vms:
      - name: "vm-win-01"
        size: "Standard_B2s"

  pre_tasks:
    - name: Azure Anmeldeinformationen laden
      set_fact:
        azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"

  tasks:
    - name: Linux-VMs erstellen
      azure.azcollection.azure_rm_virtualmachine:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ item.name }}"
        vm_size: "{{ item.size }}"
        admin_username: "{{ admin_username }}"
        ssh_password_enabled: false
        ssh_public_keys:
          - path: "/home/{{ admin_username }}/.ssh/authorized_keys"
            key_data: "{{ ssh_public_key }}"
        image:
          offer: "0001-com-ubuntu-server-jammy"
          publisher: "Canonical"
          sku: "22_04-lts"
          version: "latest"
        os_type: "Linux"
        state: present
        started: true
        network_interfaces:
          - name: "{{ item.name }}-nic"
            virtual_network: "{{ vnet_name }}"
            subnet: "{{ subnet_name }}"
            public_ip_allocation_method: "Dynamic"
      loop: "{{ linux_vms }}"

    - name: Windows-VMs erstellen
      azure.azcollection.azure_rm_virtualmachine:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ item.name }}"
        vm_size: "{{ item.size }}"
        admin_username: "azureadmin"
        admin_password: "{{ win_admin_password }}"
        image:
          offer: "WindowsServer"
          publisher: "MicrosoftWindowsServer"
          sku: "2022-Datacenter"
          version: "latest"
        os_type: "Windows"
        state: present
        started: true
        network_interfaces:
          - name: "{{ item.name }}-nic"
            virtual_network: "{{ vnet_name }}"
            subnet: "{{ subnet_name }}"
            public_ip_allocation_method: "Dynamic"
      loop: "{{ windows_vms }}"

Ausführung:

polycrate run azure-vms provision

Alle Module stammen aus azure.azcollection. Polycrate bringt die passende Toolchain im Container mit – Sie müssen weder pip install noch ansible-galaxy collection install auf Ihrem Laptop pflegen.


Dynamisches Inventory aus Azure

Jetzt kommt der spannende Teil: Wir wollen, dass die frisch erstellten VMs automatisch in der inventory.yml landen – in den Gruppen azure_linux und azure_windows.

Inventory-Update als Action

# …/azure-vms/inventory.yml
- name: Azure-VMs ins Inventory schreiben
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    azure_credentials_path: "{{ block.config.azure_credentials_path }}"
    subscription_id: "{{ block.config.subscription_id }}"
    resource_group: "{{ block.config.resource_group }}"

  pre_tasks:
    - name: Azure Anmeldeinformationen laden
      set_fact:
        azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"

  tasks:
    - name: Informationen zu VMs abrufen
      azure.azcollection.azure_rm_virtualmachine_info:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
      register: vm_info

    - name: Hostliste für Inventory aufbereiten
      set_fact:
        linux_hosts: "{{ vm_info.virtual_machines | selectattr('os_type', 'equalto', 'Linux') | list }}"
        windows_hosts: "{{ vm_info.virtual_machines | selectattr('os_type', 'equalto', 'Windows') | list }}"

    - name: Neues Inventory generieren
      template:
        src: inventory.j2
        dest: "{{ workspace.path }}/inventory.yml"

Als dest nutzen Sie {{ workspace.path }}/inventory.yml: workspace.path ist in Polycrate-Ansible der Workspace-Root – stabiler als relative Pfade wie ../../inventory.yml, die von der Verzeichnistiefe des Blocks abhängen.

Dazu das Template im gleichen Block-Verzeichnis:

# …/azure-vms/inventory.j2
all:
  vars:
    ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
    ansible_python_interpreter: /usr/bin/python3

  hosts:
    server01.acme-corp.com:
      ansible_user: ubuntu
    dc01.acme-corp.com: {}
{% for vm in linux_hosts %}
    {{ vm.name }}:
      ansible_host: {{ vm.public_ip_address }}
      ansible_user: {{ block.config.admin_username }}
{% endfor %}
{% for vm in windows_hosts %}
    {{ vm.name }}:
      ansible_host: {{ vm.public_ip_address }}
      ansible_user: azureadmin
{% endfor %}

  children:
    onprem_linux:
      hosts:
        server01.acme-corp.com:
    onprem_windows:
      hosts:
        dc01.acme-corp.com:
      vars:
        ansible_connection: winrm
        ansible_winrm_transport: ntlm
        ansible_winrm_server_cert_validation: ignore
    azure_linux:
      hosts:
{% for vm in linux_hosts %}
        {{ vm.name }}:
{% endfor %}
    azure_windows:
      hosts:
{% for vm in windows_hosts %}
        {{ vm.name }}:
{% endfor %}
      vars:
        ansible_connection: winrm
        ansible_winrm_transport: ntlm
        ansible_winrm_server_cert_validation: ignore

Für SSH zu den Azure-Linux-VMs stellt Polycrate im Action-Container u. a. ANSIBLE_PRIVATE_KEY_FILE bereit – Sie tragen kein ansible_ssh_private_key_file ins Inventory. WinRM-Passwörter für Azure-Windows-Hosts gehören nicht in die YAML-Datei, sondern in secrets.poly / block.config und werden in den Playbooks verwendet (siehe Hybrid-Artikel).

Ausführung:

polycrate run azure-vms inventory

Nach dieser Action kennt Ihr Inventory sowohl On-Premise-Hosts als auch Azure-VMs. Der große Vorteil gegenüber einem klassischen dynamischen Ansible-Inventory: Das Ergebnis liegt als YAML-Datei im Workspace, versionierbar in Git und kompatibel mit allen Tools, die inventory.yml lesen.

Direkt danach: Polycrate SSH und WinRM

Für Linux-VMs:

polycrate ssh vm-ubuntu-01

Für Windows-Server nutzen Sie reguläre Ansible-Playbooks mit WinRM, z. B. mit einem Block aus der Registry:

# workspace.poly (Auszug)
blocks:
  - name: windows-hardening
    from: registry.acme-corp.com/acme/infra/windows-hardening:0.1.0
    config: {}
polycrate run windows-hardening cis-baseline --limit vm-win-01

Weitere Details zur SSH-Integration finden Sie unter SSH mit Polycrate.


Backups und Artifacts in Azure Blob Storage

Viele Backuplösungen behandeln Azure Blob Storage als S3-ähnliches Ziel, auch wenn es technisch eine eigene API ist. Mit Ansible nutzen wir die nativen Azure-Module.

Block für Blob Storage

# blocks/registry.acme-corp.com/acme/infra/azure-backup/block.poly
name: registry.acme-corp.com/acme/infra/azure-backup
version: 0.1.0
kind: generic

config:
  azure_credentials_path: "artifacts/secrets/azure-credentials.json"
  subscription_id: ""
  resource_group: "rg-acme-backup"
  storage_account: "acmehybridbackup"
  container_name: "artifacts"

actions:
  - name: prepare
    driver: ansible
    playbook: prepare.yml
  - name: upload-artifact
    driver: ansible
    playbook: upload.yml

prepare.yml sorgt für Storage Account und Container:

# …/azure-backup/prepare.yml
- name: Azure Blob Storage vorbereiten
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    azure_credentials_path: "{{ block.config.azure_credentials_path }}"
    subscription_id: "{{ block.config.subscription_id }}"
    resource_group: "{{ block.config.resource_group }}"
    storage_account: "{{ block.config.storage_account }}"
    container_name: "{{ block.config.container_name }}"

  pre_tasks:
    - name: Azure Anmeldeinformationen laden
      set_fact:
        azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"

  tasks:
    - name: Resource Group für Backups sicherstellen
      azure.azcollection.azure_rm_resourcegroup:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        name: "{{ resource_group }}"
        location: "westeurope"

    - name: Storage Account anlegen
      azure.azcollection.azure_rm_storageaccount:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ storage_account }}"
        kind: "StorageV2"
        sku: "Standard_LRS"

    - name: Blob-Container anlegen
      azure.azcollection.azure_rm_storageblob:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        storage_account_name: "{{ storage_account }}"
        container: "{{ container_name }}"
        state: present

Ein einfaches Upload-Playbook könnte lokale Artefakte aus artifacts/ in den Container schieben. Sobald der Storage bereitsteht, können externe Tools, die S3-kompatible Endpoints sprechen, via Gateway oder Backup-Software darauf zugreifen.


Kosten im Griff: VMs stoppen und starten

Für kleinere Teams ist Kostenkontrolle oft ein zentraler Grund, Azure nur vorsichtig zu nutzen. Ein einfaches, praxistaugliches Pattern: Nicht-produktive VMs automatisch abends stoppen und morgens wieder starten.

Block für Kostenkontrolle

# blocks/registry.acme-corp.com/acme/infra/azure-cost-control/block.poly
name: registry.acme-corp.com/acme/infra/azure-cost-control
version: 0.1.0
kind: generic

config:
  azure_credentials_path: "artifacts/secrets/azure-credentials.json"
  subscription_id: ""
  resource_group: "rg-acme-hybrid"
  tag_filter: "env=dev"

actions:
  - name: stop
    driver: ansible
    playbook: stop.yml
  - name: start
    driver: ansible
    playbook: start.yml

stop.yml kann alle VMs mit einem bestimmten Tag herunterfahren:

# …/azure-cost-control/stop.yml
- name: Dev-VMs stoppen
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    azure_credentials_path: "{{ block.config.azure_credentials_path }}"
    subscription_id: "{{ block.config.subscription_id }}"
    resource_group: "{{ block.config.resource_group }}"
    tag_filter: "{{ block.config.tag_filter }}"

  pre_tasks:
    - name: Azure Anmeldeinformationen laden
      set_fact:
        azure_credentials: "{{ lookup('file', azure_credentials_path) | from_json }}"

  tasks:
    - name: Ziel-VMs ermitteln
      azure.azcollection.azure_rm_virtualmachine_info:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
      register: vm_info

    - name: VM-Liste nach Tag filtern
      set_fact:
        target_vms: >-
          {{ vm_info.virtual_machines
             | selectattr('tags', 'defined')
             | selectattr('tags.env', 'equalto', 'dev')
             | list }}

    - name: Dev-VMs stoppen
      azure.azcollection.azure_rm_virtualmachine:
        subscription_id: "{{ subscription_id }}"
        tenant: "{{ azure_credentials.tenant }}"
        client_id: "{{ azure_credentials.client_id }}"
        secret: "{{ azure_credentials.client_secret }}"
        resource_group: "{{ resource_group }}"
        name: "{{ item.name }}"
        state: present
        started: false
      loop: "{{ target_vms }}"

start.yml ist analog, setzt started: true.

Ein Cronjob oder ein kleiner CI-Job kann dann einfach:

polycrate run azure-cost-control stop

um 20:00 Uhr und

polycrate run azure-cost-control start

um 07:00 Uhr ausführen. Polycrate sorgt dafür, dass dieselbe Automatisierung überall gleich läuft – ob auf einem Admin-Laptop, einem Build-Agent oder einem zentralen Automatisierungsserver.


Häufige Fragen

Wie unterscheidet sich das von klassischem Ansible mit Azure?

Mit plain Ansible müssten Sie:

  • lokal Python und azure.azcollection installieren,
  • ansible.cfg und Credential-Handling pro Entwicklerarbeitsplatz pflegen,
  • das dynamische Inventory mit Azure-Plugins konfigurieren und separat betreiben.

Mit Polycrate bekommen Sie:

  • eine containerisierte Toolchain (Ansible, Python, Azure-Module) pro Workspace,
  • strukturierte Blöcke, die klar trennen, wofür ein Playbook zuständig ist,
  • ein zentrales, YAML-basiertes Inventory, das von Actions gepflegt wird.

Das reduziert Reibungsverluste im Team und vereinfacht auch Compliance, weil Sie genau sehen, welche Blöcke welche Aktionen ausführen.

Wie sicher ist das Speichern von Azure-Credentials und SSH-Keys im Workspace?

Sensible Dateien (z. B. azure-credentials.json, SSH-Keys, Passwörter) liegen im Verzeichnis artifacts/secrets/ und werden mit age verschlüsselt. Polycrate bringt die entsprechende Verschlüsselungslogik mit, sodass Sie keinen separaten Secret Store aufbauen müssen. Details finden Sie unter Workspace-Verschlüsselung.

In vielen Teams ersetzt das in frühen Phasen einen externen Vault und ist deutlich einfacher zu handhaben – gerade, wenn nur wenige Personen Zugriff auf den Workspace haben und trotzdem ein Audit-Trail über Git gewünscht ist.

Kann ich diese Blöcke mit anderen Teams teilen?

Ja. Blöcke wie azure-infra, azure-vms oder azure-cost-control können versioniert und als OCI-Image in einer Registry veröffentlicht werden. Über PolyHub (siehe PolyHub-Dokumentation) lassen sich solche Bausteine teamübergreifend oder sogar öffentlich teilen.

In der Praxis heißt das: Ein Team baut saubere Azure-Blöcke, andere Teams binden sie einfach per from: cargo.ayedo.cloud/...:0.1.0 in ihren Workspace ein – inklusive konsistenter Versionierung und klar definierten config-Parametern.

Weitere Fragen? Siehe unsere FAQ


Der nächste Schritt

Mit dem gezeigten Setup haben Sie:

  • einen Polycrate-Workspace, der On-Premise- und Azure-Hosts im gleichen inventory.yml verwaltet,
  • Azure-Basisressourcen (Resource Group, VNet/Subnet) in einem wiederverwendbaren Block gekapselt,
  • Linux- und Windows-VMs automatisiert mit azure.azcollection.azure_rm_virtualmachine provisioniert,
  • ein dynamisches Inventory, das neue VMs sofort für weitere Ansible-Rollen verfügbar macht,
  • zusätzliche Blöcke für Backups in Azure Blob Storage und eine einfache, aber wirkungsvolle Kostenkontrolle über Stop/Start-Actions.

Sie haben damit den typischen Wildwuchs an losen Ansible-Playbooks hinter sich gelassen und eine strukturierte, wiederverwendbare Automatisierung aufgebaut – ohne lokale Abhängigkeiten, mit verschlüsselten Secrets und klaren Guardrails durch das Block-Modell. Genau diese Kombination macht Polycrate zu einem starken Hybrid-Framework: On-Premise-Server, Azure-VMs, Container-Workloads – alles im selben Arbeitsmodell.

Wenn Sie diesen Ansatz für Ihre eigene Umgebung evaluieren möchten, unterstützen wir Sie bei ayedo mit:

  • vorbereiteten Azure-Blocks (nach Best Practices modelliert, siehe Best Practices),
  • gemeinsamen Sessions, in denen wir Ihre bestehende Ansible-Landschaft in einen Polycrate-Workspace überführen,
  • einer individuell abgestimmten Demo zu Ihren Anforderungen an On-Premise und Azure.

Vertiefung zu Inventories und Hybrid-Setups: Multi-Server-Management und Hybrid-Automatisierung. Für Formate mit ayedo: Workshops.

Polycrate fasst On-Premise und Azure in einem Workspace zusammen – ein gemeinsames Arbeitsmodell für hybride Teams.

Ähnliche Artikel