度:Docker 安裝與工作流實戰(zhàn))
簡介Azkaban Solo Server 單機版編譯包面向需要快速搭建工作流調(diào)度環(huán)境的大數(shù)據(jù)開發(fā)者、運維人員及個人學習者用于解決 Hadoop 作業(yè)與 Shell、Java 任務按依賴順序自動執(zhí)行的問題。資源為 azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz壓縮包約 42.28MB解壓后可直接運行無需自行編譯。包內(nèi)包含 Web 服務、執(zhí)行器與內(nèi)嵌 H2 數(shù)據(jù)庫等組件通過 conf 配置與 bin 腳本即可完成初始化、啟動與訪問適合小型團隊或個人在單機上驗證任務調(diào)度流程。目前已有 256 人學習下載。借助該包讀者可快速體驗項目創(chuàng)建、作業(yè)定義、依賴編排、定時調(diào)度及日志監(jiān)控等完整環(huán)節(jié)并對照配置項理解單機部署的目錄結(jié)構(gòu)與運行機制為后續(xù)遷移至集群模式或排查調(diào)度異常提供實踐基礎。1. 從 azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz 說起單機調(diào)度器到底能扛多少活手里拿到一個azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz第一反應往往是「這玩意兒解壓完能不能直接跑」。能跑而且 solo-server 模式就是 Azkaban 官方給單機場景留的口子它把 Web Server 和 Executor Server 塞進同一個 JVM 進程元數(shù)據(jù)默認落在本地 H2 文件庫不需要 MySQL不需要多節(jié)點協(xié)調(diào)。對于只有幾臺機器、幾十個定時任務、又不想維護一套分布式調(diào)度集群的團隊來說這個 tar.gz 反而是最省心的起點。它解決的問題很具體把散落在 crontab 里的腳本收攏成有依賴關(guān)系、有重試、有日志、有失敗告警的工作流。適合誰數(shù)據(jù)量不大、任務鏈路不復雜、運維人手緊張的小團隊或者你只是想在本機先把 Azkaban 的 job 語法和調(diào)度邏輯摸熟。但 solo-server 的邊界也很硬——它不適合高并發(fā)觸發(fā)、不適合多執(zhí)行器橫向擴展這一點后面會反復提到。2. 解壓即用的 solo-server目錄結(jié)構(gòu)、啟動鏈路與 JVM 參數(shù)2.1 tar.gz 解開后到底有什么先把包解開別急著啟動先看清楚里面裝了什么。不同構(gòu)建來源的目錄名可能略有差異但 solo-server 發(fā)行包的結(jié)構(gòu)基本固定tar -zxvf azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz cd azkaban-solo-server-0.1.0-SNAPSHOT ls -la典型輸出里你會看到這幾個關(guān)鍵目錄目錄/文件作用是否要改bin/啟動、停止腳本核心是start-solo.sh/shutdown-solo.sh一般不改conf/azkaban.properties、log4j.properties、global.properties必須改lib/所有依賴 jarsolo 模式已打包齊全不動plugins/job 類型插件如 jobtype、common按需加sql/H2 建庫腳本首次啟動自動執(zhí)行不動executions/運行時生成存放執(zhí)行日志不動解壓后先確認conf/azkaban.properties存在這是整個 solo-server 的命門。如果這個文件缺失或路徑寫錯啟動腳本會在初始化階段直接拋異常日志里通常是一句Cannot find azkaban.properties。2.2 啟動腳本背后做了什么solo-server 的啟動不是簡單java -jar它走的是bin/start-solo.sh腳本內(nèi)部會拼裝 classpath、設置-Dazkaban.home和-Dazkaban.conf兩個系統(tǒng)屬性然后調(diào)用azkaban.soloserver.AzkabanSingleServer這個主類。手動模擬一遍能幫你排查啟動失敗# 進入解壓目錄后手動拼一條啟動命令方便看真實報錯 java -Dazkaban.home$(pwd) \ -Dazkaban.conf$(pwd)/conf \ -cp lib/*:plugins/* \ azkaban.soloserver.AzkabanSingleServer邏輯說明azkaban.home告訴程序工作根目錄在哪executions/、projects/都會基于它生成azkaban.conf指向配置目錄程序會去這里讀azkaban.properties。classpath 里lib/*和plugins/*缺一不可少了 plugins 會導致 job 類型注冊失敗提交任務時報Job type not found。參數(shù)說明如果你機器內(nèi)存小默認 JVM 堆可能偏大可以在start-solo.sh里找到JAVA_OPTS或類似變量改成-Xmx512m。solo 模式單進程堆給 512M 到 1G 足夠跑幾十個輕量任務給太大反而拖慢 GC。2.3 第一次啟動必須改的三個配置打開conf/azkaban.properties下面三項不改大概率出問題# 1. 時區(qū)不設會導致調(diào)度時間整體偏移 azkaban.default.timezoneAsia/Shanghai # 2. Web 端口默認 8081被占用就換 jetty.port8081 # 3. 元數(shù)據(jù)落盤位置solo 模式用 H2 本地文件 database.typeh2 h2.path./h2db時區(qū)這項是血淚經(jīng)驗不設azkaban.default.timezone容器或服務器 UTC 環(huán)境下你配的0 2 * * *會在凌晨 10 點觸發(fā)排查半天才發(fā)現(xiàn)是時區(qū)。h2.path用相對路徑時基準是azkaban.home所以別在別的目錄啟動腳本否則 H2 文件會生成到意想不到的地方。啟動成功后訪問http://localhost:8081默認賬號密碼通常是azkaban/azkaban首次登錄后立刻改掉。3. 用 Docker 安裝 azkaban solo-server鏡像構(gòu)建與數(shù)據(jù)卷掛載3.1 為什么 solo-server 反而適合容器化熱搜里docker安裝azkaban出現(xiàn)頻率很高原因很實在solo-server 單進程、無外部數(shù)據(jù)庫依賴天然適合打成鏡像。容器化之后H2 數(shù)據(jù)、執(zhí)行日志、項目包都能通過 volume 掛出來升級時換鏡像即可不用在宿主機上折騰 Java 環(huán)境。但要注意solo-server 是有狀態(tài)的容器刪了 H2 文件就沒了所以數(shù)據(jù)卷必須掛。3.2 寫一個能復現(xiàn)的 Dockerfile不要直接找網(wǎng)上來路不明的鏡像自己寫一個最可控。假設 tar.gz 和 Dockerfile 在同一目錄FROM eclipse-temurin:8-jre # solo-server 對 JDK8 兼容最好別盲目上高版本 WORKDIR /opt/azkaban # 拷貝并解壓發(fā)行包 COPY azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz /tmp/ RUN tar -xzf /tmp/azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz -C /opt/azkaban --strip-components1 \ rm -f /tmp/azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz # 時區(qū)避免調(diào)度偏移 ENV TZAsia/Shanghai EXPOSE 8081 # 前臺啟動保證容器不退出 CMD [bin/start-solo.sh, , tail, -f, /dev/null]邏輯說明--strip-components1把解壓出來的頂層目錄去掉讓內(nèi)容直接落在/opt/azkaban這樣azkaban.home就是固定路徑。CMD里用start-solo.sh啟動后接tail -f是因為啟動腳本本身會后臺化進程然后退出容器會跟著停必須留一個前臺進程撐住。參數(shù)說明基礎鏡像選eclipse-temurin:8-jre而不是latest是因為 Azkaban 0.1.0 這類老版本在高版本 JDK 上可能遇到反射和模塊化限制。如果你確實要用 JDK11得額外加--add-opens參數(shù)屬于自找麻煩。3.3 構(gòu)建、掛載、啟動的完整命令# 構(gòu)建鏡像 docker build -t azkaban-solo:0.1.0 . # 準備宿主機目錄用于持久化 mkdir -p /data/azkaban/{h2db,executions,projects,logs} # 啟動容器把有狀態(tài)的目錄全部掛出來 docker run -d --name azkaban-solo \ -p 8081:8081 \ -e TZAsia/Shanghai \ -v /data/azkaban/h2db:/opt/azkaban/h2db \ -v /data/azkaban/executions:/opt/azkaban/executions \ -v /data/azkaban/projects:/opt/azkaban/projects \ -v /data/azkaban/logs:/opt/azkaban/logs \ azkaban-solo:0.1.0邏輯說明四個 volume 對應四類狀態(tài)。h2db是元數(shù)據(jù)庫丟了所有項目和歷史都沒了executions是執(zhí)行日志排查失敗任務全靠它projects是上傳的項目包解壓目錄logs是服務端日志。只掛h2db不掛executions容器重建后歷史執(zhí)行記錄會指向空目錄頁面點進去看不到日志。參數(shù)說明-e TZAsia/Shanghai和配置文件里的時區(qū)雙保險。端口映射如果宿主機 8081 被占改成-p 18081:8081容器內(nèi)始終是 8081。3.4 容器里改配置的正確姿勢配置文件在鏡像里直接docker exec進去改容器一重建就白改。正確做法是構(gòu)建時用COPY覆蓋或者運行時掛載單個配置文件docker run -d --name azkaban-solo \ -p 8081:8081 \ -v /data/azkaban/conf/azkaban.properties:/opt/azkaban/conf/azkaban.properties \ azkaban-solo:0.1.0掛載單個文件前宿主機上那份azkaban.properties必須已經(jīng)存在且內(nèi)容完整否則 Docker 會把它當目錄創(chuàng)建啟動直接失敗。這是新手最常翻的車之一。4. 提交第一個工作流job 文件語法、依賴與調(diào)度參數(shù)4.1 最小可運行 job 長什么樣Azkaban 的 job 就是一個.job后綴的 properties 文件。建一個目錄放兩個有依賴的任務# first.job typecommand commandecho first job at $(date)# second.job typecommand commandecho second job runs after first dependenciesfirst邏輯說明typecommand表示用 shell 執(zhí)行command字段。dependenciesfirst聲明依賴Azkaban 會先跑first成功后才跑second。依賴名是 job 文件名去掉.job不是command內(nèi)容。參數(shù)說明command里可以寫多條命令用連接但更推薦把邏輯寫進獨立腳本再調(diào)用job 文件保持干凈。$(date)這種變量在 command 里能正常展開因為最終是交給 shell 執(zhí)行的。4.2 打包上傳與觸發(fā)把兩個.job文件打成一個 zip注意是 zip 不是 tar.gzAzkaban 只認 zipzip workflow.zip first.job second.job在 Web 界面Projects里新建項目上傳workflow.zip然后點Execute Flow。如果想用命令行觸發(fā)solo-server 也支持curl -k --data actionexecuteprojectmyprojectflowfirst \ http://localhost:8081/executor邏輯說明actionexecute觸發(fā)指定 flowproject是項目名flow是 flow 名。solo 模式下 flow 名默認取第一個 job 或顯式配置的azkaban.flow。參數(shù)說明命令行觸發(fā)需要先登錄拿 session.id上面這條是簡化示意實際要帶session.id參數(shù)。生產(chǎn)里更常用的是 Web 界面或 API 封裝別裸調(diào)。4.3 調(diào)度參數(shù)怎么設才不踩時區(qū)坑在 flow 配置里設置定時核心是 cron 表達式和時區(qū)# 在 flow 的 schedule 配置中 azkaban.schedule.cron0 0 2 * * ? azkaban.schedule.timezoneAsia/Shanghai邏輯說明cron 是 Quartz 風格六位秒 分 時 日 月 周。0 0 2 * * ?表示每天 2 點整。注意 Azkaban 用的是 Quartz cron不是 Linux crontab 的五位格式多一個秒位這是最容易寫錯的地方。參數(shù)說明azkaban.schedule.timezone不寫就取azkaban.properties里的全局時區(qū)。如果全局和 flow 級都設了flow 級優(yōu)先。建議全局設一次flow 級不重復設減少不一致。5. solo-server 避坑與排查五個真實翻車現(xiàn)場5.1 啟動報 H2 數(shù)據(jù)庫鎖現(xiàn)象重啟容器后服務起不來日志里Database may be already in use或Lock file exists。原因上一次進程沒正常退出H2 的.lock文件殘留或者兩個進程同時指向同一個h2db目錄。解決確認沒有殘留 Java 進程后刪掉h2db目錄下的.lock文件再啟動。容器場景下docker stop要給足超時時間讓 JVM 走完 shutdown hook別直接docker kill。5.2 任務一直處于 Preparing 不執(zhí)行現(xiàn)象flow 提交后卡在 Preparingexecutor 不接活。原因solo 模式下 Web 和 Executor 同進程如果azkaban.properties里 executor 端口配置和實際不符或者executor.port被防火墻攔內(nèi)部通信就斷了。解決檢查executor.port配置solo 模式默認走本地回環(huán)一般不會被防火墻影響但如果你改過azkaban.properties里的 host 綁定可能綁到了錯誤網(wǎng)卡?;謴湍J配置對比測試。5.3 中文日志亂碼現(xiàn)象job 輸出里的中文在 Web 界面顯示成問號或方塊。原因JVM 默認字符集不是 UTF-8或者 job 腳本輸出編碼和頁面解析編碼不一致。解決啟動參數(shù)加-Dfile.encodingUTF-8同時在azkaban.properties里確認沒有覆蓋編碼相關(guān)配置。job 腳本里顯式export LANGen_US.UTF-8或zh_CN.UTF-8。5.4 上傳 zip 后提示項目為空現(xiàn)象zip 上傳成功但項目里看不到任何 flow。原因zip 打包時把.job文件套了一層目錄Azkaban 只掃描 zip 根目錄下的.job文件。解決打包時進入 job 文件所在目錄再執(zhí)行zip不要在上級目錄打包。用unzip -l workflow.zip確認文件在根層。5.5 定時任務不觸發(fā)現(xiàn)象cron 配好了到點沒反應。原因時區(qū)偏移、cron 位數(shù)寫錯、或者 flow 沒有處于Schedule狀態(tài)只是保存了。解決先看azkaban.default.timezone再看 cron 是不是六位最后確認 flow 頁面上的調(diào)度開關(guān)是打開狀態(tài)。三個都對了還不觸發(fā)去logs目錄看 Quartz 相關(guān)日志。6. 從 solo 到可維護驗證調(diào)度是否真的按預期跑solo-server 跑起來容易難的是確認它「按你以為的方式」在跑。我一般會做一個最小驗證閉環(huán)建一個每分鐘觸發(fā)、只輸出當前時間的 job觀察一小時內(nèi)日志時間戳是否連續(xù)且間隔穩(wěn)定。# heartbeat.job typecommand commandecho heartbeat $(date %Y-%m-%d %H:%M:%S)配0 * * * * ?每分鐘一次跑一小時后去executions目錄翻日志。如果時間戳出現(xiàn)跳變或重復說明調(diào)度線程被阻塞或時區(qū)有問題。這個笨辦法比看任何文檔都直接。再進一步把關(guān)鍵 flow 的執(zhí)行結(jié)果通過command里的curl推到一個你自己的接收端形成最簡告警。solo-server 沒有內(nèi)置告警但 job 本身就是 shell能做的事很多。我吃過虧的地方在于早期覺得 solo 夠用把所有任務堆上去直到某天一個長任務把 executor 線程占滿后面所有 flow 全部排隊。后來養(yǎng)成習慣給每個 job 加timeout類的前置判斷長任務拆細solo 的線程池就那么大別把它當分布式集群使。如果你現(xiàn)在只是想讓調(diào)度先跑起來、把 crontab 收編solo-server 這個 tar.gz 完全夠用但心里要清楚它的天花板在哪等任務量和并發(fā)上來遷移到多執(zhí)行器模式是遲早的事。希望幫到你。本文還有配套的精品資源點擊獲取