預發部署時機器總是重啓兩次的“簡單”排查

問題

前天同學反饋, 搜索業務的核心應用 magellan 在預發環境部署時總是重啓兩次,剛部署好,開始聯調,突然又重啓了,也導致老是被人抱怨搜索環境不穩定。

第一反應是,大概率是應用第一次啓動失敗了吧?總不可能是 Aone(阿里內部 CI/CD 系統)調度兩次吧。結果:

這,的確沒有遇到過,只能表示:

這麼神奇的現象是偶爾還是必現呢?額,竟然是必現。。。。。。

既然必現,那還是能排查的、好排查的,試試吧~

查看日誌,確認到底部署了幾次

 

 

開發同學發來了部署日誌截圖,如上面幾張圖所示:

  • 01:41 時停止應用,然後銷燬容器,創新新容器
  • 01:43 時開始啓動應用,啓動成功
  • 01:50 時又開始停止應用、重啓應用了,但此時並沒有新的部署記錄。

當然上面的圖裏看的不太清晰,我們還是做下簡單匹配:匹配下停止和啓動時的日誌(grep -E),同時向上向下各顯示一行日誌(-C 1),主要是爲了把時間打印出來。

cat magellan_deploy.log  |grep -E "INFO: magellan try to stop...|INFO: magellan try to start..." -C 1

機器 1 的啓動日誌

機器 2 的啓動日誌

當然上面這命令,也只是此刻我梳理整體過程時纔想起來(所以跟開發同學提供的截圖不太一致),排查問題時也就大概看看日誌。不過通過上面的圖,我倒是又發現了一個之前遺漏的點:兩個機器的第一次啓動時間不一樣(分 2 批啓動,機器 1 是第一批啓動,機器 2 是第二批啓動),但是他們第二次的重啓時間是一樣的,都是 21:00:02 ,說明是同一時刻被調度的,這也印證了後面的結論,不過,目前我們暫且忽略該信息。無論是從上面事前開發同學截的圖,還是從我事後截的圖,都可以看出:應用的確是重啓了兩次,第一次應該是 Aone 調度的,但第二次不知道是誰調度的。

手動重啓應用會不會也有這個問題呢?

手動重啓了下,啓動成功後,應用就上線了,等了 2、3 分鐘,應用沒有再次重啓。。。額,難道只有在 Aone 部署的時候纔會?看了最近一週的部署日誌,的確基本都是重啓兩次。

有沒有定時任務

額,沒有。

沒啥思路,看看有沒有有用的報錯信息吧

仔細翻了翻,應用啓動日誌中並沒有什麼特別的、新的報錯,部署日誌倒是有一個警告信息:Pandoraboot 可以類比於 Springboot

記得之前看過一些文章,說這個錯誤有可能會影響 JDK 版本的判斷(主要是由於部分 JDK 版本判斷的腳本不太健壯)。另外,我剛纔手動部署時,好像也有一行報錯,估計是由這個錯誤引起的,趕緊重新執行下 sh stop.sh(阿里內部手動下線某臺機器的命令):

提示 update_setenv.sh(阿里內部應用啓動腳本之一) 的 21 行有問題,看下代碼:

梳理了邏輯,大概是執行 java -version ,獲取版本號,如果大於等於 JDK8,則替換一些 JVM 參數。估計是當年升級 JDK8 時的遺留產物。爲啥會報錯呢?登錄機器執行了下命令:

額,執行該命令時 OpenJDK 報了 Warning 信息,而且報錯信息在 version 那行之前,這樣第一行就匹配不到真正的版本號 8 了,按照上面代碼的執行邏輯,JAVA_VERSION_MAJOR 會取到 "Server" 中的第一個"e",取到了一個字符串,導致下面和數字 8 比較時報錯。那這裏執行報錯會帶來什麼影響呢?下面的替換邏輯就不會執行了,最終 JVM 的啓動參數設置不合理,可能導致 JVM 被殺掉了?那看看應用現在的啓動參數設置吧:

額,啓動參數已經改成 JDK8 之後的了,所以上面的替換邏輯不執行也不會影響最終的啓動參數。雖然不影響啓動參數,但部署日誌裏,有這麼多的這行錯誤日誌,而且 JDK 版本獲取錯誤估計也會引起一些不可知的問題。先修復掉試試~

修復 JDK 版本判斷錯誤的邏輯

看了下這個 update_setenv.sh 的代碼,發現已經沒用了,而且判斷 JDK 版本的代碼邏輯也寫的很有問題,可以直接刪除。拉變更,刪除,部署預發。

部署成功,應用開始啓動後,登錄機器觀察部署日誌:應用部署正常,無 JDK warning 信息,等了幾分鐘也沒有重新部署。好像是解決了。但爲什麼解決了呢?不科學呀。照理說,這個版本判斷和兩次重啓關係不是很大呀。算了,先不糾結,趕緊反饋給開發同學。

 
 

爲了能將這份喜悅第一時間傳遞給開發,我還特意使用了快速通道——DING,結果很快就打臉了。

是運行時問題?

趕緊上機器看了下日誌,發現:這個機器在 20:54 分的時候已經啓動成功了,運行了 5 分鐘後才被重啓(我只等了 3、4 分鐘)。這就說明:不是應用啓動時的問題,而是運行時問題,怪不着我之前老是觀察不到,原來是啓動後不確定的時間內會被重啓。嘴上跟開發同學說,我再努力找找,但其實內心沒有一點思路。。。找 Aone 同學問問吧,萬一是 Aone 重複調度了呢?

諮詢 Aone 同學是否存在重複調度的可能性

Aone(阿里內部 CI/CD 系統) 右下角諮詢了研發小蜜,很快就有了答覆。

 

不過,同學回覆的答案跟我的問題並不相關,應該是理解錯我的意思了。他估計以爲我要暫停容器、排查問題,可以理解,問題是比較詭異。提問前,我還仔細閱讀了下 Aone 的歷史提問記錄,發現裏面並沒有類似的問題,大概率不是 Aone 的問題。還是先再試試其他方法,實在不行的話,再找 Aone 同學確認是否有重複調度。

還能從什麼角度進行排查呢?有點排查不下去了。想起來了,據開發同學說,只有預發機器有,線上機器沒有這個問題,那就對比下線上和預發的機器吧。

全方位對比線上和預發機器

對比應用部署日誌:無異常對比應用啓動日誌:無異常對比 JVM 參數:有點不一樣,如下,第一張是線上機器的參數,第二張是預發機器的參數

 

區別有幾個地方:

  • 使用的 java 路徑不一樣:線上是/opt/taobao/install/ajdk-8_2_4-b52/bin/java,預發是 /opt/taobao/java/bin/java
  • 預發環境的機器開啓了 Debug 端口: -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
  • 預發環境的機器掛載了一個 Java Agent: -javaagent:/home/admin/remote-debug/libs/remote-debug-agent.jar

Java 路徑的:登錄機器看了下,兩個路徑做了軟鏈接,本質是一樣的(預發和線上有區別是由於我在預發環境刪除了 update_setenv.sh 導致的):

預發機器的 Debug 端口開啓:估計是有同學在預發 Debug,這也不會有啥問題。預發環境的機器掛載 Java Agent:這個一般也是常規操作了,比如用來做啓動耗時分析的 start-ops,用來做代碼染色的 rbc 等,都是隻掛載預發,防止 Agent 影響線上真實用戶,就是不知道這個 remote-debug 是用來幹啥的。對比了半天,也沒有任何頭緒。。。總不能是這個 Agent 引起的吧?Agent 一般也不會,並且也不能重啓應用的呀。算了,先看看這個 Agent 是幹啥的

看看 remote-debug Agent 是幹啥的

既然是 Java Agent,而應用代碼裏又沒有 Agent 部署的相關代碼,那麼這個 Agent 應該是通過運維插件下發的,這樣應用纔是無感的。先在 staragent 插件市場(阿里內部運維容器插件市場)裏搜索看看是幹啥的:

試了 remote debug、remote debug agent 等一系列關鍵詞,發現都搜索不到,奇怪,難道插件不叫這個名字??那就網上搜索下,信息都沒啥用,全是遠程 debug 的,沒辦法,誰讓這個插件叫這個名字呢。

語雀搜索,內網公開,排在前面的也沒啥用(其實這裏,我忘記在外網搜索了,其實 github 是可以搜索到一些相關信息的)。代碼搜索(阿里內部代碼倉庫搜索平臺)下吧,不過這次我爲了更精確的匹配使用了關鍵詞“remote-debug-agent”,有戲!

路徑完全一致,QA 出品,放在 euler-service 的倉庫裏,難道插件名字叫 euler?這腳本里好像執行了 appctl.sh restart 重啓!趕緊再次在插件市場搜索了下,果然有!

登錄預發機器看看 staragent 的插件目錄,沒錯,就是你,原來叫 euler !

進去目錄看看實際的腳本,果然與代碼搜索到的基本一致:

看看邏輯:

  • 在預發、測試、日常、項目環境下,如果 remote-debug-agent.jar 不存在,就從 oss 下載到 /home/admin 目錄下
  • 如果 remote-debug-agent 已經被掛載了,就啥也不幹
  • 如果 remote-debug-agent 沒有被掛載,就修改 setenv.sh 腳本里的 JVM 參數,追加 Agent 參數,然後重啓應用

難道第二次的重啓是爲了掛載 remote-debug-agent 這個 Agent?

觀察應用的兩次重啓

第一次重啓後,趕緊觀察:

等待第二次重啓後,觀察:

果然,第二次多了 -javaagent:/home/admin/remote-debug/libs/remote-debug-agent.jar!八九不離十了,應該就是這個 euler 運維插件引起的了。

找插件負責人確認

找 euler 插件的維護同學確認了下是否存在這個邏輯:

哈哈,終於找到了,測試同學表示:你是怎麼查出來的,這個很難查到是這個插件引起的。我說,是難,我都打算放棄了。趕緊約測試同學當面溝通了下,確認了他們的訴求:他們期望,在不需要開發同學修改代碼的前提下,應用預發部署的時候就可以掛載這個 Java Agent,輔助他們採集一些數據。但他們研究了之後,發現無法做到在應用啓動前就修改啓動腳本里的 JVM 參數,所以只好採取了重啓的方式。每 10 分鐘左右調度一次,所以纔會出現啓動 5 分鐘後突然重啓的現象。他們以爲應用啓動一般比較快,對開發的影響較小。其實,正常情況下影響的確很小,但現在的應用一般都需要 3 分鐘才能完成重啓,同時 magellan 又是高頻發佈應用(1 個月預發部署 150 次左右),開發人員多,需求多,所以很容易被開發同學發現:


知道了問題,怎麼解決呢?簡單,近期我正好在和架構組同學在一起開發、推廣另一款插件,我們的插件在第一次重啓的時候就掛載上了,不用二次重啓,趕緊拉上測試同學和架構組同學一起溝通下修改方案(本文重點不在於怎麼修復,所以就不放出修復方案相關的內容了)。確定方案後,測試同學就趕緊回去改代碼了,說是太不好意思了,今天肯定優化好。

其實,這有啥不好意思的,大家不都是互相傷害來傷害去的嘛,如果實在不好意思,一杯咖啡的事。
最後

  • 先給 magellan 預發環境摘除了插件,保證開發體驗,等插件邏輯修復好了再重新掛載

  • 在設計上,運維容器和主容器在同一個 Pod 內,共享磁盤,運維容器的確有權限操作主容器裏的進程,那麼在架構上要如何防範呢?我還沒有答案,不知各位是否有,有的話,請留言告知。
  • 如果非要說本次排查過程有什麼深刻體會的話,那就是“不要放過任何一個可疑的地方”!

補:如果代碼搜索沒找到,是否還有其他方法

昨晚在回家的路上,在想一個問題,如果在使用代碼搜索並沒有搜到“remote-debug-agent”相關的任何信息,我是否還有其他方法?想了一會,發現還有一個笨方法——關鍵字匹配,即全文搜索“ restart”關鍵詞。雖然笨,但很有效。先在 /home/admin 目錄下搜索,沒有結果就在 /home 目錄下,還沒有結果就在根目錄下搜索。爲什麼這個方法可以呢?因爲看部署日誌,一定是執行了應用啓動腳本 appctrl.sh 裏的 restart 命令,所以一定含有“appctrl.sh restart” 或“ restart”關鍵字。

額,搜索的文件太多了,執行有點慢,被我終止了,那能不能快點?既然要執行這個命令,一般情況下應該是個腳本文件,可以優先在 *.sh 腳本文件中查找。

/home/admin 目錄下,結果較少。既然擴大搜索範圍,在 /home 目錄下有 57 條記錄,裏面就有 euler-service 插件的腳本:

作者|曲池

點擊立即免費試用雲產品 開啓雲上實踐之旅!

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章