问题描述
多种多样的日志:
1)应用程序具有日志,用于排查问题;
2)集群具有日志,用于排查问题;
3)容器环境具有日志机制,容器化应用应将日志写入标准输出与标准错误;
但这些日志机制存在问题:
1)容器引擎提供的日志功能远远不够:容器崩溃,驱逐 POD 实例,节点崩溃,在这些情况下我们依旧希望访问日志。所以日志需要独立存储,并且生命周期与节点、容器等等无关;
该概念被称为“集群日志”。“集群日志”需要单独存储,但是 Kubernetes 并没有提供日志后端存储,需要我们自己集成;
该笔记将记录:与 Kubernetes Cluster 日志有关内容,包括日志种类、收集方法等等,及相关问题的解决办法。该笔记结合官方 Logging Architecture 文档,整理与日志有关内容;
解决方案
在 Kubernetes Cluster 中,需要处理的日志分为以下几种:
1)容器外日志:kubelet、Docker
2)容器内日志:(已写标准输入、标准错误)容器应用程序,包括集群组件(比如 kube-porxy,etcd 等等)
3)容器内日志:(未写标准输入、标准错误)容器应用应用,写入容器本地
使用 DaemonSet 运行 POD 实例,在节点中收集日志;
写入标准输出的日志
使用 kubectl logs 查看日志,添加–previous 选项查看已崩溃容器的日志;
如果在 POD 实例中具有容器,可以指定容器名查看特定容器日志;
节点级日志类型
应用程序日志
由容器应用写入标准输出与标准错误的日志,会被容器引擎重定向。例如在 Docker 中,由日志驱动处理(在 Kubernetes 中,被配置写入 JSON 格式的文件中);
注意,使用 Docker 日志驱动无法处理多行日志,需要在日志收集工具中进行处理;
如果容器重启,则 kubelet 会保存单个容器及它的日志。若驱逐 POD 实例,所有对应的容器将被驱逐,包括日志;
另外节点日志还要考虑轮转问题,防止日志消耗过多磁盘。但是 Kubernetes 当前不负责日志轮转,这个问题应该由容器应用处理。另外可以可以配置容器环境处理日志轮转,例如使用 Docker 的--log-opt选项;
当执行 kubectl logs 时,由对应节点的 kubelet 响应,直接读取日志文件。注意,如果外部系统执行轮转,日志截断为多个文件时,则 kubectl logs 只能读取组后一个文件;
系统组件日志
系统组件也有日志,但是分为两类:(1)运行在容器内的组件;(2)运行在容器外的组件;
运行在容器外的组件,例如 kubelet 及 Docker 等等:如果使用 systemd 管理,则日志写入 journald 中;如果未使用 systemd 管理,则日志写入 /var/log 中;
运行在容器内的组件,例如 kube-proxy 或 scheduler 等等:使用默认日志机制,将日志写入 /var/log 中;
同样,写入 /var/log 中的日志也需要轮转;
集群级日志的解决方案
由于 Kubernetes 没有提供集群日志解决方案,有以下集中途径解决:
使用专用容器(Sidecar),收集应用程序日志
从应用程序中直接将日志写入后端日志存储
下面我们将简述各种解决方法
使用节点日志代理
以 DeamonSet 在每个节点运行 POD 实例,用于直接读取日志文件。但是这只适用于将日志写入标准错误与标准输出的容器;
常用解决方案有 Elasticsaerch+Fluentd 服务;
使用专用容器(Sidecar)
使用 Sidecar 容器(与应用容器处于相同 POD 实例的容器),有两种方式:(1)Sidecar 容器将应用日志“流入”自己的标准输出;(2)Sidecar 容器运行日志代理,收集应用程序日志;
# 流式 Sidecar 容器:
当 Sidecar 容器使用自身的标准错误与标准输出时,可以利用 kubelet 与每个节点的日志代理。Sidecar 容器可以读取文件、套接字、journald,然后将日志写入自己的标准错误、标准输出中;
这种方法可以从应用程序不同部分中分离出不同的日志流,即使有些应用程序可能不支持写入标准输入、与标准输出。日志重定向每次只需要处理很小日志,因此不会出现过渡的开销。另外由于 Sidecar 的标准输出与标准错误与 kubelet 处理,因此可以通过 kubectl logs 查看日志;
虽然 Sidecar 是额外的容器,但是它可以简单到只运行 tail 命令。Sidecar 是一种涉及模式;
另外节点级日志代理会自动处理日志,无需进一步配置。还可以配置收集代理来根据“源容器”日志类型进行解析;
尽管 CPU 使用降低,但是会增加磁盘使用量。如果你的应用程序需要将日志写入文件,那尽量写入到标准输出中,而不是使用 Sidecar 容器处理;
# 带有日志代理的 Sidecar 容器:
如果节点级日志代理无法满足需求,可以运行在 Sidecar 容器中运行日志收集代理。该代理可以经过配置,适用于特定应用程序。但是该类型的 Sidecar 会消耗更多资源,并且不能使用 kubectl logs 查看日志;
直接暴露日志
最后一种方法是将日志直接写入后端存储,这是一种日志存储方案,但是与 Kubernetes 集群的关系并不大,这里不再讨论;
Using Elasticsearch/Fluentd/Kibana (EFK) on Minikube
如何以集中的方式査看集群中所有应用的日志?
可以使用 Elasticsearch + Fluentd + Kibana,具体内容如下;
首先,为了做好准备,请确保为 Minitube 分配了足够的资源。例如,使用–cpus=4 –memory=4000,并确保 ingress 插件已被激活;
# minitube addons list | grep ingress
# minikube addons enable ingress
接下来,创建名为 efk-logging.yaml 的清单文件,跳过……
现在可以启动 EFK 了: kubectl create -f efk-logging.yaml
所有应用都启动以后,所有应用都启动以后,可以利用下面的用户名和密码登录 Kiana,用户名: kiana;密码: changer
打开“https://$IP/app/kiana#/discover?_g=()”,并单击 Discover 页签,就可以看到日志了;
可以使用下列命令清理或重启 EFK 栈
kubectl delete deploy/kiana && \
kubectl delete svc/elasticsearch && \
kubectl delete svc/kiana &&\
kubectl delete Ingress/Kibana-public && \
kubectl delete daemonset/fluent
通过 Logstash 也可以査看日志。我们在解決方案中选择使用 Fluent,是因为它是云原生计算基金会( Cloud Native Computing Foundation,CNCF)的项日且备受关注;
请注意启动 Kiana 需要花费一定的花时间,而且可能需要反复加载几次该网络应用才能完成配置;
Manoj Bhagwat 的博文“在 Kubernetes 上利用 Fluent 和 Elasticsearch 集中管理 Docker 日志
hrps://ediun.com%E2%91%A1nano/.bhaga60ocentralize-your-docker-logs-with-fluenid-and-elasticsearch-on-kubernetes42d2acOe8b6c
Kubernetes 基于 AWS 的 EFK 機
https://github.com/skillshare/kubernetes-elk
Elk-kubernetes https://github.com/kayrus/elk-kubernetes
容器日志采集
连续性 Pod 日志采集(Grafana Loki)
问题描述:随着 Pod 的重启、驱逐、调度,Pod 的名称可能会发生变化。但是这些 Pod 都属于用一个应用,我们希望能够连续显示这些 Pod 的日志(放在一起),而不是选择不同的 Pod 来查看各自的日志。
最开始,我们期望通过 app.kubernetes.io/instance 标签来归类 Pod 实例:这就需要应用程序的支持,在部署应用时添加特定标签。但是在 Pod 多实例的场景中,这些 Pod 具有相同的标签。如果仅通过 Pod Label 来标注,这将导致 Pod 的日志混合在一起。如果要进行区分,则由要引入 Pod 名称进行区分。
想到这里,我们就发现,无法将 Pod Log 连接在一起(主要原因还是 Pod 能够同时以多实例运行)。所以在查看日志时,必须选择不同的 Pod 实例。
或者,能够得到 Pod 的创建时间也可以:连续性并非我们的最终目的,我们是期望了解到 Deployment 的 Pod 随着时间的变化。
若不可行,则只能结合 Controller Name 来对 Kubernetes Event 进行分析,以此找到 Pod 的变化过程:
1)通过 Controler Name 来抓取与之相关的 Kubernetes Event 信息;
2)针对 Kubernetes Event 分析,提取 Pod Name的变换、相关时间、所在节点等等信息;
3)根据 Kubernetes Event 时间,对 Pod Name 以列表的方式在 Dashboard 中进行展示;
参考文献