docker入門基礎(七)

[toc] 9、docker 日誌html

一、 Docker 的日誌功能。node

對於一個運行的容器,Docker 會將日誌發送到 容器的 標準輸出設備(STDOUT)和標準錯誤設備(STDERR),STDOUT 和 STDERR 實際上就是容器的控制檯終端。web

舉個例子,用下面的命令運行 httpd 容器:docker

root@node1 ~]# docker run -p 80:80 httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Wed Dec 19 16:19:19.135837 2018] [mpm_event:notice] [pid 1:tid 139659397657792] AH00489: Apache/2.4.37 (Unix) configured -- resuming normal operations
[Wed Dec 19 16:19:19.136196 2018] [core:notice] [pid 1:tid 139659397657792] AH00094: Command line: 'httpd -D FOREGROUND'

由於咱們在啓動日誌的時候沒有用 -d 參數,httpd 容器之前臺方式啓動,日誌會直接打印在當前的終端窗口。json

若是加上 -d 參數之後臺方式運行容器,咱們就看不到輸出的日誌了。api

[root@node1 ~]# docker run -p 80:80 -d  httpd
8a4e90384f42279573a98665c08e929c5b871cfed14f4873b62081db22579d86

這種狀況下若是要查看容器的日誌,有兩種方法:瀏覽器

  1. attach 到該容器。
  2. 用 docker logs 命令查看日誌。

attach方法負載均衡

attach 到了 httpd 容器,但並無任何輸出,這是由於當前沒有新的日誌信息。dom

爲了產生一條新的日誌,能夠在 host 的另外一個命令行終端執行 curl localhost。curl

[root@node1 ~]# docker attach 8a4e90384f42279573a98665c08e929c5b871cfed14f4873b62081db22579d86

[white@node1 ~]$ curl localhost
<html><body><h1>It works!</h1></body></html>

[root@node1 ~]# docker attach 8a4e90384f42279573a98665c08e929c5b871cfed14f4873b62081db22579d86
172.17.0.1 - - [20/Dec/2018:06:26:28 +0000] "GET / HTTP/1.1" 200 45

attach 的方法在實際使用中不太方便,由於:

  1. 只能看到 attach 以後的日誌,之前的日誌不可見。
  2. 退出 attach 狀態比較麻煩(Ctrl+p 而後 Ctrl+q 組合鍵),一不當心很容器將容器殺掉(好比按下 Ctrl+C)。

查看容器日誌推薦的方法是用 docker logs 命令。

docker logs 可以打印出自容器啓動以來完整的日誌,而且 -f 參數能夠繼續打印出新產生的日誌,效果上與 Linux 命令 tail -f 同樣。

二、多種日誌方案

將容器日誌發送到 STDOUT 和 STDERR 是 Docker 的默認日誌行爲。實際上,Docker 提供了多種日誌機制幫助用戶從運行的容器中提取日誌信息。這些機制被稱做 logging driver。

Docker 的默認 logging driver 是 json-file。

[root@node1 ~]# docker info |grep 'Logging Driver'
Logging Driver: json-file

json-file 會將容器的日誌保存在 json 文件中,Docker 負責格式化其內容並輸出到 STDOUT 和 STDERR。

咱們能夠在 Host 的容器目錄中找到這個文件,器路徑爲 /var/lib/docker/containers/<contariner ID>/<contariner ID>-json.log

好比咱們能夠查看前面 httpd 容器 json 格式的日誌文件。

[root@node1 ~]# cat /var/lib/docker/containers/8a4e90384f42279573a98665c08e929c5b871cfed14f4873b62081db22579d86/8a4e90384f42279573a98665c08e929c5b871cfed14f4873b62081db22579d86-json.log 
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message\n","stream":"stderr","time":"2018-12-19T16:20:06.529205619Z"}
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message\n","stream":"stderr","time":"2018-12-19T16:20:06.52927816Z"}
{"log":"[Wed Dec 19 16:20:06.531616 2018] [mpm_event:notice] [pid 1:tid 139645179663552] AH00489: Apache/2.4.37 (Unix) configured -- resuming normal operations\n","stream":"stderr","time":"2018-12-19T16:20:06.539621015Z"}
{"log":"[Wed Dec 19 16:20:06.531941 2018] [core:notice] [pid 1:tid 139645179663552] AH00094: Command line: 'httpd -D FOREGROUND'\n","stream":"stderr","time":"2018-12-19T16:20:06.539658478Z"}
{"log":"172.17.0.1 - - [20/Dec/2018:06:26:28 +0000] \"GET / HTTP/1.1\" 200 45\n","stream":"stdout","time":"2018-12-20T06:26:28.088467341Z"}
{"log":"[Thu Dec 20 06:27:06.465698 2018] [mpm_event:notice] [pid 1:tid 139645179663552] AH00491: caught SIGTERM, shutting down\n","stream":"stderr","time":"2018-12-20T06:27:06.46593144Z"}

除了 json-file,Docker 還支持多種 logging driver。完整列表可訪問官方文檔 https://docs.docker.com/engine/admin/logging/overview/#supported-logging-drivers

none 是 disable 容器日誌功能。

syslog 和 journald 是 Linux 上的兩種日誌管理服務。

awslogs、splunk 和 gcplogs 是第三方日誌託管服務。

gelf 和 fluentd 是兩種開源的日誌管理方案,咱們會在後面分別討論。

容器啓動時能夠經過 --log-driver 指定使用的 logging driver。若是要設置 Docker 默認的 logging driver,須要修改 Docker daemon 的啓動腳本,指定 --log-driver 參數,好比:ExecStart=/usr/bin/dockerd -H fd:// --log-driver=syslog --log-opt ......

每種 logging driver 都有本身的 --log-opt,使用時請參考官方文檔。

三、ELK

在開源的日誌管理方案中,最出名的莫過於 ELK 了。ELK 是三個軟件的合稱:Elasticsearch、Logstash、Kibana。

Elasticsearch 一個近乎實時查詢的全文搜索引擎。Elasticsearch 的設計目標就是要可以處理和搜索巨量的日誌數據。

Logstash 讀取原始日誌,並對其進行分析和過濾,而後將其轉發給其餘組件(好比 Elasticsearch)進行索引或存儲。Logstash 支持豐富的 Input 和 Output 類型,可以處理各類應用的日誌。

Kibana 一個基於 JavaScript 的 Web 圖形界面程序,專門用於可視化 Elasticsearch 的數據。Kibana 可以查詢 Elasticsearch 並經過豐富的圖表展現結果。用戶能夠建立 Dashboard 來監控系統的日誌。

本節將討論如何用 ELK 這組黃金搭檔來監控 Docker 容器的日誌。

Logstash 負責從各個 Docker 容器中提取日誌,Logstash將日誌轉發到 Elasticsearch 進行索引和保存,Kibana 分析和可視化數據。

下面開始實踐這套流程。

1\安裝 ELK 套件

ELK 的部署方案能夠很是靈活,在規模較大的生產系統中,ELK 有本身的集羣,實現了高可用和負載均衡。咱們的目標是在最短的時間內學習並實踐 ELK,所以將採用最小部署方案:在容器中搭建 ELK。

[root@node1 ~]# docker run --name elk -p 5601:5601 -p 9200:9200 -p:5044:5044 -it sebp/elk

咱們使用的是 sebp/elk 這個現成的 image,裏面已經包含了整個 ELK stack。容器啓動後 ELK 各組件將分別監聽以下端口:

5601 - Kibana web 接口 9200 - Elasticsearch JSON 接口 5044 - Logstash 日誌接收接口

先訪問一下 Kibana http://[Host IP]:5601/ 看看效果。

當前 Kibana 沒有可顯示的數據,由於當前 Elasticsearch 尚未任何日誌數據。

訪問一下 Elasticsearch 的 JSON 接口 http://[Host IP]:9200/_search?pretty

{
  "name" : "lW3S7Mf",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "9iqURI_vQdeIKVXTWJD_Ug",
  "version" : {
    "number" : "6.5.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "8c58350",
    "build_date" : "2018-11-16T02:22:42.182257Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

確實,目前 Elasticsearch 沒有與日誌相關的 index。

接下來的工做就是將 Docker 的日誌導入 ELK,

幾乎全部的軟件和應用都有本身的日誌文件,容器也不例外。前面咱們已經知道 Docker 會將容器日誌記錄到 /var/lib/docker/containers/<contariner ID>/<contariner ID>-json.log,那麼只要咱們可以將此文件發送給 ELK 就能夠實現日誌管理。

要實現這一步其實不難,由於 ELK 提供了一個配套小工具 Filebeat,它能將指定路徑下的日誌文件轉發給 ELK。同時 Filebeat 很聰明,它會監控日誌文件,當日志更新時,Filebeat 會將新的內容發送給 ELK。

2\安裝 Filebeat**

下面在 Docker Host 中安裝和配置 Filebeat。

[root@node1 ~]# curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-5.1.1-x86_64.rpm
[root@node1 ~]# yum localinstall filebeat-5.1.1-x86_64.rpm -y

配置 Filebeat

Filebeat 的配置文件爲 /etc/filebeat/filebeat.yml,咱們須要告訴 Filebeat 兩件事:

  1. 監控哪些日誌文件?

  2. 將日誌發送到哪裏?

    • input_type: log

      Paths that should be crawled and fetched. Glob based paths.

      paths:

      • /var/lib/docker/containers//.log
      • /var/log/syslog

在 paths 中咱們配置了兩條路徑:

  1. /var/lib/docker/containers//.log 是全部容器的日誌文件。
  2. /var/log/syslog 是 Host 操做系統的 syslog。

接下來告訴 Filebeat 將這些日誌發送給 ELK。

Filebeat 能夠將日誌發送給 Elasticsearch 進行索引和保存;也能夠先發送給 Logstash 進行分析和過濾,而後由 Logstash 轉發給 Elasticsearch

爲了避免引入過多的複雜性,咱們這裏將日誌直接發送給 Elasticsearch。

output.elasticsearch:
  # Array of hosts to connect to.
  hosts: ["localhost:9200"]

啓動 Filebeat

Filebeat 安裝時已經註冊爲 systemd 的服務,能夠直接啓動服務。

[root@node1 ~]# systemctl start filebeat.service

管理日誌**

Filebeat 啓動後,正常狀況下會將監控的日誌發送給 Elasticsearch。刷新 Elasticsearch 的 JSON 接口 http://[Host IP]:9200/_search?pretty 進行確認。

"_type" : "log",
        "_id" : "0L6rymcBMWBsEwm5rF3p",
        "_score" : 1.0,
        "_source" : {
          "@timestamp" : "2018-12-20T08:11:47.138Z",
          "beat" : {
            "hostname" : "node1",
            "name" : "node1",
            "version" : "5.1.1"
          },
          "input_type" : "log",
          "message" : "{\"log\":\"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message\\n\",\"stream\":\"stderr\",\"time\":\"2018-12-17T03:16:55.290537706Z\"}",
          "offset" : 480,
          "source" : "/var/lib/docker/containers/0fe49ea429a2cee05de5705ba83f89ecac7bea812a24ec041f957ab7bf05b199/0fe49ea429a2cee05de5705ba83f89ecac7bea812a24ec041f957ab7bf05b199-json.log",
          "type" : "log"

此次咱們可以看到 filebeat-* 的 index,以及 Filebeat 監控的那兩個路徑下的日誌。

好,Elasticsearch 已經建立了日誌的索引並保存起來,接下來是在 Kibana 中展現日誌。

首先須要配置一個 index pattern,即告訴 Kibana 查詢和分析 Elasticsearch 中的哪些日誌。

指定 index pattern 爲 filebeat-*,這與 Elasticsearch 中的 index一致。

Time-field name 選擇 @timestamp。

點擊 Create 建立 index pattern。

點擊 Kibana 左側 Discover 菜單,即可看到容器和 syslog 日誌信息。

下面咱們啓動一個新的容器,該容器將向控制檯打印信息,模擬日誌輸出。

[root@node1 ~]# docker run busybox sh -c 'while true; do echo "This is a log message from container busybox!"; sleep 10; done;'

刷新 Kibana 頁面或者點擊右上角 圖標,立刻就能看到 busybox 的日誌。

Kibana 也提供了強大的查詢功能,好比輸入關鍵字 busybox 能搜索出全部匹配的日誌條目。

咱們這裏只是簡單地將日誌導入 ELK 並樸素地顯示出來,實際上 ELK 還能夠對日誌進行歸類彙總、分析聚合、建立炫酷的 Dashboard 等,能夠挖掘的內容不少,玩法很豐富。

3\Fluentd

ELK 中咱們是用 Filebeat 收集 Docker 容器日誌,利用的是 Docker 默認的 logging driver json-file,本節咱們將使用 fluentd 來收集容器的日誌。

Fluentd 是一個開源的數據收集器,它目前有超過 500 種的 plugin,能夠鏈接各類數據源和數據輸出組件。在接下來的實踐中,Fluentd 會負責收集容器日誌,而後發送給 Elasticsearch。

這裏咱們用 Filebeat 將 Fluentd 收集到的日誌轉發給 Elasticsearch。這固然不是惟一的方案,Fluentd 有一個 plugin fluent-plugin-elasticsearch 能夠直接將日誌發送給 Elasticsearch。條條道路通羅馬,開源世界給予了咱們多種可能性,能夠根據須要選擇合適的方案。

安裝 Fluentd

一樣的,最高效的實踐方式是運行一個 fluentd 容器。

[root@node1 ~]# docker run -d -p 24224:24224 -p 24224:24224/udp -v /data:/fluentd/log fluent/fluentd

fluentd 會在 TCP/UDP 端口 24224 上接收日誌數據,日誌將保存在 Host 的 /data 目錄中。

從新配置 Filebeat

編輯 Filebeat 的配置文件 /etc/filebeat/filebeat.yml,將 /data 添加到監控路徑中。

- input_type: log

  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    - /data/*.log

重啓 Filebeat。

[root@node1 ~]# systemctl restart filebeat.service

監控容器日誌,啓動測試容器

[root@node1 ~]# docker run -d \
>            --log-driver=fluentd \
>            --log-opt fluentd-address=localhost:24224 \
>            --log-opt tag="log-test-container-A" \
>            busybox sh -c 'while true; do echo "This is a log message from container A"; sleep 10; done;'

[root@node1 ~]# docker run -d \
>            --log-driver=fluentd \
>            --log-opt fluentd-address=localhost:24224 \
>            --log-opt tag="log-test-container-B" \
>            busybox sh -c 'while true; do echo "This is a log message from container B"; sleep 10; done;'

--log-driver=fluentd 告訴 Docker 使用 Fluentd 的 logging driver。

--log-opt fluentd-address=localhost:24224 將容器日誌發送到 Fluentd 的數據接收端口。

--log-opt tag="log-test-container-A" 和 --log-opt tag="log-test-container-B" 在日誌中添加一個可選的 tag,用於區分不一樣的容器。

容器啓動後,Kibana 很快就可以查詢到容器的日誌。

四、Graylog

Graylog 是與 ELK 能夠相提並論的一款集中式日誌管理方案,支持數據收集、檢索、可視化 Dashboard。本節將實踐用 Graylog 來管理 Docker 日誌。

Graylog 負責接收來自各類設備和應用的日誌,併爲用戶提供 Web 訪問接口。

Elasticsearch 用於索引和保存 Graylog 接收到的日誌。

MongoDB 負責保存 Graylog 自身的配置信息。

與 ELK 同樣,Graylog 的部署方案很靈活,快速搭建一個 all-in-one 的環境對於學習頗有益處;部署一個高可用高伸縮性的集羣對於生成環境也是必要的。

接下來咱們將在容器環境下搭建 Graylog。

部署 Graylog

Graylog 及其相關組件都將以容器的方式部署。

MongoDB

[root@node1 ~]# docker run --name graylog-mongo -d mongo:3

Elasticsearch

[root@node1 ~]# docker run --name graylog-elasticsearch -d elasticsearch:2 elasticsearch -Des.cluster.name="graylog"

Graylog

[root@node1 ~]# docker run --link graylog-mongo:mongo \
>            --link graylog-elasticsearch:elasticsearch \
>            -p 9000:9000 \
>            -p 12201:12201/udp \
>            -e GRAYLOG_WEB_ENDPOINT_URI="http://192.168.2.110:9000/api" \
>            -e GRAYLOG_PASSWORD_SECRET=somepasswordpepper \
>            -e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 \
>            -d graylog2/server

--link 參數讓 Graylog 容器可以用主機名 mongo 和 elasticsearch 訪問 MongoDB 和 Elasticsearch 的服務。

-p 9000:9000 映射 Graylog 的 Web 服務端口 9000。

-p 12201:12201/udp 映射 Graylog 接收日誌數據的 UDP 端口 12201。

GRAYLOG_WEB_ENDPOINT_URI 指定 Graylog 的 Web 訪問 URI,請注意這裏須要使用 Docker Host 的外部 IP(在實驗環境中爲 192.168.2.110)。

GRAYLOG_ROOT_PASSWORD_SHA2 指定 Graylog 管理員用戶密碼的哈希值,在這個例子中密碼爲 admin。能夠經過以下命令生成本身的密碼哈希,好比:

echo -n yourpassword | shasum -a 256

容器啓動後,在 Web 瀏覽器中訪問 http://[Docker Host IP]:9000

用戶名/密碼 = admin/admin

登陸後顯示 Getting Started 頁面。

配置 Graylog**

目前 Graylog 還無法接收任何日誌,咱們須要配置一個 Input,點擊頂部菜單 System -> Inputs。

Graylog 支持多種 Input 類型,與 Graylog 對接的 Docker logging driver 是 gelf,所以這裏咱們須要運行一個 GELF UDP 類型的 Input。

在 Node 列表中選擇 Graylog 容器。 Title 命名爲 docker GELF input。 其餘保持默認值,其中 port 12201 即爲前面啓動容器時映射到 Host 的端口,用於接收日誌數據。

Graylog 已經準備就緒,接下來就能夠將容器的日誌發送給 Graylog 了

使用Graylog管理容器日誌

首先啓動測試容器。

[root@node1 ~]# docker run -d \
>            --log-driver=gelf \
>            --log-opt gelf-address=udp://localhost:12201 \
>            --log-opt tag="log-test-container-A" \
>            busybox sh -c 'while true; do echo "This is a log message from container A"; sleep 10; done;'
[root@node1 ~]# docker run -d \
>            --log-driver=gelf \
>            --log-opt gelf-address=udp://localhost:12201 \
>            --log-opt tag="log-test-container-B" \
>            busybox sh -c 'while true; do echo "This is a log message from container B"; sleep 10; done;'

--log-driver=gelf 告訴 Docker 使用 GELF 的 logging driver。

--log-opt gelf-address=localhost:12201 將容器日誌發送到 Graylog 的日誌接收端口。

--log-opt tag="log-test-container-A" 和 --log-opt tag="log-test-container-B" 在日誌中添加一個可選的 tag,用於區分不一樣的容器。

容器啓動後,點擊 Graylog 頂部菜單 Search,就可以查詢到容器的日誌了。

與 Kibana 同樣,Graylog 也提供了強大的查詢功能,好比輸入關鍵字 container B 能搜索出全部匹配的日誌條目。

與前面 ELK 同樣,這裏咱們只是簡單的將日誌導入到 Graylog。實際上 Graylog 也能夠對日誌進行歸類彙總、分析聚合、建立 Dashboard 等

相關文章
相關標籤/搜索