生产指南

以下是在生产环境中使用此 Helm 图表时需要考虑的事项。

数据库

建议为 Airflow 元数据存储设置外部数据库。默认的 Helm 图表部署了一个在容器中运行的 Postgres 数据库。对于生产环境,应使用在专用机器上运行的数据库或利用云提供商的数据库服务(如 AWS RDS),因为嵌入式 Postgres 缺乏生产数据库所需的稳定性、监控和持久性功能。它只是为了更容易地在“独立”版本中测试 Helm 图表,但当您使用它时,您可能会遇到数据丢失。支持的数据库和版本可以在 设置数据库后端 中找到。

注意

使用 helm 图表时,您不需要使用 设置数据库后端 中所述的 airflow db migrate 初始化数据库。

首先禁用 Postgres,这样图表就不会部署自己的 Postgres 容器

postgresql:
  enabled: false

要向 Airflow 提供数据库凭据,您有两种选择 - 在值文件中或在 Kubernetes 密钥中。

值文件

这是更简单的选择,因为图表将为您创建一个 Kubernetes 密钥。但是,请记住,您的凭据将在您的值文件中。

data:
  metadataConnection:
    user: <username>
    pass: <password>
    protocol: postgresql
    host: <hostname>
    port: 5432
    db: <database name>

Kubernetes 密钥

您也可以将凭据存储在您创建的 Kubernetes 密钥中。请注意,用户名/密码中的特殊字符必须进行 URL 编码。

kubectl create secret generic mydatabase --from-literal=connection=postgresql://user:pass@host:5432/db

最后,配置图表以使用您创建的密钥

data:
  metadataSecretName: mydatabase

警告

如果您使用 CeleryExecutor 且 Airflow 版本 < 2.4,请记住 resultBackendSecretName 需要以 db+postgresql:// 开头的 URL,而 metadataSecretName 需要 postgresql:// 并且不能与 db+postgresql:// 一起使用。您需要创建具有正确方案的单独密钥。对于 Airflow 版本 >= 2.4,可以省略结果后端密钥,因为 Airflow 默认情况下将使用 sql_alchemy_conn(在 metadataSecret 中指定)和 db+ 方案前缀。

PgBouncer

如果您使用 PostgreSQL 作为数据库,您可能还需要启用 PgBouncer。由于 Airflow 的分布式特性,它可能会打开许多数据库连接,而使用连接池可以显著减少数据库上的打开连接数。

pgbouncer:
  enabled: true

根据您的 Airflow 实例的大小,您可能还需要调整以下内容(显示默认值)

pgbouncer:
  # The maximum number of connections to PgBouncer
  maxClientConn: 100
  # The maximum number of server connections to the metadata database from PgBouncer
  metadataPoolSize: 10
  # The maximum number of server connections to the result backend database from PgBouncer
  resultBackendPoolSize: 5

Web 服务器密钥

使用此图表进行部署时,您应该设置一个静态的 Web 服务器密钥,因为它将有助于确保您的 Airflow 组件仅在必要时重新启动。

警告

您应该为运行的每个实例使用不同的密钥,因为此密钥用于对会话 cookie 进行签名并执行其他与安全相关的功能!

首先,生成一个强密钥

python3 -c 'import secrets; print(secrets.token_hex(16))'

现在将密钥添加到您的值文件中

webserverSecretKey: <secret_key>

或者,创建一个 Kubernetes 密钥并使用 webserverSecretKeySecretName

webserverSecretKeySecretName: my-webserver-secret
# where the random key is under `webserver-secret-key` in the k8s Secret

kubectl 创建 Kubernetes 密钥的示例

kubectl create secret generic my-webserver-secret --from-literal="webserver-secret-key=$(python3 -c 'import secrets; print(secrets.token_hex(16))')"

Web 服务器密钥还用于在检索日志时授权对 Celery 工作器的请求。但是,使用密钥生成的令牌的有效期很短 - 确保运行 Airflow 组件的所有机器上的时间同步(例如使用 ntpd),否则在访问日志时可能会出现“禁止”错误。

驱逐配置

在将 Airflow 与 Kubernetes 集群自动缩放器 一起运行时,配置 Pod 是否可以安全驱逐非常重要。此设置可以在 Airflow 图表中以不同的级别进行配置

workers:
  safeToEvict: true
scheduler:
  safeToEvict: true
webserver:
  safeToEvict: true

使用 KubernetesExecutor 时,应将 workers.safeToEvict 设置为 false,以避免它们在完成之前被删除。

扩展和自定义 Airflow 镜像

Apache Airflow 社区发布了 Docker 镜像,这些镜像是 Apache Airflow 的 参考镜像。但是,Airflow 拥有超过 60 个社区管理的提供程序(可通过 extras 安装),并且并非每个人都使用默认安装的一些 extras/providers,有时需要其他 extras/providers,有时(实际上经常)您需要添加自己的自定义依赖项、包甚至自定义提供程序,或者添加部署中需要的自定义工具和二进制文件。

在 Kubernetes 和 Docker 术语中,这意味着您需要另一个具有特定要求的镜像。这就是为什么您应该学习如何构建自己的 Docker(或更准确地说是 容器)镜像。

您希望使用自定义镜像的典型场景

  • 添加 apt

  • 添加 PyPI

  • 添加部署所需的二进制资源

  • 添加部署中需要的自定义工具

有关如何扩展和自定义 Airflow 镜像的更多详细信息,请参阅 构建镜像

管理 DAG 文件

请参阅 管理 DAG 文件

knownHosts

如果您使用的是 dags.gitSync.sshKeySecret,那么您还应该设置 dags.gitSync.knownHosts。这里我们将展示 GitHub 的流程,但其他提供商也可以这样做

获取 GitHub 的公钥

ssh-keyscan -t rsa github.com > github_public_key

接下来,打印公钥的指纹

ssh-keygen -lf github_public_key

将该输出与 GitHub 的 SSH 密钥指纹 进行比较。

它们匹配,对吧?很好。现在,将公钥添加到您的值中。它看起来像这样

dags:
  gitSync:
    knownHosts: |
      github.com ssh-rsa AAAA...1/wsjk=

外部调度器

要使用外部调度器实例

scheduler:
  enabled: false

确保您的外部 Web 服务器/调度器连接到同一个 Redis 主机。这将确保调度器知道 helm-chart 中部署的工作器。

访问 Airflow UI

您如何访问 Airflow UI 将取决于您的环境;但是,图表确实支持各种选项

外部 Web 服务器

要使用外部 Web 服务器

webserver:
  enabled: false

确保您的外部 Web 服务器/调度器连接到同一个 Redis 主机。这将确保调度器知道 helm-chart 中部署的工作器。

Ingress

您可以创建和配置 Ingress 对象。请参阅 Ingress 图表参数。有关 Ingress 的更多信息,请参阅 Kubernetes Ingress 文档

LoadBalancer 服务

您可以将 Web 服务器的 Service 类型更改为 LoadBalancer,并设置任何必要的注释

webserver:
  service:
    type: LoadBalancer

有关 LoadBalancer 服务的更多信息,请参阅 Kubernetes LoadBalancer 服务文档

日志记录

根据您选择的执行器,任务日志可能无法开箱即用。所有日志记录选项都可以在 管理日志 中找到。

指标

图表可以支持将指标发送到现有的 StatsD 实例或提供 Prometheus 端点。

Prometheus

指标端点位于 svc/{{ .Release.Name }}-statsd:9102/metrics

外部 StatsD

要使用外部 StatsD 实例

statsd:
  enabled: false
config:
  metrics:  # or 'scheduler' for Airflow 1
    statsd_on: true
    statsd_host: ...
    statsd_port: ...

Datadog

如果您在环境中使用 Datadog 代理,这将使 Airflow 能够将指标导出到 Datadog 代理。

statsd:
  enabled: false
config:
  metrics: # or 'scheduler' for Airflow 1
    statsd_on: true
    statsd_port: 8125
extraEnv: |-
  - name: AIRFLOW__METRICS__STATSD_HOST
    valueFrom:
      fieldRef:
        fieldPath: status.hostIP

Celery 后端

如果您使用的是 CeleryExecutorCeleryKubernetesExecutor,则可以使用您自己的 Celery 后端。

默认情况下,图表将部署 Redis。但是,您可以使用任何受支持的 Celery 后端来代替

redis:
  enabled: false
data:
  brokerUrl: redis://redis-user:password@redis-host:6379/0

有关设置 Celery 代理的更多信息,请参阅Celery 文档中关于此主题的详尽说明

安全上下文约束

安全上下文约束 (SCC) 是 OpenShift 的一种结构,其作用类似于 RBAC 规则;但是,它的目标是 Pod 而不是用户。在定义 SCC 时,可以控制 Pod 在启动和运行期间可以执行的操作和访问的资源。

SCC 被划分为不同的级别或类别,其中 restricted SCC 是分配给 Pod 的默认 SCC。在将 Airflow 部署到 OpenShift 时,可以利用 SCC 并允许 Pod 使用 anyuid SCC 启动容器。

为了启用 SCC 的使用,必须将参数 rbac.createSCCRoleBinding 设置为 true,如下所示

rbac:
  create: true
  createSCCRoleBinding: true

在此图表中,SCC 通过 RoleBindings 绑定到 Pod,这意味着还必须将选项 rbac.create 设置为 true 才能完全启用 SCC 的使用。

有关 SCC 以及可以使用此结构实现的功能的更多信息,请参阅管理安全上下文约束

安全上下文

在 Kubernetes 中,可以使用 securityContext 定义用户 ID、组 ID 和功能,例如以特权模式运行容器。

将应用程序部署到 Kubernetes 时,建议为容器赋予最小权限,以减少访问权限并保护运行容器的主机。

在 Airflow Helm 图表中,可以通过以下几种方式配置 securityContext

与配置全局 securityContexts 相同,也可以通过设置其本地 securityContexts 为特定工作负载配置不同的值,如下所示

workers:
  securityContexts:
    pod:
      runAsUser: 5000
      fsGroup: 0
    containers:
      allowPrivilegeEscalation: false

在上面的示例中,工作程序 Pod securityContexts 将设置为 runAsUser: 5000fsGroup: 0。容器 pod 将设置为 allowPrivilegeEscalation: false

如您所见,本地设置在定义时将优先于全局设置。以下说明了此图表中 securityContexts 选项的优先级规则

uid: 40000
gid: 0

securityContexts:
  pod:
    runAsUser: 50000
    fsGroup: 0

workers:
  securityContexts:
    pod:
      runAsUser: 1001
      fsGroup: 0

这将生成以下工作程序部署

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: airflow-worker
spec:
  serviceName: airflow-worker
  template:
    spec:
      securityContext:    # As the securityContexts was defined in ``workers``, its value will take priority
        runAsUser: 1001
        fsGroup: 0

如果我们从上面的示例中删除 securityContextsworkers.securityContexts,则输出将如下所示

uid: 40000
gid: 0

securityContexts: {}

workers:
  securityContexts: {}

这将生成以下工作程序部署

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: airflow-worker
spec:
  serviceName: airflow-worker
  template:
    spec:
      securityContext:
        runAsUser: 40000   # As the securityContext was not defined in ``workers`` or ``podSecurity``, the value from uid will be used
        fsGroup: 0         # As the securityContext was not defined in ``workers`` or ``podSecurity``, the value from gid will be used
      initContainers:
        - name: wait-for-airflow-migrations
      ...
      containers:
        - name: worker
      ...

最后,如果我们设置了 securityContexts 但没有设置 workers.securityContexts

uid: 40000
gid: 0

securityContexts:
  pod:
    runAsUser: 50000
    fsGroup: 0

workers:
  securityContexts: {}

这将生成以下工作程序部署

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: airflow-worker
spec:
  serviceName: airflow-worker
  template:
    spec:
      securityContext:     # As the securityContexts was not defined in ``workers``, the values from securityContexts will take priority
        runAsUser: 50000
        fsGroup: 0
      initContainers:
        - name: wait-for-airflow-migrations
      ...
      containers:
        - name: worker
      ...

内置密钥和环境变量

默认情况下,Helm 图表使用 Kubernetes Secrets 存储 Airflow 所需的密钥。默认情况下,这些密钥的内容将转换为 Airflow 读取的环境变量(某些环境变量具有多个变体以支持旧版本的 Airflow)。

默认情况下,密钥名称由部署 Helm 图表时使用的版本名称确定,但您也可以使用其他密钥来设置变量,或者完全禁用使用密钥并依赖环境变量(特别是如果您想使用环境变量的 _CMD__SECRET 变体)。

但是,Airflow 支持其他设置密钥配置的变体 - 您可以指定一个系统命令来检索和自动轮换密钥(通过使用 _CMD 后缀定义变量)或从密钥支持中检索变量(通过使用 _SECRET 后缀定义变量)。

如果设置了 <VARIABLE_NAME>>,它将优先于 _CMD_SECRET 变体,因此如果您想设置 _CMD_SECRET 变体之一,则必须通过将 .Values.enableBuiltInSecretEnvVars.<VARIABLE_NAME> 设置为 false 来禁用从 Kubernetes 密钥检索的内置变量。

例如,为了使用命令检索数据库连接,您应该(在您的 values.yaml 文件中)指定

extraEnv:
  AIRFLOW_CONN_AIRFLOW_DB_CMD: "/usr/local/bin/retrieve_connection_url"
enableBuiltInSecretEnvVars:
  AIRFLOW_CONN_AIRFLOW_DB: false

以下是可以通过 _CMD_SECRET 变体禁用和替换的密钥的完整列表

如果未指定密钥名称,则默认密钥名称

使用其他 Kubernetes Secret

Airflow 环境变量

<RELEASE_NAME>-airflow-metadata

.Values.data.metadataSecretName

AIRFLOW_CONN_AIRFLOW_DB
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN

<RELEASE_NAME>-fernet-key

.Values.fernetKeySecretName

AIRFLOW__CORE__FERNET_KEY

<RELEASE_NAME>-webserver-secret-key

.Values.webserverSecretKeySecretName

AIRFLOW__WEBSERVER__SECRET_KEY

<RELEASE_NAME>-airflow-result-backend

.Values.data.resultBackendSecretName

AIRFLOW__CELERY__CELERY_RESULT_BACKEND
AIRFLOW__CELERY__RESULT_BACKEND

<RELEASE_NAME>-airflow-brokerUrl

.Values.data.brokerUrlSecretName

AIRFLOW__CELERY__BROKER_URL

<RELEASE_NAME>-elasticsearch

.Values.elasticsearch.secretName

AIRFLOW__ELASTICSEARCH__HOST
AIRFLOW__ELASTICSEARCH__ELASTICSEARCH_HOST

还有许多密钥,其名称也由版本名称确定,不需要禁用。这是因为它们要么不遵循 _CMD_SECRET 模式,要么是不以 AIRFLOW__ 开头的变量,要么是没有对应变量的变量。

还有一个 _AIRFLOW__* 变量 AIRFLOW__CELERY__FLOWER_BASIC_AUTH 不需要禁用,即使您想设置 _CMD_SECRET 变体。默认情况下不设置此变量。仅当设置了 .Values.flower.secretName 或设置了 .Values.flower.user.Values.flower.password 时才会设置它。因此,如果您没有设置任何 .Values.flower.* 变量,则可以使用 _CMD_SECRET 变体自由配置 Flower Basic Auth,而无需禁用基本变体。

如果未指定密钥名称,则默认密钥名称

使用其他 Kubernetes Secret

Airflow 环境变量

<RELEASE_NAME>-redis-password

.Values.redis.passwordSecretName

REDIS_PASSWORD

<RELEASE_NAME>-pgbouncer-config

.Values.pgbouncer.configSecretName

<RELEASE_NAME>-pgbouncer-certificates

<RELEASE_NAME>-registry

.Values.registry.secretName

<RELEASE_NAME>-kerberos-keytab

<RELEASE_NAME>-flower

.Values.flower.secretName

AIRFLOW__CELERY__FLOWER_BASIC_AUTH

您可以在设置配置选项中阅读有关设置配置变量的高级方法的更多信息。

此条目有帮助吗?