最近在部署rails專案到GKE上,發現rolling update在關掉container時會跳出「Pod errors: Error with exit code 1」,然後狀態變成紅色的
雖然只是要被關閉的pod壞掉不影響更新流程,但偶爾會造成服務中斷,看起來不是件好事
最初推測是puma在關閉的時候有什麼問題,找到一個issue說bundler在1.16版以前跑「bundle exec」會造成puma收到SIGTERM後回傳exit code 1
這現象剛好很符合遇到的情境,但我用的是1.16版以後的bundler,而且測試發現,bash上跑的puma收到SIGTERM會正確的回傳code 143,唯有放在container裡用docker開起來,傳送SIGTERM才會遇到code 1的結果
當時完全沒有頭緒,過了幾天同事剛好提到說他以前有看過一個叫做dumb-init的東西
dumb-init是設計給container用的init process,有回收process和轉送signal的功能,至於為什麼container還需要init process的原因可以看這一篇文章的說明
查了之後覺得可能很有幫助,畢竟bundler跟puma都曾有過signal處理不好的問題,而且在bash上可以正確關閉,代表直接把puma放在PID 1會缺某種東西
一試用下去,puma還真的能正確回傳code 143了,正想說可以放上GKE的時候,GKE又亮紅燈了....
他對143這個回答也不高興Orz
code 143是由128 + 15組成,signal 15也就是SIGTERM,不一定是異常的狀態
為了要讓GKE滿意,只好想怎麼把code變成0
翻了翻手冊並測試確定puma在收到SIGINT時會回傳code 0,剛好dumb-init有支援signal rewrite,可以直接把SIGTERM改成SIGINT傳給puma
於是最終透過dumb-init成功解決了exit code造成GKE不爽的問題
另外有個值得注意的地方是docker的entrypoint跟cmd分別等於kubernetes的command跟args,如果設錯會產生不同的效果,細節可以看手冊的Notes
留言