在本文中,您會使用 Helm 在 Azure Kubernetes Service (AKS) 上設定及部署 Apache Airflow。
設定工作負載身分識別
使用
kubectl create namespace命令建立 Airflow 叢集的命名空間。kubectl create namespace ${AKS_AIRFLOW_NAMESPACE} --dry-run=client --output yaml | kubectl apply -f -範例輸出:
namespace/airflow created使用 命令建立服務帳戶並設定工作負載身分
kubectl apply識別。export TENANT_ID=$(az account show --query tenantId -o tsv) cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: "${MY_IDENTITY_NAME_CLIENT_ID}" azure.workload.identity/tenant-id: "${TENANT_ID}" name: "${SERVICE_ACCOUNT_NAME}" namespace: "${AKS_AIRFLOW_NAMESPACE}" EOF範例輸出:
serviceaccount/airflow created
安裝外部秘密操作員
在本節中,我們使用 Helm 來安裝外部秘密操作員。 外部秘密操作員是 Kubernetes 操作員,可管理儲存在 Azure 金鑰保存庫 等外部秘密存放區中的外部秘密生命週期。
新增外部秘密 Helm 存放庫,並使用
helm repo add和helm repo update命令更新存放庫。helm repo add external-secrets https://charts.external-secrets.io helm repo update範例輸出:
Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "external-secrets" chart repository使用
helm install命令安裝外部秘密操作員。helm install external-secrets \ external-secrets/external-secrets \ --namespace ${AKS_AIRFLOW_NAMESPACE} \ --create-namespace \ --set installCRDs=true \ --wait範例輸出:
NAME: external-secrets LAST DEPLOYED: Thu Nov 7 11:16:07 2024 NAMESPACE: airflow STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: external-secrets has been deployed successfully in namespace airflow! In order to begin using ExternalSecrets, you will need to set up a SecretStore or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore). More information on the different types of SecretStores and how to configure them can be found in our Github: https://github.com/external-secrets/external-secrets
建立祕密
使用 命令建立
SecretStore資源,以存取儲存在密鑰保存庫中kubectl apply的 Airflow 密碼。kubectl apply -f - <<EOF apiVersion: external-secrets.io/v1 kind: SecretStore metadata: name: azure-store namespace: ${AKS_AIRFLOW_NAMESPACE} spec: provider: # provider type: azure keyvault azurekv: authType: WorkloadIdentity vaultUrl: "${KEYVAULTURL}" serviceAccountRef: name: ${SERVICE_ACCOUNT_NAME} EOF範例輸出:
secretstore.external-secrets.io/azure-store created建立
ExternalSecret資源,其會使用Secret命令,在命名空間中airflow建立 KubernetesAirflow,其中包含kubectl apply儲存在密鑰保存庫中的秘密。kubectl apply -f - <<EOF apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: airflow-aks-azure-logs-secrets namespace: ${AKS_AIRFLOW_NAMESPACE} spec: refreshInterval: 1h secretStoreRef: kind: SecretStore name: azure-store target: name: ${AKS_AIRFLOW_LOGS_STORAGE_SECRET_NAME} creationPolicy: Owner data: # name of the SECRET in the Azure KV (no prefix is by default a SECRET) - secretKey: azurestorageaccountname remoteRef: key: AKS-AIRFLOW-LOGS-STORAGE-ACCOUNT-NAME - secretKey: azurestorageaccountkey remoteRef: key: AKS-AIRFLOW-LOGS-STORAGE-ACCOUNT-KEY EOF範例輸出:
externalsecret.external-secrets.io/airflow-aks-azure-logs-secrets created使用
az identity federated-credential create命令建立同盟認證。az identity federated-credential create \ --name external-secret-operator \ --identity-name ${MY_IDENTITY_NAME} \ --resource-group ${MY_RESOURCE_GROUP_NAME} \ --issuer ${OIDC_URL} \ --subject system:serviceaccount:${AKS_AIRFLOW_NAMESPACE}:${SERVICE_ACCOUNT_NAME} \ --output table範例輸出:
Issuer Name ResourceGroup Subject ----------------------------------------------------------------------------------------------------------------------- ------------------------ ----------------------- ------------------------------------- https://$MY_LOCATION.oic.prod-aks.azure.com/c2c2c2c2-dddd-eeee-ffff-a3a3a3a3a3a3/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/ external-secret-operator $MY_RESOURCE_GROUP_NAME system:serviceaccount:airflow:airflow將許可權授與使用者指派的身分識別,以使用
az keyvault set-policy命令存取秘密。az keyvault set-policy --name $MY_KEYVAULT_NAME --object-id $MY_IDENTITY_NAME_PRINCIPAL_ID --secret-permissions get --output table範例輸出:
Location Name ResourceGroup ------------- ---------------------- ----------------------- $MY_LOCATION $MY_KEYVAULT_NAME $MY_RESOURCE_GROUP_NAME
建立 Apache Airflow 記錄的永續性磁碟區
使用
kubectl apply命令建立永續性磁碟區。kubectl apply -f - <<EOF apiVersion: v1 kind: PersistentVolume metadata: name: pv-airflow-logs labels: type: local spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain # If set as "Delete" container would be removed after pvc deletion storageClassName: azureblob-fuse-premium mountOptions: - -o allow_other - --file-cache-timeout-in-seconds=120 csi: driver: blob.csi.azure.com readOnly: false volumeHandle: airflow-logs-1 volumeAttributes: resourceGroup: ${MY_RESOURCE_GROUP_NAME} storageAccount: ${AKS_AIRFLOW_LOGS_STORAGE_ACCOUNT_NAME} containerName: ${AKS_AIRFLOW_LOGS_STORAGE_CONTAINER_NAME} nodeStageSecretRef: name: ${AKS_AIRFLOW_LOGS_STORAGE_SECRET_NAME} namespace: ${AKS_AIRFLOW_NAMESPACE} EOF範例輸出:
persistentvolume/pv-airflow-logs created
建立 Apache Airflow 記錄的永續性磁碟區宣告
使用
kubectl apply命令建立永續性磁碟區宣告。kubectl apply -f - <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-airflow-logs namespace: ${AKS_AIRFLOW_NAMESPACE} spec: storageClassName: azureblob-fuse-premium accessModes: - ReadWriteMany resources: requests: storage: 5Gi volumeName: pv-airflow-logs EOF範例輸出:
persistentvolumeclaim/pvc-airflow-logs created
使用 Helm 部署 Apache Airflow
配置檔
airflow_values.yaml案以變更圖表的預設部署組態,並更新映像的容器登錄。cat <<EOF> airflow_values.yaml images: airflow: repository: $MY_ACR_REGISTRY.azurecr.io/airflow tag: 3.0.2 # Specifying digest takes precedence over tag. digest: ~ pullPolicy: IfNotPresent # To avoid images with user code, you can turn this to 'true' and # all the 'run-airflow-migrations' and 'wait-for-airflow-migrations' containers/jobs # will use the images from 'defaultAirflowRepository:defaultAirflowTag' values # to run and wait for DB migrations . useDefaultImageForMigration: false # timeout (in seconds) for airflow-migrations to complete migrationsWaitTimeout: 60 pod_template: # Note that `images.pod_template.repository` and `images.pod_template.tag` parameters # can be overridden in `config.kubernetes` section. So for these parameters to have effect # `config.kubernetes.worker_container_repository` and `config.kubernetes.worker_container_tag` # must be not set . repository: $MY_ACR_REGISTRY.azurecr.io/airflow tag: 3.0.2 pullPolicy: IfNotPresent flower: repository: $MY_ACR_REGISTRY.azurecr.io/airflow tag: 3.0.2 pullPolicy: IfNotPresent statsd: repository: $MY_ACR_REGISTRY.azurecr.io/statsd-exporter tag: v0.28.0 pullPolicy: IfNotPresent pgbouncer: repository: $MY_ACR_REGISTRY.azurecr.io/airflow tag: airflow-pgbouncer-2025.03.05-1.23.1 pullPolicy: IfNotPresent pgbouncerExporter: repository: $MY_ACR_REGISTRY.azurecr.io/airflow tag: airflow-pgbouncer-exporter-2025.03.05-0.18.0 pullPolicy: IfNotPresent gitSync: repository: $MY_ACR_REGISTRY.azurecr.io/git-sync tag: v4.3.0 pullPolicy: IfNotPresent # Airflow executor executor: "KubernetesExecutor" # Environment variables for all airflow containers env: - name: ENVIRONMENT value: dev extraEnv: | - name: AIRFLOW__CORE__DEFAULT_TIMEZONE value: 'America/New_York' # Configuration for postgresql subchart # Not recommended for production! Instead, spin up your own Postgresql server and use the `data` attribute in this # yaml file. postgresql: enabled: true image: registry: $MY_ACR_REGISTRY.azurecr.io repository: postgresql tag: 16.1.0-debian-11-r15 # Enable pgbouncer. See https://airflow.apache.org/docs/helm-chart/stable/production-guide.html#pgbouncer pgbouncer: enabled: true dags: gitSync: enabled: true repo: https://github.com/donhighmsft/airflowexamples.git branch: main rev: HEAD depth: 1 maxFailures: 0 subPath: "dags" # sshKeySecret: airflow-git-ssh-secret # knownHosts: | # github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= logs: persistence: enabled: true existingClaim: pvc-airflow-logs storageClassName: azureblob-fuse-premium # We disable the log groomer sidecar because we use Azure Blob Storage for logs, with lifecyle policy set. triggerer: logGroomerSidecar: enabled: false scheduler: logGroomerSidecar: enabled: false workers: logGroomerSidecar: enabled: false EOF新增 Apache Airflow Helm 存放庫,並使用
helm repo add和helm repo update命令更新存放庫。helm repo add apache-airflow https://airflow.apache.org helm repo update範例輸出:
"apache-airflow" has been added to your repositories Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "apache-airflow" chart repository使用
helm search repo命令搜尋 Helm 存放庫以尋找 Apache Airflow 圖表。helm search repo airflow範例輸出:
NAME CHART VERSION APP VERSION DESCRIPTION apache-airflow/airflow 1.15.0 3.0.2 The official Helm chart to deploy Apache Airflo...使用
helm install命令安裝 Apache Airflow 圖表。helm install airflow apache-airflow/airflow --version 1.15.0 --namespace airflow --create-namespace -f airflow_values.yaml --debug範例輸出:
NAME: airflow LAST DEPLOYED: Fri Nov 8 11:59:43 2024 NAMESPACE: airflow STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Thank you for installing Apache Airflow 3.0.2! Your release is named airflow. You can now access your dashboard(s) by executing the following command(s) and visiting the corresponding port at localhost in your browser: Airflow Webserver: kubectl port-forward svc/airflow-webserver 8080:8080 --namespace airflow Default Webserver (Airflow UI) Login credentials: username: admin password: admin Default Postgres connection credentials: username: postgres password: postgres port: 5432 You can get Fernet Key value by running the following: echo Fernet Key: $(kubectl get secret --namespace airflow airflow-fernet-key -o jsonpath="{.data.fernet-key}" | base64 --decode) ########################################################### # WARNING: You should set a static webserver secret key # ########################################################### You are using a dynamically generated webserver secret key, which can lead to unnecessary restarts of your Airflow components. Information on how to set a static webserver secret key can be found here: https://airflow.apache.org/docs/helm-chart/stable/production-guide.html#webserver-secret-key使用
kubectl get pods命令確認安裝。kubectl get pods -n airflow範例輸出:
NAME READY STATUS RESTARTS AGE airflow-create-user-kklqf 1/1 Running 0 12s airflow-pgbouncer-d7bf9f649-25fnt 2/2 Running 0 61s airflow-postgresql-0 1/1 Running 0 61s airflow-run-airflow-migrations-zns2b 0/1 Completed 0 60s airflow-scheduler-5c45c6dbdd-7t6hv 1/2 Running 0 61s airflow-statsd-6df8564664-6rbw8 1/1 Running 0 61s airflow-triggerer-0 2/2 Running 0 61s airflow-webserver-7df76f944c-vcd5s 0/1 Running 0 61s external-secrets-748f44c8b8-w7qrk 1/1 Running 0 3h6m external-secrets-cert-controller-57b9f4cb7c-vl4m8 1/1 Running 0 3h6m external-secrets-webhook-5954b69786-69rlp 1/1 Running 0 3h6m
存取 Airflow UI
使用
kubectl port-forward命令透過埠轉送安全地存取 Airflow UI。kubectl port-forward svc/airflow-webserver 8080:8080 -n airflow開啟瀏覽器並流覽至
localhost:8080以存取 Airflow UI。登入時,請使用安裝 Airflow Helm 圖表時提供的預設網頁伺服器網址及登入憑證。
透過 Airflow UI 安全地探索和管理您的工作流程。
整合 Git 與 Airflow
Git 與 Apache Airflow 整合可讓您順暢地控制版本,並簡化工作流程定義的管理,確保所有 DAG 都能組織且易於稽核。
- 設定 DAG 的 Git 存放庫。 建立專用的 Git 存放庫,以存放所有 Airflow DAG 定義。 此存放庫是工作流程的核心真相來源,可讓您有效地管理、追蹤和共同作業 DAG。
- 設定 Airflow 以從 Git 同步處理 DAG。 更新 Airflow 的設定,透過設定 Git 儲存庫的 URL 及任何必要的認證憑證,直接在 Airflow 的設定檔中或透過 Helm 圖表值,自動從你的 Git 儲存庫拉取 DAG。 此設定可讓您自動同步處理 DAG,確保 Airflow 一律是最新版的工作流程。
這項整合可藉由引進完整版本控制、啟用復原和支援生產等級設定中的小組共同作業,來增強開發和部署工作流程。
在 Kubernetes 生產等級上製作您的 Airflow
下列最佳做法可協助您在 Kubernetes 部署生產等級上建立 Apache Airflow:
- 請確定您有一個穩固的設定,著重於延展性、安全性和可靠性。
- 使用專用的自動調整節點,並選取復原的執行程式,例如 KubernetesExecutor、CeleryExecutor 或 CeleryKubernetesExecutor。
- 使用受控、高可用性的資料庫後端,例如 MySQL 或 PostgreSQL。
- 建立完整的監視和集中式記錄,以維護效能深入解析。
- 使用網路原則、SSL 和角色型 存取控制(RBAC)保護您的環境,並設定 Airflow 元件(排程器、網頁伺服器、背景工作角色)以提供高可用性。
- 實作 CI/CD 管線以進行順暢的 DAG 部署,並設定災害復原的一般備份。
下一步
若要深入瞭解如何在 Azure Kubernetes Service 上部署開放原始碼軟體(AKS),請參閱下列文章:
- 在 Azure Kubernetes Service 上部署 MongoDB 叢集 (AKS)
- 在 Azure Kubernetes Service 上部署高可用性 PostgreSQL 資料庫 (AKS)
- 在 Azure Kubernetes Service 上部署 Valkey 叢集 (AKS)
參與者
本文由 Microsoft 維護。 下列參與者最初撰寫:
- Don High |首席客戶工程師
- Satya Chandragiri |資深數位雲端解決方案架構師
- Erin Schaffer |內容開發人員 2