Das Polycrate-Ökosystem: PolyHub, API, MCP und die Zukunft der Automatisierung
TL;DR Polycrate ist längst mehr als ein CLI-Tool: Mit PolyHub, API-Plattform und MCP entsteht ein …
Diese Serie zeigt Schritt für Schritt, wie Ansible mit Polycrate zu einer strukturierten, teilbaren und compliance-fähigen Automatisierungsplattform wird – von den Grundlagen bis zu Enterprise-Szenarien.
block.poly, Ansible-Playbook und drei Kubernetes-Templates für Deployment, Service und Ingress.block.config dient als Single Source of Truth für Image, Replikas, Namespace und Domain; der Upgrade-Workflow reduziert sich auf: Image-Tag im Workspace ändern, polycrate run myapp install ausführen, fertig.kubectl – die komplette Toolchain wird im Container bereitgestellt und ist für das ganze Team identisch.install, uninstall und status bekommen Sie ein sauberes, wiederverwendbares Interface statt lose verteilter Playbooks; der Block kann versioniert und in einer OCI-Registry geteilt werden.Viele Kubernetes-Teams starten mit Helm-Charts und ein paar YAML-Dateien im Git-Repo. Spätestens wenn mehrere interne Services, unterschiedliche Umgebungen und Compliance-Anforderungen dazukommen, wird es unübersichtlich:
kubectl, Ansible, Auth-Tools.Mit Polycrate bringen Sie Ordnung in diese Automatisierung, ohne auf Ansible oder bekannte Kubernetes-Patterns zu verzichten:
install, uninstall, status). Kein „Playbook-Wildwuchs“, sondern ein klares Interface.kubectl, kubernetes.core-Collection – alles läuft im Polycrate-Container. Keine lokal installierten Tools, keine Version-Hölle.Ein eigener Block lohnt sich immer dann, wenn:
polycrate run myapp install statt „lies bitte die README und ruf diese fünf kubectl-Kommandos auf“.In diesem Beitrag bauen wir genau so einen Block – komplett, von der Struktur bis zum Registry-Push.
Unser Beispiel:
Firma: ACME Corp.
Workspace: acme-corp-automation
App: myapp, ein interner Webservice (HTTP auf Port 8080)
Cluster: Bereits vorhanden, kubeconfig liegt lokal vor
Domain: myapp.acme-corp.com
Ziel: Ein Polycrate-Block myapp-k8s, den wir mit
polycrate run myapp installfür verschiedene Cluster/Umgebungen nutzen können.
Wichtig: Wir verwenden das Ansible-Modul kubernetes.core.k8s, das direkt mit der Kubernetes-API spricht. Das Playbook läuft innerhalb des Polycrate-Containers mit hosts: localhost und connection: local. Es wird also nichts im Container selbst installiert, sondern nur via API im Cluster geändert.
Die Details zur Kubernetes-Integration finden Sie auch in der offiziellen Dokumentation:
https://docs.ayedo.de/polycrate/kubernetes/
Zuerst definieren wir unseren Workspace und binden dort den Block ein. Die workspace.poly liegt im Root-Verzeichnis Ihres Git-Repos:
# workspace.poly
name: acme-corp-automation
organization: acme
blocks:
- name: myapp
from: registry.acme.corp/blocks/myapp-k8s:0.1.0
config:
image: "registry.acme-corp.com/myapp"
image_tag: "1.0.0"
replicas: 2
namespace: "apps"
domain: "myapp.acme-corp.com"Ein paar Hinweise:
from: nutzt die Registry-Notation (<registry>/<pfad>:<version>). registry.acme.corp ist hier nur ein fiktives Beispiel; in der Praxis ziehen Sie den Block z. B. mit polycrate blocks pull … oder aus Ihrer OCI-Registry.config: geben wir App-spezifische Werte an. Diese landen als block.config.* im Block und sind unsere Single Source of Truth.dev, staging, prod).Die kubeconfig legen wir – Polycrate-konform – im Workspace unter artifacts/secrets/kubeconfig.yml ab. Im Workspace-Repository liegt typischerweise nur Konfiguration und Secrets – kein eingechecktes blocks/myapp-k8s/, wenn der Block aus der Registry kommt:
acme-corp-automation/
workspace.poly
artifacts/
secrets/
kubeconfig.ymlPolycrate setzt im Action-Container KUBECONFIG auf die Workspace-Kubeconfig; kubectl und Ansible (kubernetes.core) nutzen sie ohne extra Pfadvariable. Sie können den Workspace (inklusive kubeconfig) mit der eingebauten Encryption-Funktion und age verschlüsseln, um Compliance-Anforderungen sauber abzudecken (siehe Workspace-Verschlüsselung) – ganz ohne zusätzliches Tool wie Vault.
So sieht der Block aus – beim lokalen Entwickeln unter blocks/myapp-k8s/ oder im Workspace-Cache nach dem Pull aus der Registry:
blocks/myapp-k8s/
block.poly
install.yml
templates/
deployment.yml.j2
service.yml.j2
ingress.yml.j2block.poly beschreibt den Block, seine Konfiguration und Actions.install.yml ist das zentrale Ansible-Playbook. Wir nutzen es für install, uninstall und status.templates/ liegen die Jinja2-Templates für die Kubernetes-Manifeste.Hier die vollständige block.poly:
# blocks/myapp-k8s/block.poly
name: myapp-k8s
version: 0.1.0
kind: generic
config:
image: "registry.acme-corp.com/myapp"
image_tag: "1.0.0"
replicas: 2
namespace: "apps"
domain: "myapp.acme-corp.com"
actions:
- name: install
playbook: install.yml
- name: uninstall
playbook: install.yml
- name: status
playbook: install.ymlWichtiges dazu:
config: definiert Default-Werte. Sie werden durch workspace.blocks[].config überschrieben. In den Templates und im Playbook greifen wir immer über block.config.* darauf zu.install, uninstall und status bilden ein Standard-Interface, das sich für alle Kubernetes-Apps anbietet:
install: Erzeugt/aktualisiert alle Ressourcen.uninstall: Entfernt alle Ressourcen.status: Zeigt den aktuellen Zustand im Cluster an.install.yml. Über die Polycrate-Variable action.name unterscheiden wir später im Playbook, welcher Pfad genommen wird.Dieses Interface ist auch für Betriebsteams wertvoll: egal welche App – das Interface bleibt gleich.
Jetzt kommen die Kubernetes-Manifeste. Sie werden als Jinja2-Templates definiert und greifen direkt auf block.config.* zu. So ist block.config unsere Single Source of Truth.
# blocks/myapp-k8s/templates/deployment.yml.j2
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: {{ block.config.namespace }}
labels:
app: myapp
spec:
replicas: {{ block.config.replicas }}
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: "{{ block.config.image }}:{{ block.config.image_tag }}"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 15
periodSeconds: 20# blocks/myapp-k8s/templates/service.yml.j2
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: {{ block.config.namespace }}
labels:
app: myapp
spec:
type: ClusterIP
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP# blocks/myapp-k8s/templates/ingress.yml.j2
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
namespace: {{ block.config.namespace }}
labels:
app: myapp
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- host: {{ block.config.domain }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
number: 80
tls:
- hosts:
- {{ block.config.domain }}
secretName: myapp-tlsSie sehen: Alle variablen Werte (Namespace, Replikas, Domain, Image + Tag) kommen direkt aus block.config. Ein Upgrade wird später einfach, weil wir nur dort drehen müssen.
install.yml mit kubernetes.core.k8sJetzt bauen wir das Herzstück: ein Playbook, das je nach Action install, uninstall oder status ausführt.
Wichtig: Das Playbook läuft innerhalb des Polycrate-Containers auf localhost und spricht über die kubernetes.core-Collection mit dem Kubernetes-API-Server. Polycrate setzt KUBECONFIG; die Module brauchen kein explizites kubeconfig: im Task.
# blocks/myapp-k8s/install.yml
- name: Manage myapp Kubernetes resources
hosts: localhost
connection: local
gather_facts: false
vars:
manifest_dir: "/tmp/myapp-k8s"
tasks:
- name: Ensure manifest directory exists (container-local)
ansible.builtin.file:
path: "{{ manifest_dir }}"
state: directory
mode: "0755"
when: action.name in ['install', 'uninstall', 'status']
# INSTALL: Namespace + Manifeste anwenden
- name: Ensure namespace exists
kubernetes.core.k8s:
api_version: v1
kind: Namespace
name: "{{ block.config.namespace }}"
state: present
when: action.name == 'install'
- name: Render Deployment manifest
ansible.builtin.template:
src: "templates/deployment.yml.j2"
dest: "{{ manifest_dir }}/deployment.yml"
mode: "0644"
when: action.name == 'install'
- name: Render Service manifest
ansible.builtin.template:
src: "templates/service.yml.j2"
dest: "{{ manifest_dir }}/service.yml"
mode: "0644"
when: action.name == 'install'
- name: Render Ingress manifest
ansible.builtin.template:
src: "templates/ingress.yml.j2"
dest: "{{ manifest_dir }}/ingress.yml"
mode: "0644"
when: action.name == 'install'
- name: Apply Deployment
kubernetes.core.k8s:
state: present
src: "{{ manifest_dir }}/deployment.yml"
wait: true
wait_timeout: 300
when: action.name == 'install'
- name: Apply Service
kubernetes.core.k8s:
state: present
src: "{{ manifest_dir }}/service.yml"
when: action.name == 'install'
- name: Apply Ingress
kubernetes.core.k8s:
state: present
src: "{{ manifest_dir }}/ingress.yml"
when: action.name == 'install'
# UNINSTALL: Ressourcen entfernen
- name: Delete Ingress
kubernetes.core.k8s:
state: absent
api_version: networking.k8s.io/v1
kind: Ingress
name: "myapp"
namespace: "{{ block.config.namespace }}"
when: action.name == 'uninstall'
- name: Delete Service
kubernetes.core.k8s:
state: absent
api_version: v1
kind: Service
name: "myapp"
namespace: "{{ block.config.namespace }}"
when: action.name == 'uninstall'
- name: Delete Deployment
kubernetes.core.k8s:
state: absent
api_version: apps/v1
kind: Deployment
name: "myapp"
namespace: "{{ block.config.namespace }}"
when: action.name == 'uninstall'
# STATUS: Aktueller Zustand abfragen
- name: Get Deployment status
kubernetes.core.k8s_info:
api_version: apps/v1
kind: Deployment
namespace: "{{ block.config.namespace }}"
name: "myapp"
register: deployment_info
when: action.name == 'status'
- name: Show Deployment status
ansible.builtin.debug:
var: deployment_info.resources[0].status
when:
- action.name == 'status'
- deployment_info.resources | length > 0Ein paar zentrale Punkte:
KUBECONFIG im Container; kubernetes.core nutzt sie ohne kubeconfig:-Parameter im Task.manifest_dir: Für gerenderte YAML-Dateien ist ein temporäres Verzeichnis unter /tmp/… üblich (verschwindet mit dem Container). Sollen die Manifeste dauerhaft im Workspace landen (z. B. Review, GitOps), verwenden Sie stattdessen z. B. {{ block.artifacts.path }}/… – siehe Artefakte.install:
manifest_dir.kubernetes.core.k8s die Dateien an und wartet auf einen „Ready“-Status des Deployments.uninstall werden die Ressourcen explizit mit state: absent entfernt.status nutzen wir kubernetes.core.k8s_info, um den aktuellen Status zu ermitteln.Die Variable action.name stellt Polycrate automatisch bereit (siehe Actions-Dokumentation). Damit können Sie bequem in einem Playbook unterschiedliche Pfade steuern.
Mit der obigen Struktur können Sie den Block direkt lokal testen:
# Im Workspace-Root
cd /pfad/zu/acme-corp-automation
# Install: Ressourcen im Cluster erzeugen/aktualisieren
polycrate run myapp installPolycrate startet nun einen Container mit einer vollständig konfigurierten Toolchain (Ansible, kubernetes.core, Python, ggf. kubectl), mounted den Workspace hinein und führt install.yml mit dem Kontext des Blocks myapp aus.
Weitere Actions:
# Status abfragen
polycrate run myapp status
# Ressourcen wieder entfernen
polycrate run myapp uninstallIm Gegensatz zu plain Ansible müssen Sie:
ansible.cfg pflegen,Alles ist im Block gekapselt und wird im Container reproduzierbar ausgeführt.
Ohne Polycrate würden Sie typischerweise:
playbooks/, roles/, group_vars/).kubernetes.core-Collection.kubeconfig verteilen und schützen (Polycrate setzt KUBECONFIG im Container).ansible-playbook install.yml -e env=prod?Playbooks teilen bedeutet in der Regel: Git-Repo clonen, lokale Umgebung einrichten, README lesen, manuell Kommandozeilen eintippen.
Mit Polycrate:
polycrate run myapp install|uninstall|status.Ansible bleibt das gleiche starke Werkzeug – Polycrate gibt ihm Struktur, Reproduzierbarkeit und ein klares Packaging-Modell.
Sobald Sie mit dem Ergebnis zufrieden sind, können Sie den Block in eine Registry pushen. Das macht ihn:
:0.1.0, :0.2.0, …),Push erfolgt mit polycrate blocks push, nicht mit registry push: Sie übergeben den vollständigen Registry-Pfad zum Block (wie bei from:), z. B. cargo.ayedo.cloud/acme/myapp-k8s – nicht den Workspace-Instanznamen myapp. Das OCI-Tag kommt aus version in der block.poly (kein Versions-Suffix im Push-Befehl). Details: CLI-Referenz – polycrate blocks push.
Beispiel: Push in eine OCI-Registry (z. B. cargo.ayedo.cloud):
# Im Workspace-Root, in dem blocks/myapp-k8s liegt (oder --workspace <pfad>)
polycrate blocks push cargo.ayedo.cloud/acme/myapp-k8s
# Kurzform (Alias):
# polycrate push cargo.ayedo.cloud/acme/myapp-k8sIn einem anderen Workspace können Sie diesen Block dann referenzieren:
# workspace.poly in einem anderen Projekt
name: another-workspace
organization: acme
blocks:
- name: myapp-prod
from: cargo.ayedo.cloud/acme/myapp-k8s:0.1.0
config:
image: "registry.acme-corp.com/myapp"
image_tag: "1.0.0"
replicas: 3
namespace: "apps-prod"
domain: "myapp.acme-corp.com"Wichtig: Versionen immer explizit pinnen (:0.1.0), niemals :latest verwenden. Das ist eine zentrale Best Practice in Polycrate (siehe Best Practices).
Der wahrscheinlich wichtigste Use Case im Alltag: eine neue Version der App ausrollen.
Mit unserem Setup ist der Workflow bewusst simpel:
Image-Tag im Workspace anpassen
# workspace.poly (Ausschnitt)
blocks:
- name: myapp
from: registry.acme.corp/blocks/myapp-k8s:0.1.0
config:
image: "registry.acme-corp.com/myapp"
image_tag: "1.1.0" # <-- Neues Tag
replicas: 2
namespace: "apps"
domain: "myapp.acme-corp.com"Install-Action erneut ausführen
polycrate run myapp installDa Ansible und das kubernetes.core.k8s-Modul idempotent arbeiten, wird das Deployment erkannt und mit dem neuen Image-Tag aktualisiert. Sie müssen keine zusätzlichen Flags oder „Upgrade“-Kommandos erfinden – die Idempotenz plus Single Source of Truth erledigen den Rest.
Optional: Status prüfen
polycrate run myapp statusSo behalten Sie im Blick, ob das Deployment tatsächlich so läuft, wie erwartet.
Dieser Ansatz skaliert gut:
config-Werten.install auf.Polycrate unterstützt verschiedene Technologien, aber Ansible ist für Kubernetes-Workloads eine sehr gute Wahl:
kubernetes.core-Module.Wenn Sie heute schon stark mit Ansible arbeiten, ist der Schritt zu Kubernetes-Blöcken mit Polycrate sehr klein – Sie erweitern Ihre Playbooks lediglich um Kubernetes-spezifische Tasks.
Polycrate bringt einen eigenen Mechanismus für Workspace-Verschlüsselung mit:
artifacts/secrets/ – wie unsere kubeconfig.yml – können mit age verschlüsselt werden.Details dazu finden Sie in der Dokumentation zur Workspace-Verschlüsselung. Sie brauchen dafür kein zusätzliches Vault-Produkt – ein echter Vorteil für Teams, die schnell, aber trotzdem compliant arbeiten möchten.
Ja, genau dafür ist das Zusammenspiel von Workspace und Block gedacht:
Für mehrere Cluster definieren Sie einfach mehrere Workspaces (oder mehrere Block-Instanzen im gleichen Workspace) mit unterschiedlichen kubeconfigs und Config-Werten. Der Block-Code bleibt unverändert.
Weitere Fragen? Siehe unsere FAQ
Mit dem Block myapp-k8s haben Sie einen vollständigen, wiederverwendbaren Baustein geschaffen:
block.config dient als Single Source of Truth – Image, Replikas, Namespace und Domain sind zentral definiert.install, uninstall und status entsteht ein stabiles Interface, das auch Betriebsteams und Compliance-Verantwortliche nachvollziehen können.kubernetes.core und allen Abhängigkeiten. Lokale Setups werden deutlich einfacher.In vielen Organisationen ist dieser erste Block der Auftakt zu einer breiteren Automatisierungsstrategie:
install/uninstall/status).Als ayedo begleiten wir Teams genau auf diesem Weg – von den ersten Schritten mit einem einzelnen Kubernetes-Service bis hin zu umfassenden Plattform- und Automatisierungs-Landschaften. In unseren Workshops zeigen wir praxisnah, wie Sie:
Wenn Sie Ihre eigenen Kubernetes-Apps als Polycrate-Blöcke strukturieren und dabei von erprobten Best Practices profitieren möchten, ist unser Kubernetes-Block Workshop ein guter nächster Schritt:
Kubernetes-Block Workshop
TL;DR Polycrate ist längst mehr als ein CLI-Tool: Mit PolyHub, API-Plattform und MCP entsteht ein …
TL;DR PolyHub funktioniert wie ein App-Store für Infrastruktur: Fertige ayedo-Blöcke für …
TL;DR Die Polycrate API macht aus einzelnen Workspaces eine Team-Plattform: alle Workspaces, Action …