dlt Skalierung: Multi-Pipeline & Secrets Management
Dieser Beitrag zur dlt Skalierung ist Teil unserer Blog Post Serie zu dlt und setzt Grundkenntnisse in Airflow, AWS und Snowflake voraus. Wenn du neu bei dlt bist, empfehlen wir, zuerst unseren ersten Beitrag zu lesen, in dem wir erklären, warum wir dlt eingeführt und wie wir es in unseren Data Stack integriert haben.
Die Herausforderung: dlt skalieren
dlt funktioniert hervorragend, solange man eine einzige Umgebung nutzt oder wenn mehrere Pipelines dieselben Quellen und Ziele teilen. In solchen Fällen reicht eine einzelne .toml-Konfiguration oder Umgebungsvariablen mit Zugangsdaten, Schema-Definitionen und Zielsystemen völlig aus. Lokale Läufe sind damit reibungslos und vorhersehbar.
Die Realität sieht allerdings oftmals anders aus:
- Wir betreiben Dutzende gleichzeitiger dlt-Pipelines.
- Wir integrieren Dutzende Marketingquellen – viele davon mit mehreren Accounts und jeweils eigenen Zugangsdaten.
- Wir verwalten mehrere Snowflake-Zielsysteme.
- Die Pipelines werden über MWAA (Managed Airflow) orchestriert, der Code liegt in GitHub und wird über S3 bereitgestellt.
In diesem Setup wurden dlt’s empfohlene statische .toml-Konfigurationen und der Einsatz von Umgebungsvariablen schnell zum Skalierungsengpass. Der One-size-fits-all-Ansatz konnte die Vielfalt an Quellen, Zielen und parallelen Läufen in unserer Cloud-Umgebung schlicht nicht abbilden.
Wo es anfing, schwierig zu werden
Als wir versuchten, dlt über eine einzelne Umgebung hinaus zu skalieren, wurden die Grenzen statischer .toml-Dateien deutlich:
1. Parameter Store Limits
AWS begrenzt die Größe gespeicherter Parameter. Das Hinzufügen zahlreicher explizit benannter Zugangsdaten in eine .toml-Datei brachte uns an diese Grenze. Unsere temporäre Lösung war, Zugangsdaten über Pipelines hinweg zu teilen. Dies löste das nächste Problem aus.
2. Destination Switching
Wir mussten zwischen verschiedenen Snowflake-Umgebungen wechseln. In einer statischen Konfiguration bedeutete das Workarounds wie das Wiederverwenden von Pipeline-Namen. Dies verursachte wiederum Konflikte mit dem State Management von dlt.
3. Pipeline-Name-Konflikte
dlt verknüpft den Pipeline-State mit dem Pipeline-Namen. Um Pipelines parallel laufen zu lassen, brauchten wir eindeutige Namen. Doch in der statischen Konfiguration konnten Secrets nicht korrekt aufgelöst werden, wenn Namen nicht übereinstimmten.
4. Parallele Schreibvorgänge
Mehrere Pipelines mit demselben Namen führten zu Race Conditions. Während der Laufzeit überschrieben sich Konfigurationen gegenseitig: Pipeline A nutzte plötzlich Secrets von Pipeline B, was zu unvorhersehbarem Verhalten und schwer nachvollziehbaren Fehlern führte.
Überdenken, wie wir mit Secrets umgehen
Eines war klar: Statische .toml-Dateien sind in einem Multi-Pipeline-Setup keine Lösung. Bei Dutzenden parallelen Runs, individuellen Zugangsdaten und unterschiedlichen Zielsystemen brauchten wir einen dynamischen, pipeline-spezifischen Ansatz.
Unsere Lösung: Secrets zur Laufzeit generieren und direkt in jede DLT-Pipeline injizieren, anstatt globale Umgebungsvariablen oder vordefinierte Konfigurationsdateien zu nutzen.
Vorteile dieser Lösung
- Isolierung pro Pipeline: Jede Airflow-Task ruft nur die Zugangsdaten ab, die sie wirklich benötigt, und weist sie dlt.secrets zu.
- Sichere gleichzeitige Ausführung: Da dlt.secrets pro Python-Prozess im Speicher lebt, kann keine Pipeline die Zugangsdaten einer anderen überschreiben.
- Dynamische Konfiguration: Pipelines können unterschiedliche Buckets, Snowflake-Umgebungen oder API-Credentials ansprechen, ohne sich gegenseitig zu beeinflussen.
- Kein globaler Zustand, keine Disk Writes: Secrets werden nur zur Laufzeit verwaltet und verschwinden, sobald der Airflow-Task abgeschlossen ist. Dies ist sicherer in einer mandantenfähigen Ausführungsumgebung.
Hinweis: dlt unterstützt derzeit nativ Google Cloud Secrets Manager, aber noch nicht AWS Parameter Store. Das kann sich in künftigen Versionen ändern. Prüfen Sie daher bitte immer die aktuelle Dokumentation, wenn Sie andere Secret-Backends nutzen möchten.
Auch wenn Umgebungsvariablen in containerisierten Umgebungen Standard sind, ist unser Ansatz in einem konkurrierenden MWAA-Setup mit unterschiedlichen Werten pro DAG sicherer und stabiler. Temporäre Secrets im Speicher werden nie auf die Festplatte geschrieben, und AWS SSM Parameter Store bleibt die „Single Source of Truth“.
Da alles innerhalb einer Airflow-Task läuft, bleiben keine Zugangsdaten nach Abschluss des Tasks bestehen. Sie werden vollständig aus dem Speicher gelöscht.
Unser Ansatz zur dlt Skalierung
- Alle Zugangsdaten sicher im AWS Parameter Store speichern
- Airflow Connections zur Verwaltung der Snowflake-Credentials verwenden
- Temporäre AWS Session Tokens zur Laufzeit abrufen
- Secrets dynamisch mit dlt.secrets injizieren
- Konfigurationen pro Pipeline zur Laufzeit generieren, keine statischen .toml-Dateien notwendig
Beispielhafte (gekürzte) Version unserer Funktion zur Secrets-Injektion, die unmittelbar vor dem Erstellen der dlt-Pipeline ausgeführt wird:
def set_dlt_secrets(snowflake_conn_id: str) -> None:
"""
Loads AWS and Snowflake credentials into dlt secrets from Airflow connection metadata.
dlt's filesystem destination uses boto3 by default, but manually setting
dlt.secrets["destination.filesystem.credentials.*"] overrides that chain.
If any credential is defined, the rest becomes mandatory, so we set them all explicitly.
"""
import boto3
from airflow.hooks.base import BaseHook
import json
import dlt
# Fetch Snowflake connection from Airflow
snowflake_conn = BaseHook.get_connection(snowflake_conn_id)
snowflake_extra = json.loads(snowflake_conn.extra) if snowflake_conn.extra else {}
# Retrieve temporary AWS credentials from session
session = boto3.Session()
credentials = session.get_credentials().get_frozen_credentials()
logger.info("🔑 Successfully retrieved AWS temporary credentials")
# Set dlt secrets for S3
dlt.secrets["destination.filesystem.bucket_url"] = f"s3://{bucket_name}"
dlt.secrets["destination.filesystem.credentials.aws_access_key_id"] = credentials.access_key
dlt.secrets["destination.filesystem.credentials.aws_secret_access_key"] = credentials.secret_key
dlt.secrets["destination.filesystem.credentials.aws_session_token"] = credentials.token
dlt.secrets["destination.filesystem.credentials.aws_default_region"] = "eu-central-1"
# Set dlt secrets for Snowflake external stage
Ergebnisse dieses Ansatzes
Dieser Ansatz ermöglichte vollständige Pipeline-Isolation und eliminierte Konfigurationskonflikte. Jede Airflow-DAG erhält nun ihre eigene kurzlebig Konfiguration, die nur die Secrets enthält, die sie für diesen Run benötigt.
Dadurch konnten wir:
- Eindeutige Pipenamen vergeben
- Secrets sauber pro Pipeline trennen
- Beliebig viele parallele Pipelines betreiben, die Amazon Managed Workflow for Apache Airflow (MWAA) unabhängig orchestriert
Was waren unsere Learnings zur dlt Skalierung?
Die Skalierung von dlt zwang uns, unser Secrets- und Konfigurationsmanagement neu zu denken:
- dlt’s Standardkonfiguration ist auf Einfachheit, nicht Skalierung ausgelegt. .toml funktioniert lokal, aber nicht unter hoher Parallelität.
- Dynamische Konfiguration ist der Schlüssel: Pipeline-spezifische Secrets und Configs vermeiden Konflikte.
- AWS Parameter Store funktioniert hervorragend, solange man nicht versucht, alles in einer großen Datei zu bündeln.
- Isolation ist die Grundlage: Jede Pipeline sollte ihre Secrets und Schemata unabhängig verwalten.
- MWAA bringt Einschränkungen mit sich, die statische Konfigurationen unpraktisch machen, aber die dynamische Generierung löst dies elegant.
Was als Nächstes kommt
Im nächsten Beitrag beschäftigen wir uns mit dem Thema Schema-Persistenz und -Evolution. Marketingdaten ändern sich ständig, und manchmal werden dlt’s clevere Automatismen zu einer Herausforderung, wenn sich Schemas laufend weiterentwickeln.
Falls Sie in der Zwischenzeit Hilfe mit der Skalierung Ihrer Datenprojekte benötigen, sind wir natürlich jederzeit gerne für Sie da.