入口點¶
如果您使用生產映象的預設入口點,容器啟動時會自動執行一些操作。在某些情況下,您可以透過向映象傳遞環境變數來觸發這些行為。
控制“執行”行為的變數以 _AIRFLOW 開頭,以區分用於構建映象的以 AIRFLOW 開頭的變數。
允許任意使用者執行容器¶
Airflow 映象與 OpenShift 相容,這意味著您可以使用隨機使用者 ID 和組 ID 0 (root) 來啟動它。如果您想使用 Airflow 以外的使用者執行映象,則必須將使用者的 GID 設定為 0。如果您嘗試使用不同的組,入口點將退出並報錯。
OpenShift 在啟動容器時隨機分配 UID,但您也可以在手動執行映象時利用這種靈活的 UID。這可能很有用,例如當您想在 Linux 上從主機系統掛載 dag 和 logs 資料夾時,在這種情況下,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,並且使用了 scheduler、celery 命令之一,則入口點將等待直到 Celery 代理 DB 連線可用。
該指令碼根據 URL 方案檢測後端型別,並在 URL 中未指定埠號時分配預設埠號。然後它會迴圈直到可以建立到指定主機/埠的連線。它會嘗試 CONNECTION_CHECK_MAX_COUNT 次,並在每次檢查之間休眠 CONNECTION_CHECK_SLEEP_TIME。要停用檢查,請設定 CONNECTION_CHECK_MAX_COUNT=0。
支援的方案
amqp(s)://(rabbitmq) - 預設埠 5672redis://- 預設埠 6379postgres://- 預設埠 5432mysql://- 預設埠 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、設定變數並檢查資料庫正在執行之後執行額外的程式碼。
與其執行常規命令 - scheduler、webserver,不如執行可以嵌入到映象中的自定義指令碼。完成自定義設定後,您甚至可以在自定義指令碼中執行 Airflow 的常用元件 - scheduler、webserver。與自定義入口點類似,可以透過擴充套件映象來新增它。
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-init 的 single-child 行為,該行為僅將訊號傳播到單個子程序。
下表總結了 DUMB_INIT_SETSID 的可能值及其用例。
變數值 |
用例 |
1 (預設) |
將訊號傳播到容器中執行的主程序的程序組中的所有程序。 如果您透過 |
0 |
僅將訊號傳播到主程序。 如果您的主程序正常處理訊號,這將非常有用。一個很好的例子是 Celery worker 的溫和關閉。 對於 Airflow 的 Celery worker,您應該將變數設定為 0,並使用 |
額外的快速測試選項¶
以下選項主要用於快速測試映象 - 例如使用 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 |
|
姓氏 |
Admin |
|
郵箱 |
|
|
角色 |
Admin |
|
如果指定了密碼,將嘗試建立使用者,但如果嘗試失敗,入口點不會失敗(這考慮了使用者已存在的情況)。
例如,您可以在生產映象中啟動 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 映象中可用。