容器內的日誌輸出有多重方式:容器內文件、stdout、stderr等等,咱們在解決nginx-ingress-controller的日誌持久化過程當中,以k8s的編排和組織能力,嘗試非侵入地解決各類問題,包括目錄權限與掛載的問題、nginx配置問題、日誌輪轉的問題。但願這些解決方法,能夠爲讀者容器化應用的日誌落盤提供思路。nginx
輕舟微服務平臺大量地依賴nginx-ingress-controller進行流量管理和負載均衡,所以該組件的日誌維護很是重要。docker
輕舟k8s團隊設計了一個較爲無侵入的方案,經過這個方案能夠將nginx-ingress-controller的日誌輸出,不管是accesslog仍是klog庫輸出的日誌,都能進行重定向落盤和輪轉、清理。 咱們發現這個日誌持久化方案基本能夠應對絕大多數的容器應用的日誌持久化需求。bash
nginx-ingress-controller的日誌包括三個部分:markdown
controller日誌:輸出到stdout,經過啓動參數中的–log_dir可已配置輸出到文件,重定向到文件後會自動輪轉,但不會自動清理負載均衡
accesslog:輸出到stdout,經過nginx-ingress-controller的配置文件——configmap:
nginx-configuration中的字段能夠配置輸出到哪一個文件。輸出到文件後不會自動輪轉或清理運維
errorlog:輸出到stderr,配置方式與accesslog相似。ide
controller的日誌須要作定時清理。因爲controller的日誌是經過klog(k8s.io/klog)輸出的,會進行日誌滾動,因此咱們經過腳本定時清理必定時間以前的日誌文件便可。微服務
修改configmap:
nginx-configuration。配置accesslog和errorlog的輸出路徑,替換默認的stdout和stderr。輸出路徑咱們能夠與controller一致,便於查找。spa
accesslog和errorlog都只有一個日誌文件,咱們可使用logrotate進行日誌輪轉,將輸出到宿主機上的日誌進行輪轉和清理。配置如:設計
$ cat /etc/logrotate.d/nginx.log /data/log/nginx_ingress_controller/access.log { su root list rotate 7 daily maxsize 50M copytruncate missingok create 0644 www-data root } 12345678910
官方提供的模板中,nginx-ingress-controller默認都是以33這個用戶登陸啓動容器的,所以掛載hostpath路徑時存在權限問題。咱們須要手動在機器上執行chown
-R 33:33 /data/log/nginx_ingress_controller.
nginx日誌落盤中,第二、3兩點均須要人工運維,有什麼解決辦法嗎?
問題的關鍵是:有什麼辦法能夠在nginx-ingress-controller容器啓動以前加一個hook,將宿主機的指定目錄執行chown呢?
能夠用initContainer。initcontainer必須在containers中的容器運行前運行完畢併成功退出。利用這一k8s特性,咱們開發一個docker image:hub.c.163.com/combk8s/adddirperm:1.0.0 ,裏面只執行以下腳本:
#!/bin/bash
logdir=$LOG_DIR
userID=$USER_ID
echo "try to set dir: $logdir 's group as $userID"
chown -R $userID:$userID $logdir
12345
複製代碼
腳本讀取一些環境變量, 確認須要修改哪一個目錄,改爲怎樣的user group。
將腳本打包成dockerimage, 放在nginx-ingress-controller的deploy yaml中,做爲initcontainers。 注意要對該initcontainer配置環境變量和volumeMount.
再說第二點,咱們注意到nginx-ingress-controller的基礎鏡像中並不包含logrotate,因此咱們初步的思路是在宿主機上運行並配置logrotate。 但機器上安裝和運行logrotate有須要批量運維的腳本,而且有些環境的機器可能不容許咱們安裝這些東西。 因此仍是應該思考一個容器化的方案。
咱們因而設計了一個sidecar,使用咱們本身構建好的鏡像:hub.c.163.com/combk8s/logrotate:v1.1 。這個鏡像啓動的容器中,會每一個6小時執行一次logrotate,定時時間能夠經過環境變量CRON_EXPR注入,例如CRON_EXPR= */3 * * * * 表示每隔三分鐘執行一次。
咱們將針對nginx accesslog和errorlog的日誌的輪轉策略保存到configmap中,並以volume的方式mount到這個sidecar容器中, 同時,這個sidecar容器也要mount nginx-ingress-controller的日誌目錄。
咱們總結一下這些問題的解決辦法:
有的人建議將initcontainer去掉,改成基於原有的nginx-ingress-controller鏡像加一層layer,將配置路徑權限的腳本放在該層執行。 我的認爲這種方法既不美觀,也不方便。惟一的好處僅在於deploy yaml仍然簡潔(但少不了volumeMount之類的配置)。
不過仍是看我的使用感覺吧~
做者:黃揚