霍明明 360雲計算
docker 作為時下最火爆的容器技術,我們hulk虛拟化團隊也推出了基于docker+k8s的stark容器管理平台,目前已經開始為業務部門提供容器化服務。 該文章就是基于業務部門在使用過程中遇到的日志問題展開的,主要描述了 docker 中啟動syslog記錄日志時候遇到的坑,坑,坑。最終刨根問底給出了解決方案,希望能給大家一些啟發。 ps:豐富的一線技術、多元化的表現形式,盡在“hulk一線技術雜談”,點關注哦!
一天,小剛在群裡吼說:“ 親們,我在docker(centos:7.2)容器中,想調用syslog記錄資訊,是這樣做的:我自己在容器中啟動了rsyslogd,之後記錄普通info級别資訊,但是我在/var/log/messages中看不到,我檢查了rsyslog.conf沒有發現問題,請問親們知道這個是為什麼嗎? ”
我的第一反應是權限的問題,然後在群裡對吼了一句:“很可能是權限的問題,啟動容器時加一下--privileged試試呢? ”
然後,小剛就屁颠屁颠去試了。過了不一會兒,小剛又在群裡吼說:“還是不行哈!這可咋整?你們給看一下吧!!!”
我擦,頓時腦子有點懵b:“看來問題沒這麼簡單哈。需要好好看看。”
我趕緊使用centos7.2 的鏡像啟動個容器安裝 rsyslog也感受一下。不試不知道,一試問題還不少。容器裡居然沒有 systemd,使用systemctl start rsyslog 啟動 rsyslog 服務時報“failedto get d-bus connection: operation not permitted”異常。也就是說目前的使用者沒有權限執行該操作。 centos7的坑真多,一個問題一個問題解決吧。
啥都不說,加--privileged試試,居然還是不行,汗!google了一把,搜出一票來(大部分是雷同轉載),掃了一遍,對于容器内部 systemd 不能使用,官方的理由是:
systemd requires the cap_sys_admin capability. this means runningdocker with --privileged. not good for a base image.
systemd requires access to the cgroups filesystem.
systemd has a number of unit files that don’t matter in a container, andthey cause errors if they’re not removed
總的來說還是權限的問題,處于安全的考慮,很多capability 宿主系統是沒有直接放開給預設啟動的容器的。
那為啥我加了--privileged 特權還是無法使用 systemd呢?搜了一下,看大家都是在 dockerrun 時執行cmd為/sbin/init 就可以了
例如: dockerrun --privileged -itd centos:latest /sbin/init,看下/sbin/init 是什麼:
是 systemd的軟連,還是不太明白,為什麼必須啟動程序為systemd才可以。難道 systemd 和rsyslog 有什麼特殊的關系?經過一番倒騰沒找到這倆東東有啥必然的關系,放棄這條路,繼續找…..
思路二
在走頭無路的時候,我突然想起來,官方 dockerhub 應該會有 centos 7 的 rsyslog 鏡像吧,搞一個下來,研究研究不就知道了,太瘋狂了,高興地不得了。趕緊搞個鏡像試試:
以下是我搜到的官方rsyslog的鏡像清單
拉取了标紅的鏡像 quiver/rsyslog 建立容器看了一下,容器正常啟動,rsyslog 也正常工作,docker inspect 看了一下該鏡像沒有發現做過什麼特殊設定。奇了怪啦!它是怎麼做到的?
檢查下rsyslog版本,我擦,有新發現,版本不一樣,哈哈,難道是版本的問題?不說了,趕緊試試這個版本吧。他用的版本是:rsyslog-7.6.7-1.el7.x86_64,我們鏡像中yum install後安裝的版本是rsyslog-7.4.7-12.el7.x86_64。
快來嘗嘗鮮!經過一番折騰(國外的源,不解釋…...)終于安裝完成,更令人興奮的是居然working、working、working……
到此,我認為終于可以松一口氣了,更新一下rsyslog版本呗,先讓業務用着,然後我再慢慢去刨根問底兒。
技術人員總有一種情懷,那就是----不抛棄不放棄,遇到問題總要搞個明白。為了找到問題的根源,我進行了如下嘗試:
strace 跟蹤 rsyslogd 程序的系統調用,用 logger 給 rsyslog 發送資料,然後觀察是否有資料寫入。
了解 rsyslog 工作原理,從 rsyslog 本身去尋找原因。
第一個方法并沒有任何收獲,正常工作的rsyslog和不正常工作的rsyslog都沒有任何資訊。此路放棄。
然後依然決然的去了解了一下rsyslog的工作原理,其實最想搞明白的就是“系統日志是如何與 rsyslog 互動的?如何将資料寫入 rsyslog 的?”知道了這些問題,也就能更好的理順整個流程。
經過一番學習,焦點定位到了 rsyslog配置檔案 /etc/rsyslog.con 中的下面幾項配置:
很明顯,這裡标紅的部分很明确的告訴了我們系統日志是如何寫入到 rsyslog中的。
對,就是通過這個子產品imuxsock完成的。從字面來看應該是通過socket來通信的,順着這條思路繼續往下縷,然後找到一篇文章,其中開篇是這樣一句:“imuxsock子產品提供通過本地 unix sockets 通路 syslog 消息的能力。最重要的,這是 syslog 遞送資訊給 rsyslog 的機制,是以需要加載這個子產品來讀取系統日志socket,并處理本地運作的應用的日志。
先看看我的 rsyslog是否加載了該子產品
恩,已經加載了,放心了。再看看對應的 unix 域套接字是否存在
我擦,居然沒有,抓緊看看正常運作的容器裡面是否有,标紅部分即是.
[root@1e603440b4a9 /]# netstat -anlp
active internet connections (serversand established)
proto recv-q send-q localaddress foreign address state pid/program name
active unix domain sockets (serversand established)
proto refcnt flags type state i-node pid/program name path
unix 2 [ ] dgram 1694177 38/rsyslogd /dev/log
nm,居然有,此時有一種“柳暗花明又一村”的趕腳,感覺我找到問題的真谛了!!!
從上面我們可以看到這個 unixsocket 的路徑為/dev/log:這是一個unix域套接字,這個套接字用來接收任何系統程式發送來的日志事件并将事件傳遞給 syslogd或者 rsyslogd 守護程序。原文是
這個套接字會在兩個地方被建立:一是 rsyslog 啟動時建立;二是 systemd 啟動時建立。
其實從這裡再回頭看 docker run --privileged -itd centos:latest /sbin/init 方式啟動容器為啥可以的話,就會知道原來是 systemd 建立了 /dev/log 套接字,那,我們啟動 rsyslog 時為啥就沒建立成功呢?原因可能有多種:
rsyslog 對 /dev/log 套接字建立邏輯的bug。
docker 權限限制
docker 内啟動 rsyslog 服務時權限不夠。
具體是什麼原因,下篇博文給出答案及分析。
以上是對 docker 中運作 rsyslog 問題的一個處理過程。類似這種問題的處理,通常先是從 docker 本身的限制出發去尋找問題的原因,在排除 docker 本身問題後,再從應用本身或者環境角度去考慮可能的原因,最終經過排查一步一步找到問題的根源。雖然經過3年的錘煉,docker 正逐漸的轉變為基礎架構的重要組成部分,但在實際使用過程中依然會有很多問題,而這些問題需要我們大家共同努力去不斷的發掘、摸索和分享,為加快 docker 的落地做一點貢獻。