Docker 容器監控系統初探

weixin_33766168發表於2018-07-12

本文已獲得原作者__七把刀__授權。

隨著線上服務的全面 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 CloudData 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 構建容器資源監控系統,是可行而且是較為簡便的方式。這三個元件全部以容器的方式執行,也符合我們線上服務皆為容器的理念。目前已經全面上線該監控系統,執行正常,資料視覺化效果良好。除了用於視覺化監控之外,這些資料後續還會用於系統異常檢測演算法和容器智慧排程演算法中。

作者:__七把刀__
連結:https://www.jianshu.com/p/abf...
來源:簡書

更多相關內容
Docker底層技術
Docker視覺化監控?看這篇文章
利用TICK搭建Docker容器視覺化監控中心
Docker容器視覺化監控中心搭建

如果你還想了解更多,想和技術同僚分享切磋,可掃下方二維碼,回覆yw,加入掘金運維技術交流群

掘金-餅餅

相關文章