本文的测试环境为CentOS 7.3,Kubernetes集群为1.11.2,安装步骤参见kubeadm安装kubernetes V1.11.1 集群
日志对于我们管理Kubernetes集群及其上的应用具有非常重要的作用,特别是在出现故障或者Bug的时候。如果你能回答下面几个问题,那么可以不用再看本文了,如果不能回答,本文可能正好适合你。
Docker产生的日志有两类:
stdout
和stderr
中,可以通过docker logs
来访问。Docker为容器日志提供了多种实现机制称为logging driver。通过docker info
可以查看本机使用的logging driver,默认为json-file
形式,这种形式下每个容器的日志默认以json格式存储在/var/lib/docker/containers/<容器id>/<容器id>-json.log
下。下面两种情况使用docker logs
看不到什么有用的信息: Docker目前支持的logging driver类型:
运行容器时,可以通过命令行参数指定logging driver的类型。
bogon:log rousseau$ docker run -it --log-driver none alpine sh
/ # ls
#切换一个终端
bogon:log rousseau$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8ec61e8feb61 alpine "sh" 13 seconds ago Up 12 seconds xenodochial_ptolemy
bogon:log rousseau$ docker logs 8ec61e8feb61
Error response from daemon: configured logging driver does not support reading
bogon:log rousseau$ docker inspect -f '{{.HostConfig.LogConfig.Type}}' 8ec61e8feb61
none
对于日志输出到文件的应用,可以通过软连接的方式将日志输出到标准输出和标准错误输出。例如:The official nginx image creates a symbolic link from /var/log/nginx/access.log to /dev/stdout, and creates another symbolic link from /var/log/nginx/error.log to /dev/stderr, overwriting the log files and causing logs to be sent to the relevant special device instead. 对于多行格式的日志信息,有一点需要特别关注。The Docker json logging driver treats each line as a separate message. When using the Docker logging driver, there is no direct support for multi-line messages. You need to handle multi-line messages at the logging agent level or higher.
在CentOS中,可以通过修改/etc/docker/daemon.json
来配置Docker的日志分割策略。
{
"log-driver": "json-file",
"log-opts": {
"max-size": "9m", # Max size of the log files.
"max-file": "5" # The maximum number of log files that can be present.
}
}
总结:对于单机的Docker来说,可以将日志以json-file的形式存储到本地磁盘,同时提供了根据文件大小进行文件分割的配置,也提供了根据文件数量进行文件清理的策略。配置好这两个参数,基本上就不需要担心容器应用将磁盘写满的风险了。而Docker引擎本身的日志则是通过journald来进行管理的。
Kubernetes的日志管理方式与Docker有所不同,因为容器封装在Pod中,当遇到Pod被删除或者Node节点故障的情况下,日志会被删除,单纯依靠Docker本身的日志机制将无法在故障后查询日志,因此在管理集群时需要认真考虑日志的管理问题。
Kubernetes集群的日志包括以下几种:
kubectl describe pod
查看到详细信息Kubernetes集群中包含众多组件,在用kubeadm方式安装的集群上,有些组件不是容器化运行的,包括Master节点的kubelet、kube-scheduler、kube-controller-manager、kube-apiserver,Node节点上运行了kubelet和kube-proxy。有些组件是容器化方式运行的,当然包括我们的应用。因此日志就分为两类:容器化组件及应用的日志,非容器化组件的日志。
对于容器化的组件和应用,其日志的管理方式都通过Docker的log-driver来进行指定,因此Kubernetes本身并不提供日志分割的功能。有两种方式来实现日志的分割:
log-opt
参数,与上一节的方式相同。如果使用外部工具对日志进行了分割,再通过
docker logs
目录查看日志时,仅返回最新的文件中的内容。
系统组件也分为两种,一种是运行在容器中的应用,包括scheduler
、kube-proxy
等;一种是没有运行在容器中的应用,包括kubelet
和容器运行环境。这些组件的日志都是通过journald
来进行管理的。
Kubernetes本身没有提供集群级别的日志管理功能,如想实现集群级别的日志管理有三种方案:
这种方案在每台Node上运行一个专用的日志采集代理,可以是容器化的应用(需要能够在容器内访问节点上的日志文件),可以采用DaemonSet
来确保代理在每个Node中都运行。
Sidecar的本意是挎斗摩托车,这种车型在摩托车旁边加了一个边斗来提高运载量,是二战时期日军广泛使用的一种运输工具。
类似于挎斗摩托车,Sidecar方案是在应用Pod中增加一个或多个负责处理日志的容器,根据增加容器的作用,可以分为日志分离和容器内代理。
尽管CPU和内存资源的消耗非常少,但是读取日志文件并且重写到标准输出会加倍磁盘的负载,这一点需要特别注意。
采用这种方案,通过容器内代理直接将应用的日志上传到统一的日志管理平台,会增加Pod的资源消耗,同时无法通过kubectl logs
命令来查看日志。