Benutzer-Werkzeuge

Webseiten-Werkzeuge


blog:automatisches_paperless-ngx_backup_in_kubernetes_cronjobs_mit_dynamischer_pod-ermittlung

Automatisches Paperless-ngx Backup in Kubernetes: CronJobs mit dynamischer Pod-Ermittlung

Manchmal ist es notwendig, in einem Kubernetes-Cluster regelmäßig Aufgaben auszuführen, die sich auf laufende Anwendungspods beziehen. Denken Sie an die Erstellung von Backups, das Generieren von Berichten oder das Ausführen von Wartungsskripten. Kubernetes bietet hierfür CronJobs an. Doch was, wenn der Ziel-Pod für Ihre Aufgabe nicht immer denselben Namen hat, weil er zum Beispiel bei jedem Deployment neu erstellt wird oder dynamisch skaliert wird?

Genau hier kommt die dynamische Pod-Ermittlung in Kubernetes CronJobs ins Spiel! In diesem Blogbeitrag zeigen wir Ihnen, wie Sie einen Kubernetes CronJob konfigurieren, der den zu interagierenden Pod dynamisch zur Laufzeit identifiziert. Dies macht Ihre Automatisierung robuster und wartungsfreundlicher, da Sie den CronJob nicht bei jeder Pod-Änderung anpassen müssen.


Warum dynamische Pod-Ermittlung?

Stellen Sie sich vor, Sie haben eine Anwendung wie Paperless-ngx, die in einem Kubernetes-Deployment läuft. Jedes Mal, wenn Sie ein Update bereitstellen oder die Anwendung neu startet, könnte der Pod, in dem die Hauptanwendung läuft, einen neuen Namen erhalten (z.B. paperless-ngx-789abcde-xyz12). Wenn Ihr CronJob fest an einen spezifischen Pod-Namen gebunden wäre, würde er fehlschlagen, sobald der Pod-Name sich ändert.

Durch die dynamische Ermittlung des Pod-Namens zur Laufzeit des CronJobs umgehen wir dieses Problem vollständig. Der CronJob sucht einfach nach einem Pod, der bestimmte Kriterien erfüllt (z.B. ein spezifisches Label), und führt den Befehl dann im aktuell gefundenen Pod aus.

Das Kernstück: Der Kubernetes CronJob

Das Herzstück unserer Lösung ist der Kubernetes CronJob. Er definiert den Zeitplan und die auszuführende Aufgabe. Werfen wir einen Blick auf die entscheidenden Teile des Manifests:

# =================================================================
#  ServiceAccount, Role, RoleBinding
# =================================================================
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubectl-exec-sa
  namespace: paperless-production # <-- Anpassen
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-exec-role
  namespace: paperless-production # <-- Anpassen
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-exec-binding
  namespace: paperless-production # <-- Anpassen
subjects:
  - kind: ServiceAccount
    name: kubectl-exec-sa
    namespace: paperless-production # <-- Anpassen
roleRef:
  kind: Role
  name: pod-exec-role
  apiGroup: rbac.authorization.k8s.io
---
# =================================================================
#  CronJob (mit dynamischer Pod-Ermittlung)
# =================================================================
apiVersion: batch/v1
kind: CronJob
metadata:
  name: run-document-exporter-dynamic
  namespace: paperless-production # <-- Anpassen
spec:
  timeZone: Europe/Berlin # Zeitzone für den Zeitplan

  schedule: "12 5 * * *" # Jeden Tag um 05:12 Uhr

  concurrencyPolicy: Forbid # Verhindert parallele Ausführungen
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1

  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: kubectl-exec-sa # Verwendet das ServiceAccount für die Berechtigungen
          restartPolicy: OnFailure
          containers:
            - name: kubectl-executor
              image: bitnami/kubectl:1.29 # Ein Container mit kubectl
              command:
                - "sh"
                - "-c"
                - |
                  set -e # Bricht bei Fehlern ab
                  echo "Suche nach einem laufenden Pod mit dem Label-Selector '$TARGET_POD_LABEL_SELECTOR' im Namespace '$KUBERNETES_NAMESPACE'..."
 
                  # Finde den Namen des ERSTEN laufenden Pods, der dem Label-Selector entspricht.
                  TARGET_POD_NAME=$(kubectl get pods --namespace "$KUBERNETES_NAMESPACE" -l "$TARGET_POD_LABEL_SELECTOR" --field-selector=status.phase=Running -o jsonpath='{.items[0].metadata.name}')
 
                  # Überprüfe, ob ein Pod-Name gefunden wurde.
                  if [ -z "$TARGET_POD_NAME" ]; then
                    echo "FEHLER: Kein laufender Pod mit dem Label-Selector '$TARGET_POD_LABEL_SELECTOR' gefunden."
                    exit 1
                  fi
 
                  echo "Pod '$TARGET_POD_NAME' gefunden. Führe Befehl im Container '$TARGET_CONTAINER_NAME' aus..."
 
                  # Führe den eigentlichen Befehl aus, jetzt mit dem dynamisch ermittelten Pod-Namen
                  kubectl exec --namespace "$KUBERNETES_NAMESPACE" "$TARGET_POD_NAME" -c "$TARGET_CONTAINER_NAME" -- /bin/sh -c "document_exporter ../export -z --delete"
 
                  echo "Befehlsausführung erfolgreich abgeschlossen."

              env:
                - name: TARGET_POD_LABEL_SELECTOR
                  value: "app.kubernetes.io/name=paperless-ngx" # <-- Anpassen: Label des Ziel-Pods
 
                # - name: TARGET_CONTAINER_NAME
                #   value: "<NAME_DES_ZIEL-CONTAINERS_HIER_EINFUEGEN>" # <-- Anpassen (optional): Name des Ziel-Containers

                - name: KUBERNETES_NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace # Der Namespace wird automatisch bereitgestellt

Erläuterung der Schlüsselkomponenten

  • ServiceAccount, Role, RoleBinding:
    • ServiceAccount (kubectl-exec-sa): Dieses Dienstkonto wird dem CronJob zugewiesen, um ihm die notwendigen Berechtigungen innerhalb des Clusters zu geben.
    • Role (pod-exec-role): Diese Rolle definiert die Berechtigungen. Hier erlauben wir dem ServiceAccount, Pods zu get (abzurufen) und zu list (aufzulisten) sowie pods/exec (create) zu nutzen, um Befehle in einem Pod auszuführen.
    • RoleBinding (pod-exec-binding): Dieses Binding verknüpft das ServiceAccount mit der Role im angegebenen namespace.
  • CronJob (run-document-exporter-dynamic):
    • namespace: paperless-production: Stellen Sie sicher, dass dieser Namespace zu Ihrem tatsächlichen Anwendungs-Namespace passt.
    • timeZone: Europe/Berlin: Wichtig für die korrekte Planung der Ausführung, insbesondere bei Sommer- und Winterzeitumstellungen.
    • schedule: „12 5 * * *“: Dies ist der Cron-String. In diesem Beispiel bedeutet er „jeden Tag um 5:12 Uhr“. Passen Sie ihn an Ihre Bedürfnisse an.
    • concurrencyPolicy: Forbid: Verhindert, dass neue Job-Instanzen gestartet werden, wenn eine vorherige Instanz noch läuft. Dies ist oft ratsam für Wartungsaufgaben.
    • successfulJobsHistoryLimit und failedJobsHistoryLimit: Legt fest, wie viele vergangene Job-Ausführungen im Kubernetes-API gespeichert werden. Nützlich für die Fehlerbehebung.
    • serviceAccountName: kubectl-exec-sa: Verbindet den Job mit dem zuvor definierten ServiceAccount.
    • image: bitnami/kubectl:1.29: Dieser Container enthält das kubectl-Tool, das wir für die Pod-Ermittlung und Befehlsausführung benötigen. Stellen Sie sicher, dass Sie eine passende Version für Ihre Kubernetes-Cluster-Version verwenden.
  • Dynamische Logik im command Sektion:
    • set -e: Stellt sicher, dass das Skript sofort beendet wird, wenn ein Befehl fehlschlägt. Das ist eine gute Praxis für Shell-Skripte.
    • TARGET_POD_NAME=$(kubectl get pods … -o jsonpath='{.items[0].metadata.name}'): Dies ist der Kern der dynamischen Ermittlung.
      • kubectl get pods: Listet die Pods auf.
      • –namespace „$KUBERNETES_NAMESPACE“: Sucht im aktuellen Namespace.
      • -l „$TARGET_POD_LABEL_SELECTOR“: Filtert die Pods nach einem bestimmten Label. Sie müssen den Wert für TARGET_POD_LABEL_SELECTOR anpassen, um Ihre Ziel-Anwendung zu identifizieren (z.B. app.kubernetes.io/name=paperless-ngx).
      • –field-selector=status.phase=Running: Stellt sicher, dass nur laufende Pods berücksichtigt werden.
      • -o jsonpath='{.items[0].metadata.name}: Extrahiert den Namen des ersten gefundenen Pods aus der JSON-Ausgabe.
    • Fehlerbehandlung: Das Skript prüft, ob ein Pod-Name gefunden wurde. Wenn nicht, wird eine Fehlermeldung ausgegeben und das Skript mit exit 1 beendet.
    • kubectl exec –namespace „$KUBERNETES_NAMESPACE“ „$TARGET_POD_NAME“ -c „$TARGET_CONTAINER_NAME“ – /bin/sh -c „document_exporter ../export -z –delete“: Sobald der Pod-Name ermittelt wurde, wird der eigentliche Befehl (document_exporter ../export -z –delete) im Ziel-Pod ausgeführt.
      • TARGET_CONTAINER_NAME: Optional können Sie auch den Namen des spezifischen Containers im Pod angeben, falls der Pod mehrere Container hat und der Befehl in einem bestimmten Container ausgeführt werden muss. Wenn nicht angegeben, versucht kubectl exec den Befehl im ersten Container des Pods auszuführen
      • TARGET_POD_LABEL_SELECTOR: Diesen Wert müssen Sie anpassen, um das spezifische Label Ihrer Anwendung zu verwenden. Zum Beispiel: value: „app=my-web-app“ oder value: „app.kubernetes.io/name=my-application“.
      • KUBERNETES_NAMESPACE: Dieser Wert wird automatisch über die Downward API aus den Metadaten des Jobs bezogen, was die Konfiguration flexibler macht.

Anpassung und Bereitstellung

Bevor Sie dieses Manifest anwenden, stellen Sie sicher, dass Sie die folgenden Platzhalter in den Kommentaren (# ←- Anpassen) und den env-Variablen aktualisieren:

  • namespace: Ersetzen Sie paperless-production durch den tatsächlichen Namespace Ihrer Anwendung.
  • TARGET_POD_LABEL_SELECTOR: Dies ist das wichtigste Element. Ersetzen Sie app.kubernetes.io/name=paperless-ngx durch den Label-Selector, der Ihren Ziel-Pod eindeutig identifiziert. Sie können kubectl get pods -n <your-namespace> –show-labels verwenden, um die Labels Ihrer Pods zu überprüfen.
  • TARGET_CONTAINER_NAME (optional): Wenn Ihr Ziel-Pod mehrere Container hat und Sie den Befehl in einem bestimmten Container ausführen müssen, uncommenten Sie diese Zeile und geben Sie den Containernamen an.

Sobald Sie die Anpassungen vorgenommen haben, können Sie das Manifest mit kubectl apply -f your-cronjob-manifest.yaml in Ihrem Kubernetes-Cluster bereitstellen.

Fazit

Die Verwendung der dynamischen Pod-Ermittlung in Kubernetes CronJobs ist eine elegante Lösung, um Ihre geplanten Aufgaben widerstandsfähiger gegen Änderungen in Ihrer Pod-Infrastruktur zu machen. Es reduziert den Wartungsaufwand und sorgt dafür, dass Ihre Automatisierung auch in dynamischen Umgebungen zuverlässig funktioniert.

blog/automatisches_paperless-ngx_backup_in_kubernetes_cronjobs_mit_dynamischer_pod-ermittlung.txt · Zuletzt geändert: von marko