zoukankan      html  css  js  c++  java
  • Docker 容器日志管理

    Docker 日志分为两类:

    • Docker 引擎日志(也就是 dockerd 运行时的日志),
    • 容器的日志,容器内的服务产生的日志。

    一 、Docker 引擎日志

    Docker 引擎日志一般是交给了 Upstart(Ubuntu 14.04) 或者 systemd (CentOS 7, Ubuntu 16.04)。前者一般位于 /var/log/upstart/docker.log 下,后者我们一般 通过 journalctl -u docker.service 来进行查看。

    二、容器日志

    2.1、常用查看日志命令——docker logs

    docker logs CONTAINER 显示当前运行的容器的日志信息, UNIX 和 Linux 的命令有三种 输入输出,分别是 STDIN(标准输入)、STDOUT(标准输出)、STDERR(标准错误输出),docker logs 显示的内容包含 STOUT 和 STDERR。在生产环境,如果我们的应用输出到我们的日志文件里,所以我们在使用 docker logs 一般收集不到太多重要的日志信息。

    nginx 官方镜像,使用了一种方式,让日志输出到 STDOUT,也就是 创建一个符号链接/var/log/nginx/access.log 到 /dev/stdout。
    httpd 使用的是 让其输出到指定文件 ,正常日志输出到 /proc/self/fd/1 (STDOUT) ,错误日志输出到 /proc/self/fd/2 (STDERR)。
    当日志量比较大的时候,我们使用 docker logs   来查看日志,会对 docker daemon 造成比较大的压力,容器导致容器创建慢等一系列问题。
    只有使用了 `local 、json-file、journald`  的日志驱动的容器才可以使用 docker logs 捕获日志,使用其他日志驱动无法使用 `docker logs`
    

    2.2 、Docker 日志 驱动

    Docker 提供了两种模式用于将消息从容器到日志驱动。

    • (默认)拒绝,阻塞从容器到容器驱动
    • 非阻塞传递,日志将储存在容器的缓冲区。

    当缓冲区满,旧的日志将被丢弃。

    在 mode 日志选项控制使用 blocking(默认) 或者 non-blocking, 当设置为 non-blocking需要设置 max-buffer-size 参数(默认为 1MB)。

    支持的驱动

    使用 Docker-CE 版本,docker logs命令 仅仅适用于以下驱动程序(前面 docker logs 详解也提及到了)

    • local
    • json-file
    • journald

    Docker 日志驱动常用命令

    查看系统当前设置的日志驱动

    docker  info |grep  "Logging Driver" 
    docker info --format '{{.LoggingDriver}}'
    

    查看单个容器的设置的日志驱动

    docker inspect  -f '{{.HostConfig.LogConfig.Type}}'   容器id
    

    Docker 日志驱动全局配置更改

    修改日志驱动,在配置文件 /etc/docker/daemon.json(注意该文件内容是 JSON 格式的)进行配置即可。
    示例:

    {
      "log-driver": "syslog"
    }
    

    以上更改是针对所有的容器的日志驱动的。我们也可以单独为单一容器设置日志驱动。

    Docker 单一容器日志驱动配置

    在 运行容器的时候指定 日志驱动 --log-driver

    docker  run  -itd --log-driver none alpine ash # 这里指定的日志驱动为 none 
    

    日志驱动 一 、local

    local 日志驱动 记录从容器的 STOUT/STDERR 的输出,并写到宿主机的磁盘。
    默认情况下,local 日志驱动为每个容器保留 100MB 的日志信息,并启用自动压缩来保存。(经过测试,保留100MB 的日志是指没有经过压缩的日志)
    local 日志驱动的储存位置 /var/lib/docker/containers/容器id/local-logs/ 以container.log 命名。

    local 驱动支持的选项

    全局日志驱动设置为—local

    在配置文件 /etc/docker/daemon.json(注意该文件内容是 JSON 格式的)进行配置即可。

    {
      "log-driver": "local",
      "log-opts": {
        "max-size": "10m"
      }
    }
    

    重启 docker 即可生效。

    单个容器日志驱动设置为—local
    运行容器并设定为 local 驱动。

    #  运行一个容器 ,并设定日志驱动为 local ,并运行命令 ping www.baidu.com
    [root@localhost docker]# docker run  -itd  --log-driver  local  alpine  ping www.baidu.com 
    3795b6483534961c1d5223359ad1106433ce2bf25e18b981a47a2d79ad7a3156
    #  查看运行的容器的 日志驱动是否是 local
    [root@localhost docker]# docker inspect  -f '{{.HostConfig.LogConfig.Type}}'   3795b6483534961c
    local
    # 查看日志
    [root@localhost local-logs]# tail -f  /var/lib/docker/containers/3795b6483534961c1d5223359ad1106433ce2bf25e18b981a47a2d79ad7a3156/local-logs/container.log 
    NNdout????:64 bytes from 14.215.177.38: seq=816 ttl=55 time=5.320 ms
    NNdout?μ???:64 bytes from 14.215.177.38: seq=817 ttl=55 time=4.950 ms
    
    注意事项: 经过测试,当我们产生了100 MB 大小的日志时 会有 四个压缩文件和一个container.log:
    [root@localhost local-logs]# ls -l
    total 32544
    -rw-r-----. 1 root root 18339944 May 16 09:41 container.log
    -rw-r-----. 1 root root  3698660 May 16 09:41 container.log.1.gz
    -rw-r-----. 1 root root  3726315 May 16 09:41 container.log.2.gz
    -rw-r-----. 1 root root  3805668 May 16 09:41 container.log.3.gz
    -rw-r-----. 1 root root  3744104 May 16 09:41 container.log.4.gz
    
    那么当超过了 100MB 的日志文件,日志文件会继续写入到  container.log,但是会将  container.log 日志中老的日志删除,追加新的,
    也就是 当写满 100MB 日志后 ,再产生一条新日志,会删除  container.log 中的一条老日志,保存 100MB 的大小。这个 对我们是会有一些影响的,
    当我运行系统时 第一天由于bug产生了 100MB 日志,那么之前的日志就已经有 80MB 日志变成的压缩包,所以我在后续的运行中,只能获取最近的 20MB日志。
    

    日志驱动 二、 默认的日志驱动—JSON

    所有容器默认的日志驱动 json-file。
    json-file 日志驱动 记录从容器的 STOUT/STDERR 的输出 ,用 JSON 的格式写到文件中,日志中不仅包含着 输出日志,还有时间戳和 输出格式。下面是一个 ping www.baidu.com 对应的 JSON 日志

    {"log":"64 bytes from 14.215.177.39: seq=34 ttl=55 time=7.067 ms
    ","stream":"stdout","time":"2019-05-16T14:14:15.030612567Z"}
    

    json-file 日志的路径位于 /var/lib/docker/containers/container_id/container_id-json.log

    json-file 的 日志驱动支持以下选项:

    json-file 的日志驱动示例

    # 设置 日志驱动为 json-file ,我们也可以不设置,因为默认就是 json-file
    docker run  -itd  --name  test-log-json  --log-driver json-file   alpine  ping www.baidu.com
    199608b2e2c52136d2a17e539e9ef7fbacf97f1293678aded421dadbdb006a5e
    
    # 查看日志,日志名称就是 容器名称-json.log
    tail -f /var/lib/docker/containers/199608b2e2c52136d2a17e539e9ef7fbacf97f1293678aded421dadbdb006a5e/199608b2e2c52136d2a17e539e9ef7fbacf97f1293678aded421dadbdb006a5e-json.log
    
    {"log":"64 bytes from 14.215.177.39: seq=13 ttl=55 time=15.023 ms
    ","stream":"stdout","time":"2019-05-16T14:13:54.003118877Z"}
    {"log":"64 bytes from 14.215.177.39: seq=14 ttl=55 time=9.640 ms
    ","stream":"stdout","time":"2019-05-16T14:13:54.999011017Z"}
    {"log":"64 bytes from 14.215.177.39: seq=15 ttl=55 time=8.938 ms
    ","stream":"stdout","time":"2019-05-16T14:13:55.998612636Z"}
    {"log":"64 bytes from 14.215.177.39: seq=16 ttl=55 time=18.086 ms
    ","stream":"stdout","time":"2019-05-16T14:13:57.011235913Z"}
    {"log":"64 bytes from 14.215.177.39: seq=17 ttl=55 time=12.615 ms
    ","stream":"stdout","time":"2019-05-16T14:13:58.007104112Z"}
    {"log":"64 bytes from 14.215.177.39: seq=18 ttl=55 time=11.001 ms
    ","stream":"stdout","time":"2019-05-16T14:13:59.007559413Z"}
    

    日志驱动 三、syslog

    syslog 日志驱动将日志路由到 syslog 服务器,syslog 以原始的字符串作为 日志消息元数据,接收方可以提取以下的消息:

    • level 日志等级 ,如debug,warning,error,info。
    • timestamp 时间戳
    • hostname 事件发生的主机
    • facillty 系统模块
    • 进程名称和进程 ID
    • syslog 日志驱动全局配置

    编辑 /etc/docker/daemon.json 文件

    {
      "log-driver": "syslog",
      "log-opts": {
        "syslog-address": "udp://1.2.3.4:1111"
      }
    }
    

    重启 docker 即可生效。

    Option Description Example value
    syslog-address 指定syslog 服务所在的服务器和使用的协议和端口。 格式:[tcp|udp|tcp+tls]://host:port,unix://path, orunixgram://path. 默认端口是 514. --log-opt syslog-address=tcp+tls://192.168.1.3:514, --log-opt syslog-address=unix:///tmp/syslog.sock
    syslog-facility 使用的 syslog 的设备, 具体设备名称见 syslog documentation. --log-opt syslog-facility=daemon
    syslog-tls-ca-cert 如果使用的是 tcp+tls的地址,指定CA 证书的地址,如果没有使用,则不设置该选项。 --log-opt syslog-tls-ca-cert=/etc/ca-certificates/custom/ca.pem
    syslog-tls-cert 如果使用的是 tcp+tls的地址,指定 TLS 证书的地址,如果没有使用,则不设置该选项。 --log-opt syslog-tls-cert=/etc/ca-certificates/custom/cert.pem
    syslog-tls-key 如果使用的是 tcp+tls的地址,指定 TLS 证书 key的地址,如果没有使用,则不设置该选项。** --log-opt syslog-tls-key=/etc/ca-certificates/custom/key.pem
    syslog-tls-skip-verify 如果设置为 true ,会跳过 TLS 验证,默认为 false --log-opt syslog-tls-skip-verify=true
    tag 将应用程序的名称附加到 syslog 消息中,默认情况下使用容器ID的前12位去 标记这个日志信息。 --log-opt tag=mailer
    syslog-format syslog 使用的消息格式 如果未指定则使用本地 UNIX syslog 格式,rfc5424micro 格式具有微妙时间戳。 --log-opt syslog-format=rfc5424micro
    labels 启动 docker 时,配置与日志相关的标签,以逗号分割 --log-opt labels=production_status,geo
    env 启动 docker 时,指定环境变量用于日志中,以逗号分隔 --log-opt env=os,customer
    env-regex 类似并兼容 env, --log-opt env-regex=^(os|customer)

    **单个容器日志驱动设置为—syslog **

    Linux 系统中 我们用的系统日志模块时 rsyslog ,它是基于syslog 的标准实现。我们要使用 syslog 驱动需要使用 系统自带的 rsyslog 服务。

    # 查看当前 rsyslog 版本和基本信息
    [root@localhost harbor]# rsyslogd  -v
    rsyslogd 8.24.0, compiled with:
        PLATFORM:               x86_64-redhat-linux-gnu
        PLATFORM (lsb_release -d):      
        FEATURE_REGEXP:             Yes
        GSSAPI Kerberos 5 support:      Yes
        FEATURE_DEBUG (debug build, slow code): No
        32bit Atomic operations supported:  Yes
        64bit Atomic operations supported:  Yes
        memory allocator:           system default
        Runtime Instrumentation (slow code):    No
        uuid support:               Yes
        Number of Bits in RainerScript integers: 64
    
    See http://www.rsyslog.com for more information.
    

    配置 syslog , 在配置文件 /etc/rsyslog.conf 大约14-20行,我们可以看到两个配置,一个udp,一个tcp ,都是监听 514 端口,提供 syslog 的接收。选择 tcp 就将 tcp 的两个配置的前面 # 号注释即可。

    # Provides UDP syslog reception
    #$ModLoad imudp
    #$UDPServerRun 514
    
    # Provides TCP syslog reception
    #$ModLoad imtcp  
    #$InputTCPServerRun 514
    

    然后重启 rsyslog,我们可以看到514端口在监听。

    systemctl restart  rsyslog
    [root@localhost harbor]# netstat -ntul |grep 514
    tcp        0      0 0.0.0.0:514             0.0.0.0:*               LISTEN     
    tcp6       0      0 :::514                  :::*                    LISTEN  
    

    启动一个以 syslog 为驱动的容器。

    docker  run -d -it  -p 87:80 --log-driver syslog --log-opt syslog-address=tcp://127.0.0.1:514  --name nginx-syslog   nginx
    

    日志驱动 四、Journald

    journald 日志驱动程序将容器的日志发送到 systemd journal, 可以使用 journal API 或者使用 docker logs 来查日志。

    除了日志本身以外, journald 日志驱动还会在日志加上下面的数据与消息一起储存。

    journald 日志驱动全局配置

    编辑 /etc/docker/daemon.json 文件

    {
      "log-driver": "journald"
    }
    
    

    单个容器日志驱动设置为—journald

    docker  run  -d -it --log-driver=journald 
        --log-opt labels=location 
        --log-opt env=TEST 
        --env "TEST=false" 
        --label location=china 
        --name  nginx-journald
        -p 80:80
        nginx
    

    查看日志 journalctl

    # 只查询指定容器的相关消息
     journalctl CONTAINER_NAME=webserver
    # -b 指定从上次启动以来的所有消息
     journalctl -b CONTAINER_NAME=webserver
    # -o 指定日志消息格式,-o json 表示以json 格式返回日志消息
     journalctl -o json CONTAINER_NAME=webserver
    # -f 一直捕获日志输出
     journalctl -f CONTAINER_NAME=webserver
    如果我们的容器在启动的时候加了 -t 参数,启用了 TTY 的话,那么我查看日志是会像下面一样
    May 17 17:19:26 localhost.localdomain 2a338e4631fe[6141]: [104B blob data]
    May 17 17:19:32 localhost.localdomain 2a338e4631fe[6141]: [104B blob data]
    
    显示[104B blob data] 而不是完整日志原因是因为有 
     的存在,如果我们要完整显示,需要加上参数 --all 。
    

    容器的日志实际是有两大类的

    1.标准输出的 ,也就是 STDOUT 、STDERR ,这类日志我们可以通过 Docker 官方的日志驱动进行收集。
    可以选择 json-file 、syslog、local 等 Docker 支持的日志驱动。
    2.文本日志,存在在于容器内部,并没有重定向到 容器的标准输出的日志。
    方案一 挂载目录,创建一个目录,将目录挂载到 容器中产生日志的目录。

    方案二 使用数据卷 volume,创建数据卷,创建容器时绑定数据卷,

    --mount  type=volume  src=volume_name  dst=/usr/local/tomcat/logs/ 
    

    方案三 计算容器 rootfs 挂载点

    采用这种方法相当于登录到容器中查看日志

    使用挂载宿主机目录的方式采集日志对应用会有一定的侵入性,因为它要求容器启动的时候包含挂载命令。如果采集过程能对用户透明那就太棒了。事实上,可以通过计算容器 rootfs 挂载点来达到这种目的。

    和容器 rootfs 挂载点密不可分的一个概念是 storage driver。实际使用过程中,用户往往会根据 linux 版本、文件系统类型、容器读写情况等因素选择合适的 storage driver。不同 storage driver 下,容器的 rootfs 挂载点遵循一定规律,因此我们可以根据 storage driver 的类型推断出容器的 rootfs 挂载点,进而采集容器内部日志。下表展示了部分 storage dirver 的 rootfs 挂载点及其计算方法。

    Storage driver rootfs 挂载点 计算方法
    aufs /var/lib/docker/aufs/mnt/ id 可以从如下文件读到。 /var/lib/docker/image/aufs/layerdb/mounts//mount-id
    overlay /var/lib/docker/overlay//merged 完整路径可以通过如下命令得到。 docker inspect -f '{{.GraphDriver.Data.MergedDir}}'
    overlay2 /var/lib/docker/overlay2//merged 完整路径可以通过如下命令得到。 docker inspect -f '{{.GraphDriver.Data.MergedDir}}'
    devicemapper /var/lib/docker/devicemapper/mnt//rootfs id 可以通过如下命令得到。 docker inspect -f '{{.GraphDriver.Data.DeviceName}}'

    示例:

    # 创建容器 tomcat-test
    [root@fy-local-2 /]# docker  run -d  --name  tomcat-test  -P  tomcat
    36510dd653ae7dcac1d017174b1c38b3f9a226f9c4e329d0ff656cfe041939ff  
    # 查看tomcat-test 容器的 挂载点位置
    [root@fy-local-2 /]# docker inspect -f '{{.GraphDriver.Data.MergedDir}}' 36510dd653ae7dcac1d017174b1c38b3f9a226f9c4e329d0ff656cfe041939ff  
    /var/lib/docker/overlay2/c10ec54bab8f3fccd2c5f1a305df6f3b1e53068776363ab0c104d253216b799d/merged
    # 查看挂载点的目录结构
    [root@fy-local-2 /]# ls -l /var/lib/docker/overlay2/c10ec54bab8f3fccd2c5f1a305df6f3b1e53068776363ab0c104d253216b799d/merged
    total 4
    drwxr-xr-x 1 root root  179 May  8 13:05 bin
    drwxr-xr-x 2 root root    6 Mar 28 17:12 boot
    drwxr-xr-x 1 root root   43 May 22 17:27 dev
    lrwxrwxrwx 1 root root   33 May  8 13:08 docker-java-home -> /usr/lib/jvm/java-8-openjdk-amd64
    drwxr-xr-x 1 root root   66 May 22 17:27 etc
    drwxr-xr-x 2 root root    6 Mar 28 17:12 home
    drwxr-xr-x 1 root root    6 May 16 08:50 lib
    drwxr-xr-x 2 root root   34 May  6 08:00 lib64
    drwxr-xr-x 2 root root    6 May  6 08:00 media
    drwxr-xr-x 2 root root    6 May  6 08:00 mnt
    drwxr-xr-x 2 root root    6 May  6 08:00 opt
    drwxr-xr-x 2 root root    6 Mar 28 17:12 proc
    drwx------ 1 root root   27 May 22 17:29 root
    drwxr-xr-x 3 root root   30 May  6 08:00 run
    drwxr-xr-x 2 root root 4096 May  6 08:00 sbin
    drwxr-xr-x 2 root root    6 May  6 08:00 srv
    drwxr-xr-x 2 root root    6 Mar 28 17:12 sys
    drwxrwxrwt 1 root root   29 May 16 08:50 tmp
    drwxr-xr-x 1 root root   19 May  6 08:00 usr
    drwxr-xr-x 1 root root   41 May  6 08:00 var
    # 查看日志
    [root@fy-local-2 /]# ls -l /var/lib/docker/overlay2/c10ec54bab8f3fccd2c5f1a305df6f3b1e53068776363ab0c104d253216b799d/merged/usr/local/tomcat/logs/
    total 20
    -rw-r----- 1 root root 14514 May 22 17:40 catalina.2019-05-22.log
    -rw-r----- 1 root root     0 May 22 17:27 host-manager.2019-05-22.log
    -rw-r----- 1 root root  1194 May 22 17:40 localhost.2019-05-22.log
    -rw-r----- 1 root root     0 May 22 17:27 localhost_access_log.2019-05-22.txt
    -rw-r----- 1 root root     0 May 22 17:27 manager.2019-05-22.log
    

    方案四 在代码层中实现直接将日志写入redis
    docker ——》redis ——》Logstash——》Elasticsearch
    通过代码层面,直接将日志写入redis,最后写入 Elasticsearch

  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/14688857.html
Copyright © 2011-2022 走看看