docker的日志管理工作和时区本地化设置(docker日志过大,造成磁盘空间被占满的两种处理方法,以及时区的准确设置)

  docker的日志管理工作和时区本地化设置(docker日志过大,造成磁盘空间被占满的两种处理方法,以及时区的准确设置)

说来话长,某次迁移服务器,该服务器跑的是一个Python项目,由于原服务器和目标服务器操作系统不一样,因此,迁移工作并不顺利,因此,决定使用docker把该Python项目容器化。

说干就干,docker确实是效率神器,半天功夫就迁移完毕了,但是前方有两个坑,很可惜,我掉进去了。第一个坑是docker的日志,第二个坑是docker容器化后的时区问题。

首先说一说docker的日志,docker的日志分为两种,第一种是docker引擎的日志,第二种是docker容器运行时的服务日志,默认为json-file格式,json-file日志驱动 记录从容器的 STOUT/STDERR的输出 ,用 JSON 的格式写到文件中,日志中不仅包含着 输出日志,还有时间戳和 输出格式。

所有的驱动如下:

none 运行的容器没有日志,docker logs也不返回任何输出。
local 日志以自定义格式存储,旨在实现最小开销。
json-file 日志格式为JSON。Docker的默认日志记录驱动程序。
syslog 将日志消息写入syslog。该syslog守护程序必须在主机上运行。
journald 将日志消息写入journald。该journald守护程序必须在主机上运行。
gelf 将日志消息写入Graylog扩展日志格式(GELF)端点,例如Graylog或Logstash。
fluentd 将日志消息写入fluentd(转发输入)。该fluentd守护程序必须在主机上运行。
awslogs 将日志消息写入Amazon CloudWatch Logs。
splunk 使用HTTP事件收集器将日志消息写入splunk。
etwlogs 将日志消息写为Windows事件跟踪(ETW)事件。仅适用于Windows平台。
gcplogs 将日志消息写入Google Cloud Platform(GCP)Logging。
logentries

将日志消息写入Rapid7 Logentries。

  

常用的驱动是json-file,syslog ,journald 这三种,json-file 是默认的日志驱动。

docker的日志通常默认是保存在 /var/lib/docker/containers/容器名称/ 目录下,如果是默认的json-file 驱动,那么日志文件名称为 容器名称-json-log,当然,docker日志也有级别,通常级别为info,如果为debug的话,那么日志增长会非常快的。

回到前面所说的迁移项目,我并没有对日志做任何限制和改动,也就是所有的都是默认的,迁移完成的比较顺利,也就等待验收了,然后大概过了四五天时间,需要在迁移的机器上做一点小改动,登陆服务器后cd 切换目录报错:bash: cannot create temp file for here-document: No space left on device,这就让人很奇怪了,什么也没干怎么就没磁盘空间了??

df -ah 命令一看, 根目录使用了百分百。(这个不是服务器的,是我的实验机)

怎么办?find / -type f -size +100M -print0 | xargs -0 du -h | sort -nr 这个命令查找大于100M的文件,发现/var/lib/docker/containers/容器名称/容器名称-json.log 文件500多g大,然后就使用了错误的命令 rm -rf   文件名  删除了,没想到仍然是磁盘占用百分百,遂重启docker服务,重启容器,仍然是百分百,无奈,重启服务器后恢复正常的磁盘使用。

后面查阅资料发现,日志文件清空一般不是删除rm命令,而是 > 文件名这样的清空方式

那么,docker日志野蛮增长的情况应该如何处理呢?

有如下两个办法,第一,定时任务清空日志,但,该方法治标不治本,第二,限制日志的大小,指定日志只能多大,超过了设定值就不增加。这个方法是通过docker自身的引擎来实现的。可以根除日志无限增长的问题。第三,更改 docker的工作目录到一个磁盘空间多的分区,结合第一个方法,经常性的定时任务清理日志。

那么,第一个方法可以考虑放弃,自然使用最有效率的第二种方法啦。

通常,在centos系列操作系统中,docker是使用systemctl 管理服务的,docker当然也有这么一个服务管理脚本文件,找到它,修改它的工作路径到另一个分区。找这么一个文件也比较简单,

systemctl status docker  输出如下:

vim /etc/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/local/bin/dockerd --graph=/opt/docker
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

比如,现在我将docker的工作目录更改到了 /opt/docker 目录下,然后 重启docker服务,重启命令为 systemctl daemon-reload&&systemctl restart docker

[root@centos11 ~]# cd /opt/docker/
[root@centos11 docker]# ls
builder  buildkit  containerd  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes

将原来的目录移动到新目录下即可,通常原目录为 /var/lib/docker/ ,移动前请先停止docker服务。 然后编写crontab 定时任务,这个就不演示了。移动完毕后在启动docker服务即可。以上是第三种方法结合第一种方法,只是转移日志文件目录并且定期删除日志,这样其实并不好。应该使用第二种方法的哦。

第二种方法限制日志增长,可以分为三种形式,1,全局限制,也就是所有的docker容器统一使用一个限定值,不管是原来已启动的镜像还是以后将要启动的镜像,统统限制日志大小,2,docker run 阶段,某一个容器单独限定日志大小。3,docker-compose 编排启动一组容器时组内每个容器日志限制大小。

全局限制建/etc/docker/daemon.json,若有就不用新建了。添加log-dirver和log-opts参数,

{
  "log-driver":"json-file",
  "log-opts": {"max-size":"500m", "max-file":"3"}
}

max-size=500m,意味着一个容器日志大小上限是500M,max-file=3,意味着一个容器有三个日志,分别是id+.json、id+1.json、id+2.json使用的驱动是json-file驱动,如果是为了试验看到效果,那么max-size的值修改为2M,文件数量修改为1,我试验的时候是使用的mysql镜像,反复重启容器后,很快日志就达到了512k,并且不在继续增长,证明该方法确实可行。

容器run时单独限制

--log-driver json-file --log-opt max-size=10m,比如,将这一段加在docker run 后面,那么以这条命令启动的容器日志将会限定在10m大小,并且使用的日志驱动是json-file。

[root@centos11 ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
hub.c.163.com/library/mysql   latest              9e64176cd8a2        3 years ago         407MB
[root@centos11 ~]# docker run -itd --name mysql1 --log-driver json-file --log-opt max-size=10m -e MYSQL_ROOT_PASSWORD=123456 hub.c.163.com/library/mysql
bf402735afc0d18b0a72c68850a0b1f3579e810594a1bf9267e7183a6c47e379

这个MySQL容器的日志将会保持在10m大小。使用的日志驱动是json-file。

docker-compose 编排文件限制:比如一个nginx容器,限制它的日志大小为2G。

nginx: 
  image: nginx:1.12.1 
  restart: always 
  logging: 
    driver: “json-file” 
    options: 
      max-size: “2g” 

关于时区问题

时区问题是大问题,时间没统一好,业务会乱套。究其原因,大部分 Docker 镜像都是基于 Alpine,Ubuntu,Debian,CentOS 等基础镜像制作而成。基本上都采用 UTC 时间,默认时区为零时区。

1,通过传递环境变量改变容器时区

  • 适用于基于 Debian 基础镜像, CentOS 基础镜像 制作的 Docker 镜像
  • 不适用于基于 Alpine 基础镜像, Ubuntu 基础镜像 制作的 Docker 镜像

比如前面的MySQL镜像这样启动:

root@centos11 ~]# docker run -it --name mysql2 -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=12345 -p 3306:3306 hub.c.163.com/library/mysql /bin/bash
root@d0d8ba4c6135:/# date
Sat Jan 23 16:31:39 CST 2021
root@d0d8ba4c6135:/# exit
[root@centos11 ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
hub.c.163.com/library/mysql   latest              9e64176cd8a2        3 years ago         407M

2,在docker-compose 编排时指定环境变量,同样的只适用于debian系列操作系统镜像,还是以上面所使用的MySQL镜像为例:

version: '3'

services:
  mysql:
    container_name: mysql_57
    image: hub.c.163.com/library/mysql:5.7.18
    restart: always
    environment:
      MYSQL_USER: admin
      MYSQL_PASSWORD: admins
      MYSQL_DATABASE: database
      MYSQL_ROOT_PASSWORD: admin
      TZ: Asia/Shanghai
    volumes:
      - /usr/local/mysql/data:/var/lib/mysql
    ports:
      - 3306:3306
    network_mode: host

3,彻底的解决时区问题,通过dockerfile重新制作镜像

(1). Alpine

将以下代码添加到 Dockerfile 中:

ENV TZ Asia/Shanghai

RUN apk add tzdata && cp /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && apk del tzdata

(2). Debian

Debian 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中:

ENV TZ=Asia/Shanghai \
    DEBIAN_FRONTEND=noninteractive

RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata \
    && rm -rf /var/lib/apt/lists/*

(3). Ubuntu

Ubuntu 基础镜像中没有安装了 tzdata 包,因此我们需要先安装 tzdata 包。

我们可以将以下代码添加到 Dockerfile 中。

ENV TZ=Asia/Shanghai \
    DEBIAN_FRONTEND=noninteractive

RUN apt update \
    && apt install -y tzdata \
    && ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata \
    && rm -rf /var/lib/apt/lists/*

(4). CentOS

CentOS 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中。

ENV TZ Asia/Shanghai

RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone

 

猜你喜欢

转载自blog.csdn.net/alwaysbefine/article/details/113005296