3、日志采集基础:如何通过 Sidecar 或 DaemonSet 采集 CoreDNS 日志到 ELK/Loki
CoreDNS 作为 Kubernetes 集群的 DNS 核心组件,其日志是排查服务发现异常、域名解析超时、缓存污染等问题的第一手数据。在生产环境中,CoreDNS 通常以 Deployment 形式运行,日志采集方案需兼顾资源开销、采集可靠性与运维复杂度。本章聚焦两种主流采集模式:Sidecar(每个 Pod 内伴生采集器)与 DaemonSet(节点级采集代理),并分别给出输出到 ELK(Elasticsearch + Logstash + Kibana)与 Loki 的完整链路。
3.1 采集架构总览
下图展示了两种采集模式在 Kubernetes 集群中的部署位置与数据流向。Sidecar 模式将采集器注入 CoreDNS Pod 内,与容器共享日志文件;DaemonSet 模式则在每个节点上运行采集代理,通过挂载宿主机路径或 CRI 接口获取日志。
3.2 Sidecar 模式:精准采集,隔离性强
Sidecar 模式在 CoreDNS 的 Deployment 定义中额外添加一个日志采集容器(如 Filebeat、Fluent Bit),两个容器共享一个 emptyDir 卷。CoreDNS 容器将日志写入共享卷,采集容器读取并转发。此模式适用于对日志格式有定制需求、或需要避免节点级采集器干扰的场景。
3.2.1 部署示例:CoreDNS + Filebeat Sidecar
以下 YAML 片段展示了在 CoreDNS Deployment 中注入 Filebeat Sidecar 的核心配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
spec:
template:
spec:
containers:
- name: coredns
image: coredns/coredns:1.11.1
args: [ "-conf", "/etc/coredns/Corefile" ]
volumeMounts:
- name: log-volume
mountPath: /var/log/coredns
- name: filebeat
image: docker.elastic.co/beats/filebeat:8.12.0
args: [ "-c", "/etc/filebeat.yml", "-e" ]
volumeMounts:
- name: log-volume
mountPath: /var/log/coredns
readOnly: true
- name: filebeat-config
mountPath: /etc/filebeat.yml
subPath: filebeat.yml
volumes:
- name: log-volume
emptyDir: {}
- name: filebeat-config
configMap:
name: filebeat-config
3.2.2 Filebeat 配置要点
Filebeat 的配置文件需指定输入源为共享卷中的日志文件,并设置多行合并规则以处理 CoreDNS 的堆栈日志:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/coredns/*.log
multiline.pattern: '^\d{4}-\d{2}-\d{2}'
multiline.negate: true
multiline.match: after
output.elasticsearch:
hosts: ["http://elasticsearch:9200"]
index: "coredns-%{+yyyy.MM.dd}"
# 若输出到 Loki,则使用 output.logstash 或 elasticsearch 的 Loki 插件
log 插件配置 output file /var/log/coredns/access.log 并设置 format json),便于采集器直接解析结构化字段,减少后续 Logstash 或 Loki 的解析开销。
3.3 DaemonSet 模式:零侵入,运维简单
DaemonSet 模式在每个节点上部署一个日志采集代理(如 Fluentd、Logstash),通过挂载宿主机 /var/log/pods 或 /var/log/containers 路径读取所有 Pod 的日志。CoreDNS 的日志文件位于 /var/log/pods/kube-system_coredns-* 下,采集器通过路径匹配或 Kubernetes 元数据过滤获取。
3.3.1 部署示例:Fluentd DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.16-debian-elasticsearch
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
volumeMounts:
- name: varlog
mountPath: /var/log
- name: dockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: dockercontainers
hostPath:
path: /var/lib/docker/containers
3.3.2 Fluentd 配置:过滤 CoreDNS 日志
在 Fluentd 的配置中,使用 @label 和 kubernetes_metadata 插件过滤出 CoreDNS 的日志流:
<source>
@type tail
path /var/log/containers/coredns-*.log
pos_file /var/log/fluentd-coredns.pos
tag kubernetes.coredns.*
format json
read_from_head true
</source>
<filter kubernetes.coredns.*>
@type kubernetes_metadata
</filter>
<match kubernetes.coredns.*>
@type elasticsearch
host "#{ENV['FLUENT_ELASTICSEARCH_HOST']}"
port "#{ENV['FLUENT_ELASTICSEARCH_PORT']}"
index_name coredns
<buffer>
flush_interval 5s
</buffer>
</match>
3.4 两种模式对比与选型
| 对比维度 | Sidecar 模式 | DaemonSet 模式 |
|---|---|---|
| 资源开销 | 每个 CoreDNS Pod 额外占用 1 个采集容器(约 50-100MB 内存) | 每个节点 1 个采集代理,节点数远少于 Pod 数时更省资源 |
| 采集隔离性 | 高,采集器故障不影响其他 Pod | 低,节点级采集器故障影响该节点所有 Pod 日志 |
| 部署复杂度 | 需修改 CoreDNS Deployment,注入 Sidecar 容器与 ConfigMap | 独立部署 DaemonSet,无需修改 CoreDNS |
| 日志格式灵活性 | 高,可在 Sidecar 内定制解析逻辑 | 中,需通过标签或路径过滤,可能采集到无关日志 |
| 适用场景 | CoreDNS 日志格式特殊、需独立处理;集群规模较小 | 大规模集群、希望统一管理所有日志采集 |
3.5 输出到 ELK 与 Loki 的差异
无论采用哪种采集模式,最终日志都会发送到后端存储。ELK 与 Loki 在日志存储、查询方式上存在本质区别,直接影响采集器的输出配置:
| 特性 | ELK (Elasticsearch + Logstash + Kibana) | Loki (Grafana Loki) |
|---|---|---|
| 存储模型 | 全文索引,存储原始日志与倒排索引 | 仅压缩存储日志内容,索引元数据(标签) |
| 采集器输出协议 | HTTP Bulk API / Logstash 输出插件 | HTTP Push API (Promtail 原生支持) |
| 日志解析位置 | Logstash 或采集器端解析为结构化字段 | 采集器端(Promtail)或查询时(LogQL)解析 |
| 查询语言 | Kibana Query Language (KQL) / Lucene | LogQL(类 PromQL 语法) |
| 资源消耗 | 高(索引写入与存储开销大) | 低(无索引,存储成本低) |
| 适用场景 | 需要复杂全文搜索、聚合分析、历史趋势 | 快速日志检索、与 Prometheus 指标关联、成本敏感 |
3.6 输出到 Loki 的采集配置示例(Promtail)
若选择 Loki 作为日志后端,推荐使用 Promtail 作为采集器。以下为 Promtail 的 Sidecar 配置片段,直接输出到 Loki:
# promtail-config.yaml
scrape_configs:
- job_name: coredns
static_configs:
- targets: [localhost]
labels:
job: coredns
namespace: kube-system
__path__: /var/log/coredns/*.log
pipeline_stages:
- regex:
expression: '^(?P<time>\S+)\s+(?P<level>\S+)\s+(?P<msg>.*)'
- labels:
level:
- timestamp:
source: time
format: RFC3339
clients:
- url: http://loki:3100/loki/api/v1/push
level、query_type、rcode),以便在 LogQL 中高效过滤。避免将高基数字段(如客户端 IP)直接作为标签,否则会导致索引膨胀。
3.7 日志采集的可靠性保障
无论采用 Sidecar 还是 DaemonSet,都需要考虑以下可靠性措施:
- 日志轮转兼容:CoreDNS 默认不轮转日志,建议在 Corefile 中配置
log插件的rotate参数,或依赖容器运行时(如 containerd)的日志轮转策略。采集器需支持copytruncate或inode跟踪。 - 断点续传:Filebeat 和 Fluentd 均支持
registry/position文件,记录已读取的偏移量。确保这些文件存储在持久卷或 hostPath 上,避免 Pod 重启后重复采集。 - 背压与缓冲:当后端(Elasticsearch / Loki)不可用时,采集器应具备本地缓冲能力。Filebeat 使用
queue.mem,Fluentd 使用buffer插件,Promtail 使用client的buffer配置。 - 监控采集器自身:为采集器暴露 Prometheus 指标(如
filebeat_input_events、fluentd_output_status_buffer_queue_length),纳入可观测性体系。