生产指南¶
以下是在生产环境中使用此 Helm Chart 时需要考虑的事项。
数据库¶
建议为 Airflow 元数据存储设置外部数据库。默认的 Helm Chart 会部署一个运行在容器中的 Postgres 数据库。对于生产用途,应使用运行在专用机器上或利用云提供商的数据库服务(例如 AWS RDS)的数据库,因为嵌入式 Postgres 缺乏生产数据库所需的稳定性、监控和持久化功能。它仅用于方便在“独立”版本中测试 Helm Chart,但使用它可能会导致数据丢失。支持的数据库和版本可以在此处找到:设置数据库后端。
注意
使用 helm chart 时,无需使用 airflow db migrate
初始化数据库,如 设置数据库后端 中所述。
首先禁用 Postgres,这样 chart 就不会部署自己的 Postgres 容器
postgresql:
enabled: false
要向 Airflow 提供数据库凭据,您有两种选择——在您的 values 文件中或在 Kubernetes Secret 中。
Values 文件¶
这是更简单的选项,因为 chart 将为您创建一个 Kubernetes Secret。但是,请记住您的凭据将存储在您的 values 文件中。
data:
metadataConnection:
user: <username>
pass: <password>
protocol: postgresql
host: <hostname>
port: 5432
db: <database name>
Kubernetes Secret¶
您还可以将凭据存储在您创建的 Kubernetes Secret 中。请注意,用户名/密码中的特殊字符必须进行 URL 编码。
kubectl create secret generic mydatabase --from-literal=connection=postgresql://user:pass@host:5432/db
最后,配置 chart 以使用您创建的 secret
data:
metadataSecretName: mydatabase
警告
如果您使用 CeleryExecutor
且 Airflow 版本小于 2.4
,请记住 resultBackendSecretName
期望以 db+postgresql://
开头的 URL,而 metadataSecretName
期望使用 postgresql://
并且不适用于 db+postgresql://
。您需要创建使用正确 scheme 的单独 secret。对于 Airflow 版本大于等于 2.4
,可以省略 result backend secret,因为 Airflow 默认将使用 sql_alchemy_conn
(在 metadataSecret
中指定)并带有 db+ scheme 前缀。
PgBouncer¶
如果您使用 PostgreSQL 作为数据库,您很可能也想启用 PgBouncer。Airflow 由于其分布式特性可以打开大量数据库连接,而使用连接池可以显著减少数据库上的开放连接数。
数据库凭据存储在 Values 文件中¶
pgbouncer:
enabled: true
数据库凭据存储在 Kubernetes Secret 中¶
在这种情况下,默认连接字符串将不起作用,您需要相应地修改
kubectl create secret generic mydatabase --from-literal=connection=postgresql://user:pass@pgbouncer_svc_name.deployment_namespace:6543/airflow-metadata
在此配置中,PgBouncer 要正常工作还需要两个额外的 Kubernetes Secret
airflow-pgbouncer-stats
kubectl create secret generic airflow-pgbouncer-stats --from-literal=connection=postgresql://user:pass@127.0.0.1:6543/pgbouncer?sslmode=disable
airflow-pgbouncer-config
apiVersion: v1
kind: Secret
metadata:
name: airflow-pgbouncer-config
data:
pgbouncer.ini: dmFsdWUtMg0KDQo=
users.txt: dmFsdWUtMg0KDQo=
pgbouncer.ini
等于此文本的 base64 编码版本
[databases]
airflow-metadata = host={external_database_host} dbname={external_database_dbname} port=5432 pool_size=10
[pgbouncer]
pool_mode = transaction
listen_port = 6543
listen_addr = *
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/users.txt
stats_users = postgres
ignore_startup_parameters = extra_float_digits
max_client_conn = 100
verbose = 0
log_disconnections = 0
log_connections = 0
server_tls_sslmode = prefer
server_tls_ciphers = normal
users.txt
等于此文本的 base64 编码版本
"{ external_database_host }" "{ external_database_pass }"
values.yaml
应如下所示
pgbouncer:
enabled: true
configSecretName: airflow-pgbouncer-config
metricsExporterSidecar:
statsSecretName: airflow-pgbouncer-stats
根据您的 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
Webserver Secret Key¶
使用此 chart 进行部署时,应设置一个静态 webserver secret key,这将有助于确保您的 Airflow 组件仅在必要时重启。
警告
您运行的每个实例都应使用不同的 secret key,因为此 key 用于签署会话 cookie 并执行其他安全相关功能!
首先,生成一个强 secret key
python3 -c 'import secrets; print(secrets.token_hex(16))'
现在将此 secret 添加到您的 values 文件中
webserverSecretKey: <secret_key>
或者,创建一个 Kubernetes Secret 并使用 webserverSecretKeySecretName
webserverSecretKeySecretName: my-webserver-secret
# where the random key is under `webserver-secret-key` in the k8s Secret
从 kubectl
创建 Kubernetes Secret 的示例
kubectl create secret generic my-webserver-secret --from-literal="webserver-secret-key=$(python3 -c 'import secrets; print(secrets.token_hex(16))')"
Webserver key 还用于在检索日志时授权对 Celery worker 的请求。但是,使用 secret key 生成的 token 有一个较短的过期时间 - 请确保运行 airflow 组件的所有机器上的时间都已同步(例如使用 ntpd),否则在访问日志时可能会出现“forbidden”错误。
驱逐配置¶
与 Kubernetes Cluster Autoscaler 一起运行 Airflow 时,配置 pod 是否可以安全驱逐非常重要。此设置可以在 Airflow chart 的不同级别进行配置
workers:
safeToEvict: true
scheduler:
safeToEvict: true
webserver:
safeToEvict: true
workers.safeToEvict
默认为 false
,并且在使用 KubernetesExecutor
时,workers.safeToEvict
不应设置为 true
,否则 worker 可能会在完成前被移除。
扩展和定制 Airflow 镜像¶
Apache Airflow 社区发布 Docker 镜像,这些镜像 是 Apache Airflow 的 参考镜像
。然而,Airflow 拥有超过 60 个社区管理的 provider(可通过 extra 安装),其中一些默认安装的 extras/providers 并非每个人都使用,有时需要其他 extras/providers,有时(实际上非常频繁)您需要添加自己的自定义依赖、包,甚至自定义 provider,或者添加部署所需的自定义工具和二进制文件。
在 Kubernetes 和 Docker 术语中,这意味着您需要一个包含您特定需求的另一个镜像。这就是为什么您应该学习如何构建自己的 Docker
(或更准确地说 容器
)镜像。
您可能想要使用自定义镜像的典型场景
添加
apt
包添加
PyPI
包添加部署所需的二进制资源
添加部署所需的自定义工具
请参阅 构建镜像,了解如何扩展和定制 Airflow 镜像的更多详细信息。
管理 DAG 文件¶
请参阅 管理 DAG 文件。
knownHosts¶
如果您正在使用 dags.gitSync.sshKeySecret
,您还应该设置 dags.gitSync.knownHosts
。这里我们将演示 GitHub 的过程,但对于任何 provider 都可以进行相同的操作
获取 GitHub 的公钥
ssh-keyscan -t rsa github.com > github_public_key
接下来,打印公钥的 fingerprint
ssh-keygen -lf github_public_key
将该输出与 GitHub 的 SSH key fingerprint 进行比较。
它们匹配,对吧?好的。现在,将公钥添加到您的 values 文件中。它看起来像这样
dags:
gitSync:
knownHosts: |
github.com ssh-rsa AAAA...1/wsjk=
外部 Scheduler¶
要使用外部 Scheduler 实例
scheduler:
enabled: false
确保您的外部 webserver/scheduler 连接到同一个 redis 主机。这将确保 scheduler 知道 helm-chart 中部署的 worker。
访问 Airflow UI¶
您如何访问 Airflow UI 将取决于您的环境;但是,chart 支持各种选项
外部 Webserver¶
要使用外部 Webserver
webserver:
enabled: false
确保您的外部 webserver/scheduler 连接到同一个 redis 主机。这将确保 scheduler 知道 helm-chart 中部署的 worker。
Ingress¶
您可以创建和配置 Ingress
对象。请参阅 Ingress chart 参数。有关 Ingress
的更多信息,请参阅 Kubernetes Ingress 文档。
LoadBalancer Service¶
您可以将 webserver 的 Service 类型更改为 LoadBalancer
,并设置任何必要的 annotation
webserver:
service:
type: LoadBalancer
有关 LoadBalancer
Service 的更多信息,请参阅 Kubernetes LoadBalancer Service 文档。
日志记录¶
根据您选择的 executor,任务日志可能无法直接工作。所有日志记录选项都可以在此处找到:管理日志。
指标¶
chart 支持将指标发送到现有的 StatsD 实例或提供 Prometheus endpoint。
Prometheus¶
指标 endpoint 可在此处访问: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: ...
IPv6 StatsD¶
要使用带有 IPv6 地址的 StatsD 实例。示例:在启用 IPv6 的 Kubernetes 中使用
statsd:
enabled: true
config:
metrics: # or 'scheduler' for Airflow 1
statsd_on: 'True'
statsd_host: ...
statsd_ipv6: 'True'
statsd_port: ...
statsd_prefix: airflow
Datadog¶
如果您在环境中使用 Datadog agent,这将使 Airflow 能够将指标导出到 Datadog agent。
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 后端¶
如果您使用 CeleryExecutor
或 CeleryKubernetesExecutor
,您可以使用自己的 Celery 后端。
默认情况下,chart 将部署 Redis。但是,您可以使用任何支持的 Celery 后端代替
redis:
enabled: false
data:
brokerUrl: redis://redis-user:password@redis-host:6379/0
有关设置 Celery broker 的更多信息,请参阅详细的 Celery 相关主题文档。
Security Context Constraints¶
Security Context Constraint
(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
在此 chart 中,SCC 通过 RoleBindings 绑定到 Pod,这意味着选项 rbac.create
也必须设置为 true
,以完全启用 SCC 的使用。
有关 SCC 以及通过此构造可以实现的功能的更多信息,请参阅 管理 security context constraints。
Security Context¶
在 Kubernetes 中,securityContext
可用于定义用户 ID、组 ID 和能力,例如以特权模式运行容器。
将应用程序部署到 Kubernetes 时,建议赋予容器最小权限,以减少访问并保护容器运行的主机。
在 Airflow Helm chart 中,securityContext
可以通过多种方式进行配置
uid (配置全局 uid 或 RunAsUser)
gid (配置全局 gid 或 fsGroup)
securityContexts (与
uid
相同,但允许设置所有 Pod securityContext 选项 和 Container securityContext 选项)
与配置全局 securityContexts 的方式相同,也可以通过设置特定工作负载的本地 securityContexts
如下所示配置不同的值
workers:
securityContexts:
pod:
runAsUser: 5000
fsGroup: 0
containers:
allowPrivilegeEscalation: false
在上面的示例中,worker Pod 的 securityContexts
将设置为 runAsUser: 5000
和 fsGroup: 0
。容器 Pod 将设置为 allowPrivilegeEscalation: false
。
可以看到,本地设置优先于全局设置(如果已定义)。下面解释了此 chart 中 securityContexts
选项的优先级规则
uid: 40000
gid: 0
securityContexts:
pod:
runAsUser: 50000
fsGroup: 0
workers:
securityContexts:
pod:
runAsUser: 1001
fsGroup: 0
这将生成以下 worker 部署
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
如果我们从上面的示例中同时删除 securityContexts
和 workers.securityContexts
,输出将如下所示
uid: 40000
gid: 0
securityContexts: {}
workers:
securityContexts: {}
这将生成以下 worker 部署
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: {}
这将生成以下 worker 部署
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
...
内置 Secret 和环境变量¶
默认情况下,Helm Chart 使用 Kubernetes Secret 来存储 Airflow 所需的 secret。这些 secret 的内容默认会转换为 Airflow 读取的环境变量(一些环境变量有多种变体以支持旧版本的 Airflow)。
默认情况下,secret 名称是根据部署 Helm Chart 时使用的 Release Name 确定的,但您也可以使用不同的 secret 来设置变量,或者完全禁用使用 secret,转而依赖环境变量(特别是如果您想使用环境变量的 _CMD
或 __SECRET
变体)。
然而,Airflow 支持其他设置 secret 配置的变体——您可以指定一个系统命令来检索并自动轮换 secret(通过定义带有 _CMD
后缀的变量),或者从 secret 后端检索变量(通过定义带有 _SECRET
后缀的变量)。
如果设置了 <VARIABLE_NAME>>
,它将优先于 _CMD
和 _SECRET
变体,因此如果您想设置 _CMD
或 _SECRET
变体之一,则必须通过将 .Values.enableBuiltInSecretEnvVars.<VARIABLE_NAME>
设置为 false 来禁用从 Kubernetes secret 中检索的内置变量。
例如,为了使用命令检索数据库连接,您应该(在您的 values.yaml
文件中)指定
extraEnv:
AIRFLOW_CONN_AIRFLOW_DB_CMD: "/usr/local/bin/retrieve_connection_url"
enableBuiltInSecretEnvVars:
AIRFLOW_CONN_AIRFLOW_DB: false
以下是可以禁用并由 _CMD
和 _SECRET
变体替换的全部 secret 列表
未指定 secret 名称时的默认 secret 名称 |
使用不同的 Kubernetes Secret |
Airflow 环境变量 |
---|---|---|
|
|
AIRFLOW_CONN_AIRFLOW_DB AIRFLOW__DATABASE__SQL_ALCHEMY_CONN |
|
|
|
|
|
|
|
|
AIRFLOW__CELERY__CELERY_RESULT_BACKEND AIRFLOW__CELERY__RESULT_BACKEND |
|
|
|
|
|
AIRFLOW__ELASTICSEARCH__HOST AIRFLOW__ELASTICSEARCH__ELASTICSEARCH_HOST |
还有一些 secret,它们的名称也是根据 release name 确定的,但不需要禁用。这是因为它们要么不遵循 _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,而无需禁用基本变体。
未指定 secret 名称时的默认 secret 名称 |
使用不同的 Kubernetes Secret |
Airflow 环境变量 |
---|---|---|
|
|
|
|
|
|
|
||
|
|
|
|
||
|
|
|
您可以在 设置配置选项 中阅读有关设置配置变量的高级方法的更多信息。