Entrypoint¶
如果您正在使用生產映像檔的預設 entrypoint,則容器啟動時會自動執行一些動作。在某些情況下,您可以將環境變數傳遞給映像檔以觸發某些行為。
控制「執行」行為的變數以 _AIRFLOW
開頭,以將它們與用於建置映像檔且以 AIRFLOW
開頭的變數區分開來。
允許任意使用者執行容器¶
Airflow 映像檔與 Open-Shift 相容,這表示您可以使用隨機使用者 ID 和群組 ID 0
(root
) 啟動它。如果您想使用與 Airflow 不同的使用者執行映像檔,您必須將使用者的 GID 設定為 0
。如果您嘗試使用不同的群組,entrypoint 將會以錯誤退出。
OpenShift 在啟動容器時會隨機分配 UID,但如果您手動執行映像檔,您也可以利用這種彈性的 UID。例如,如果您想從 Linux 主機系統掛載 dag
和 logs
資料夾,在這種情況下,UID 應該設定為與您的主機使用者相同的 ID,這可能會很有用。
這可以透過多種方式實現 - 您可以在擴展或自訂映像檔時變更 USER,或者您可以透過在 docker run
命令中新增 --user
旗標,以動態方式將使用者傳遞給 docker run
命令,格式如下 (詳情請參閱 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
。許多協力廠商函式庫和套件都需要使用者的主目錄存在,因為它們需要在其中寫入一些快取資訊,因此動態建立使用者是必要的。
此類任意使用者必須能夠寫入需要寫入權限的某些目錄,並且由於不建議允許「其他」寫入權限以確保安全,因此 OpenShift 指南引入了使所有此類資料夾都具有 0
(root
) 群組 ID (GID) 的概念。Airflow 生產映像檔中需要寫入權限的所有目錄都將 GID 設定為 0 (並且它們對於群組是可寫入的)。我們遵循這個概念,所有需要寫入權限的目錄都遵循這個概念。
GID=0 設定為 airflow
使用者的預設值,因此它建立的任何目錄預設都將 GID 設定為 0。entrypoint 將 umask
設定為 0002
- 這表示使用者建立的任何目錄也具有群組 0
的「群組寫入」權限 - 它們將可由具有 root
群組的其他使用者寫入。此外,每當任何「任意」使用者建立資料夾 (例如在掛載的磁碟區中) 時,該資料夾都將具有「群組寫入」權限和 GID=0
,以便即使稍後由另一個任意使用者掛載此類目錄,使用另一個任意使用者的執行仍將繼續運作。
但是,umask
設定僅適用於容器的執行時間 - 它在映像檔的建置期間未使用。如果您想擴展映像檔並新增自己的套件,您應該記住在您的 docker 命令前面新增 umask 0002
- 這樣任何需要群組存取的安裝所建立的目錄對於群組來說也是可寫入的。例如,可以透過這種方式完成
RUN umask 0002; \ do_something; \ do_otherthing;
您可以在 Openshift 最佳實務 中的「支援任意使用者 ID」章節中閱讀更多相關資訊。
等待 Airflow DB 連線¶
entrypoint 正在等待資料庫連線,與資料庫引擎無關。這讓我們能夠提高環境的穩定性。
等待連線涉及執行 airflow db check
命令,這表示將執行 select 1 as is_alive;
陳述式。然後它會迴圈,直到命令成功為止。它會嘗試 CONNECTION_CHECK_MAX_COUNT
次,並在檢查之間休眠 CONNECTION_CHECK_SLEEP_TIME
。若要停用檢查,請設定 CONNECTION_CHECK_MAX_COUNT=0
。
等待 Celery broker 連線¶
如果使用 CeleryExecutor,並且使用了 scheduler
、celery
命令之一,則 entrypoint 將等待,直到 Celery broker 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:2.10.4-python3.8 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:2.10.4-python3.8 python -c "print('test')"
test
如果第一個引數等於 “airflow” - 其餘引數將被視為要執行的 airflow 命令。範例
docker run -it apache/airflow:2.10.4-python3.8 airflow webserver
如果還有任何其他引數 - 它們只會傳遞給 “airflow” 命令
> docker run -it apache/airflow:2.10.4-python3.8 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 a Airflow webserver instance
optional arguments:
-h, --help show this help message and exit
在 Airflow entrypoint 之前執行自訂程式碼¶
如果您想在 Airflow 的 entrypoint 之前執行一些自訂程式碼,您可以使用自訂腳本,並將 Airflow 的 entrypoint 作為自訂腳本中的最後一個 exec
指令呼叫。但是,您必須記住以與 Airflow 的 entrypoint 相同的方式使用 dumb-init
,否則您可能會遇到訊號傳遞不正確的問題 (請參閱下一章)。
FROM airflow:2.9.0.dev0
COPY my_entrypoint.sh /
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/my_entrypoint.sh"]
您的 entrypoint 可能會動態修改或新增變數。例如,以下 entrypoint 從作為映像檔執行參數傳遞的第一個參數設定 DB 檢查的最大計數 (一個有點沒用的範例,但應該讓讀者了解您可以如何使用它)。
#!/bin/bash
export CONNECTION_CHECK_MAX_COUNT=${1}
shift
exec /entrypoint "${@}"
請確保 Airflow 的 entrypoint 使用 exec /entrypoint "${@}"
作為自訂 entrypoint 中的最後一個命令執行。這樣,訊號將被正確傳遞,並且引數將像往常一樣傳遞給 entrypoint (如果您需要傳遞一些額外引數,可以使用上面的 shift
)。請注意,從安全角度來看,以這種方式傳遞機密值或將機密儲存在映像檔中是一個壞主意 - 因為任何有權存取您的 Kubernetes 或映像檔登錄檔日誌的人都可以存取映像檔和執行映像檔的參數。
另請注意,在 Airflow 的 entrypoint 之前執行的程式碼不應在容器內建立任何檔案或目錄,並且在執行時,一切可能無法以相同的方式運作。在執行 Airflow entrypoint 之前,以下功能不可用
umask 未正確設定以允許
group
寫入權限如果使用任意使用者執行映像檔,則使用者尚未在
/etc/passwd
中建立資料庫和 broker 可能尚未可用
新增自訂映像檔行為¶
Airflow 映像檔在 entrypoint 中執行許多步驟,並設定正確的環境,但您可能希望在 entrypoint 建立使用者、設定 umask、設定變數並檢查資料庫是否正在執行後執行額外程式碼。
您可以執行自訂腳本 (您可以將其嵌入到映像檔中),而不是執行常規命令 - scheduler
、webserver
。當您完成自訂設定後,您甚至可以在您的自訂腳本中執行 airflow 的常用元件 - scheduler
、webserver
。與自訂 entrypoint 類似,它可以透過擴展映像檔新增到映像檔中。
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
作為 entrypoint 中的 “init” 執行。這是為了正確傳遞訊號和清除子程序。這表示您執行的程序不必安裝訊號處理常式即可正常運作,並在容器正常終止時被終止。訊號傳遞的行為由 DUMB_INIT_SETSID
變數配置,預設設定為 1
- 表示訊號將傳遞到整個程序群組,但您可以將其設定為 0
以啟用 dumb-init
的 single-child
行為,該行為僅將訊號傳遞到單個子程序。
下表總結了 DUMB_INIT_SETSID
的可能值及其使用案例。
變數值 |
使用案例 |
1 (預設) |
將訊號傳遞到容器中執行的主程序之程序群組中的所有程序。 如果您透過 |
0 |
將訊號僅傳遞到主程序。 如果您的主程序優雅地處理訊號,這將非常有用。Celery worker 的暖關機便是一個很好的例子。在這種情況下, 對於 Airflow 的 Celery worker,您應該將變數設定為 0,並使用 |
額外的快速測試選項¶
以下選項主要用於快速測試映像檔 - 例如使用快速入門 docker-compose 或當您想要使用新增的套件執行本機測試時。它們不應在生產環境中執行,因為它們會為執行額外命令增加額外負荷。生產環境中的這些選項應作為資料庫的維護操作實現,或應嵌入到使用的自訂映像檔中 (當您想要新增套件時)。
升級 Airflow DB¶
如果您將 _AIRFLOW_DB_MIGRATE
變數設定為非空值,則 entrypoint 將在驗證連線後立即執行 airflow db migrate
命令。當您使用內部 SQLite 資料庫 (預設) 執行 airflow 時,您也可以使用它來升級資料庫並在 entrypoint 建立管理員使用者,以便您可以立即啟動 webserver。注意 - 使用 SQLite 僅適用於測試目的,永遠不要在生產環境中使用 SQLite,因為它在並行性方面存在嚴重限制。
建立管理員使用者¶
當您進入 entrypoint 時,它也可以自動建立 webserver 使用者。您需要將 _AIRFLOW_WWW_USER_CREATE
設定為非空值才能執行此操作。這不適用於生產環境,僅當您想使用生產映像檔執行快速測試時才有用。您需要至少傳遞密碼,才能透過 _AIRFLOW_WWW_USER_PASSWORD
或 _AIRFLOW_WWW_USER_PASSWORD_CMD
建立此類使用者,與其他 *_CMD
變數類似,*_CMD
的內容將被評估為 shell 命令,其輸出將設定為密碼。
如果未設定任何 PASSWORD
變數,使用者建立將會失敗 - 由於安全原因,密碼沒有預設值。
參數 |
預設值 |
環境變數 |
---|---|---|
使用者名稱 |
admin |
|
密碼 |
|
|
名字 |
Airflow |
|
姓氏 |
Admin |
|
電子郵件 |
|
|
角色 |
Admin |
|
如果指定了密碼,將嘗試建立使用者,但如果嘗試失敗,entrypoint 不會失敗 (這說明了使用者已建立的情況)。
例如,您可以使用以下命令在生產映像檔中啟動 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:2.10.4-python3.8 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:2.10.4-python3.8 webserver
上述命令執行 SQLite 資料庫的初始化,建立具有 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:2.10.4-python3.8 webserver
此方法僅適用於 Airflow 2.1.1 及更高版本的 Docker 映像檔。