概述
作者:正范
链接:https://kaiwu.lagou.com/course/courseInfo.htm?sid=&courseId=447&lagoufrom=noapp&wxinfo=2#/detail/pc?id=4517
说到日志,你应该不陌生。日志中不仅记录了代码运行的实时轨迹,往往还包含着一些关键的数据、错误信息,等等。日志方便我们进行分析统计及监控告警,尤其是在后期问题排查的时候,我们通过日志可以很方便地定位问题、现场复现及问题修复。日志也是做可观测性(Observability)必不可少的一部分。
因此在使用 Kubernetes 的过程中,对应的日志收集也是我们不得不考虑的问题。我们需要日志去了解集群内部的运行状况。
我们先来看看 Kubernetes 的日志收集和以往的日志收集有什么差别,以及为什么我们需要为 Kubernetes 的日志收集单独设计方案。
Kubernetes 中的日志收集 VS 传统日志收集
对于传统的应用来说,它们大都都是直接运行在宿主机上的,会将日志直接写入本地的文件中或者由 systemd-journald 直接管理。在做日志收集的时候,只需要访问这些日志所在的目录即可。此类日志系统解决方案非常多,也相对比较成熟,在这里就不再过多说明。
我们重点来看看 Kubernetes 的日志系统建设问题。
在 Kubernetes 中,日志采集相比传统虚拟机、物理机方式要复杂很多。
首先,日志的形式非常多样化,日志需求主要集中在如下三个部分:
系统各组件的日志,比如 Kubernetes 自身各大组件的日志(包括 kubelet、kube-proxy 等),容器运行时的日志(比如 Docker);
以容器化方式运行的应用程序自身的日志,比如 Nginx、Tomcat 的运行日志;
Kubernetes 内部各种 Event(事件),比如通过kubebctl create创建一个 Pod 后,可以通过kubectl describe pod pod-xxx命令查看到的这个 Pod 的 Event 信息。
其次,集群环境时刻在动态变化。我们都知道 Pod “用完即焚”,Pod 销毁后日志也会一同被删除。但是这个时候我们仍然希望可以看到具体的日志,用于查看和分析业务的运行情况,以及帮助我们发现出容器异常的原因。
同时新的 Pod 可能随时会 “飘” 到别的节点上重新 “生长” 出来,我们无法提前预知具体是哪个节点。而且 Kubernetes 的节点也会存在宕机等异常情况。所以说,Kubernetes 的日志系统在设计的时候,必须得独立于节点和 Pod 的生命周期,且保证日志数据可以实时采集到服务端,即完全独立于 Kubernetes 系统,使用自己的后端存储和查询工具。
再次,日志规模会越来越大。很多人在 Kubernetes 中喜欢使用 hostpath 来保存 Pod 的日志,并且不做日志轮转(可以配置 Docker 的log-opts来设置容器的日志轮转 ),这很容易将宿主机的磁盘“打爆”。这里你是不是觉得如果做了轮转,磁盘打爆的问题就可以完美解决了?
其实虽有所缓解,并不会让你安全无忧。虽说日志轮转可以有效减少日志的文件大小,但是你会丢失掉不少日志,后续想要分析和排查问题时就无从下手了。想想看如果容器内的应用出现异常并疯狂报错,这个时候又有大量的并发请求,那么日志就会急剧增多。
配置了日志轮转,会让你丢失很多重要的上下文信息。如果没有配置日志轮转,这些日志很快就会将磁盘打爆。还有可能引发该节点的 Kubelet 异常,导致该节点上的 Pod 被驱逐。我们在一些生产实践中,就遇到过这种情况。同时当 Pod 被删除后,这些 hostpath 的文件并不会被及时删除,会继续占用很多磁盘空间。此外,随着业务逐渐增长,在这个节点上运行过的 Pod 也会变多,这就会残留大量的日志文件。
此外,日志非常分散且种类多变。单纯查找一个应用的日志,就需要查看其关联的分散在各个节点上的各个 Pod 的日志。在出现紧急情况需要排查的时候,这种方式极其低效,会严重影响到问题修复和服务恢复。如果这个应用还通过 Ingress 对外暴露服务,并使用了 Service Mesh 等,那么此时做日志收集就更复杂了。
随着在 Kubernetes 上落地越来越多的微服务,各个服务之间的依赖也越来越多。这个时候各个维度的日志关联也是一个非常困难的问题。那么,下面我们就来看看如何对 Kubernetes 做日志收集。
几种常见的 Kubernetes 日志收集架构
Kubernetes 集群本身其实并没有提供日志收集的解决方案,但依赖 Kubernetes 自身提供的各项能力,可以帮助我们解决日志收集的诉求。根据上面提到的三大基本日志需求,一般来说我们有如下有三种方案来做日志收集:
直接在应用程序中将日志信息推送到采集后端;
在节点上运行一个 Agent 来采集节点级别的日志;
在应用的 Pod 内使用一个 Sidecar 容器来收集应用日志。
我们来分别看看这三种方式。
先来看直接在应用程序中将日志信息推送到采集后端,即Pod 内的应用直接将日志写到后端的日志中心。
(https://github.com/kubernetes/website/blob/master/static/images/docs/user-guide/logging/logging-from-application.png)
通常有两种做法,一个就是应用程序通过对应的日志 SDK 进行接入,不过这种做法一般不推荐,和应用本身耦合太严重,也不方便后续对接其他的日志系统。
还有一种做法就是通过容器运行时提供的 Logging Driver 来实现。以最常用的 Docker 为例,目前已经支持了十多种 Logging Driver (https://docs.docker.com/config/containers/logging/configure/#supported-logging-drivers)。比如你可以配置为fluentd,这个时候 Docker 就会将容器的标准输出日志(stdout、stderr)直接写到fluentd中。你也可以设置成awslogs,这样就会直接将日志写到 Amazon CloudWatch Logs 中。但是在和 Kubernetes 一起使用的时候,使用较多的是json-file,这也是 Docker 默认的 Logging Driver。
$ docker info |grep 'Logging Driver'Logging Driver: json-file
你经常使用的kubectl logs就是基于json-flle这种 Logging Driver 来实现的,目前 Kubernetes 也只支持json-flle这一种 Logging Driver。
所以在 Kubernetes 的这套体系中,直接将日志写到后端日志采集系统中去,并不是特别好的做法。
我们来看第二种方法,在节点上运行一个 Agent 来采集节点级别的日志。如下图所示,我们可以在每一个 Kubernetes Node 上都部署一个 Agent,该 Agent 负责对该节点上运行的所有容器进行日志收集,并推送到后端的日志存储系统里。这个 Agent 通常需要可以访问到宿主机上的指定目录,比如/var/lib/docker/containers/。
(https://github.com/kubernetes/website/blob/master/static/images/docs/user-guide/logging/logging-with-node-agent.png)
由于这样的 Agent 需要在每个 Node 上都运行,因此我们都是通过 上节课讲到的DaemonSet的方式来部署的。对于 Kubernetes 集群来说,这种使用节点级的DaemonSet日志代理是最常用,也是最被推荐的方式,不仅可以节约资源,而且对于应用来说也是无侵入的。
但是这种方式也有个缺点,就是只适应于容器内应用日志是标准输出的场景,即应用把日志输出到stdout和stderr。
最后来看通过 Sidecar 来收集容器日志。在 Pod 里面,容器的输出日志可以是stdout、stderr和日志文件。那么基于这三种形式,我们可以借助于 Sidecar 容器
将基于文件的日志来帮助我们。
通过 Sidecar 容器读取日志文件,并定向到自己的标准输出。如下图所示,这里streaming container就是一个 Sidecar 容器,可以将app-container的日志文件重新定向到自己的标准输出。同时还可以归并多个日志文件。而且这里也可以使用多个 Sidecar 容器,你可以参考这个例子。
Sidecar容器运行一个日志代理,配置该日志代理以便从应用容器收集日志。这种方式就解决了我们上面方案一的问题,将日志处理部分和应用程序本身进行了解耦,可以方便切换到其他的日志系统中。可以参考这个使用 fluentd 的例子。https://github.com/kubernetes/website/blob/master/content/en/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml
(https://github.com/kubernetes/website/blob/master/static/images/docs/user-guide/logging/logging-with-sidecar-agent.png)
可以看到,通过 Sidecar 的方式来收集日志,会增加额外的开销。在集群规模较小的情况下可以忽略不计,但是对于大规模集群来说,这些开销还是不可忽略的。
那么,上面的这几套方案,在实际使用的时候,又该如何选择呢?社区又有什么推荐方案呢?
基于 Fluentd + ElasticSearch 的日志收集方案
Kubernetes 社区官方推荐的方案是使用 Fluentd + ElasticSearch + Kibana 进行日志的收集和管理 ,通过Fluentd将日志导入到Elasticsearch中,用户可以通过Kibana来查看到所有的日志。
(https://docs.fluentd.org/container-deployment/kubernetes)
关于 ElasticSearch 和 Kibana 如何部署,在此就不过多地介绍了,你可以通过添加 helm 的 repo即 helm repo add elastic https://helm.elastic.co ,然后通过 helm来快速地自行部署,相关的 Chart 见https://github.com/elastic/helm-charts。
现在我们就来看看这套方案的几个技术点。
Fluentd 提供了强大的日志统一接入能力,同时内置了插件,可以对接 ElasticSearch。这里 Fluentd 主要有如下四个配置:
fluent.conf 这个文件主要是用来设置一些地址,比如 ElasticSearch 的地址等;.
kubernetes.conf 这个文件记录了与 Kubernetes 相关的配置,比如 Kubernetes 各组件的日志配置、容器的日志收集规则,等等;
prometheus.conf 这个文件定义了 Prometheus 的地址,方便 Fluentd 暴露自己的统计指标;
systemd.conf 这个文件可以配置 Fluentd 通过 systemd-journal 来收集哪些服务的日志,比如 Docker 的日志、Kubelet 的日志等。
上面的这些配置,都默认内置到了 fluent/fluentd-kubernetes-daemonset的镜像中,你可以使用官方的默认配置。如果你想要定制化更改一些,可以参照这份默认示例配置。
如下的 YAML 是一段 fluentd 的 DaemonSet 定义,源自这里:
https://github.com/fluent/fluentd-kubernetes-daemonset/blob/master/fluentd-daemonset-elasticsearch.yaml
apiVersion: apps/v1kind: DaemonSetmetadata: name: fluentd namespace: kube-system labels: k8s-app: fluentd-logging version: v1spec: selector: matchLabels: k8s-app: fluentd-logging version: v1 template: metadata: labels: k8s-app: fluentd-logging version: v1 spec: tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch-logging" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" # Option to configure elasticsearch plugin with self signed certs # ================================================================ - name: FLUENT_ELASTICSEARCH_SSL_VERIFY value: "true" # Option to configure elasticsearch plugin with tls # ================================================================ - name: FLUENT_ELASTICSEARCH_SSL_VERSION value: "TLSv1_2" # X-Pack Authentication # ===================== - name: FLUENT_ELASTICSEARCH_USER value: "elastic" - name: FLUENT_ELASTICSEARCH_PASSWORD value: "changeme" # Logz.io Authentication # ====================== - name: LOGZIO_TOKEN value: "ThisIsASuperLongToken" - name: LOGZIO_LOGTYPE value: "kubernetes" resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers
写在最后
在实际采集日志的时候,你可以根据自己的场景和集群规模选择适用的方案。或者也可以将上面的这几种方案进行合理地组合。
往期文章
Kubernetes部署篇
Kubernetes 1.18.2集群部署 (单Master)+docker—kubeadm方式
Kubernetes 1.18.2集群部署 (多Master)+docker—kubeadm方式
Kubernetes 1.18.2集群部署 (多Master)+docker—二进制方式
Kubernetes 1.18.2集群部署 (单Master)+docker—shell脚本方式
Kubernetes 1.19.0集群部署 (多Master)+docker—kubeadm方式
Kubernetes 1.19.0集群部署 (多Master)+docker—二进制方式
Kubernetes 一条命令快速部署 Kubernetes 高可用集群—sealos
Kubernetes 一条命令快速部署 Kubernetes 高可用集群—kubei
Kubernetes Harbor v2.0.0私有镜像仓库部署
Kubernetes Harbor v2.0.2高可用私有镜像仓库部署
Kubernetes kubectx/kubens切换context和namespace
Kubernetes kubeadm更新一个10年有效期的证书
Kubernetes kubeadm初始化kubernetes集群延长证书过期时间
Kubernetes kubeadm升级集群
Kubernetes kubeadm基础使用
Kubernetes基础篇
Kubernetes 是什么?
Kubernetes 基础概念
Kubernetes 从零开始了解
Kubernetes 快速了解Kubernetes
Kubernetes kubectl命令
Kubernetes kubectl常用命令
Kubernetes kubectl常用命令大全
Kubernetes 创建、更新应用
Kubernetes 资源清单
Kubernetes Pod状态和生命周期管理
Kubernetes Pod Controller
Kubernetes ReplicaSet Controller
Kubernetes Deployment Controller
Kubernetes DamonSet Controller
Kubernetes Job、CronJob Controller
Kubernetes HPA Controller
Kubernetes HPA Controller 使用详解
Kubernetes KEDA基于Kubernetes事件驱动的自动缩放
Kubernetes 服务发现—Service
Kubernetes 内部服务发现—Coredns
Kubernetes 外部服务发现—Traefik ingress
Kubernetes 外部服务发现—Nginx Ingress Controller
Kubernetes 存储卷—Volumes
Kubernetes 存储卷—部署NFS服务器,供给静态pv和动态pv
Kubernetes 存储卷—PV和PVC的状态变化
Kubernetes 特殊存储卷—Secret和ConfigMap
Kubernetes StatefulSet Controller
Kubernetes 认证、授权和准入控制
Kubernetes dashboard认证访问-更新
Kubernetes 网络模型和网络策略
Kubernetes 网络原理解析
Kubernetes 网络插件-flannel
Kubernetes 网络插件-calico
Kubernetes Pod资源调度
Kubernetes 资源指标和集群监控
Kubernetes 容器云平台技术落地方案
Kubernetes v1.19.0 正式发布
Kubernetes Ratel自动生成yaml文件
Kubernetes 部署策略详解
Kubernetes 集群规模应该有多大?
Kubernetes 集群备份/恢复velero实战
Kubernetes 集群备份/恢复etcd数据实战
Kubernetes基础篇—Kubernetes 原理剖析与实战应用
Kubernetes 如何深入掌握 Kubernetes
Kubernetes 如何火起来的
Kubernetes 架构为什么是这样的
Kubernetes 集群搭建
Kubernetes 是如何搞定“不可变基础设施”的
Kubernetes Pod:最小调度单元的使用进阶及实践
Kubernetes 无状态应用:剖析K8S业务副本及水平扩展底层原理
Kubernetes 有状态应用:K8S如何通过 StatefulSet 支持有状态应用
Kubernetes 配置管理:K8S管理业务配置方式有哪些
Kubernetes 存储类型:如何挑选合适的存储插件
Kubernetes 存储管理:怎样对业务数据进行持久化存储
Kubernetes Service:轻松搞定服务发现和负载均衡
Kubernetes Helm Charts:如何在生产环境中释放部署生产力
Kubernetes基础篇—Kubernetes 入门到实战
Kubernetes 入门到实战(一)俯瞰kubernetes全貌
Kubernetes 入门到实战(二)kubeadm部署kubernetes集群
Kubernetes 入门到实战(三)kubernetes快速入门
Kubernetes 入门到实战(四)kubernetes dashboard图形界面
Kubernetes 入门到实战(五)深入浅出详解Pod
Kubernetes 入门到实战(六)资源管理和服务质量
Kubernetes 入门到实战(七)深入玩转pod调度
Kubernetes 入门到实战(八)Pod健康检查机制
Kubernetes 入门到实战(九)初识Pod存储管理
Kubernetes 入门到实战(十)深入学习持久化存储PV和PVC
Kubernetes 入门到实战(十一)深入学习Deployment控制器
Kubernetes 入门到实战(十二)详解DaemonSet控制器
Kubernetes 入门到实战(十三)一次性任务Job和周期任务
Kubernetes 入门到实战(十四)statefulset(待续)
Kubernetes 入门到实战(十五)services的实现(待续)
Kubernetes 入门到实战(十六)基于nginx ingress实现服务暴露
Kubernetes 入门到实战 (十七) 基于haproxy实现ingress服务暴露
Kubernetes 入门到实战 (十八) 使用metric-server让HPA弹性伸缩愉快运行
Kubernetes 入门到实战 (十九) prometheus提供完备监控系统
Kubernetes应用部署篇
Kubernetes 部署WordPress博客
Kubernetes 部署Nginx+php-fpm+MySQL并运行Discuz
Kubernetes 使用StatefulSet部署MySQL高可用集群
Kubernetes 使用StatefulSet部署MongoDB高可用集群
Kubernetes 包管理工具—Helm2.13安装和使用
Kubernetes Helm2部署gitlab私有代码仓库
Kubernetes Helm2部署MySQL数据库
Kubernetes 包管理工具—Helm3.3安装和使用
Kubernetes Helm3部署MySQL数据库
Kubernetes Helm3部署kubernetes-dashboard
Kubernetes Helm3部署nginx-ingress NodePort方式
Kubernetes Helm3部署nginx-ingress LoadBalancer方式
Kubernetes监控篇
Kubernetes 部署Prometheus+Grafana+Alertmanager监控告警系统
Kubernetes Prometheus监控Nginx
Kubernetes Prometheus监控MySQL
Kubernetes Prometheus监控tomcat
Kubernetes 部署kube-prometheus监控告警系统
Kubernetes kube-prometheus中添加自定义监控项-监控etcd
Kubernetes kube-prometheus监控指标targets
Kubernetes kube-prometheus配置kubernetes-cadvisor服务自动发现
Kubernetes kube-prometheus Configuration信息
Kubernetes kube-prometheus中添加自定义监控项-监控MySQL
Kubernetes Grafana匿名登录/密码登录Kubernetes
Kubernetes Grafana迁移(导出导入)dashboard
Kubernetes Grafana数据持久化
Kubernetes日志篇
Kubernetes 使用Elastic Stack构建Kubernetes全栈监控
Kubernetes 日志架构
Kubernetes 使用 Loki 进行日志监控和报警
Kubernetes故障排除篇
Kubernetes 删除namespace时卡在Terminating状态
Kubernetes deploy,rs,sts Mismatch 的处理
Kubernetes master机器文件系统故障恢复过程
Kubernetes 如何修改容器时间而不改变宿主机时间?
Kubernetes面试问题篇
Kubernetes IT运维面试问题总结-简述Etcd、Kubernetes、Lvs、HAProxy等
Kubernetes 50个必须了解的Kubernetes面试问题
Kubernetes 面试题汇总1
Kubernetes 面试题汇总2
最后
以上就是笨笨白云为你收集整理的file_get_contents采集https报错_Kubernetes 日志采集:如何在 Kubernetes 中做日志收集与管理...往期文章的全部内容,希望文章能够帮你解决file_get_contents采集https报错_Kubernetes 日志采集:如何在 Kubernetes 中做日志收集与管理...往期文章所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复