導讀:容器對於物理機和虛擬機,單從監控上看就不是一個數量級的,但監控又是相當重要的,沒有監控如同閉眼開車。git
本次分享邀請數人云運維總監龐錚,本文將從如下幾個方面聊聊容器監控的相關思考:github
容器監控面臨問題-容器設計及運營複雜性的挑戰;docker
容器的三種監控收集指標;數據庫
容器性能監控能力把控及報警調查。centos
爲何要使用Dockerapi
須要一個可靠可擴展的基礎設施平臺緩存
大量的流量和用戶安全
大量的內部服務服務器
不須要改造基礎設施:負載均衡、HTTP服務、日誌系統、數據庫、監控系統等網絡
抽象標準基礎設施服務,如 HaproxyMongodbEs等
提供快速的更新部署能力
簡介
容器對於物理機和虛擬機,單從監控上看就不是一個數量級的。可是監控又是相當重要的,若是沒有監控,如同閉着眼開車。先看下傳統監控解決的問題:
對於應用層:應用層的性能監控將找到代碼的瓶頸和錯誤。
對於基礎設施:收集基礎設施層的資源指標,如CPUMEM。
而使用容器則在於資源層和應用層之間,應用監控和基礎設施監控沒法起做用,形成了監控系統的盲點。
容器的設計
原始初衷:安全
容器最開始設計就是爲了提供運行時的安全隔離,且沒有虛擬化的資源開銷。容器提供了一種孤立運行軟件的方法,既不是進程也不是主機,而存在於二者之間。
如今
如今使用容器主要有兩個重要緣由:
提供了一個規模的標準
若是軟件是微服務架構,在 KubernetesMesos 等容器平臺上進行無停機的擴縮和升級等系統操做。
擺脫對於軟件系統的依賴
一直以來使用 Lib直接編譯成二進制可執行文件是最好的,但 Lib 的增長,爲了不內存的過分消耗,致使運行時共享 Lib 的出現。爲了解決軟件依賴的問題,建立了不少方法如:Apt、Yum、Rvm、V1irtualenv 等,但這會致使拖慢發佈週期,而容器直接解決了這個問題。
容器挑戰:運營的巨大複雜性
能夠將每一個容器當作一個迷你的主機,但它與主機的操做並非很相同。
上圖顯示了15年的系統演進過程。
15年前仍是主機天下。
7年前引進虛擬化技術,而虛擬化技術帶來的是更好的資源利用率,但對於工程師來講沒有什麼變化。
而今天 Datadog 的數據顯示從收到了數十萬的主機數據中,愈來愈多的主機開始運行容器。
2016年開始使用 Docker 的用戶增加率爲 40%。
運行容器實例主機佔總主機數量的 15%。
大型企業使用容器的用戶更多(超過500臺主機集羣)佔 60%,另外一方面說明了容器對於規模性和擺脫軟件依賴的對於大型企業的用處更高,數人云的核心業務是幫客戶把已有的系統容器化,再將其應用搬到調度系統上,以及開發一些周邊系統,接觸的客戶也反映了這一點。
有 40% 的用戶將容器運行在相似 Mesos 和 Kubernetes 等容器集羣軟件中。
使用容器用戶中在第一個月到第十個月的九個月中,容器數量增加了 5 倍,而且數據很是線性。
運行應用統計比例。
在使用容器的公司中,每一個主機運行容器實例爲 7 個左右,而 25% 的公司每一個主機運行容器實例爲14個左右。
容器的生命週期爲 2.5 天,在自動化平臺的更短爲不到 1 天,主要由於自動修復緣由,而非自動平臺則 5.5 天。
監控的爆炸性增加
在沒有容器之前,監控數量如:
使用容器後公式:假設每一個容器收集 50 個度量,再加上應用收集 50 個度量。
系統監控 (容器數量*(容器監控 應用監控))= 每一個主機監控數量100 (4 *(50 50))= 500/主機監控項
以主機爲中心的監控體系
容器做爲主機,以主機爲中心將有兩個問題沒法解決:
容器做爲主機,由於容器生命週期很是短暫,因此監控系統會認爲一半主機在頻發故障。
若是不監控容器,那麼從主機到應用之間的監控是空白的,產生監控黑洞。
簡化監控體系
如圖採用分層監控架構,更符合現有監控體系。主機層和應用層保持不變使用傳統的 Apm 和主機層監控,而容器層使用新的監控模式。
容器相似主機
它有一個迷你主機該有的一切,包含常駐程序、CPU、MEM、IO 和網絡資源。但容器不能報告和主機徹底相同的 Cgroup 指標。
容器監控資源
cpu
容器 CPU 會給出如下數據而不會有和主機同樣的全數據,如 IdleIowaitIrq。
內存
使用內存區別
rss
屬於進程的數據,如 Stacks、Heaps 等。能夠被進一步分解爲
活動內存(active_anon)
非活動內存(inactive_anon)
必要時,非活動內存能夠被交換到磁盤
cache
緩存存儲器存儲當前保存在內存中的磁盤數據。能夠進一步分解爲
活動內存(active_file)
非活動內存(inactive_file)
必要時,首先回收非活動內存
swap 使用量
io
容器對於每一個塊設別彙報4個指標,這種狀況下,在主機監控層面跟蹤主機隊列和服務時間是個好辦法,若是同塊的隊列和服務時間增加,那麼因同塊 IO 是共享的,因此容器 IO 也受到影響。
讀取
寫入
同步
異步
網絡
和普通主機同樣,分爲接收和發送的多個度量數據。
容器有三種指標收集方法,但標準並不同:
Sysfs 中的 Pseudo-files
默認狀況下,經過Sysfs中的僞文件能夠獲得容器的度量指標,且不須要 Root 權限。這個方法是最快最清亮的方法。若是須要監控不少主機,速度多是一個很重要的指標。但沒法用這個方法收集到全部指標,如 IO 和網絡指標會受到限制。
收集位置
假定僞文件在操做系統目錄中的 /sys/fs/cgroup 中,某些系統可能在 /cgroup 中。訪問路徑包含容器ID。
CONTAINER_ID=$(docker run [OPTIONS] IMAGE [COMMAND] [ARG...] )
CPU 獲取方法
cd /sys/fs/cgroupu/docker/&& ll
-rw-r--r-- 1 root root 0 5月 31 10:17 cgroup.clone_children --w--w--w- 1 root root 0 5月 31 10:17 cgroup.event_control -rw-r--r-- 1 root root 0 5月 31 10:17 cgroup.procs -r--r--r-- 1 root root 0 5月 31 10:17 cpuacct.stat -rw-r--r-- 1 root root 0 5月 31 10:17 cpuacct.usage -r--r--r-- 1 root root 0 5月 31 10:17 cpuacct.usage_percpu -rw-r--r-- 1 root root 0 5月 31 10:17 cpu.cfs_period_us -rw-r--r-- 1 root root 0 5月 31 10:17 cpu.cfs_quota_us -rw-r--r-- 1 root root 0 5月 31 10:17 cpu.rt_period_us -rw-r--r-- 1 root root 0 5月 31 10:17 cpu.rt_runtime_us -rw-r--r-- 1 root root 0 5月 31 10:17 cpu.shares -r--r--r-- 1 root root 0 5月 31 10:17 cpu.stat -rw-r--r-- 1 root root 0 5月 31 10:17 notify_on_release -rw-r--r-- 1 root root 0 5月 31 10:17 tasks
CPU 使用(單位是10毫秒)
# cat $CONTAINER_ID/cpuacct.stat user 46409 #進程佔用 464.09s system 22162 #系統調用佔用 221.62s
CPU 每核使用量
能夠幫助識別每一個核心的壓力
# cat $CONTAINER_ID/cpuacct.usage_percpu 362316789800 #自啓動以來佔用,單位納秒 360108180815
若是想要獲得對於服務器彙總的cpu指標
# cat $CONTAINER_ID/cpuacct.usage 722473378982
CPU 節流
若是對 CPU 使用作了限制,能夠從下面的方法中查看
$ cat /sys/fs/cgroup/cpu/docker/$CONTAINER_ID/cpu.stat nr_periods 565 # 已經執行間隔數 nr_throttled 559 # 被組抑制的次數 throttled_time 12119585961 # 總使用時間,單位納秒(12.12s)
內存獲取方法
ll /sys/fs/cgroup/memory/docker/$CONTAINER_ID/ # 沒有 total 標籤,不包含於子cgroup組 cache 2015232 rss 15654912 rss_huge 0 mapped_file 131072 swap 0 pgpgin 22623 pgpgout 18309 pgfault 27855 pgmajfault 7 inactive_anon 12148736 active_anon 3506176 inactive_file 2011136 active_file 4096 unevictable 0 hierarchical_memory_limit 9223372036854775807 hierarchical_memsw_limit 9223372036854775807 # 有 total 標籤,包含於子cgroup組 total_cache 2015232 total_rss 15654912 total_rss_huge 0 total_mapped_file 131072 total_swap 0 total_pgpgin 22623 total_pgpgout 18309 total_pgfault 27855 total_pgmajfault 7 total_inactive_anon 12148736 total_active_anon 3506176 total_inactive_file 2011136 total_active_file 4096 total_unevictable 0
能夠經過特定命令直接獲取一些指標:
# 總物理內存佔用 cached + rss ,單位爲字節 $ cat /sys/fs/cgroup/memory/docker/$CONTAINER_ID/memory.usage_in_bytes # 總物理內存+swap 佔用 ,單位爲字節 $ cat /sys/fs/cgroup/memory/docker/$CONTAINER_ID/memory.memsw.usage_in_bytes # 內存使用次數限制 $ cat /sys/fs/cgroup/memory/docker/$CONTAINER_ID/memory.failcnt # cgroup 內存限制,單位爲字節 $ cat /sys/fs/cgroup/memory/docker/$CONTAINER_ID/memory.limit_in_bytes 注意若是最終返回的是一個很長的數值表明容器實例並無限制,若是想增長限制 $ docker run -m 500M IMAGE [COMMAND] [ARG...]
IO
ll /sys/fs/cgroup/blkio/docker/$CONTAINER_ID -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_merged -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_merged_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_queued -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_queued_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_service_bytes -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_service_bytes_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_serviced -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_serviced_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_service_time -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_service_time_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_wait_time -r--r--r-- 1 root root 0 5月 31 10:17 blkio.io_wait_time_recursive -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.leaf_weight -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.leaf_weight_device --w------- 1 root root 0 5月 31 10:17 blkio.reset_stats -r--r--r-- 1 root root 0 5月 31 10:17 blkio.sectors -r--r--r-- 1 root root 0 5月 31 10:17 blkio.sectors_recursive -r--r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.io_service_bytes -r--r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.io_serviced -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.read_bps_device -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.read_iops_device -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.write_bps_device -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.throttle.write_iops_device -r--r--r-- 1 root root 0 5月 31 10:17 blkio.time -r--r--r-- 1 root root 0 5月 31 10:17 blkio.time_recursive -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.weight -rw-r--r-- 1 root root 0 5月 31 10:17 blkio.weight_device -rw-r--r-- 1 root root 0 5月 31 10:17 cgroup.clone_children --w--w--w- 1 root root 0 5月 31 10:17 cgroup.event_control -rw-r--r-- 1 root root 0 5月 31 10:17 cgroup.procs -rw-r--r-- 1 root root 0 5月 31 10:17 notify_on_release -rw-r--r-- 1 root root 0 5月 31 10:17 tasks
根據系統不一樣可能會有更多的指標文件,然而大部分的文件返回值是零。這種狀況下一般還有兩個能夠工做的文件。
blkio.throttle.io_service_bytes #io 操做字節,實際操做而非限制,前面兩個用冒號分割的數字是-主設備id:次要設備Id。
8:0 Read 2080768 8:0 Write 0 8:0 Sync 0 8:0 Async 2080768 8:0 Total 2080768 253:0 Read 2080768 253:0 Write 0 253:0 Sync 0 253:0 Async 2080768 253:0 Total 2080768 Total 4161536
blkio.throttle.io_serviced #io 操做次數,實際操做而非限制。
8:0 Read 226 8:0 Write 0 8:0 Sync 0 8:0 Async 226 8:0 Total 226 253:0 Read 226 253:0 Write 0 253:0 Sync 0 253:0 Async 226 253:0 Total 226 Total 452
想查看設備之間的關係可使用:
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 50G 0 disk ├─sda1 8:1 0 500M 0 part /boot ├─sda2 8:2 0 29.5G 0 part │ ├─centos-root 253:0 0 46.5G 0 lvm / │ └─centos-swap 253:1 0 3G 0 lvm [SWAP] └─sda3 8:3 0 20G 0 part └─centos-root 253:0 0 46.5G 0 lvm /
網絡
網絡從 1.6.1版本之後才支持,和以上的路徑有所不一樣,獲取使用容器Pid獲取,注意Host模式獲取的是主機網絡數據,因此 host 模式沒法從容器數據統計網絡數據。
$ CONTAINER_PID=`docker inspect -f '{{ .State.Pid }}' $CONTAINER_ID` $ cat /proc/$CONTAINER_PID/net/dev Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed eth0: 9655 90 0 0 0 0 0 0 31435 78 0 0 0 0 0 0 lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
cli 的 stats
使用 docker stats 會不斷的接收監控指標,1.9.0 之後指標包含磁盤io
cpu stats
cpu 佔用百分比,多個實例佔用cpu會根據分配進行佔用峯值,若是設定強制規約,那麼cpu只能佔設定的數值,好比20%
內存 stats
若是沒有明確內存限制,則限制爲主機內存限制。若是主機上還有其餘使用內存進程,那麼會在到達限制前耗盡內存。
io stats
1.9.0 版本後支持,顯示總讀寫字節
網絡 stats
顯示總進/出流量字節
api
和 docker stats 命令同樣,可是提供更多的細節。守護進程監聽 unix:///var/run/docker.sock,只容許本地鏈接。使用 nc 調用方法:
echo "" | nc -U /var/run/docker.sock 例子 echo -ne "GET /containers/$CONTAINER_ID/stats HTTP/1.1\r\n\r\n" | sudo nc -U /var/run/docker.sock
監控都須要有什麼能力
從每一個 Docker 容器收集CPU、內存、IO、網絡指標,並能夠經過人和標籤或者標籤聚合作成指標,用來提供高分辨率資源指標。
微服務體系結構中,服務能夠直接通信或者使用隊列進行通信,沒有中央負載均衡很難進行計量,經過標籤聚合能力能夠很好的解決這個問題。
須要經過圖形得之哪些服務超載,哪些服務致使其餘服務失敗,哪些服務流量太多
還能夠監控其餘非 Docker 服務,如 Haproxy、MongoDB、Es等等。
內部網絡流量變化做爲最重要的指標來觸發報警而不會引發報警洪水。所以聚合和分解服務級別流量可見性是相當重要的。此外,即便在測量交叉異常閥值前,報警系統也能夠提醒網絡流量變化。而其他的資源指標是用來調查排錯的。
Q:有對Docker自己作什麼監控麼?
A:能夠認爲 Docker 監控是類主機監控,只不過是縮小版,基本上分爲4部分:CPU、內存、磁盤、網絡。
Q:使用的整套監控工具是哪些?容器CPU內存網絡 如何監控?容器事件好比起停如何監控。
A:整套工具數人云使用的是Cadvisor + Prometheus + Grafana ,固然中間的組件是能夠替換的,但基本上圍繞着採集、存儲計算、展示來作。採集也可使用本身的,好比文章說的本身寫代理去拿。容器的監控數據固然靠採集程序了。起停這個通常經過監控Docker的事件來實現,採集工具也能收。
Q:分享的監控圖片,有數據的,是使用什麼監控工具達成的?
A:這個分兩種,一種是靠底層的繪圖引擎,將數據從存儲裏讀出來本身繪製,一種就是用類Grafana的程序。
Q:若是用Zabbix監控,是否須要定義容器的的歷史數據保留時間和趨勢數據存儲週期,我設定的時歷史數據保留7天,趨勢數據14天,這樣是否合理?
A:我認爲Zabbix 是上一代監控體系,或者以主機爲中心的監控體系,若是是容器監控,建議仍是考慮時序類的監控體系,好比InfluxdbPrometheus等,Zabbix還能夠沿用做爲主機的,只是Docker單獨分離出來,這樣基礎建設能夠複用。
Q:建不建議經過Pod中放一個監控容器來監控應用容器,好比Zabbix客戶端的監控容器在Pod中,若是這麼作 優缺點哪些?
A:Pod應該是Kubernetes的概念,和容器其實關係不大,這個Kubernetes本身應該會提供數據,具體不是很清楚。可是Abbix仍是建議保留在主機層面使用,除非大改,不然即便靠拆分數據庫什麼的解決,將來維護和性能也是運維大坑。
Q:Cadvisor Heapster 和 Prometheus 哪一種好用一些,各自優缺點有哪些。
A: Heapster不熟悉, Prometheus很好,Google我的的開源項目,都是Google套路,惟獨存儲是個問題,這塊還須要看他們將來如何處理,如今單機存儲雖然性能上還能夠,可是擴展能力比較差。
Q:監控工具推薦哪一個?對於容器生命週期短,有何策略應對?如何實現快速監控策略?
A:監控工具推薦剛纔已經說了,能夠參考數人云的方案而後本身摸索出適合本身的。至於容器生命週期短的問題,這個不就是容器設計嘛,很正常,多起幾個相同的服務頂上。
Q:容器的一大特色是IP或者ID信息變化頻繁,這就會致使時間序列數據庫存儲的監控數據量增加和vm相比大上很多,這塊有什麼應對方案嗎?嘗試過固定ID的,可是效果不佳。
A:這塊確實沒有什麼好辦法,不過能夠換個角度,能夠將底層的實例抽象一個維度,好比起了1個服務10個容器,把容器編號0-9,對應掛掉的容器,新啓動繼承這個編號。從時序上用這個做爲標記,就能看比較直觀的顯示了。此功能數人云Swan (歡迎Star&Fork)實現了,能夠考慮。
Q:容器的安全如何作監控?
A:這個問題問的好,如今比較通用的監控基本上走的是兩條路,一個是監控性能,一個是監控業務,安全層面監控,到如今我以爲仍是要靠網絡層來監控比較靠譜。
Q:Docker啓動Kafka集羣的問題,有沒有控制內存方面的經驗呢?
A:Kafka集羣,性能監控的話,能夠沿用原來的Kafka集羣監控軟件,固然若是想作數據匯聚,也可使用開源軟件將數據匯聚到一個數據存儲,而後在匯聚出來。關於Docker內存的超出被殺問題,這個主要是看自身對於容器內存設置的容忍度問題,這裏能夠把容器當成一個機器,看到底給這個機器插多少內存合適。
Q:Promethues有沒有作高可用?
A:若是存儲高可用的話,能夠考慮使用兩臺Prometheus同時抓,這樣數據徹底同樣,也沒啥壓力。
分享人龐錚,數人云運維總監。15 年以上運維工做經驗。就任過宏碁戲谷、第三波、SQUARE ENIX CO, LTD 等。2015年加入數人云,從事數人云平臺運維管理,在容器技術及SRE實踐方面有深刻研究。