使用 Vector 将日志转换为 JSON 并添加 Kubernetes Pod 标签?
解读
在国内云原生面试中,这道题表面问“日志转 JSON”,实则考察是否能把非结构化日志与 Kubernetes 元数据打通并落地到 CouchDB。
Vector 作为 CNCF 毕业项目,已大量替代 Logstash/Fluent Bit,面试官想确认:
- 你熟悉 Vector 的 transform 阶段 能否完成正则→JSON 的解析;
- 你能否利用 kubernetes_logs source 自动注入 Pod 标签;
- 最终写入 CouchDB 时,如何构造 _id 与 _rev 以避免写冲突;
- 是否考虑离线场景(边缘节点断网续传)与多主复制带来的幂等性要求。
知识点
- Vector 的 remap (VRL) 语言:parse_regex、parse_json、merge 函数
- kubernetes_logs source 内置字段:kubernetes.pod_labels、kubernetes.pod_namespace、kubernetes.pod_name
- CouchDB bulk docs API 与 _bulk_get 的幂等写入策略
- 国内主流镜像站(阿里云、DaoCloud)拉取 timberio/vector 镜像的加速配置
- 离线优先场景下,Vector 的 disk_buffer 与 CouchDB 的 _local 文档协同做断点续传
- 多主复制时,_id 必须包含宿主机+Pod UUID+时间戳 避免不同边缘节点冲突
答案
- 部署 Vector DaemonSet,使用国内镜像
registry.cn-hangzhou.aliyuncs.com/acs/vector:0.38.0-alpine,挂载/var/log/pods与/var/lib/docker/containers。 - 配置 kubernetes_logs source,自动注入 Pod 标签:
[sources.k8s]
type = "kubernetes_logs"
extra_label_selector = "app in (order, payment)" # 仅采集业务 Pod,降低 60% 流量
- 在 transform 阶段用 VRL 把原始日志转为 JSON 并合并标签:
[transforms.to_json]
type = "remap"
inputs = ["k8s"]
source = '''
# 业务日志格式:2025-06-05 14:23:01 | INFO | userId=123 | action=pay
parsed = parse_regex!(.message, r'^(?P<timestamp>\S+ \S+) \| (?P<level>\w+) \| userId=(?P<userId>\d+) \| action=(?P<action>\w+)')
. = merge(., parsed)
.pod_labels = .kubernetes.pod_labels # 保留 Pod 标签
.couch_id = join!([.kubernetes.pod_name, .timestamp, .userId], "-") # 构造唯一 _id
'''
- sink 到 CouchDB,开启 bulk 与幂等:
[sinks.couch]
type = "http"
inputs = ["to_json"]
uri = "http://couchdb-svc.couchdb.svc.cluster.local:5984/logs/_bulk_docs"
method = "post"
encoding.codec = "json"
request.concurrency = "adaptive"
request.headers = "Content-Type:application/json"
auth.strategy = "basic"
auth.user = "admin"
auth.password = "${COUCH_PW}"
# 国内集群 TLS 普遍自签,需跳过校验
tls.verify_certificate = false
- 在 CouchDB 侧预置设计文档
_design/vector,把couch_id设为唯一索引,避免重复写入;同时开启 q=2 n=3 保证跨可用区高可用。 - 离线节点启用 Vector 的
disk_buffer.max_size = 10GB与acknowledgements.enabled = true,网络恢复后自动重放;CouchDB 的 _local/vector_checkpoint 记录最后一条成功 _rev,实现断点续传。
拓展思考
- 如果日志量超过 5 万条/秒,可把 Vector 的 sink 换成 kafka 先削峰,再用独立 Consumer 组批量写 CouchDB,避免直接打爆单节点。
- 国内金融场景要求 6 个月可追溯,可在 CouchDB 里按 年月分库,利用 _partition 插件把同一 Pod 的日志路由到同一分片,查询时加
?partition=order-202506把扫描范围缩小 1/30。 - 多活容灾时,北京与深圳两套 CouchDB 集群做 双向同步,需给每个地区加 region 前缀到 _id,防止冲突;Vector 侧通过 环境变量 REGION=bj 动态拼接 _id,实现单元化闭环。