Airflow Summit 2025 將於 10 月 07-09 日舉行。立即註冊獲取早鳥票!

入口點

如果您使用生產映象的預設入口點,容器啟動時會自動執行一些操作。在某些情況下,您可以透過向映象傳遞環境變數來觸發這些行為。

控制“執行”行為的變數以 _AIRFLOW 開頭,以區分用於構建映象的以 AIRFLOW 開頭的變數。

允許任意使用者執行容器

Airflow 映象與 OpenShift 相容,這意味著您可以使用隨機使用者 ID 和組 ID 0 (root) 來啟動它。如果您想使用 Airflow 以外的使用者執行映象,則必須將使用者的 GID 設定為 0。如果您嘗試使用不同的組,入口點將退出並報錯。

OpenShift 在啟動容器時隨機分配 UID,但您也可以在手動執行映象時利用這種靈活的 UID。這可能很有用,例如當您想在 Linux 上從主機系統掛載 daglogs 資料夾時,在這種情況下,UID 應設定為與主機使用者相同的 ID。

這可以透過多種方式實現 - 您可以在擴充套件或定製映象時更改 USER,或者透過在 docker run 命令中新增 --user 標誌來動態地將使用者傳遞給該命令,格式如下(詳情請參閱 Docker Run 參考

[ user | user:group | uid | uid:gid | user:gid | uid:group ]

在使用 Docker Compose 環境時,可以透過 docker-compose.yaml 檔案中的 user: 條目進行更改。詳情請參閱 Docker compose 參考。在我們使用 Docker-Compose 的快速入門指南中,UID 可以透過 AIRFLOW_UID 變數傳遞,如 初始化 docker compose 環境 中所述。

使用者可以是任何 UID。如果 UID 與預設的 airflow (UID=50000) 不同,則在進入容器時將自動建立使用者。

為了適應許多外部庫和專案,Airflow 將在 (/etc/passwd) 中自動建立這樣一個任意使用者,並將其主目錄指向 /home/airflow。許多第三方庫和包要求使用者的 home 目錄存在,因為它們需要在那裡寫入一些快取資訊,因此動態建立使用者是必要的。

這樣的任意使用者必須能夠寫入需要寫入許可權的特定目錄,並且由於安全原因,不建議允許“其他”使用者具有寫入許可權,因此 OpenShift 指南引入了一個概念,即將所有此類資料夾的組 ID (GID) 設定為 0 (root)。Airflow 生產映象中所有需要寫入許可權的目錄的 GID 都設定為 0(並且組可寫)。我們遵循這個概念,所有需要寫入許可權的目錄都遵循這個原則。

GID=0 被設定為 airflow 使用者的預設值,因此它建立的任何目錄預設都將 GID 設定為 0。入口點將 umask 設定為 0002 - 這意味著使用者建立的任何目錄對組 0 也具有“組寫入”許可權 - 它們將可由具有 root 組的其他使用者寫入。此外,無論何時任何“任意”使用者建立一個資料夾(例如在掛載的卷中),該資料夾都將具有“組寫入”許可權和 GID=0,這樣即使該目錄後來被另一個任意使用者掛載,使用另一個任意使用者執行操作仍將繼續有效。

然而,umask 設定僅在容器執行時有效 - 在構建映象期間不使用。如果您想擴充套件映象並新增自己的包,您應該記住在 docker 命令前面新增 umask 0002 - 這樣任何需要組訪問的安裝建立的目錄也將可由組寫入。例如,可以透過以下方式實現

RUN umask 0002; \
    do_something; \
    do_otherthing;

您可以在 Openshift 最佳實踐 的“支援任意使用者 ID”章節中閱讀更多相關資訊。

等待 Airflow DB 連線

入口點正在等待資料庫連線,與資料庫引擎無關。這有助於提高環境的穩定性。

等待連線涉及執行 airflow db check 命令,這意味著將執行一條 select 1 as is_alive; 語句。然後它會迴圈直到命令成功。它會嘗試 CONNECTION_CHECK_MAX_COUNT 次,並在每次檢查之間休眠 CONNECTION_CHECK_SLEEP_TIME。要停用檢查,請設定 CONNECTION_CHECK_MAX_COUNT=0

等待 Celery 代理連線

如果使用 CeleryExecutor,並且使用了 schedulercelery 命令之一,則入口點將等待直到 Celery 代理 DB 連線可用。

該指令碼根據 URL 方案檢測後端型別,並在 URL 中未指定埠號時分配預設埠號。然後它會迴圈直到可以建立到指定主機/埠的連線。它會嘗試 CONNECTION_CHECK_MAX_COUNT 次,並在每次檢查之間休眠 CONNECTION_CHECK_SLEEP_TIME。要停用檢查,請設定 CONNECTION_CHECK_MAX_COUNT=0

支援的方案

  • amqp(s):// (rabbitmq) - 預設埠 5672

  • redis:// - 預設埠 6379

  • postgres:// - 預設埠 5432

  • mysql:// - 預設埠 3306

等待連線涉及檢查匹配的埠是否開啟。主機資訊派生自 Airflow 配置。

執行命令

如果第一個引數等於“bash” - 您將進入 bash shell,或者如果您指定額外引數,則可以執行 bash 命令。例如

docker run -it apache/airflow:3.0.0-python3.9 bash -c "ls -la"
total 16
drwxr-xr-x 4 airflow root 4096 Jun  5 18:12 .
drwxr-xr-x 1 root    root 4096 Jun  5 18:12 ..
drwxr-xr-x 2 airflow root 4096 Jun  5 18:12 dags
drwxr-xr-x 2 airflow root 4096 Jun  5 18:12 logs

如果第一個引數等於 python - 您將進入 python shell,或者如果您傳遞額外引數,則執行 python 命令。例如

> docker run -it apache/airflow:3.0.0-python3.9 python -c "print('test')"
test

如果第一個引數等於 airflow - 其餘引數將被視為要執行的 Airflow 命令。示例

docker run -it apache/airflow:3.0.0-python3.9 airflow webserver

如果還有其他引數 - 它們將直接傳遞給“airflow”命令

> docker run -it apache/airflow:3.0.0-python3.9 help
  usage: airflow [-h] GROUP_OR_COMMAND ...

  positional arguments:
    GROUP_OR_COMMAND

      Groups:
        celery         Celery components
        config         View configuration
        connections    Manage connections
        dags           Manage dags
        db             Database operations
        jobs           Manage jobs
        kubernetes     Tools to help run the KubernetesExecutor
        pools          Manage pools
        providers      Display providers
        roles          Manage roles
        tasks          Manage tasks
        users          Manage users
        variables      Manage variables

      Commands:
        cheat-sheet    Display cheat sheet
        info           Show information about current Airflow and environment
        kerberos       Start a Kerberos ticket renewer
        plugins        Dump information about loaded plugins
        rotate-fernet-key
                       Rotate encrypted connection credentials and variables
        scheduler      Start a scheduler instance
        sync-perm      Update permissions for existing roles and optionally dags
        version        Show the version
        webserver      Start an Airflow webserver instance

  optional arguments:
    -h, --help         show this help message and exit

在 Airflow 入口點之前執行自定義程式碼

如果您想在 Airflow 的入口點之前執行一些自定義程式碼,可以使用自定義指令碼,並在自定義指令碼中將 Airflow 的入口點作為最後一個 exec 指令呼叫。但是,您必須記住以與 Airflow 入口點相同的方式使用 dumb-init,否則可能會在訊號傳播方面遇到問題(請參閱下一章)。

FROM airflow:2.9.0.dev0
COPY my_entrypoint.sh /
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/my_entrypoint.sh"]

您的入口點可以例如動態修改或新增變數。例如,下面的入口點根據作為映象執行引數傳遞的第一個引數來設定 DB 檢查的最大次數(一個有點沒用的例子,但應該能給讀者一個如何使用的示例)。

#!/bin/bash
export CONNECTION_CHECK_MAX_COUNT=${1}
shift
exec /entrypoint "${@}"

確保在自定義入口點中將 exec /entrypoint "${@}" 作為最後一個命令執行 Airflow 的入口點。這樣訊號將得到正確傳播,並且引數將照常傳遞給入口點(如果需要傳遞一些額外引數,可以使用上面的 shift)。請注意,從安全形度來看,以這種方式傳遞秘密值或將秘密儲存在映象中是一個糟糕的主意 - 因為映象和執行映象的引數都可以被有權訪問 Kubernetes 或映象登錄檔日誌的任何人訪問。

另請注意,在 Airflow 入口點執行之前執行的程式碼不應在容器內建立任何檔案或目錄,並且執行時所有功能可能無法正常工作。在 Airflow 入口點執行之前,以下功能不可用:

  • umask 未正確設定,不允許 group 寫訪問

  • 如果使用任意使用者執行映象,則使用者尚未在 /etc/passwd 中建立

  • 資料庫和代理可能尚未可用

新增自定義映象行為

Airflow 映象在入口點執行許多步驟,並設定正確的環境,但您可能希望在入口點建立使用者、設定 umask、設定變數並檢查資料庫正在執行之後執行額外的程式碼。

與其執行常規命令 - schedulerwebserver,不如執行可以嵌入到映象中的自定義指令碼。完成自定義設定後,您甚至可以在自定義指令碼中執行 Airflow 的常用元件 - schedulerwebserver。與自定義入口點類似,可以透過擴充套件映象來新增它。

FROM airflow:2.9.0.dev0
COPY my_after_entrypoint_script.sh /

構建您的映象,然後您可以透過執行以下命令來執行此指令碼

docker build . --pull --tag my-image:0.0.1
docker run -it my-image:0.0.1 bash -c "/my_after_entrypoint_script.sh"

訊號傳播

Airflow 在入口點中使用 dumb-init 作為“init”執行。這樣做是為了正確傳播訊號並回收子程序。這意味著您執行的程序不必安裝訊號處理程式即可正常工作並在容器正常終止時被殺死。訊號傳播的行為由 DUMB_INIT_SETSID 變數配置,該變數預設為 1 - 這意味著訊號將傳播到整個程序組,但您可以將其設定為 0 以啟用 dumb-initsingle-child 行為,該行為僅將訊號傳播到單個子程序。

下表總結了 DUMB_INIT_SETSID 的可能值及其用例。

變數值

用例

1 (預設)

將訊號傳播到容器中執行的主程序的程序組中的所有程序。

如果您透過 ["bash", "-c"] 命令執行您的程序,並且 bash 在沒有 exec 的情況下建立新程序,這將有助於正常終止容器,因為所有程序都將接收到訊號。

0

僅將訊號傳播到主程序。

如果您的主程序正常處理訊號,這將非常有用。一個很好的例子是 Celery worker 的溫和關閉。dumb-init 在這種情況下只會將訊號傳播到主程序,而不會傳播到與主程序在同一程序組中建立的程序。例如,在 Celery 的情況下,主程序會將 worker 置於“離線”模式,並等待所有正在執行的任務完成,然後才會終止所有程序。

對於 Airflow 的 Celery worker,您應該將變數設定為 0,並使用 ["celery", "worker"] 命令。如果您透過 ["bash", "-c"] 命令執行它,則需要將 exec airflow celery worker 作為最後一個執行的命令來啟動 worker。

額外的快速測試選項

以下選項主要用於快速測試映象 - 例如使用 quick-start docker-compose,或在新增新包時進行本地測試。它們不應在生產環境中執行,因為它們會增加執行額外命令的開銷。在生產環境中,這些選項應作為資料庫上的維護操作實現,或嵌入到使用的自定義映象中(當您想新增新包時)。

升級 Airflow DB

如果您將 _AIRFLOW_DB_MIGRATE 變數設定為非空值,入口點將在驗證連線後立即執行 airflow db migrate 命令。當您使用內部 SQLite 資料庫(預設)執行 Airflow 時,也可以使用此選項在入口點升級資料庫並建立管理員使用者,以便您可以立即啟動 webserver。注意 - 使用 SQLite 僅用於測試目的,切勿在生產環境中使用 SQLite,因為它在併發方面存在嚴重限制。

建立管理員使用者

入口點也可以在您進入時自動建立 webserver 使用者。為此,您需要將 _AIRFLOW_WWW_USER_CREATE 設定為非空值。這不適用於生產環境,僅在您想使用生產映象進行快速測試時有用。您至少需要透過 _AIRFLOW_WWW_USER_PASSWORD_AIRFLOW_WWW_USER_PASSWORD_CMD 傳遞密碼來建立此類使用者,類似於其他 *_CMD 變數,*_CMD 的內容將被評估為 shell 命令,其輸出將設定為密碼。

如果未設定任何 PASSWORD 變數,則使用者建立將失敗 - 出於安全原因,密碼沒有預設值。

引數

預設值

環境變數

使用者名稱

admin

_AIRFLOW_WWW_USER_USERNAME

密碼

_AIRFLOW_WWW_USER_PASSWORD_CMD_AIRFLOW_WWW_USER_PASSWORD

名字

Airflow

_AIRFLOW_WWW_USER_FIRSTNAME

姓氏

Admin

_AIRFLOW_WWW_USER_LASTNAME

郵箱

airflowadmin@example.com

_AIRFLOW_WWW_USER_EMAIL

角色

Admin

_AIRFLOW_WWW_USER_ROLE

如果指定了密碼,將嘗試建立使用者,但如果嘗試失敗,入口點不會失敗(這考慮了使用者已存在的情況)。

例如,您可以在生產映象中啟動 webserver,同時初始化內部 SQLite 資料庫並使用以下命令建立 admin/admin 管理員使用者

docker run -it -p 8080:8080 \
  --env "_AIRFLOW_DB_MIGRATE=true" \
  --env "_AIRFLOW_WWW_USER_CREATE=true" \
  --env "_AIRFLOW_WWW_USER_PASSWORD=admin" \
    apache/airflow:3.0.0-python3.9 webserver
docker run -it -p 8080:8080 \
  --env "_AIRFLOW_DB_MIGRATE=true" \
  --env "_AIRFLOW_WWW_USER_CREATE=true" \
  --env "_AIRFLOW_WWW_USER_PASSWORD_CMD=echo admin" \
    apache/airflow:3.0.0-python3.9 webserver

上述命令執行 SQLite 資料庫的初始化,使用 admin 密碼和 Admin 角色建立管理員使用者。它們還將本地埠 8080 轉發到 webserver 埠,最後啟動 webserver。

安裝額外的依賴項

警告

以這種方式安裝依賴項是一種非常方便的執行 Airflow 的方法,對於測試和除錯非常有用。然而,不要被它的便利性所迷惑。您絕不應在生產環境中使用它。我們特意將其作為開發/測試依賴項,並且每當使用它時,我們都會列印警告。在生產環境中使用此方法存在固有的安全相關問題。以這種方式安裝依賴項可能發生在任何時候 - 當您的容器重啟時,當您的 K8S 叢集中的機器重啟時。在 K8S 叢集中,這些事件可能在任何時候發生。這使您面臨嚴重的漏洞,您的生產環境可能因 PyPI 中移除單個依賴項 - 甚至您依賴項的依賴項 - 而癱瘓。這意味著您將生產服務的可用性置於第三方開發人員手中。在任何時間、任何時刻,包括週末和節假日,這些第三方開發人員都可能導致您的生產 Airflow 例項崩潰,而您甚至可能不知道。這是一個嚴重的漏洞,類似於臭名昭著的 leftpad 問題。您可以透過構建自己的、不可變的自定義映象來完全防止這種情況,其中依賴項已內建。您已收到警告。

可以透過指定 _PIP_ADDITIONAL_REQUIREMENTS 變數來安裝額外的依賴項。該變數應包含在進入容器時應額外安裝的依賴項列表。請注意,此選項會減慢 Airflow 的啟動速度,因為每當任何容器啟動時,它都必須安裝新包,並且在生產環境中使用時會帶來巨大的潛在安全漏洞(見下文)。因此,此選項僅應用於測試。測試完成後,您應建立內建依賴項的自定義映象。

示例

docker run -it -p 8080:8080 \
  --env "_PIP_ADDITIONAL_REQUIREMENTS=lxml==4.6.3 charset-normalizer==1.4.1" \
  --env "_AIRFLOW_DB_MIGRATE=true" \
  --env "_AIRFLOW_WWW_USER_CREATE=true" \
  --env "_AIRFLOW_WWW_USER_PASSWORD_CMD=echo admin" \
    apache/airflow:3.0.0-python3.9 webserver

此方法僅在 Airflow 2.1.1 及以上版本的 Docker 映象中可用。

本條目有幫助嗎?