管理 DAG 文件

创建新 DAG 文件或修改现有 DAG 文件时,需要将其部署到环境中。本节将介绍一些您可以使用的基本技术。

将 DAG 文件集成到 Docker 镜像中

使用这种方法,您可以将 DAG 文件和相关代码包含在 Airflow 镜像中。

这种方法需要使用新的 Docker 镜像重新部署 helm chart 中的服务,以便部署新的 DAG 代码。当 DAG 代码预计不会频繁更改时,这种方法效果很好。

docker build --pull --tag "my-company/airflow:8a0da78" . -f - <<EOF
FROM apache/airflow

COPY ./dags/ \${AIRFLOW_HOME}/dags/

EOF

注意

在 2.0.2 版本之前的 Airflow 镜像中,存在一个错误,需要使用稍长的 Dockerfile,以确保镜像与 OpenShift 兼容(即 DAG 具有与其它文件类似的 root 组)。在 2.0.2 版本中,此问题已修复。

docker build --pull --tag "my-company/airflow:8a0da78" . -f - <<EOF
FROM apache/airflow:2.0.2

USER root

COPY --chown=airflow:root ./dags/ \${AIRFLOW_HOME}/dags/

USER airflow

EOF

然后将其发布到可访问的仓库中

docker push my-company/airflow:8a0da78

最后,使用该镜像更新 Airflow Pods

helm upgrade --install airflow apache-airflow/airflow \
  --set images.airflow.repository=my-company/airflow \
  --set images.airflow.tag=8a0da78

如果您正在部署具有固定标签的镜像,您需要确保每次都拉取该镜像。

警告

使用固定标签仅应用于测试/开发目的。使用相同的标签是一种不良实践,因为您将丢失代码的历史记录。

helm upgrade --install airflow apache-airflow/airflow \
  --set images.airflow.repository=my-company/airflow \
  --set images.airflow.tag=8a0da78 \
  --set images.airflow.pullPolicy=Always \
  --set airflowPodAnnotations.random=r$(uuidgen)

随机生成的 Pod 注解将确保在进行 helm 升级时 Pods 被刷新。

如果您正在从私有仓库部署镜像,您需要创建一个 Secret,例如 gitlab-registry-credentials(详情请参阅 从私有仓库拉取镜像),并使用 --set registry.secretName 指定它

helm upgrade --install airflow apache-airflow/airflow \
  --set images.airflow.repository=my-company/airflow \
  --set images.airflow.tag=8a0da78 \
  --set images.airflow.pullPolicy=Always \
  --set registry.secretName=gitlab-registry-credentials

使用 git-sync

使用启用持久化的 git-sync sidecar 挂载 DAG 文件

此选项将使用一个访问模式为 ReadWriteMany 的 Persistent Volume Claim。scheduler pod 将每隔配置的秒数将 DAG 文件从 Git 仓库同步到 PVC 上。其他 Pods 将读取已同步的 DAG 文件。并非所有卷插件都支持 ReadWriteMany 访问模式。详情请参阅 持久卷访问模式

helm upgrade --install airflow apache-airflow/airflow \
  --set dags.persistence.enabled=true \
  --set dags.gitSync.enabled=true
  # you can also override the other persistence or gitSync values
  # by setting the  dags.persistence.* and dags.gitSync.* values
  # Please refer to values.yaml for details

使用未启用持久化的 git-sync sidecar 挂载 DAG 文件

此选项将在每个 scheduler、webserver (如果 airflowVersion < 2.0.0) 和 worker pod 上使用一个始终运行的 Git-Sync sidecar。Git-Sync sidecar 容器将每隔配置的秒数将 DAG 文件从 Git 仓库同步到。如果您正在使用 KubernetesExecutor,Git-sync 将作为 init 容器在您的 worker pods 上运行。

helm upgrade --install airflow apache-airflow/airflow \
  --set dags.persistence.enabled=false \
  --set dags.gitSync.enabled=true
  # you can also override the other gitSync values
  # by setting the  dags.gitSync.* values
  # Refer values.yaml for details

使用 apache-airflow >= 2.0.0 时,DAG 序列化 默认启用,因此 Webserver 不需要访问 DAG 文件,所以 git-sync sidecar 不在 Webserver 上运行。

结合使用 git-sync 和持久化的注意事项

虽然可以将 git-sync 和持久化同时用于 DAG 文件,但通常不建议这样做,除非部署管理者仔细考虑了其带来的权衡。在某些情况下,不使用持久化的 git-sync 也有其他权衡(例如 DAG 同步延迟与 Git 服务器的速率限制),这些权衡通常可以缓解(例如当有新提交推送到仓库时,通过 web-hooks 向 git-sync 容器发送信号),但在某些情况下,您仍然可能希望将 git-sync 和持久化结合使用,但作为部署管理者,您应该意识到它的一些后果。

git-sync 解决方案主要设计用于本地的、符合 POSIX 标准的卷,将 Git 仓库检出到其中。git-sync 同步提交过程的一部分涉及在新创建的文件夹中检出新版本的文件,并在检出完成后将符号链接切换到新文件夹。这样做是为了确保整个 dags 文件夹始终保持一致。git-sync 通过符号链接切换的方式,确保解析 dags 始终在整个 DAG 文件夹中一个一致的(基于单次提交的)文件集合上工作。

然而,当 git-sync 工作的文件夹不是本地卷而是持久卷(因此实际上是一个网络分布式卷)时,这种方法可能会产生不良的副作用。取决于持久卷背后的技术,可能会以不同的方式处理 git-sync 方法并产生不明显的后果。有许多适用于各种 K8S 安装的持久化解决方案,它们各自具有不同的特性,因此您需要仔细测试和监控您的文件系统,以确保这些不良副作用不会影响您。这些影响可能会随时间变化,或取决于诸如 Dag File Processor 扫描文件的频率、您的 dags 的数量和复杂性、您的持久卷的远程程度和分布式程度、您为某些文件系统分配的 IOPS 数量(通常这类文件系统的一个高价特性是您可以获得的 IOPS 数量)以及许多其他因素。

git-sync 通过符号链接切换的方式工作,通常会导致吞吐量线性增长以及潜在的同步延迟。检出产生的网络流量以突发形式出现,并且突发流量与仓库中的文件数量和大小呈线性比例,这使得它容易受到突然和意外的需求增长的影响。大多数持久化解决方案对于较小/较短的突发流量工作“足够好”,但当它们超出特定阈值时,您需要升级网络到更强大且昂贵的选项。这很难控制且无法缓解,因此您可能突然面临这样的情况:需要为 IOPS/持久化选项支付更多费用,以使您的 dags 保持充分同步,从而避免不一致和同步延迟。

您可能观察到的副作用

  • 在新提交被检出时出现的网络/通信流量突发(因为快速连续进行删除旧文件、创建新文件、符号链接切换的操作)。

  • 在 DAGs 同步过程中,DAG 文件夹中的文件之间暂时的不一致(由于在集群中将更改分发到各个节点的单个文件时存在延迟)。

  • 当您的 DAG 数量增长时,持久化解决方案性能的明显下降,这种下降可能会放大上述副作用。

  • 一些持久化解决方案可能缺乏 git-sync 执行同步所需的文件系统功能(例如更改权限或创建符号链接)。虽然这些问题通常可以缓解,但仅推荐将 git-sync 与完全符合 POSIX 文件系统标准的持久化文件系统配合使用。

一般建议仅将 git-sync 与本地卷一起使用,如果您还想使用持久化,您需要确保您使用的持久化解决方案符合 POSIX 标准,并监控它可能产生的副作用。

使用 git-sync 同步多个 Git 仓库

Helm Chart 中的 Airflow git-sync 集成不允许同时配置多个仓库进行同步。DAG 文件夹必须来自单个 Git 仓库。但是,可以使用 子模块 创建一个“伞形”仓库,您可以使用它将多个 Git 仓库一起检出(使用 --submodules recursive 选项)。有 Airflow 用户通过这种“伞形”仓库方法将数百个仓库作为子模块组织起来的成功案例。然而,当您选择这种解决方案时,您需要找出如何链接子模块、何时在“子模块”仓库更改时更新伞形仓库,并找出版本控制方法并自动化它。这可能像始终使用所有子模块仓库的最新版本一样简单,或者像跨多个团队管理共享库、dags 和代码的版本一样复杂,并按照您的发布流程进行。

这种复杂方法的一个例子可以在 Airflow Summit 的 大规模管理 dags 演讲中找到。

从外部填充的 PVC 挂载 DAG 文件

使用这种方法,Airflow 将从具有 ReadOnlyManyReadWriteMany 访问模式的 PVC 读取 dags。您必须确保 PVC 已填充/更新了所需的 dags(这不会由 chart 处理)。您将卷声明的名称传递给 chart。

helm upgrade --install airflow apache-airflow/airflow \
  --set dags.persistence.enabled=true \
  --set dags.persistence.existingClaim=my-volume-claim \
  --set dags.gitSync.enabled=false

使用 Git-Sync sidecar 从私有 GitHub 仓库挂载 DAG 文件

如果您尚未创建私有仓库,请在 GitHub 上创建一个。

然后创建您的 SSH 密钥。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

将公钥添加到您的私有仓库中(在 Settings > Deploy keys 下)。

您必须将私有 SSH 密钥转换为 base64 字符串。您可以像这样转换私有 SSH 密钥文件:

base64 <my-private-ssh-key> -w 0 > temp.txt

然后从 temp.txt 文件中复制字符串。接下来,您将其添加到您的 override-values.yaml 文件中。

在此示例中,您将创建一个名为 override-values.yaml 的 yaml 文件,以覆盖 values.yaml 文件中的值,而不是使用 --set

dags:
  gitSync:
    enabled: true
    repo: git@github.com:<username>/<private-repo-name>.git
    branch: <branch-name>
    subPath: ""
    sshKeySecret: airflow-ssh-secret
extraSecrets:
  airflow-ssh-secret:
    data: |
      gitSshKey: '<base64-converted-ssh-private-key>'

不要忘记复制您的私钥 base64 字符串。

最后,在您的 Airflow Helm chart 目录下,您可以安装 Airflow。

helm upgrade --install airflow apache-airflow/airflow -f override-values.yaml

如果您正确完成了所有步骤,Git-Sync 将会获取您在私有 GitHub 仓库中对 dags 所做的更改。

您应该更进一步,并设置 dags.gitSync.knownHosts,以避免中间人攻击。此过程已在 生产环境指南 中记录。

本条目有帮助吗?