Polycrate Operator¶
Der Polycrate Operator ist ein Kubernetes Operator, der Cluster-Ressourcen automatisch mit der Polycrate API synchronisiert: Ingresses, Nodes, Velero-Backups, TLS-Zertifikate, Volumes und deployte Apps werden kontinuierlich erkannt und an die API gemeldet.
Übersicht¶
Der Operator überwacht Kubernetes-Ressourcen und synchronisiert sie mit der Polycrate API:
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ polycrate Namespace │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Polycrate Operator │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Custom Resources (CRs) │ │ │
│ │ │ - OperatorConfig │ │ │
│ │ │ - K8sCluster │ │ │
│ │ │ - Endpoint / Host / K8sApp / K8sVolume │ │ │
│ │ │ - Backup / BackupSchedule / Certificate │ │ │
│ │ │ - S3Bucket │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ Polycrate API │
└─────────────────────┘
Custom Resource Definitions (CRDs)¶
Der Operator verwaltet 10 Custom Resource Typen:
| CRD | Kurzname | Beschreibung |
|---|---|---|
OperatorConfig | oc, opcfg | Operator-weite Konfiguration (Discovery, API-Sync, Local Cluster) |
K8sCluster | k8sc | Registrierung externer Kubernetes Cluster |
Endpoint | ep, pep | Endpoint für HTTP-Monitoring (automatisch aus Ingress erstellt) |
Host | — | Node im Cluster (automatisch aus Kubernetes-Nodes erstellt) |
K8sApp | app, pca | Deployed App (aus Meta-Secrets oder Pod-Annotations erkannt) |
K8sVolume | vol, pvol | PersistentVolume im Cluster (automatisch aus PersistentVolumes erstellt) |
Backup | backup | Backup-Status (automatisch aus Velero erstellt) |
BackupSchedule | bs | Backup-Schedule (automatisch aus Velero erstellt) |
Certificate | cert, pcert | TLS-Zertifikat (automatisch aus cert-manager erstellt) |
S3Bucket | s3 | S3 Bucket (deklarativ per CR provisioniert, Credentials als Secret) |
Installation¶
1. CRDs installieren¶
Ab Polycrate CLI 0.30.0 sind die CRDs im polycrate-operator Block enthalten (im crds/-Verzeichnis) und werden beim install-Playbook automatisch angewendet. Der empfohlene Weg ist daher:
# Empfohlen: CRDs werden automatisch bei der Installation angewendet
polycrate run polycrate-operator install
Für manuelle CRD-Installation (z.B. GitOps):
# CRDs direkt aus der CLI installieren (legacy)
polycrate operator install-crds
# Alternativ: CRDs ausgeben und manuell installieren
polycrate operator crds | kubectl apply -f -
# Nur bestimmte CRDs ausgeben
polycrate operator crds --kind Organization
polycrate operator crds --kind OperatorConfig
# Alle verfügbaren CRDs auflisten
polycrate operator crds --list
Für GitOps-Setups, bei denen CRDs separat verwaltet werden, kann die automatische Installation deaktiviert werden:
# workspace.poly
blocks:
- name: polycrate-operator
from: cargo.ayedo.cloud/ayedo/k8s/polycrate-operator
config:
crds:
install: false # CRDs werden separat via GitOps deployed
2. Operator starten¶
# Lokal ausführen (Development)
polycrate operator run --kubeconfig ~/.kube/config
# Mit spezifischem Kubeconfig
polycrate operator run --kubeconfig /path/to/kubeconfig.yml
# Mit Leader Election (für HA-Deployments)
polycrate operator run --leader-elect
Ressourcen erstellen¶
K8sCluster¶
Registriert einen externen Kubernetes Cluster:
apiVersion: polycrate.io/v1alpha1
kind: K8sCluster
metadata:
name: production-cluster
namespace: polycrate
spec:
displayName: "Production Cluster"
apiServer: "https://api.prod.example.com:6443"
authentication:
serviceAccountToken:
secretRef:
name: prod-cluster-token
key: token
# Oder via Kubeconfig
# authentication:
# kubeconfig:
# secretRef:
# name: prod-cluster-kubeconfig
# key: kubeconfig
caCertificate: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
→ Loopback-Integration — Anwendersicht
CLI Commands¶
polycrate operator crds¶
Gibt CRD-Definitionen aus:
# Alle CRDs ausgeben
polycrate operator crds
# Bestimmten CRD-Typ ausgeben
polycrate operator crds --kind Organization
# In Datei speichern
polycrate operator crds --output-dir ./crds/
# CRDs auflisten
polycrate operator crds --list
polycrate operator install-crds¶
Installiert CRDs direkt ins Cluster:
# Mit Standard-Kubeconfig
polycrate operator install-crds
# Mit spezifischer Kubeconfig
polycrate operator install-crds --kubeconfig ~/.kube/admin.yaml
# Dry-run (zeigt was installiert würde)
polycrate operator install-crds --dry-run
polycrate operator run¶
Startet den Operator:
# Lokal mit Kubeconfig
polycrate operator run --kubeconfig ~/.kube/config
# Mit Leader Election
polycrate operator run --leader-elect
# Mit Metrics aktiviert
polycrate operator run --metrics-bind-address :8080
Optionen:
| Flag | Standard | Beschreibung |
|---|---|---|
--kubeconfig | $KUBECONFIG oder ~/.kube/config | Pfad zur Kubeconfig |
--leader-elect | false | Leader Election für HA aktivieren |
--metrics-bind-address | :8080 | Metrics Endpoint |
--health-probe-bind-address | :8081 | Health Probe Endpoint |
polycrate operator health¶
Prüft den Health-Status des Operators:
# Lokalen Operator prüfen
polycrate operator health
# Remote-Operator prüfen
polycrate operator health --url http://polycrate-operator.polycrate:8081
polycrate operator status¶
Zeigt Status aller Operator-Ressourcen:
polycrate operator status
# Ausgabe:
# Polycrate Operator Status
# =========================
# Cluster: https://kubernetes.default.svc
#
# K8sClusters
# -----------
# NAME NAMESPACE PHASE
# production-cluster polycrate Ready
Rate Limiting & Error Handling¶
Der Operator implementiert Rate Limiting via Controller-Manager:
- Base Delay: 5 Sekunden
- Max Delay: 60 Sekunden (Exponential Backoff)
- Max Concurrent Reconciles: konfigurierbar via
--max-concurrent-reconciles(Default: 4 für Endpoint-Monitoring und API-Agent)
Bei Fehlern (z.B. API nicht erreichbar) wird die Reconciliation mit exponentiell wachsendem Delay wiederholt.
OperatorConfig: Zentrale Discovery-Konfiguration¶
Die Discovery wird über eine OperatorConfig CR konfiguriert. Diese ist ein Singleton (Name: default, Namespace: polycrate).
apiVersion: polycrate.io/v1alpha1
kind: OperatorConfig
metadata:
name: default
namespace: polycrate
spec:
# API-Sync Konfiguration
api_sync:
enabled: true
api_url: "https://api.polycrate.io"
credentials_ref:
secret_name: polycrate-api-creds
token_key: token
# workspace_id und organization_id werden NICHT mehr im Spec konfiguriert!
# Diese Werte werden automatisch vom Agent Token abgeleitet und im Status gespeichert.
# Siehe "Auto Workspace Resolution" weiter unten.
# Lokales Cluster bei der API registrieren
# Wird ignoriert wenn API bereits ein Cluster für diesen Workspace hat
local_cluster:
enabled: true
cluster_name: "my-workspace" # Optional: Wird ignoriert wenn Cluster bereits existiert
# Endpoint-Discovery (Ingress → API)
endpoint_discovery:
enabled: true
# "annotation" (Standard ab 0.38.0): Nur Ingresses mit polycrate_endpoint_monitor=true werden verarbeitet
# "auto": Alle Ingresses werden verarbeitet (außer polycrate_endpoint_monitor=false)
mode: annotation
watch_namespaces: [] # Leer = alle Namespaces
ignore_namespaces: # Diese Namespaces werden ignoriert
- kube-system
- kube-public
- polycrate
ingress_classes: [] # Leer = alle Ingress-Klassen
# App-Discovery (Meta-Secrets + Pod-Labels → API)
app_discovery:
enabled: true
watch_namespaces: []
ignore_namespaces:
- kube-system
- kube-public
label_discovery_enabled: true # Label-basierte K8sApp Discovery (ab 0.29.17)
stale_cleanup_minutes: 10 # Intervall fuer Stale-Sweep (ab 0.29.17)
# Node-Discovery (Nodes → API)
node_discovery:
enabled: true
label_selector: ""
# Backup-Discovery (Velero → API)
backup_discovery:
enabled: true
velero_namespace: velero
ignore_namespaces: []
cnpg_enabled: true
Namespace-Filterung¶
Die Namespace-Filterung funktioniert für alle Discovery-Typen gleich:
| Konfiguration | Verhalten |
|---|---|
watch_namespaces: [] | Alle Namespaces überwachen |
watch_namespaces: [prod, staging] | Nur diese Namespaces |
ignore_namespaces: [kube-system] | Diese Namespaces immer ignorieren |
Wichtig: ignore_namespaces wird von watch_namespaces subtrahiert. Wenn ein Namespace in beiden Listen ist, wird er ignoriert.
Local Cluster Registration¶
Der Operator kann das Cluster, in dem er läuft, mit der Polycrate API verknüpfen:
Idempotenz-Logik:
- Prüft ob in der API bereits ein Cluster für diesen Workspace existiert
- Falls ja: API-Cluster hat Vorrang,
cluster_namewird ignoriert - Falls nein und
cluster_namegesetzt: Neues Cluster wird angelegt - Falls nein und
cluster_namenicht gesetzt: Kein Cluster wird angelegt
Die aufgelöste Cluster-ID wird im OperatorConfig.status.local_cluster gespeichert für idempotente Operationen.
Wichtig: Die Kubeconfig wird nicht automatisch synchronisiert – dies übernimmt der Git-Sync der Workspaces.
Auto Workspace Resolution (ab 0.29.0)¶
Ab Version 0.29.0 werden workspace_id und organization_id automatisch vom Agent Token abgeleitet.
Wie funktioniert es:
- Der Operator sendet einen Health-Report an die API mit dem konfigurierten Agent Token
- Die API erkennt anhand des Tokens den zugehörigen Workspace und die Organization
- Die API gibt
workspace_id,workspace_name,organization_idundorganization_namein der Health-Response zurück - Der Operator speichert diese Werte im
OperatorConfig.status.api_sync
Vorteile:
- Keine manuelle UUID-Konfiguration mehr erforderlich
- Token-basierte Authentifizierung = automatische Workspace-Zuordnung
- Reduzierte Fehlerquellen bei der Konfiguration
Status-Felder:
status:
api_sync:
workspace_id: "550e8400-e29b-41d4-a716-446655440000"
workspace_name: "production"
organization_id: "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
organization_name: "acme-corp"
resolved_at: "2026-01-06T14:30:00Z"
Migration von älteren Versionen:
Falls in älteren Versionen workspace_id und organization_id im Spec konfiguriert waren, können diese Felder nach dem Update auf 0.29.0 entfernt werden. Die Werte werden automatisch aus dem Token abgeleitet.
Discovery: Operator-Driven API-Synchronisation¶
Der Operator erkennt automatisch Kubernetes-Ressourcen und synchronisiert sie direkt mit der Polycrate API. Im Gegensatz zu server-side Import geschieht die Synchronisation in Echtzeit durch den Operator.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ K8s Ressource │ │ Operator │ │ Polycrate API │
│ (Ingress, etc) │ │ Controller │ │ (Django) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ 1. Watch │ │
│◄──────────────────────│ │
│ │ 2. Create/Update │
│ │──────────────────────►│
│ 3. Annotate │ 4. Response: id │
│ (id, synced-at) │◄──────────────────────│
│◄──────────────────────│ │
│ │ │
│ [Deletion] │ 5. Delete │
│ Finalizer Cleanup │──────────────────────►│
│◄──────────────────────│ │
Erkannte Ressourcen¶
| K8s Ressource | API-Ziel | Discovery Controller |
|---|---|---|
| Ingress | Endpoint | EndpointDiscoveryReconciler |
| Polycrate Meta-Secret | K8sApp | K8sAppDiscoveryReconciler |
Pod mit polycrate_k8sapp_name Annotation | K8sApp | K8sAppLabelDiscoveryReconciler |
| Node | Host | HostDiscoveryReconciler |
| Velero Backup | Backup | BackupDiscoveryReconciler |
| Velero Schedule | BackupSchedule | BackupDiscoveryReconciler |
| cert-manager Certificate | Certificate | CertificateDiscoveryReconciler |
| PersistentVolume | K8sVolume | K8sVolumeDiscoveryReconciler |
| S3Bucket CR | S3Bucket | S3BucketReconciler |
Label-Format seit CLI 0.35.1
Alle vom Operator geschriebenen Labels verwenden das einheitliche Präfix polycrate_* (statt zuvor polycrate.io/* und k8sapps.polycrate.io/*). Beim Lesen akzeptieren die Controller beide Formate (Dual-Support) und migrieren bestehende Ressourcen beim nächsten Reconcile transparent auf das neue Format.
Die Umstellung war nötig, weil Kubernetes Finalizer-Namen als DNS-Subdomain validiert und Werte wie polycrate.io/s3bucket-finalizer nicht mehr akzeptierte. Finalizer folgen jetzt dem Format polycrate.io/<resource>-<purpose> (korrekt FQDN), Labels dem Format polycrate_<key> (ebenfalls gültig).
API-Sync und Selbstreparatur (ab 0.30.4)¶
Der Operator hält discovered Ressourcen automatisch mit der API in Einklang – inkl. Selbstreparatur bei Abweichungen:
| Ressource | Verhalten |
|---|---|
| Endpoint | API-Existenzprüfung: Vor jedem Sync prüft der Operator, ob der Endpoint in der API noch existiert. Wenn die API den Endpoint gelöscht hat (z.B. durch Reconciliation oder manuell), wird er automatisch neu angelegt. |
| K8sApp | Adopt Existing: Wenn eine K8sApp bereits in der API existiert (z.B. durch Workspace-Sync und API-Reconciliation aus Block-Instanzen), übernimmt der Operator deren API-ID statt einen doppelten Eintrag zu erstellen. |
Praktische Auswirkung:
- Endpoints bleiben nach API-Brown-Outs oder manueller Löschung nicht dauerhaft „failed“ – der Operator repariert sie beim nächsten Reconcile.
- K8sApp-Duplikate entstehen nicht mehr, wenn Workspace und API vor dem Operator-Sync aktualisiert wurden.
Label-basierte K8sApp Discovery (ab 0.29.17)¶
Neben der bestehenden Secret-basierten Erkennung (Polycrate CLI Meta-Secrets) kann der Operator auch Pods erkennen, die mit der Annotation polycrate_k8sapp_name versehen wurden. So koennen Apps in der Polycrate API registriert werden, die nicht ueber die Polycrate CLI deployed wurden.
Verwendung¶
Pods (bzw. Deployments/StatefulSets) mit folgender Annotation versehen:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-namespace
spec:
template:
metadata:
annotations:
polycrate_k8sapp_name: my-app
spec:
containers:
- name: app
image: my-registry/my-app:latest
Label-Format (deprecated)
Das alte Label k8sapps.polycrate.io/name wird weiterhin gelesen (Dual-Read) und beim nächsten Reconcile automatisch auf die Annotation polycrate_k8sapp_name migriert.
Regeln¶
- Der Label-Wert muss innerhalb eines Namespaces eindeutig auf eine App zeigen
- Mehrere Pods mit dem gleichen Label-Wert im selben Namespace = 1 K8sApp (mehrere Replicas)
- Wenn der gleiche Label-Wert in mehreren Namespaces vorkommt, wird die App ignoriert (Cross-Namespace-Konflikt)
- Fuer Apps in mehreren Namespaces: Disjunkte Namen verwenden (
my-app-ns-a,my-app-ns-b) - Wenn eine App auch ueber die Polycrate CLI deployed wurde (Meta-Secret existiert), hat die Secret-Discovery Vorrang
Konfiguration¶
app_discovery:
enabled: true
label_discovery_enabled: true # Default: true
watch_namespaces: []
ignore_namespaces:
- kube-system
- kube-public
Unterschiede zur Secret-basierten Discovery¶
| Eigenschaft | Secret-basiert | Annotation-basiert |
|---|---|---|
| Quelle | Polycrate CLI Meta-Secret | Pod mit polycrate_k8sapp_name Annotation |
| Block-Kind | polycrate, helm, etc. | external |
| Block-Version | aus Secret | nicht verfuegbar |
| Pod-Status | alle Pods im Namespace | nur Pods mit passender Annotation |
| Cleanup | bei Secret-Loeschung | wenn keine passenden Pods mehr existieren |
Pod-Status: Job- und CronJob-Pods ausgeschlossen (ab 0.29.16)¶
Der K8sApp-Pod-Status beruecksichtigt keine Pods von Jobs oder CronJobs – z.B. Velero Backup- oder Maintain-Jobs. Diese transienten Pods wuerden die Metriken verfaelschen (Status „Completed“/„Failed“). Nur Pods von Deployments, StatefulSets und DaemonSets fliessen in den K8sApp-Status ein.
Endpoint-K8sApp-Assoziation (ab 0.29.17, Annotation ab 0.38.0)¶
Endpoints aus der Ingress Discovery koennen einer K8sApp zugeordnet werden. Ab Version 0.38.0 wird dafür eine Annotation statt einem Label verwendet:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
polycrate_endpoint_monitor: "true"
polycrate_k8sapp_name: my-app # Verknuepfung mit K8sApp (Annotation, ab 0.38.0)
# Deprecated (Label, wird on-reconcile automatisch entfernt):
# k8sapps.polycrate.io/name: my-app
spec:
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
Migration ab 0.38.0
Das Label k8sapps.polycrate.io/name wird ab 0.38.0 automatisch on-reconcile entfernt. Nutze die Annotation polycrate_k8sapp_name für neue Ingresses.
Die Zuordnung wird im Endpoint CR Status gespeichert und an die API uebermittelt. Dies ermoeglicht spaeter praezisere Downtime Detection pro K8sApp.
Stale-Sweep und Ressourcen-Cleanup (ab 0.29.17)¶
Alle Discovery-Controller verfuegen ueber einen periodischen Stale-Sweep, der verwaiste Custom Resources aufraeumt. Dies ist ein Safety-Net fuer Szenarien, in denen Source-Objekte geloescht werden, ohne dass der Operator die Loeschung direkt mitbekommt.
Funktionsweise¶
- Aktive Loeschung: Wenn ein Source-Objekt (Ingress, Secret, etc.) geloescht wird und der Operator laeuft, werden die zugehoerigen CRs sofort aktiv geloescht
- Stale-Sweep: Periodisch prueft jeder Discovery-Controller, ob die Source-Objekte seiner CRs noch existieren. Verwaiste CRs werden automatisch geloescht
- Finalizer: Der Sync-Controller eines geloeschten CRs sorgt via Finalizer fuer die Entfernung des API-Objekts
Konfiguration¶
Das Sweep-Intervall ist pro Discovery-Controller konfigurierbar:
endpoint_discovery:
stale_cleanup_minutes: 10 # Default: 10
app_discovery:
stale_cleanup_minutes: 10 # Default: 10
backup_discovery:
stale_cleanup_minutes: 10 # Default: 10
certificate_discovery:
stale_cleanup_minutes: 10 # Default: 10
Scope¶
Der Stale-Sweep behandelt ausschliesslich discovered Objekte (Label polycrate_discovered=true). API-zugewiesene Objekte (z.B. Endpoints die ueber die API konfiguriert wurden) haben einen eigenen Lifecycle und werden nicht vom Stale-Sweep betroffen.
Endpoint Discovery: Ingress → API Endpoint¶
Der Operator überwacht Ingress-Objekte und erstellt automatisch Endpoints in der Polycrate API für HTTP-Monitoring.
Discovery-Modi (ab 0.38.0)¶
Ab Version 0.38.0 unterstützt der Operator zwei Entdeckungs-Modi:
| Modus | Verhalten |
|---|---|
annotation (Standard) | Nur Ingresses mit polycrate_endpoint_monitor: "true" werden verarbeitet (opt-in) |
auto | Alle Ingresses werden verarbeitet, außer polycrate_endpoint_monitor: "false" ist gesetzt (opt-out, Legacy-Verhalten) |
Konfiguration in OperatorConfig:
Alle verfügbaren Annotationen (ab 0.38.0)¶
| Annotation (neu, canonical) | Deprecated | Typ | Default | Beschreibung |
|---|---|---|---|---|
polycrate_endpoint_monitor | (ersetzt endpoints.polycrate.io/enabled + ignore) | String | — | "true": Monitor aktivieren (in annotation-Mode Pflicht); "false": Ingress ignorieren |
polycrate_endpoint_path | endpoints.polycrate.io/path | String | / | HTTP-Pfad für Health-Check |
polycrate_endpoint_timeout | endpoints.polycrate.io/timeout | String | "5" | Timeout in Sekunden |
polycrate_endpoint_interval | endpoints.polycrate.io/interval | String | "60" | Check-Intervall in Sekunden |
polycrate_endpoint_expected_status | endpoints.polycrate.io/expected-status | String | "200" | Erwarteter HTTP-Status |
polycrate_endpoint_tls | endpoints.polycrate.io/tls | String | — | TLS-Konfiguration |
polycrate_endpoint_port | endpoints.polycrate.io/port | String | 443 | Port für Health-Check |
Dual-Read: Rückwärtskompatibilität
Alle alten endpoints.polycrate.io/* Annotationen werden weiterhin gelesen (als Fallback). Neue polycrate_* Annotationen haben Vorrang. Migriere schrittweise auf das neue Format.
Endpoint Custom Resources
Der Operator erstellt für jeden Hostname im Ingress eine separate Endpoint Custom Resource. Die API-ID wird im Status der Endpoint CR gespeichert, nicht als Annotation auf dem Ingress.
Beispiel 1: Minimale Konfiguration (annotation-Mode)¶
Im Standard-Modus (annotation) muss der Ingress explizit opt-in:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp
namespace: production
annotations:
# Opt-in für Endpoint-Monitoring (Pflicht im annotation-Mode)
polycrate_endpoint_monitor: "true"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp
port:
number: 80
Ergebnis: Endpoint mit GET / auf https://app.example.com:443, Timeout 30s, Intervall 60s.
Beispiel 2: Custom Health-Check Pfad¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-service
namespace: production
annotations:
polycrate_endpoint_monitor: "true"
# Health-Check auf /api/health statt Root
polycrate_endpoint_path: "/api/health"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 8080
Ergebnis: Endpoint mit GET /api/health auf https://api.example.com:443.
Beispiel 3: Kritischer Service mit kurzem Intervall¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: payment-gateway
namespace: production
annotations:
polycrate_endpoint_monitor: "true"
# Kritischer Service: Häufigere Checks
polycrate_endpoint_path: "/health/ready"
polycrate_endpoint_interval: "30"
polycrate_endpoint_timeout: "10"
polycrate_endpoint_expected_status: "200"
spec:
ingressClassName: nginx
tls:
- hosts:
- pay.example.com
secretName: payment-tls
rules:
- host: pay.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: payment-api
port:
number: 443
Ergebnis: Endpoint mit 30s Intervall (statt 60s), 10s Timeout, erwartet HTTP 200.
Beispiel 4: Body-Validierung für Deep Health-Check¶
Nicht von der Discovery unterstützt
Die Annotation endpoints.polycrate.io/expected-body wird von der Ingress-Discovery nicht ausgewertet. Der Operator befüllt spec.check_config beim Discovery-Reconcile nicht aus Ingress-Annotationen. Body-Validierung muss direkt über die Polycrate API oder manuell in der Endpoint CR konfiguriert werden.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: database-api
namespace: production
annotations:
polycrate_endpoint_monitor: "true"
polycrate_endpoint_path: "/health/deep"
polycrate_endpoint_expected_status: "200"
# Prüft ob "database":"connected" im Response-Body enthalten ist
endpoints.polycrate.io/expected-body: '"database":"connected"'
spec:
ingressClassName: nginx
tls:
- hosts:
- db-api.example.com
secretName: db-api-tls
rules:
- host: db-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: db-api
port:
number: 8080
Ergebnis: Check ist nur erfolgreich wenn HTTP 200 UND Body enthält "database":"connected".
Beispiel 5: Ingress von Discovery ausschließen¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: internal-admin
namespace: kube-system
annotations:
# Diesen Ingress NICHT monitoren (in beiden Modi wirksam)
polycrate_endpoint_monitor: "false"
spec:
ingressClassName: nginx
rules:
- host: admin.internal.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-dashboard
port:
number: 80
Ergebnis: Kein Endpoint wird erstellt. Nützlich für interne Services oder Test-Umgebungen.
Beispiel 6: Langsamer Backend-Service¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: report-generator
namespace: production
annotations:
# Report-Generierung braucht länger
polycrate_endpoint_monitor: "true"
polycrate_endpoint_path: "/api/health"
polycrate_endpoint_timeout: "120"
polycrate_endpoint_interval: "300"
spec:
ingressClassName: nginx
tls:
- hosts:
- reports.example.com
secretName: reports-tls
rules:
- host: reports.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: report-service
port:
number: 8080
Ergebnis: 120s Timeout, 5-Minuten-Intervall für langsame Services.
Beispiel 7: Redirect-fähiger Endpoint (3xx erlauben)¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: legacy-app
namespace: production
annotations:
polycrate_endpoint_monitor: "true"
polycrate_endpoint_path: "/"
# Redirect ist OK (z.B. HTTP→HTTPS oder /→/login)
polycrate_endpoint_expected_status: "302"
spec:
ingressClassName: nginx
rules:
- host: legacy.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: legacy-app
port:
number: 80
Beispiel 8: Komplettes Produktions-Setup¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-api
namespace: production
labels:
app: main-api
environment: production
annotations:
# === Polycrate Endpoint Discovery ===
polycrate_endpoint_monitor: "true"
polycrate_endpoint_path: "/api/v1/health"
polycrate_endpoint_timeout: "15"
polycrate_endpoint_interval: "30"
polycrate_endpoint_expected_status: "200"
# === Nginx Ingress Controller ===
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
# === Cert-Manager ===
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.mycompany.com
secretName: api-tls-cert
rules:
- host: api.mycompany.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /docs
pathType: Prefix
backend:
service:
name: docs-service
port:
number: 80
Endpoint Custom Resource¶
Für jeden Hostname in einem Ingress erstellt der Operator eine separate Endpoint Custom Resource:
apiVersion: polycrate.io/v1alpha1
kind: Endpoint
metadata:
name: app-example-com
namespace: production
labels:
endpoints.polycrate.io/source-ingress: webapp
polycrate_discovered: "true"
spec:
displayName: "app.example.com"
remoteAddress: "app.example.com"
remotePort: 443
kind: "http"
tls: true
path: "/api/health"
timeout: 30
interval: 60
expectedStatusCodes: [200]
status:
phase: "synced"
apiID: "550e8400-e29b-41d4-a716-446655440000"
configHash: "abc123..."
Vorteile des CRD-Modells:
- Klare 1:1 Zuordnung: Jeder Hostname = eine CR = eine API-ID
- Garbage Collection: OwnerReferences ermöglichen automatisches Cleanup
- Einfaches Debugging:
kubectl get endpoints.polycrate.iozeigt alle Endpoints
# Alle Endpoint CRs anzeigen
kubectl get endpoints.polycrate.io -A
# Details einer Endpoint CR
kubectl describe endpoint app-example-com -n production
Endpoint CRs nicht manuell ändern
Die Endpoint CRs werden vom Operator verwaltet. Änderungen an Annotations auf dem Ingress werden automatisch synchronisiert.
Endpoint Monitoring: Operator → API → Agent¶
Der Operator ist der erste Schritt in der Monitoring-Pipeline. Nach der Synchronisation mit der API übernehmen Monitoring-Agents die eigentlichen HTTP-Checks.
Architektur-Übersicht¶
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ Ingress Polycrate Operator ││
│ │ + Annotations ───► Endpoint Discovery ││
│ │ + API Sync ││
│ └─────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────┘
│ │
│ ▼
│ ┌─────────────────┐
│ │ Polycrate API │
│ │ - Endpoints │
│ │ - Agent-Zuweis.│
│ └─────────────────┘
│ │
│ ▼
│ ┌─────────────────┐
│◄────────────────────│ Monitoring Agent│
│ HTTP Check │ - Fetch Config │
│ │ - Execute Check │
│ │ - Prometheus │
└─────────────────────┴─────────────────┘
Datenfluss im Detail¶
| Schritt | Komponente | Aktion |
|---|---|---|
| 1 | Ingress | Annotation polycrate_endpoint_path=/health gesetzt |
| 2 | Operator | Erkennt Ingress, erstellt Endpoint CRD mit spec.path |
| 3 | Operator | Synchronisiert CRD mit API (spec.http.path) |
| 4 | API | Speichert Endpoint, weist Agents zu |
| 5 | Agent | Fragt zugewiesene Endpoints ab (inkl. spec) |
| 6 | Agent | Baut Check-URL: https://host:443/health |
| 7 | Agent | Führt HTTP-Check aus, exposed Prometheus-Metriken |
Änderungen propagieren¶
Wenn Sie eine Annotation ändern, wird die Änderung automatisch propagiert:
# Annotation ändern
kubectl annotate ingress my-app \
polycrate_endpoint_path="/api/v2/health" \
--overwrite
Propagierungs-Kette:
- Sofort: Kubernetes triggert Operator-Reconciliation
- Sofort: Operator erkennt geändertes
path, aktualisiert CRD - Sofort: CRD-Änderung triggert API-Sync
- ~60s: Agent holt bei nächstem Refresh neue Konfiguration
- Nächster Check: Agent prüft gegen neue URL
Latenz
Annotation-Änderungen sind typischerweise innerhalb von 1-2 Minuten aktiv.
Prometheus-Metriken¶
Die Monitoring-Agents exposen Check-Ergebnisse als Prometheus-Metriken:
# Endpoint-Verfügbarkeit
probe_success{endpoint="api-example-com", organization="acme-corp"}
# Response-Zeit in Sekunden
probe_duration_seconds{endpoint="api-example-com"}
# HTTP Status Code
probe_http_status_code{endpoint="api-example-com"}
Diese Metriken werden von VictoriaMetrics/Prometheus gescraped und stehen für Alerting und Dashboards zur Verfügung.
→ Ausführliche Agent-Dokumentation: Polycrate API - Endpoint Monitoring
Finalizer: Automatisches Cleanup¶
Der Operator setzt einen Finalizer auf alle entdeckten Ressourcen:
Workflow bei Deletion:
- User löscht Ingress:
kubectl delete ingress webapp - Kubernetes setzt
deletionTimestampauf Ingress - Operator erkennt Deletion, führt Cleanup durch:
- Löscht Endpoint aus Polycrate API via
DELETE /api/v1/endpoints/{id}/ - Operator entfernt Finalizer
- Kubernetes löscht Ingress-Objekt
Dies stellt sicher, dass API-Objekte immer mit ihren K8s-Quellen synchron bleiben.
K8sApp Discovery: Meta-Secrets → API¶
Polycrate Blocks erstellen Meta-Secrets die vom Operator als K8sAppInstances synchronisiert werden.
Meta-Secret Format¶
apiVersion: v1
kind: Secret
metadata:
name: polycrate-myapp-meta
namespace: production
labels:
polycrate_managed_by: cli
polycrate_object_type: meta
data:
# Base64-encoded
organization: YWNtZS1jb3Jw # acme-corp
workspace: cHJvZHVjdGlvbg== # production
block: bXlhcHA= # myapp
name: bXlhcHA= # myapp
namespace: cHJvZHVjdGlvbg== # production
Der Operator:
- Findet Secrets mit Labels
polycrate_managed_by=cliundpolycrate_object_type=meta - Löst
organizationundworkspaceNamen zu UUIDs auf (API-Lookup) - Erstellt/aktualisiert K8sAppInstance in API
Host Discovery: Nodes → API¶
Kubernetes Nodes werden automatisch als Hosts in der API erfasst.
Gemappte Felder¶
| Node-Feld | Host-Feld | Quelle |
|---|---|---|
metadata.name | name, hostname | Node Name |
status.addresses[ExternalIP] | default_ipv4 | Node IP |
status.capacity.cpu | resource_cpu_cores | CPU Cores |
status.capacity.memory | resource_memory | Memory (MB) |
status.nodeInfo.architecture | resource_cpu_architecture | Architecture |
spec.providerID | provider_id | Cloud Provider ID |
Backup Discovery: Velero → API¶
Velero Backups und Schedules werden automatisch zur API synchronisiert.
Backup-Mapping¶
| Velero Backup | API Backup | Mapping |
|---|---|---|
metadata.name | name | Direkt |
status.phase | status | Completed→completed, Failed→failed |
spec.ttl | retention_policy | TTL als String |
status.startTimestamp | started_at | ISO 8601 |
status.completionTimestamp | completed_at | ISO 8601 |
status.progress.itemsBackedUp | items_backed_up | Integer |
Schedule-Mapping¶
| Velero Schedule | API BackupSchedule | Mapping |
|---|---|---|
metadata.name | name | Direkt |
spec.schedule | schedule_cron | Cron-Expression |
spec.paused | paused | Boolean |
status.lastBackup.startTime | last_backup_at | Timestamp |
status.lastBackup.name | last_backup_name | String |
Certificate Discovery: cert-manager → API¶
Der Operator überwacht cert-manager Certificate CRs und synchronisiert sie mit der Polycrate API für zentrales TLS-Zertifikatsmanagement.
Voraussetzungen¶
- cert-manager muss im Cluster installiert sein
- Der Operator erkennt automatisch ob cert-manager CRDs vorhanden sind
- Falls cert-manager nicht installiert ist, wird der
CertificateDiscoveryControllerübersprungen
Architektur¶
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────────┐ │
│ │ cert-manager │ │ Polycrate Operator │ │
│ │ Certificate CR │────►│ CertificateDiscoveryController │ │
│ │ (cert-manager.io)│ │ ▼ │ │
│ └──────────────────┘ │ polycrate.io/Certificate CR │ │
│ │ ▼ │ │
│ │ CertificateController │ │
│ │ │ │ │
│ └───────────┼──────────────────────┘ │
└───────────────────────────────────────┼──────────────────────────┘
│
▼
┌─────────────────┐
│ Polycrate API │
│ /certificates/ │
└─────────────────┘
Zwei-Controller-Architektur¶
| Controller | Watchet | Erstellt/Aktualisiert |
|---|---|---|
CertificateDiscoveryController | cert-manager Certificate | polycrate.io Certificate CR |
CertificateController | polycrate.io Certificate | API-Objekt via REST |
Vorteile:
- CRD-basiert: Zertifikate sind als Kubernetes-Ressourcen sichtbar (
kubectl get certificates.polycrate.io) - Finalizer-Cleanup: Automatische API-Deletion bei K8s-Deletion
- Change Detection: Hash-basierte Änderungserkennung verhindert unnötige API-Updates
- Inventarprüfung: API-Objekte werden bei jedem Reconcile auf Existenz geprüft
Certificate CRD¶
Für jedes cert-manager Certificate erstellt der Operator eine polycrate.io/Certificate CR:
apiVersion: polycrate.io/v1alpha1
kind: Certificate
metadata:
name: certmanager-production-api-example-com-tls
namespace: production
labels:
certificates.polycrate.io/issuer: letsencrypt-production
certificates.polycrate.io/source: api-example-com-tls
certificates.polycrate.io/ready: "true"
operator.polycrate.io/discovered: "true"
spec:
name: api-example-com-tls
display_name: "api.example.com-tls"
namespace: production
secret_name: api-example-com-tls
dns_names:
- api.example.com
issuer_name: letsencrypt-production
issuer_kind: clusterissuer
issuer_group: cert-manager.io
certificate_status: ready
is_ready: true
not_before: "2024-01-01T00:00:00Z"
not_after: "2024-04-01T00:00:00Z"
renewal_time: "2024-03-01T00:00:00Z"
source_cert_manager:
name: api-example-com-tls
namespace: production
uid: "abc-123-..."
revision: 1
status:
phase: Synced
sync_status: synced
api_id: "550e8400-e29b-41d4-a716-446655440000"
config_hash: "abc123..."
last_synced_at: "2024-01-15T10:30:00Z"
API-Mapping¶
| cert-manager Certificate | Polycrate Certificate CR | API Certificate |
|---|---|---|
metadata.name | spec.source_cert_manager.name | - (Referenz) |
spec.secretName | spec.secret_name | secret_name |
spec.dnsNames | spec.dns_names | dns_names |
spec.ipAddresses | spec.ip_addresses | ip_addresses |
spec.issuerRef.name | spec.issuer_name | issuer_name |
spec.issuerRef.kind | spec.issuer_kind | issuer_kind |
status.notBefore | spec.not_before | not_before |
status.notAfter | spec.not_after | not_after |
status.renewalTime | spec.renewal_time | renewal_time |
| Ready Condition | spec.is_ready, spec.certificate_status | is_ready, certificate_status |
Status-Mapping¶
| cert-manager Status | certificate_status |
|---|---|
| Ready=True | ready |
| Ready=False, Reason=Issuing | pending |
| Ready=False, Reason=Failed | failed |
| Ready=True, NotAfter < now | expired |
| Ready=True, NotAfter < now+30d | expiring_soon |
OperatorConfig: Certificate Discovery¶
apiVersion: polycrate.io/v1alpha1
kind: OperatorConfig
metadata:
name: default
namespace: polycrate
spec:
# ... andere Konfiguration ...
# Certificate-Discovery (cert-manager → API)
certificate_discovery:
enabled: true
watch_namespaces: [] # Leer = alle Namespaces
ignore_namespaces: # Diese Namespaces ignorieren
- kube-system
- cert-manager
issuer_filter: # Optional: Nur bestimmte Issuers
include_issuers: [] # Leer = alle Issuers
exclude_issuers: # Diese Issuers ignorieren
- selfsigned-issuer
CLI-Commands¶
# Alle Certificate CRs anzeigen
kubectl get certificates.polycrate.io -A
# Certificate-Details anzeigen
kubectl describe certificate.polycrate.io certmanager-production-api-example-com-tls -n production
# API-Sync-Status prüfen
kubectl get certificates.polycrate.io -A -o custom-columns=\
NAME:.metadata.name,\
NAMESPACE:.metadata.namespace,\
ISSUER:.spec.issuer_name,\
READY:.spec.is_ready,\
STATUS:.spec.certificate_status,\
SYNC:.status.sync_status,\
API_ID:.status.api_id
Verwendung in der Polycrate API¶
Die synchronisierten Zertifikate sind in der Polycrate API unter /api/v1/certificates/ verfügbar:
- Zentrales Zertifikatsmanagement: Alle Cluster-Zertifikate auf einen Blick
- Ablaufwarnungen: Automatische Benachrichtigungen bei
expiring_soon - Compliance: Übersicht über alle TLS-Endpunkte und deren Zertifikate
- Korrelation: Verknüpfung mit Endpoints und K8sClusters
K8sApp Discovery: Deployed Blocks → API¶
Der Operator erkennt automatisch deployte Polycrate Blocks anhand der Meta-Secrets (*.poly) und erstellt K8sApp Custom Resources.
Architektur¶
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────────┐ │
│ │ Meta-Secret │ │ Polycrate Operator │ │
│ │ (*.poly) │────►│ K8sAppDiscoveryController │ │
│ │ │ │ ▼ │ │
│ └──────────────────┘ │ polycrate.io/K8sApp CR │ │
│ │ ▼ │ │
│ │ K8sAppController │ │
│ │ │ │ │
│ └───────────┼──────────────────────┘ │
└───────────────────────────────────────┼──────────────────────────┘
│
▼
┌─────────────────┐
│ Polycrate API │
│ /k8sapps/ │
└─────────────────┘
K8sApp CRD¶
Für jedes Meta-Secret erstellt der Operator eine K8sApp CR:
apiVersion: polycrate.io/v1alpha1
kind: K8sApp
metadata:
name: nginx-ingress
namespace: production
labels:
k8sapps.polycrate.io/block: nginx-ingress
k8sapps.polycrate.io/kind: helm
k8sapps.polycrate.io/type: ingress-controller
operator.polycrate.io/discovered: "true"
ownerReferences:
- apiVersion: v1
kind: Secret
name: nginx-ingress.poly
uid: abc-123-...
spec:
block:
name: "nginx-ingress"
display_name: "NGINX Ingress Controller"
version: "1.2.0"
app_version: "1.9.6"
from: "cargo.ayedo.cloud/ayedo/k8s/nginx-ingress"
type: "ingress-controller"
flavor: "nginx"
chart:
name: "ingress-nginx"
version: "4.9.0"
repo_url: "https://kubernetes.github.io/ingress-nginx"
workspace:
name: "production"
organization: "acme-corp"
action:
name: "install"
status: "success"
last_executed_at: "2025-12-20T10:00:00Z"
status:
phase: Synced
installed: true
api_id: "550e8400-e29b-41d4-a716-446655440000"
sync_status: synced
artifacts:
- name: "cargo-ayedo-cloud-library-nginx-1-25-3"
image: "cargo.ayedo.cloud/library/nginx:1.25.3"
pod_count: 3
artifact_count: 2
CLI-Commands¶
# Alle K8sApps anzeigen
kubectl get k8sapps -A
# Ausgabe:
# NAMESPACE NAME BLOCK VERSION ARTIFACTS PHASE AGE
# prod nginx-ingress nginx-ingress 1.2.0 3 Synced 7d
# prod redis redis 7.2.0 1 Synced 14d
# Details anzeigen
kubectl describe k8sapp nginx-ingress -n prod
Installation-Status Ableitung¶
Der Operator leitet den Installation-Status aus dem letzten Action-Run ab:
| action_name | action_status | Ergebnis |
|---|---|---|
install | success | installed=true |
install | running | installation_running=true |
install | failed | installation_failed=true |
uninstall | success | uninstalled=true |
Block-ID Verknüpfung¶
Bei der API-Synchronisierung wird automatisch die Block-ID aufgelöst:
- Workspace aus
spec.workspace.name+spec.workspace.organizationfinden - Block aus
spec.block.nameim Workspace finden - K8sApp mit Block-ID an API senden
Dies ermöglicht vollständige Korrelation zwischen K8sApp ↔ Block ↔ Workspace in der API.
S3Bucket Provisioning: CR → API → Secret (ab 0.35.0)¶
Der Operator kann S3 Buckets deklarativ über Custom Resources provisionieren. Ein Kubernetes-User erstellt eine S3Bucket CR — der Operator erstellt den Bucket in der Polycrate API und legt die Access Credentials als Secret im Namespace ab.
Verwendung¶
apiVersion: polycrate.io/v1alpha1
kind: S3Bucket
metadata:
name: my-app-data
namespace: production
spec:
name: my-app-data
region: fsn1
reclaim_policy: retain
| Feld | Pflicht | Default | Beschreibung |
|---|---|---|---|
spec.name | Ja | - | Name des S3 Buckets |
spec.region | Nein | default_s3_bucket_cluster aus SystemConfig | Region-String (muss einem S3Cluster in der API entsprechen) |
spec.reclaim_policy | Nein | retain | retain = Bucket bleibt bei CR-Löschung, delete = Bucket wird gelöscht |
Credential Secret¶
Der Operator erstellt automatisch ein Secret s3-<bucket-name>-credentials im Namespace der CR:
apiVersion: v1
kind: Secret
metadata:
name: s3-my-app-data-credentials
namespace: production
labels:
polycrate_managed_by: operator
polycrate_object_type: s3-credentials
polycrate_s3_bucket_name: my-app-data
polycrate_s3_bucket_region: fsn1
ownerReferences:
- apiVersion: polycrate.io/v1alpha1
kind: S3Bucket
name: my-app-data
type: Opaque
stringData:
AWS_ACCESS_KEY_ID: "<access-key>"
AWS_SECRET_ACCESS_KEY: "<secret-key>"
S3_ENDPOINT: "https://s3.fsn1.example.com"
S3_REGION: "fsn1"
BUCKET_NAME: "my-app-data"
Das Secret wird über ownerReferences an die CR gebunden — bei CR-Löschung wird es automatisch entfernt.
Status-Phasen¶
| Phase | Bedeutung |
|---|---|
Pending | CR erstellt, Verarbeitung steht aus |
Provisioning | Bucket wird in der API erstellt |
WaitingForCredentials | Bucket existiert, Credentials werden abgerufen |
Ready | Bucket und Secret sind verfügbar |
Error | Fehler bei Provisioning oder Credential-Abruf |
Adopt-Pattern¶
Wenn ein Bucket mit dem angegebenen Namen und der Region bereits in der API existiert, wird er übernommen (Adopt). Der Operator erstellt nur das Credential Secret — der Bucket wird nicht doppelt angelegt.
Konfiguration¶
apiVersion: polycrate.io/v1alpha1
kind: OperatorConfig
metadata:
name: default
namespace: polycrate
spec:
s3_bucket_provisioning:
enabled: true # Default: true (ab 0.35.0)
Default-Region¶
Wenn keine region in der CR angegeben ist, verwendet der Operator die default_s3_bucket_cluster-Einstellung aus der Polycrate API SystemConfig. Diese kann im Dashboard unter System Settings konfiguriert werden.