一、先搞懂啥是Vector,为啥要跟老日志工具搭伙

先给没接触过Vector的朋友说清楚:它是个专门干“数据搬运+简单加工”的工具,主要针对日志、指标、链路追踪这些数据。简单说就是“数据的快递员”——把数据从A地运到B地,路上还能给数据贴标签、拆包装、去杂质。

那为啥要跟传统日志采集工具搭伙?比如公司用了好几年的Logstash、Flume、Filebeat,甚至自己写的Python日志脚本,突然要换Vector,全换成本太高、风险大,所以得先让新旧工具一起干活,慢慢过渡。

二、Vector跟传统日志工具集成的常见难题

2.1 难题一:数据格式不兼容,老工具不认Vector的“快递盒”

传统日志工具(比如Logstash)有自己的“标准快递盒”,比如Logstash要求每条日志必须是带@timestamp、message、level这些固定字段的JSON格式。但Vector运过来的日志可能是纯文本、半结构化,或者字段名跟Logstash要求的不一样,老工具拿到手根本拆不开。

举个真实场景:公司老的Logstash流水线要求每条日志必须有@timestamp(时间戳,格式必须是ISO 8601,比如2024-05-20T12:34:56Z)、message(日志内容)、level(日志级别)。但Vector从Nginx采集的日志是纯文本的,格式是[20/May/2024:12:34:56 +0000] "GET /api/user HTTP/1.1" 200 1234,直接给Logstash的话,Logstash根本识别不了,会报错。

2.2 难题二:数据丢包,新旧工具“对接缝隙”漏数据

新旧工具之间的对接就像两个水龙头接水管,中间的缝隙如果没封好,水就漏了。Vector和传统工具的对接缝隙主要是“连接不稳定”“缓冲区太小”“超时设置不合理”。

比如用Flume采集应用日志,Flume的默认连接超时是5秒,Vector的发送超时是10秒,两边超时不匹配的话,当网络波动时,Vector发的日志Flume还没来得及处理,Flume就断开连接了,Vector再发就会丢数据。还有Flume的缓冲区默认只有1024条日志,当日志量突然变大(比如双11),缓冲区满了之后,新的日志就会被丢弃。

2.3 难题三:性能拖垮,老工具扛不住Vector的“快递量”

Vector的性能比传统工具强很多,比如Vector每秒能处理10万条日志,而老的Logstash流水线可能每秒只能处理1万条。如果Vector直接把10万条日志一股脑塞给Logstash,Logstash会被压垮,出现延迟、丢包,甚至直接崩溃。

比如某公司用Vector采集K8s集群的日志,每秒产生8万条,直接发给老的Logstash流水线,结果Logstash的CPU占用率瞬间飙到100%,日志延迟从原来的10秒变成了1小时,很多业务日志根本没法及时查看。

2.4 难题四:监控告警断链,不知道对接出问题

新旧工具集成后,原来的监控告警只盯着老工具,比如只监控Logstash的运行状态、日志吞吐量,但Vector这边出问题(比如采集不到日志、发送失败),原来的监控根本发现不了,导致问题发生很久后才被发现。

比如Vector的Nginx采集组件突然宕机,不再采集日志,但原来的监控只看Logstash的吞吐量,Logstash没日志进来,监控以为是业务没产生日志,根本不会告警,直到运维检查业务时才发现日志断了。

三、对应难题的解决方案,附完整示例

3.1 方案一:给Vector装“格式转换器”,让数据适配老工具

核心思路:在Vector这边加一个“加工环节”,把数据转换成老工具能识别的格式。Vector自带了很多加工组件,比如remap(重映射)、parse(解析)、format(格式化),专门干这个活。

示例:Vector把Nginx日志转换成Logstash要求的格式

技术栈:Vector、Logstash 首先写Vector的配置文件,步骤是:采集Nginx日志→解析纯文本日志→重命名字段→调整时间格式→发送给Logstash。

# Vector配置文件:nginx_to_logstash.yaml
api:
  enabled: true
  address: "0.0.0.0:8686"

# 1. 采集Nginx的访问日志
sources:
  nginx_access_logs:
    type: "file"  # 采集文件类型的日志
    include: ["/var/log/nginx/access.log"]  # Nginx日志的路径
    start_at_beginning: false  # 只采集新产生的日志,不采集历史的

# 2. 加工环节:把纯文本日志转成Logstash要求的格式
transforms:
  parse_nginx_log:
    type: "parse"  # 解析组件
    inputs: ["nginx_access_logs"]  # 输入是采集到的Nginx日志
    parse:
      type: "regex"  # 用正则解析纯文本
      # 正则规则:匹配Nginx日志的各个部分,给每个部分起名字
      regex: '^\[(?P<time>[^\]]+)\] "(?P<request>[^"]+)" (?P<status>\d+) (?P<size>\d+)$'

  format_for_logstash:
    type: "remap"  # 重映射组件,用来调整字段和格式
    inputs: ["parse_nginx_log"]  # 输入是解析后的Nginx日志
    remap:
      # 1. 把原来的时间格式(20/May/2024:12:34:56 +0000)转成ISO 8601格式
      # 先把时间字符串转成时间戳,再转成ISO格式
      .@timestamp = to_timestamp!(.time, "%d/%b/%Y:%H:%M:%S %z")
      # 2. 把原来的request字段改名为message(Logstash要求的字段名)
      .message = .request
      # 3. 把原来的status字段转成数字,再映射成level(Logstash要求的字段名)
      # 比如200是INFO,404是WARN,500是ERROR
      status_num = to_int!(.status)
      .level = if status_num >= 500 { "ERROR" } else if status_num >= 400 { "WARN" } else { "INFO" }
      # 4. 把原来的size字段改名为size(保留这个字段)
      .size = to_int!(.size)
      # 5. 删除不需要的字段(原来的time、request、status)
      del(.time, .request, .status)

# 3. 发送环节:把加工好的日志发给Logstash
sinks:
  logstash_output:
    type: "tcp"  # 用TCP协议发送,Logstash的输入组件支持TCP
    inputs: ["format_for_logstash"]  # 输入是加工好的日志
    address: "logstash-host:5044"  # Logstash的地址和端口(Logstash的输入组件要监听这个端口)
    encoding:
      codec: "json"  # 用JSON格式发送,Logstash能识别

然后写Logstash的配置文件,让Logstash监听Vector发过来的日志:

# Logstash配置文件:vector_input.conf
input {
  tcp {
    port => 5044  # 监听Vector发过来的端口
    codec => json  # 用JSON格式解析,和Vector的编码对应
  }
}

# 中间的过滤环节(原来的老流水线,不用改)
filter {
  # 比如原来的过滤规则:把日志按业务分类
  if [message] =~ /\/api\/user/ {
    add_tag => "业务A"
  }
}

# 输出环节(原来的老流水线,不用改)
output {
  elasticsearch {
    hosts => ["http://es-host:9200"]
    index => "logstash-%{+YYYY.MM.dd}"
  }
}

最后启动Vector和Logstash:

# 启动Vector,用刚才写的配置文件
vector --config nginx_to_logstash.yaml

# 启动Logstash,用刚才写的配置文件
logstash -f vector_input.conf

3.2 方案二:给对接处加“缓冲垫”,避免丢数据

核心思路:在Vector和传统工具之间加一个中间缓冲层,或者调整两边的连接参数,让两边的“节奏”匹配。中间缓冲层可以用Kafka、Redis、甚至Vector自己的磁盘缓冲区。

示例:用Vector的磁盘缓冲区解决Flume丢数据的问题

技术栈:Vector、Flume Flume的默认缓冲区太小,连接超时不合理,所以在Vector这边加一个磁盘缓冲区,让Vector先把日志存在本地磁盘,再慢慢发给Flume,即使Flume暂时连不上,日志也不会丢。

Vector的配置文件里,在发送给Flume的环节加磁盘缓冲区:

# Vector配置文件:vector_to_flume.yaml
api:
  enabled: true
  address: "0.0.0.0:8686"

sources:
  app_logs:
    type: "file"
    include: ["/var/log/app/*.log"]
    start_at_beginning: false

sinks:
  flume_output:
    type: "tcp"
    inputs: ["app_logs"]
    address: "flume-host:41414"  # Flume的监听端口
    encoding:
      codec: "json"
    # 加磁盘缓冲区配置
    buffer:
      type: "disk"  # 用磁盘缓冲区,数据存在本地磁盘,不会因为Vector重启丢数据
      max_size: "10GB"  # 缓冲区最大占10GB磁盘空间
      when_full: "drop_oldest"  # 缓冲区满了之后,丢弃最旧的日志(根据业务需求调整,也可以设为block,让Vector暂停采集)
    # 调整发送参数,和Flume的超时匹配
    send_timeout: "5s"  # 发送超时设为5秒,和Flume的超时一致
    connection_timeout: "10s"  # 连接超时设为10秒

然后调整Flume的配置,让Flume的缓冲区和Vector匹配:

# Flume配置文件:flume_vector.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

# Flume的输入:监听Vector发过来的TCP连接
a1.sources.r1.type = netcat
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 41414
a1.sources.r1.channels = c1

# Flume的通道(缓冲区):调大缓冲区大小,和Vector的节奏匹配
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000  # 缓冲区最大1万条日志,比原来的1024大很多
a1.channels.c1.transactionCapacity = 1000  # 每次处理1000条日志

# Flume的输出(原来的老流水线,不用改)
a1.sinks.k1.type = logger
a1.sinks.k1.channel = c1

启动Vector和Flume:

# 启动Vector
vector --config vector_to_flume.yaml

# 启动Flume
flume-ng agent -c conf -f flume_vector.conf -n a1

3.3 方案三:给Vector加“限速阀”,不让老工具被压垮

核心思路:在Vector这边加一个“限速组件”,控制Vector每秒发给老工具的日志量,让老工具能扛得住。Vector自带了throttle(限速)组件,专门干这个活。

示例:Vector限速发送给老Logstash流水线

技术栈:Vector、Logstash 老Logstash每秒最多能处理1万条日志,所以在Vector的加工环节加一个限速组件,把每秒发送的日志量限制在1万条以内。

Vector的配置文件:

# Vector配置文件:vector_throttle_logstash.yaml
api:
  enabled: true
  address: "0.0.0.0:8686"

sources:
  k8s_logs:
    type: "kubernetes_logs"  # 采集K8s集群的日志
    namespace: "default"  # 只采集default命名空间的日志

transforms:
  # 1. 限速组件:把每秒的日志量限制在1万条以内
  throttle_logs:
    type: "throttle"
    inputs: ["k8s_logs"]
    # 限速规则:每秒最多处理1万条日志
    rate: 10000
    unit: "second"
    # 当日志量超过限速时,丢弃超出的部分(根据业务需求调整,也可以设为暂停采集)
    mode: "drop"

sinks:
  logstash_output:
    type: "tcp"
    inputs: ["throttle_logs"]  # 输入是限速后的日志
    address: "logstash-host:5044"
    encoding:
      codec: "json"

3.4 方案四:给对接处加“监控探针”,及时发现问题

核心思路:在Vector这边加监控组件,同时把Vector的监控数据和老工具的监控数据整合到一起,形成一个完整的监控链。Vector自带了internal_metrics(内部指标)组件,能采集自己的运行状态,比如采集到的日志量、发送失败的日志量、缓冲区的使用情况等。

示例:Vector把自己的监控数据发给Prometheus,和老工具的监控整合

技术栈:Vector、Prometheus、Logstash 首先写Vector的配置文件,让Vector把自己的监控数据暴露给Prometheus:

# Vector配置文件:vector_monitor.yaml
api:
  enabled: true
  address: "0.0.0.0:8686"

# 1. 采集Vector自己的内部指标
sources:
  vector_metrics:
    type: "internal_metrics"  # 采集Vector内部的运行指标
    interval: "1s"  # 每秒采集一次

# 2. 加工指标:只保留需要的指标
transforms:
  filter_metrics:
    type: "remap"
    inputs: ["vector_metrics"]
    remap:
      # 只保留采集量、发送失败量、缓冲区使用量这三个指标
      if .name in ["vector_events_received_total", "vector_events_sent_failed_total", "vector_buffer_used_bytes"] {
        . = .  # 保留这个指标
      } else {
        abort()  # 丢弃其他指标
      }

# 3. 把加工好的指标发给Prometheus
sinks:
  prometheus_output:
    type: "prometheus_exporter"  # 把指标暴露给Prometheus的组件
    inputs: ["filter_metrics"]
    address: "0.0.0.0:9090"  # Prometheus的抓取地址

# 同时保留原来的日志采集和发送(原来的配置)
sources:
  app_logs:
    type: "file"
    include: ["/var/log/app/*.log"]
    start_at_beginning: false

sinks:
  logstash_output:
    type: "tcp"
    inputs: ["app_logs"]
    address: "logstash-host:5044"
    encoding:
      codec: "json"

然后配置Prometheus,让Prometheus同时抓取Vector的指标和Logstash的指标:

# Prometheus配置文件:prometheus.yml
scrape_configs:
  # 抓取Vector的指标
  - job_name: "vector"
    static_configs:
      - targets: ["vector-host:9090"]
  # 抓取Logstash的指标(原来的配置)
  - job_name: "logstash"
    static_configs:
      - targets: ["logstash-host:9600"]

最后在Grafana里做一个仪表盘,同时展示Vector的指标和Logstash的指标,比如:

  • 当Vector的vector_events_received_total停止增长,说明Vector采集不到日志了;
  • 当Vector的vector_events_sent_failed_total开始增长,说明Vector发日志给Logstash失败了;
  • 当Logstash的日志吞吐量停止增长,说明Logstash收不到日志了。

四、应用场景、优缺点、注意事项

4.1 应用场景

  1. 新旧工具过渡:公司要把老的日志采集系统换成Vector,但不能全换,先让Vector和老工具一起干活,慢慢替换。
  2. 局部升级:公司只有一部分业务用新的日志采集需求,其他业务还是用老的,所以让Vector只采集新业务的日志,发给老的流水线。
  3. 性能提升:老的日志流水线性能不够,用Vector采集日志,加工后发给老流水线,提升整体性能。

4.2 技术优缺点

  1. 优点:
    • 成本低:不用全换老工具,减少了替换成本和风险;
    • 风险小:新旧工具一起干活,即使Vector出问题,老工具还能继续运行;
    • 灵活:可以慢慢调整,比如先让Vector采集一部分业务的日志,再慢慢扩大范围。
  2. 缺点:
    • 复杂度高:新旧工具一起干活,配置和监控都比单独用一个工具复杂;
    • 性能瓶颈:老工具的性能还是会限制整体的性能;
    • 维护成本高:要同时维护新旧两个工具,增加了维护的工作量。

4.3 注意事项

  1. 提前测试:在生产环境上线之前,一定要在测试环境测试对接的兼容性、性能、稳定性,避免上线后出问题。
  2. 监控告警:一定要同时监控新旧工具的运行状态,形成完整的监控链,及时发现问题。
  3. 慢慢过渡:不要一下子把所有业务的日志都换成Vector采集,先从一个业务开始,测试没问题再扩大范围。
  4. 备份数据:在过渡期间,一定要做好数据备份,避免因为对接问题丢数据。

五、文章总结

Vector和传统日志采集工具集成,主要要解决四个问题:数据格式不兼容、数据丢包、性能拖垮、监控告警断链。对应的解决方案是:在Vector这边加格式转换、加缓冲垫、加限速阀、加监控探针。

集成的核心思路是“让新旧工具的节奏匹配”,不管是格式、速度、连接参数,都要让两边能互相适配。同时,一定要做好测试、监控、备份,确保集成的稳定性和安全性。

最后,集成只是过渡阶段的选择,最终的目标还是慢慢替换老工具,全用Vector,这样能减少复杂度,提升整体的性能和维护效率。