管理 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 pod

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 升级时刷新 pod。

如果要从私有仓库部署镜像,则需要创建一个 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 的持久卷声明。调度程序 pod 将每隔配置的秒数从 git 仓库将 DAG 同步到 PVC 上。其他 pod 将读取已同步的 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

此选项将在每个调度程序、Web 服务器(如果 airflowVersion < 2.0.0)和 worker pod 上使用始终运行的 Git-Sync sidecar。Git-Sync sidecar 容器将每隔配置的秒数从 git 仓库同步 DAG。如果您使用的是 KubernetesExecutor,则 Git-sync 将作为 worker pod 上的 init 容器运行。

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 序列化,因此 Web 服务器不需要访问 DAG 文件,因此 git-sync sidecar 不在 Web 服务器上运行。

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

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

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

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

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

您可能会观察到的副作用

  • 在检出新提交时,网络/通信突发(由于快速删除旧文件、创建新文件、符号链接交换)。

  • 在同步 DAG 时,DAG 文件夹中的文件之间暂时缺乏一致性(由于在集群中向各个节点分发更改的延迟)。

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

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

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

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

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

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

从外部填充的 PVC 挂载 DAGs

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

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 仓库挂载 DAGs

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

然后创建您的 SSH 密钥

ssh-keygen -t rsa -b 4096 -C "[email protected]"

将公钥添加到您的私有仓库(在 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: [email protected]:<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 图表目录上下文中,您可以安装 Airflow

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

如果您已正确完成所有操作,Git-Sync 将会获取您在私有 GitHub 仓库中对 DAG 所做的更改。

您应该进一步操作,设置 dags.gitSync.knownHosts,这样您就不会受到中间人攻击。此过程记录在生产指南中。

此条目是否有帮助?