Docker容器監控系統初探

隨著線上服務的全面docker化,對docker容器的監控就很重要了。SA的監控系統是物理機的監控,在一個物理機跑多個容器的情況下,我們是沒法從一個監控圖表里面區分各個容器的資源占用情況的。為了更好的監控容器運行情況,更重要的是為了后續的容器動態調度算法需要的大量運行時數據的搜集,經過調研后,基于CAdvisor + InfluxDB + Grafana搭建了這套容器監控系統。

1 容器監控方案選擇

在調研容器監控系統的時候,其實是有很多選擇的,比如docker自帶的docker stats命令,
ScoutData DogSysdig Cloud,
Sensu Monitoring FrameworkCAdvisor等。

通過docker stats命令可以很方便的看到當前宿主機上所有容器的CPU,內存以及網絡流量等數據。但是docker stats命令的缺點就是統計的只是當前宿主機的所有容器,而獲取的監控數據是實時的,沒有地方存儲,也沒有報警功能。

?  ssj docker stats
CONTAINER           CPU %               MEM USAGE / LIMIT       MEM %               NET I/O             BLOCK I/O           PIDS
f216e9be15bf        0.06%               76.27 MiB / 992.6 MiB   7.68%               5.94 kB / 2.13 kB   16.2 MB / 0 B       7
ead53a6166f0        0.00%               8.703 MiB / 992.6 MiB   0.88%               578 B / 578 B       7.01 MB / 0 B       2

ScoutSysdig Cloud
Data Dog雖然都提供了較完善的服務,但是它們都是托管的服務而且都收費,于是也不在考慮范圍之內。Sensu Monitoring Framework集成度較高,也免費,但是部署過于復雜。最后,我們選擇了CAdvisor做容器監控工具。

CAdvisor谷歌出品,優點是開源產品,監控指標齊全,部署方便,而且有官方的docker鏡像。缺點是集成度不高,默認只在本地保存2分鐘數據。不過在調研之后發現可以加上InfluxDB存儲數據,對接Grafana展示圖表,比較便利地搭建好了容器監控系統,數據收集和圖表展示效果良好,對系統性能也幾乎沒有什么影響。

2 容器資源監控-CAdvisor

2.1 部署與運行

CAdvisor是一個容器資源監控工具,包括容器的內存,CPU,網絡IO,磁盤IO等監控,同時提供了一個WEB頁面用于查看容器的實時運行狀態。CAdvisor默認存儲2分鐘的數據,而且只是針對單物理機。不過,CAdvisor提供了很多數據集成接口,支持InfluxDB,Redis,Kafka,Elasticsearch等集成,可以加上對應配置將監控數據發往這些數據庫存儲起來。

由于CAdvisor已經容器化,部署和運行很簡單,執行如下命令即可:

docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:rw \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  google/cadvisor:latest

運行之后,就可以在瀏覽器打開``http://ip:8080`查看宿主機的容器監控數據了。

2.2 集成InfluxDB

如前面說到,CAdvisor默認只在本機保存最近2分鐘的數據,為了持久化存儲數據和統一收集展示監控數據,需要將數據存儲到InfluxDB中。InfluxDB是一個時序數據庫,專門用于存儲時序相關數據,很適合存儲CAdvisor的數據。而且,CAdvisor本身已經提供了InfluxDB的集成方法,在啟動容器時指定配置即可。我們使用了管理容器來管理CAdvisor,修改后的啟動配置如下。主要指定了存儲引擎為InfluxDB,以及指定InfluxDB的HTTP API的地址(這里用到了自建DNS的域名 influxdb.service.consul以避免暴露外部端口),還有對應的數據庫和用戶名密碼。

{
    "binds": [
          "/:/rootfs:ro",
          "/var/run:/var/run:rw",
          "/sys:/sys:ro",
          "/home/docker/var/lib/docker/:/var/lib/docker:ro"
    ],
    "image": "forum-cadvisor",
    "labels": {
        "type": "cadvisor"
    },
    "command": " -docker_only=true -storage_driver=influxdb  -storage_driver_db=cadvisor  -storage_driver_host=influxdb.service.consul:8086  -storage_driver_user=testuser  -storage_driver_password=testpwd",
    "tag": "latest",
    "hostname": "cadvisor-{{lan_ip}}"
}

注意到我們使用了一個自己的forum-cadvisor鏡像來代替官方的cadvisor鏡像,這是為了修復cadvisor一些問題以及基于管理方便性的考慮。

2.3 CAdvisor存在的問題

1)運行報錯問題

運行最新的CAdvisor容器的時候,發現容器有如下的錯誤日志:

E0910 02:20:53.990423       1 fsHandler.go:121] failed to collect filesystem stats - rootDiskErr: <nil>, rootInodeErr: cmd [find /rootfs/home/docker/var/lib/docker/aufs/diff/2575b6816f03eee84c8915442129243fc03e0f5ce35c48dc42eb20a230384069 -xdev -printf .] failed. stderr: find: unrecognized: -printf

這個問題是因為沒有安裝 findutils 工具導致的。

2)統計不到容器內存數據

Debian默認沒有開啟 CGroup Memory的支持,CAdvisor默認情況下無法統計到容器內存數據,需要修改GRUB啟動參數,修改文件/etc/default/grub,加入下面這行:

GRUB_CMDLINE_LINUX=" cgroup_enable=memory"

然后更新grub2重啟即可。

# sudo update-grub2 && reboot

3)網絡流量監控數據錯誤問題

在CAdvisor上線一段時間后,順安發現容器的網絡數據跟實際情況不符,并查找資料后發現問題是因為CAdvisor默認只統計第一個網卡的流量,而在我們的容器中是有多個overlay網絡的,需要統計容器中所有的網卡流量。于是我修改了CAdvisor統計網絡流量部分的代碼并重新編譯了一個版本在線上使用,修改的代碼在這里

最后,我們自定義的鏡像文件 forum-cadvisor.Dockerfile 是這樣的(src/cadvisor是修改后重新編譯的cadvisor可執行文件):

FROM google/cadvisor:latest
RUN apk add --update findutils && rm -rf /var/cache/apk/*
COPY src/cadvisor /usr/bin/cadvisor

2.4 CAdvisor原理簡介

CAdvisor運行時掛載了宿主機根目錄,docker根目錄等多個目錄,由此可以從中讀取容器的運行時信息。docker基礎技術有Linux namespace,Control Group(CGroup),AUFS等,其中CGroup用于系統資源限制和優先級控制的。

宿主機的/sys/fs/cgroup/目錄下面存儲的就是CGroup的內容了,CGroup包括多個子系統,如對塊設備的blkio,cpu,內存,網絡IO等限制。Docker在CGroup里面的各個子系統中創建了docker目錄,而CAdvisor運行時掛載了宿主機根目錄和 /sys目錄,從而CAdvisor可以讀取到容器的資源使用記錄。比如下面可以看到容器b1f257當前時刻的CPU的使用統計。CGroup詳細介紹可以參見DOCKER基礎技術:LINUX CGROUP

# cat /sys/fs/cgroup/cpu/docker/b1f25723c5c3a17df5026cb60e1d1e1600feb293911362328bd17f671802dd31/cpuacct.stat 
user 95191
system 5028

而容器網絡流量CAdvisor是從/proc/PID/net/dev中讀取的,如上面的容器b1f257進程在宿主機的PID為6748,可以看到容器所有網卡的接收和發送流量以及錯誤數等。CAdvisor定期讀取對應目錄下面的數據并定期發送到指定的存儲引擎存儲,而本地會默認存儲最近2分鐘的數據并提供UI界面查看。

# cat /proc/6748/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
  eth0: 6266314     512    0    0    0     0          0         0    22787     292    0    0    0     0       0          0
  eth1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
    lo: 5926805    5601    0    0    0     0          0         0  5926805    5601    0    0    0     0       0          0

3 容器監控數據存儲-InfluxDB

3.1 InfluxDB配置和運行

InfluxDB是一個開源的分布式時序數據庫,使用GO語言開發。特別適合用于時序類型數據存儲,CAdvisor搜集的容器監控數據用InfluxDB存儲就很合適,而且CAdvisor本身就提供了InfluxDB的支持,集成起來非常方便。

由于線上服務都docker化了,所以InfluxDB我們也是選擇用容器來跑,通過容器管理系統統一管理。容器運行時的核心配置如下,主要掛載了數據庫目錄,以及配置了consul的服務注冊,這樣,CAdvisor由于和InfluxDB處于同一個overlay子網中,不需要再開放端口給外部訪問,CAdvisor直接通過influxdb.service.consul:8086即可連接到InfluxDB。

{
    "binds": [
         "{{volume_dir}}/influxdb/data:/var/lib/influxdb"
    ],
    "environment": {
       "SERVICE_INFO": {
             "Name": "influxdb",
             "Address": "{{register_ip}}",
             "Port": 8086,
        },
    },
    "image": "influxdb",
    "name": "influxdb-{{namespace}}",
    "tag": "latest"
}

為了存儲CAdvisor的數據,需要預先創建好數據庫并配置用戶名密碼以及相關權限。InfluxDB提供了一套influx的CLI,跟mysql client很相似。另外,InfluxDB的數據庫操作語言InfluxQL跟SQL語法也基本一致。進入InfluxDB容器,運行下面命令創建數據庫和用戶密碼并授權。

# influx
Connected to http://localhost:8086 version 1.3.5
InfluxDB shell version: 1.3.5
> create database cadvisor  ## 創建數據庫cadvisor
> show databases           
name: databases
name
----
_internal
cadvisor
> CREATE USER testuser WITH PASSWORD 'testpwd' ## 創建用戶和設置密碼
> GRANT ALL PRIVILEGES ON cadvisor TO testuser ## 授權數據庫給指定用戶
> CREATE RETENTION POLICY "cadvisor_retention" ON "cadvisor" DURATION 30d REPLICATION 1 DEFAULT ## 創建默認的數據保留策略,設置保存時間30天,副本為1

配置成功后,可以看到CAdvisor會通過InfluxDB的HTTP API自動創建好數據表,并將數據發送到InfluxDB存儲起來。

root@b1f25723c5c3:/# influx
Connected to http://localhost:8086 version 1.3.1
InfluxDB shell version: 1.3.1
> use cadvisor
Using database cadvisor
> show measurements # 顯示數據表與SQL略有不同,用的是關鍵字measurements
name: measurements
name
----
cpu_usage_per_cpu
cpu_usage_system
cpu_usage_total
cpu_usage_user
fs_limit
fs_usage
load_average
memory_usage
memory_working_set
rx_bytes
rx_errors
tx_bytes
tx_errors

> select * from rx_bytes order by time desc limit 2;
name: rx_bytes
time                container_name       game machine            namespace    type          value
----                --------------       ---- -------            ---------    ----          -----
1504685259707223192 consul-agent-dev     cadvisor-10.x.x.x   dev      consul-agent   17858781633
1504685257769130660 manager-agent-dev    cadvisor-10.x.x.x   dev      manager-agent  1359398

3.2 InfluxDB重要概念

influxdb有一些重要概念:database,timestamp,field key, field value, field set,tag key,tag value,tag set,measurement, retention policy ,series,point,下面簡要說明一下:

  • database:數據庫,如之前創建的數據庫 cadvisor。InfluxDB不是CRUD數據庫,更像是一個CR-ud數據庫,它優先考慮的是增加和讀取數據而不是更新刪除數據的性能。

  • timestamp:時間戳,因為InfluxDB是時序數據庫,它的數據里面都有一列名為time的列,存儲記錄生成時間。如 rx_bytes 中的 time 列,存儲的就是時間戳。

  • fields: 包括field key,field value和field set幾個概念。field key是字段名,在rx_bytes表中,字段名為 value。field value是字段值,如 178587816331359398等。而field set是字段集合,由field key和field value構成,如rx_bytes中的字段集合如下:

    value = 17858781633
    value = 1359398
    

    在InfluxDB表中,字段必須存在,而且字段是沒有索引的。所以,字段相當于傳統數據庫中沒有索引的列。

  • tags:包括tag key, tag value, tag set幾個概念。tag key是標簽名,在rx_bytes表中,container_name, game, machine, namespace,type都是標簽。tag value就是標簽的值了。tag set就是標簽集合,由tag key和tag value構成。InfluxDB中標簽是可選的,不過標簽是有索引的。如果查詢中經常用的字段,建議設置為標簽而不是字段。標簽相當于傳統數據庫中有索引的列。

  • retention policy: 數據保留策略,cadvisor的保留策略為cadvisor_retention,存儲30天,副本為1。一個數據庫可以有多個保留策略。

  • measurement:類似傳統數據看的表,是字段,標簽以及time列的集合。

  • series:共享同一個retention policy,measurement以及tag set的數據集合。

  • point:同一個series中具有相同時間的字段集合,相當于SQL中的數據行。

3.3 InfluxDB的特色功能

InfluxDB作為時序數據庫,相比傳統數據庫它有很多特色功能,比如獨有的一些特色函數和連續查詢功能。關于InfluxDB的更多詳細內容可以參見官方文檔

  • 特色函數:有一些聚合類函數如FILL()用于填充數據, INTEGRAL()計算字段所覆蓋的曲面面積,SPREAD()計算表中最大與最小值的差值, STDDEV()計算字段標準差,MEAN()計算平均值, MEDIAN()計算中位數,SAMPLE()函數用于隨機取樣以及DERIVATIVE()計算數據變化比等。
  • 連續查詢:InfluxDB獨有的連續查詢功能可以定期的縮小取樣,就原數據庫的數據縮小取樣后存儲到指定的新的數據庫或者新的數據表中,在歷史數據統計整理時特別有用。

4 容器監控數據可視化-Grafana

通過CAdvisor搜集容器的監控數據,存儲到InfluxDB中,接下來就剩數據可視化的問題了。畢竟,一個可視化的圖表可以很方便快速的看到容器的一些問題。圖表展示我選擇的是Grafana。

Grafana是一個開源的數據監控分析可視化平臺,支持多種數據源配置(支持的數據源包括InfluxDB,MySQL,Elasticsearch,OpenTSDB,Graphite等)和豐富的插件及模板功能,支持圖表權限控制和報警。

Grafana同樣也是以容器方式運行,容器啟動配置如下,主要是掛載了grafana的數據和日志目錄,設置了管理員的密碼,并開放了8888端口作為grafana的訪問端口:

{
    "binds": [
          "{{volume_dir}}/grafana/data:/var/lib/grafana",
          "{{volume_dir}}/grafana/log:/var/log/grafana"
    ],
    "environment": {
        "GF_SECURITY_ADMIN_PASSWORD": "testpwd"
    },
    "image": "grafana/grafana",
    "name": "grafana-{{namespace}}",
    "port_bindings": {
        "3000": 8888
    },
    "ports": [
        3000
    ],
    "tag": "latest"
}

啟動之后就可以在http://IP:8888/頁面去配置數據源了,一個示例如下:

Grafana數據源配置

配置完數據源,就可以添加Panel來實現數據可視化了。Grafana的圖表功能十分強大,在配置數據查詢語句的時候也是十分智能,會對數據源,數據表,數據字段自動提示,而且對InfluxDB的所有函數都有分類可以直接選取配置。需要注意的一點就是在配置字節類數據(比如網卡接收流量 rx_bytes 和 內存使用量 memory_usage)的時候單位要選 data(IEC)這個類別。

Grafana配置圖表示例

5 總結

使用CAdvisor+InfluxDB+Grafana構建容器資源監控系統,是可行而且是較為簡便的方式。這三個組件全部以容器的方式運行,也符合我們線上服務皆為容器的理念。目前已經全面上線該監控系統,運行正常,數據可視化效果良好。除了用于可視化監控之外,這些數據后續還會用于系統異常檢測算法和容器智能調度算法中。

6 參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容