Automatische Updates und Backups als Polycrate-Workflows
Fabian Peter 12 Minuten Lesezeit

Automatische Updates und Backups als Polycrate-Workflows

Automatische Updates und Backups als reproduzierbare Polycrate-Workflows

TL;DR

  • Du baust einen wiederverwendbaren Polycrate-Workflow, der auf deinen Linux-Servern automatisch backup → update → verify ausführt – inklusive Rollback über Ansible block/rescue.
  • Backups laufen als pg_dump + tar + Upload nach S3 mit rclone (S3-kompatibles Object Storage), Updates via apt upgrade plus Service-Restart und Health-Checks, Verifikation über Systemd-Status und HTTP-Response.
  • Polycrate-Workflows geben deinen Ansible-Actions einen Namen, eine Reihenfolge und eine Dokumentation – statt lose verteilte Playbooks und README-Dateien.
  • Alles läuft im Container: Kein lokales Python-/Ansible-Chaos, konsistente Toolchain auf jeder Admin-Workstation, Workspaces sind bei Bedarf komplett verschlüsselt.
  • ayedo unterstützt Teams dabei, solche Betriebsprozesse als Code zu etablieren – von der ersten Block-Struktur bis zu unternehmensweiten, geteilten Workflows und Operations-Automatisierung Demos.

Polycrate-Workflows: Betriebsprozesse statt CI/CD-Pipelines

Wenn du „Workflow“ hörst, denkst du vielleicht an GitHub Actions oder GitLab CI. Polycrate-Workflows sind etwas anderes:

  • Sie laufen dort, wo du Ansible einsetzt – auf deiner Admin-Workstation, einem Bastion-Host oder in einem Automation-Container.
  • Sie orchestrieren Polycrate-Actions (z.B. backup, update, verify) zu einem benannten Prozess.
  • Sie sind Teil deines Polycrate-Workspaces und damit versionierbar, verschlüsselbar und teilbar.

Ein Workflow in Polycrate ist ein Stück deklarative Orchestrierung: „Führe erst diese Action in diesem Block aus, dann jene Action in einem anderen Block, …“. Kein CI/CD-Server nötig, keine YAML-Speziallogik – nur dein Workspace und die Polycrate-CLI.

Dokumentation passiert damit im Code: Der Workflow ist die Dokumentation des Betriebsprozesses. Kein zusätzliches Word-Dokument, das nicht zur Realität passt.

Mehr Details zum Konzept findest du in der Dokumentation zu Workflows und Workspaces.


Szenario: Nächtliche Linux-Maintenance mit Backup und Rollback

Ausgangssituation – sehr typisch für Linux-/System-Admins:

  • PostgreSQL-Datenbank auf Ubuntu 24.04
  • Webapplikation als Systemd-Service (acme-app.service)
  • Backups sollen nach S3 (S3-kompatibles Object Storage)
  • Updates sollen automatisiert laufen, aber mit Safety-Net
  • Am Ende brauchst du die Sicherheit: Service läuft, HTTP-Endpoint antwortet

Der Prozess, den wir als Polycrate-Workflow abbilden:

  1. backup
    Datenbank-Dump mit pg_dump, Tarball erzeugen, mit rclone nach S3 hochladen und einen latest.tar.gz-Symlink pflegen.

  2. update
    apt update && apt upgrade -y, Service neu starten, Health-Check – alles in einem Ansible-Play mit block / rescue:

    • Im block laufen Updates und Checks.
    • Im rescue wird bei Fehlern automatisch aus latest.tar.gz wiederhergestellt.
  3. verify
    Explizite Verifikation, dass Systemd-Service läuft und ein HTTP-Endpoint mit Status 200 antwortet.

Das Ganze orchestrieren wir als Workflow nightly-maintenance, den du z.B. über einen systemd-Timer jede Nacht ausführen lässt.


Workspace-Grundlage: Blocks, Workflows, Inventory

Wir starten mit einem Polycrate-Workspace acme-corp-automation. Die Struktur:

  • workspace.poly – zentrale Definition von Blocks und Workflows
  • inventory.yml – Ansible-Inventory (YAML, nicht INI!)
  • blocks/registry.acme-corp.com/acme/infra/linux-maintenance/ – Block mit Actions und Playbooks, sobald er lokal vorliegt (beim ersten polycrate run … oder Workflow-Lauf kann Polycrate einen fehlenden Block automatisch installieren; polycrate blocks pull bleibt optional)
  • artifacts/secrets/ – z.B. Ausschnitte für rclone (Zugangsdaten zum Object Storage), bei Bedarf verschlüsselt

workspace.poly mit Workflow-Definition

name: acme-corp-automation
organization: acme

blocks:
  - name: linux-maintenance
    from: registry.acme-corp.com/acme/infra/linux-maintenance:0.1.0
    config:
      db_name: "acme_app"
      db_user: "acme"
      db_host: "localhost"
      backup_dir: "/var/backups/acme-db"
      rclone_destination: "acme-s3:acme-backups-db/postgres"
      hosts: "db_servers"
      web_hosts: "web_servers"
      service_name: "acme-app.service"
      health_url: "http://localhost:8080/health"

workflows:
  - name: nightly-maintenance
    description: "Nightly backup → update → verify for Linux application servers"
    steps:
      - name: backup
        block: linux-maintenance
        action: backup
      - name: update
        block: linux-maintenance
        action: update
      - name: verify
        block: linux-maintenance
        action: verify

Wichtig:

  • Der Block liegt in der fiktiven Firmen-Registry unter registry.acme-corp.com (kein Bezug zu ayedos Produkt-Registry); in from: steht die vollständige Referenz inkl. Tag (0.1.0 entspricht der Block-Version). Ein vorheriges polycrate blocks pull ist nicht nötig: Fehlt der Block lokal, erkennt Polycrate das beim Aufruf von polycrate run … oder eines Workflows und fragt, ob der Block automatisch installiert werden soll.
  • Alle spezifischen Parameter liegen in config. Sie stehen in den Actions über block.config.* zur Verfügung.
  • Der Workflow nightly-maintenance referenziert nur Block- und Action-Namen – keine Pfade, keine Shell-Skripte.

Mehr zu Best Practices bei Blocks und Workflows: Polycrate Best Practices.

Inventory als YAML

Polycrate setzt automatisch ANSIBLE_INVENTORY auf inventory.yml im Workspace-Root. Alle Hosts stehen unter all.hosts; unter children verweisen die Gruppen nur noch per Hostnamen darauf (kanonisches Format wie im Beitrag Multi-Server-Inventories mit Ansible):

all:
  vars:
    ansible_user: "ubuntu"
    ansible_ssh_port: 22
    ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
    ansible_python_interpreter: /usr/bin/python3

  hosts:
    db01.acme-corp.com: {}
    app01.acme-corp.com: {}

  children:
    db_servers:
      hosts:
        db01.acme-corp.com:
    web_servers:
      hosts:
        app01.acme-corp.com:

Welche Gruppe oder welcher Host pro Action läuft, steuern Sie über Block-config (hosts / web_hosts) und im Playbook hosts: "{{ block.config.… }}" – nicht über fest eingetragene Gruppennamen allein. Kein localhost für SSH-basierte Administration: Polycrate führt Ansible im Container aus, die Zielhosts sind die Einträge im Inventory. Details: Ansible-Integration.


Der Maintenance-Block: Struktur und Actions

Die folgenden Listings zeigen den Block wie bei der Entwicklung unter dem vollständigen Registry-Pfad blocks/registry.acme-corp.com/acme/infra/linux-maintenance/ – so wie Sie einen OCI-Block mit echter from:-Referenz versionieren und veröffentlichen, nicht als kurzer „Demo-Ordnername“. In anderen Workspaces referenzieren Sie ihn über from: registry.acme-corp.com/acme/infra/linux-maintenance:0.1.0. Fehlt der Block lokal, bietet Polycrate beim ersten polycrate run … oder Workflow-Lauf die automatische Installation an; optional bleibt polycrate blocks pull. Die block.poly:

name: linux-maintenance
version: 0.1.0
kind: generic

config:
  db_name: "acme_app"
  db_user: "acme"
  db_host: "localhost"
  backup_dir: "/var/backups/acme-db"
  rclone_destination: "acme-s3:acme-backups-db/postgres"
  hosts: "db_servers"
  web_hosts: "web_servers"
  service_name: "acme-app.service"
  health_url: "http://localhost:8080/health"

actions:
  - name: backup
    type: ansible
    playbook: backup.yml

  - name: update
    type: ansible
    playbook: update.yml

  - name: verify
    type: ansible
    playbook: verify.yml

Hinweis: block.poly ist reines YAML – kein Jinja-Templating. Defaults stehen hier; Abweichungen tragen Sie in workspace.poly unter config ein (Merge). Ausdrücke wie {{ block.config.* }} und Ansible-Logik gehören nur in Playbooks, Tasks und Templates.

Hier siehst du typische Polycrate-Stärken:

  • Guardrails durch das Block-Modell: Eine klare Struktur statt Playbook-Wildwuchs.
  • Gute DX: Actions heißen einfach backup, update, verify – die CLI-Befehle sind lesbar und copy-paste-bar.

Run-Befehle für einzelne Actions:

polycrate run linux-maintenance backup
polycrate run linux-maintenance update
polycrate run linux-maintenance verify

Workflow:

polycrate workflows run nightly-maintenance

Backup-Action: pg_dump, tar, rclone → S3

Die Datei blocks/registry.acme-corp.com/acme/infra/linux-maintenance/backup.yml (vereinfachtes Beispiel – Ziel-Hosts über block.config.hosts wie oben):

- name: Backup PostgreSQL database
  hosts: "{{ block.config.hosts }}"
  become: true
  gather_facts: false

  vars:
    backup_dir: "{{ block.config.backup_dir }}"
    db_name: "{{ block.config.db_name }}"
    db_user: "{{ block.config.db_user }}"
    db_host: "{{ block.config.db_host }}"
    rclone_destination: "{{ block.config.rclone_destination }}"
    timestamp: "{{ lookup('ansible.builtin.pipe', 'date +%Y%m%d-%H%M%S') }}"
    backup_file: "{{ backup_dir }}/{{ db_name }}-{{ timestamp }}.sql"
    backup_tar: "{{ backup_dir }}/{{ db_name }}-{{ timestamp }}.tar.gz"
    latest_symlink: "{{ backup_dir }}/latest.tar.gz"

  tasks:
    - name: Ensure backup directory exists
      ansible.builtin.file:
        path: "{{ backup_dir }}"
        state: directory
        owner: postgres
        group: postgres
        mode: "0750"

    - name: Dump PostgreSQL database
      ansible.builtin.command:
        cmd: >
          pg_dump -h {{ db_host }} -U {{ db_user }} -F p -f {{ backup_file }} {{ db_name }}
      environment:
        PGPASSWORD: "{{ hostvars[inventory_hostname].pg_password | default('') }}"
      become_user: postgres

    - name: Create tar archive from SQL dump
      ansible.builtin.archive:
        path: "{{ backup_file }}"
        dest: "{{ backup_tar }}"
        format: gz

    - name: Update latest backup symlink
      ansible.builtin.file:
        src: "{{ backup_tar }}"
        dest: "{{ latest_symlink }}"
        state: link
        force: true

    - name: Upload tarball to S3 with rclone
      ansible.builtin.command:
        argv:
          - rclone
          - copy
          - "{{ backup_tar }}"
          - "{{ rclone_destination }}/"

Anmerkungen:

  • Upload mit rclone (rclone copy … remote:bucket/pfad/) auf S3 oder S3-kompatibles Object Storage; Ziel kommt aus rclone_destination (Remote-Name aus rclone.conf auf dem Zielhost, z.B. acme-s3, plus Bucket und Präfix). Authentifizierung wie gewohnt über rclone (Konfiguration, Umgebungsvariablen; siehe rclone S3).
  • Der latest.tar.gz-Symlink ist unser Rollback-Anker.
  • DB-Passwort kann aus Host-Variablen oder – besser – aus einem verschlüsselten Workspace-Secret kommen.

Polycrate bringt eingebaute Workspace-Verschlüsselung mit age: Es gibt keinen Befehl polycrate secrets add. Sensible Dateien legen Sie direkt unter artifacts/secrets/ ab (workspace-weit oder block-spezifisch unter artifacts/secrets/BLOCKNAME/); polycrate workspace encrypt verschlüsselt sie zu *.age und pflegt u. a. .gitignore. Ohne Polycrate API setzen Sie vor dem ersten Verschlüsseln typischerweise WORKSPACE_ENCRYPTION_KEY – siehe Workspace-Verschlüsselung (Abschnitte zu Key-Quellen, Key-Erzeugung und „Verschlüsseln“).

mkdir -p artifacts/secrets
# z. B. rclone-Konfiguration (siehe https://rclone.org/s3/) – Klartext nur lokal, nicht committen
# cp /pfad/zur/rclone.conf artifacts/secrets/rclone.conf

# Ohne Polycrate API: age Private Key (siehe Doku „Encryption Key erzeugen“)
# export WORKSPACE_ENCRYPTION_KEY="AGE-SECRET-KEY-..."

polycrate workspace encrypt

Kein externer Vault nötig – Compliance wird damit deutlich einfacher.


Update-Action: apt upgrade mit Ansible block/rescue und automatischem Restore

Die Update-Action kümmert sich um Paketupdates, Service-Restart und initiale Health-Checks. Der Rollback-Mechanismus steckt in einem Ansible-block mit rescue.

blocks/registry.acme-corp.com/acme/infra/linux-maintenance/update.yml:

- name: Update application servers with rollback
  hosts: "{{ block.config.web_hosts }}"
  become: true
  gather_facts: false

  vars:
    service_name: "{{ block.config.service_name }}"
    health_url: "{{ block.config.health_url }}"
    backup_dir: "{{ block.config.backup_dir }}"
    latest_backup: "{{ backup_dir }}/latest.tar.gz"

  tasks:
    - name: Ensure latest backup exists before updating
      ansible.builtin.stat:
        path: "{{ latest_backup }}"
      register: backup_stat

    - name: Fail if no latest backup is available
      ansible.builtin.fail:
        msg: "No latest backup found at {{ latest_backup }}. Aborting update."
      when: not backup_stat.stat.exists

    - name: Perform apt upgrade with rollback safety
      block:
        - name: Update apt cache
          ansible.builtin.apt:
            update_cache: true

        - name: Upgrade all packages
          ansible.builtin.apt:
            upgrade: dist
            autoremove: true

        - name: Restart application service
          ansible.builtin.systemd:
            name: "{{ service_name }}"
            state: restarted
            enabled: true

        - name: Wait for application port 8080
          ansible.builtin.wait_for:
            port: 8080
            state: started
            delay: 5
            timeout: 60

        - name: HTTP health-check on application
          ansible.builtin.uri:
            url: "{{ health_url }}"
            status_code: 200
            validate_certs: false

      rescue:
        - name: Log update failure and start rollback
          ansible.builtin.debug:
            msg: "Update failed on {{ inventory_hostname }}, starting rollback from {{ latest_backup }}"

        - name: Stop application service before restore
          ansible.builtin.systemd:
            name: "{{ service_name }}"
            state: stopped

        - name: Restore application data from latest backup
          ansible.builtin.unarchive:
            src: "{{ latest_backup }}"
            dest: "/"
            remote_src: true

        - name: Start application service after rollback
          ansible.builtin.systemd:
            name: "{{ service_name }}"
            state: started
            enabled: true

        - name: HTTP health-check after rollback
          ansible.builtin.uri:
            url: "{{ health_url }}"
            status_code: 200
            validate_certs: false

        - name: Fail play to signal rollback occurred
          ansible.builtin.fail:
            msg: "Update failed and rollback from {{ latest_backup }} was executed."

So funktioniert der Safety-Net-Mechanismus:

  • Schlägt irgendetwas im block fehl (z.B. Service startet nicht, HTTP-Check liefert 500), springt Ansible in den rescue-Block.
  • Der rescue-Block spielt das Backup ein und startet den Service wieder.
  • Am Ende failt der Task explizit, damit der Workflow (und du) wissen: Es gab ein Problem, aber der Zustand wurde zurückgesetzt.

Das ist deutlich robuster als ein README mit „Bitte vor Updates ein Backup machen“.


Verify-Action: Status- und HTTP-Checks

Die verify-Action ist bewusst simpel – sie codiert das, was sonst oft nur „gefühlte“ Checks sind.

blocks/registry.acme-corp.com/acme/infra/linux-maintenance/verify.yml:

- name: Verify application servers
  hosts: "{{ block.config.web_hosts }}"
  become: true
  gather_facts: false

  vars:
    service_name: "{{ block.config.service_name }}"
    health_url: "{{ block.config.health_url }}"

  tasks:
    - name: Check service status
      ansible.builtin.systemd:
        name: "{{ service_name }}"
      register: service_state

    - name: Fail if service is not running
      ansible.builtin.fail:
        msg: "Service {{ service_name }} is not running."
      when: not service_state.status.ActiveState == "active"

    - name: HTTP health-check
      ansible.builtin.uri:
        url: "{{ health_url }}"
        status_code: 200
        validate_certs: false
      register: health_response

    - name: Show response
      ansible.builtin.debug:
        msg: "Health-check OK: {{ health_response.status }} {{ health_response.msg }}"

Dieser Schritt gibt dem ganzen Prozess einen klaren Abschluss: „Ist die Applikation nach Backup und Update in einem guten Zustand?“


Workflow-Ausführung: vom einmaligen Run bis zum systemd-Timer

Manuell ausführbar ist der Workflow sofort:

# Im Workspace-Root
polycrate workflows run nightly-maintenance

Im Gegensatz zu plain Ansible musst du dir keinen eigenen Wrapper bauen:

  • Kein Bash-Skript, das mehrere ansible-playbook-Aufrufe verkettet.
  • Kein manuelles Weiterreichen von Variablen zwischen Schritten.
  • Kein eigenes Logging-Konzept – Polycrate kümmert sich um konsistente Ausführung im Container.

Dank Containerisierung löst Polycrate das klassische Dependency-Problem:

  • Ansible, Python, rclone und weitere Tools werden durch das Container-Image definiert.
  • Dein Team arbeitet mit derselben Toolchain, unabhängig von der lokalen Workstation.
  • Supply-Chain-Risiken reduzierst du, indem du das Image selbst kontrollierst (Dockerfile.poly / Bash-Build).

Mehr dazu in der CLI-Referenz.

Zeitgesteuerte Ausführung mit systemd-Timer

Angenommen, du betreibst einen zentralen Automation-Host (z.B. automation01.acme-corp.com), auf dem Polycrate installiert ist. Dann kannst du deinen Workflow mit einem systemd-Timer planen.

Service-Unit /etc/systemd/system/polycrate-nightly-maintenance.service:

[Unit]
Description=Polycrate nightly maintenance workflow

[Service]
Type=oneshot
WorkingDirectory=/opt/polycrate-workspaces/acme-corp-automation
ExecStart=/usr/local/bin/polycrate workflows run nightly-maintenance
User=automation
Group=automation

Timer-Unit /etc/systemd/system/polycrate-nightly-maintenance.timer:

[Unit]
Description=Run Polycrate nightly maintenance workflow at 2:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Aktivieren:

sudo systemctl daemon-reload
sudo systemctl enable --now polycrate-nightly-maintenance.timer

Ab diesem Zeitpunkt läuft dein kompletter Prozess jede Nacht um 2:00 Uhr – klar definiert, versioniert und wiederholbar.


Polycrate vs. plain Ansible: Was ändert sich wirklich?

Mit plain Ansible würdest du typischerweise:

  • Mehrere Playbooks (backup.yml, update.yml, verify.yml) schreiben.
  • Ein Shell-Skript bauen, das sie in der richtigen Reihenfolge aufruft.
  • Cronjobs oder systemd-Timer direkt auf ansible-playbook legen.
  • Deine Teamkollegen mit einem README versorgen, das erklärt, in welcher Reihenfolge was zu tun ist.

Das funktioniert – aber du kämpfst mit:

  • Python-/Ansible-Versionen auf unterschiedlichen Admin-Rechnern.
  • Individuellen Tool-Setups (rclone, pg_dump-Versionen, Remote-Konfiguration).
  • Playbook-Wildwuchs ohne klaren Rahmen.
  • Dokumentation, die schnell veraltet.

Mit Polycrate:

  • Läuft Ansible immer im Container – keine lokalen Dependencies, keine Versionsdiskussionen.
  • Bekommen Playbooks eine feste Heimat als Blöcke mit klaren Actions und Konfigurationsparametern.
  • Kannst du komplette Betriebsprozesse als Workflows definieren und unter einem Namen ausführen.
  • Verschlüsselst du den gesamten Workspace auf Wunsch mit einem Befehl – inklusive Credentials und Secrets.
  • Teilt dein Team Blocks über OCI-Registries oder PolyHub – „Sharable Automation“ statt Copy-Paste zwischen Repositories.

Code ist damit nicht nur Implementierung, sondern auch Dokumentation: Wer den Workflow liest, versteht den Prozess.


Häufige Fragen

Ist ein Polycrate-Workflow das gleiche wie ein CI/CD-Workflow?

Nein. CI/CD-Workflows (GitHub Actions, GitLab CI, Jenkins-Pipelines) laufen typischerweise bei Code-Änderungen im Kontext eines Repositories. Polycrate-Workflows laufen dort, wo du Infrastruktur und Systeme verwaltest:

  • Sie orchestrieren Actions in deinen Blöcken (z.B. Backup, Update, Verify).
  • Sie sind eng an dein Ansible-Inventar und deine Betriebsrealität gekoppelt.
  • Sie lassen sich per CLI, systemd-Timer oder externen Orchestratoren triggern.

Du kannst beides kombinieren: Ein CI/CD-Workflow kann zum Beispiel polycrate workflows run nightly-maintenance auf einem Automation-Host ausführen, wenn bestimmte Bedingungen erfüllt sind.

Wie integriere ich Polycrate-Workflows mit cron statt systemd?

Wenn du lieber cron nutzt, definierst du einfach einen Cronjob, der in das Workspace-Verzeichnis wechselt und den Workflow ausführt:

0 2 * * * cd /opt/polycrate-workspaces/acme-corp-automation && /usr/local/bin/polycrate workflows run nightly-maintenance >> /var/log/polycrate-nightly.log 2>&1

Der Vorteil von Polycrate bleibt derselbe:

  • Ein einziger, stabiler Befehl pro Prozess.
  • Die interne Ausführung läuft trotzdem containerisiert, mit konsistenter Toolchain.
  • Deine Ansible-Playbooks bleiben im Block-Modell strukturiert.

Wie unterstützt ayedo Teams bei der Einführung solcher Maintenance-Workflows?

Wir sehen solche Workflows als Kern von professioneller Operations-Automatisierung:

  • In Workshops und mit unseren Beratungspaketen helfen wir Teams, bestehende Playbooks in Polycrate-Blöcke und -Workflows zu überführen.
  • Wir unterstützen beim Design von Block-Strukturen, der Nutzung von Workspace-Verschlüsselung und der Integration in bestehende Betriebsprozesse (z.B. via systemd, Cron oder Plattform-Automatisierung).
  • Über PolyHub stellen wir offizielle Blöcke bereit, die du als Bausteine für eigene Workflows nutzen kannst (Monitoring, Kubernetes, Security, Storage und mehr).

Weitere Fragen? Siehe unsere FAQ


Von der Routine zur Reproduzierbarkeit

In diesem Beitrag hast du ein komplettes Beispiel für einen realen Betriebsprozess als Polycrate-Workflow gesehen:

  • Ein Backup-Schritt, der Datenbank-Dumps erzeugt, tarballt und zuverlässig nach S3 hochlädt.
  • Einen Update-Schritt, der mit Ansible-block/rescue-Mechanik Paketupdates durchführt und bei Problemen automatisch ein Rollback aus dem letzten Backup fährt.
  • Einen Verify-Schritt, der explizit prüft, ob Service und HTTP-Endpoint nach dem Vorgang in Ordnung sind.
  • Einen Workflow, der diese drei Schritte unter einem stabilen Namen kapselt und sich per CLI, systemd oder cron ausführen lässt.

Statt fragmentierter Skripte, impliziten Abhängigkeiten und veralteten README-Dateien hast du jetzt:

  • Einen versionierten Workspace, der die Realität deiner Systeme beschreibt.
  • Containerisierte Ausführung, die Abhängigkeiten und Team-Inkonsistenzen eliminiert.
  • Die Möglichkeit, solche Blöcke im Unternehmen oder über Registries zu teilen – damit andere Teams denselben Standard nutzen können.

Bei ayedo arbeiten wir täglich mit Teams, die genau diesen Schritt gehen: von Ad-hoc-Automatisierung hin zu wiederverwendbaren, nachvollziehbaren Betriebsprozessen. Ob du gerade deine ersten Ansible-Playbooks strukturierst oder bestehende Runbooks in Code gießen willst – wir unterstützen dich dabei, ohne deine bestehende Umgebung über den Haufen zu werfen.

Wenn du sehen möchtest, wie ein solcher Workflow in deiner Umgebung aussehen kann – mit deinen Hosts, deinen Compliance-Anforderungen und deinen Toolchains – findest du passende Formate und den nächsten Schritt auf der Workshop-Übersicht (z. B. Operations-Automatisierung Demos).

Ähnliche Artikel