【发现一个问题】vector operator 中使用 CRD `ClusterVectorPipeline` 配置 sinks 时,jsonline 模式的 yaml 写错会导致 vector 使用默认配置

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


我在 Vector 的 CRD ClusterVectorPipeline 中使用了类似如下的 sinks 配置:

apiVersion: observability.kaasops.io/v1alpha1
kind: ClusterVectorPipeline
metadata:
  name: vlogs
  namespace: {{ .Release.Namespace }}
spec:
  sinks:
    vlogs:
      # see: https://vector.dev/docs/reference/configuration/sinks/http/
      # jsonline mode
      type: http
      inputs:
        - container-logs-transform
      uri: {{ .Values.vector.endpoint }}
      batch:
        timeout_secs: 5
        max_bytes: 20971520
      buffer:
        type: memory
        max_events: 15000
        when_full: drop_newest
      method: POST
      encoding:
        codec: json
      request:
        retry_attempts: 3
        # 错误在下面这行:compression 不属于 request
        compression: {{ .Values.vector.compression | default "none" }}
      framing:
        method: newline_delimited

部署后始终未生效。
查询 vector 配置对应的 secret:

KUBECONFIG=~/my-test-k8s.yaml kubectl get secret vector-agent -n logging -o json | jq -r '.data."agent.json"' | base64 -d

配置的内容为:

{
  "api": {
    "address": "0.0.0.0:8686"
  },
  "data_dir": "/vector-data-dir",
  "sinks": {
    "internalMetricsSink": {
      "inputs": [
        "internalMetricsSource"
      ],
      "type": "prometheus_exporter"
    }
  },
  "sources": {
    "internalMetricsSource": {
      "type": "internal_metrics"
    }
  },
  "transforms": {}
}

我把 jsonline 更换回 elasticsearch 格式后,又一切正常。

猜测原因如下:

  • 我的 yaml 配置中使用了 vector operator 不支持的字段
  • vector operator 对 yaml 格式没有强校验

我阅读了 https://github.com/kaasops/vector-operator 这个位置的 vector operator 源码,发现其结构体定义为:

// VectorPipelineSpec defines the desired state of VectorPipeline
type VectorPipelineSpec struct {
	// +kubebuilder:pruning:PreserveUnknownFields
	Sources *runtime.RawExtension `json:"sources,omitempty"`
	// +kubebuilder:pruning:PreserveUnknownFields
	Transforms *runtime.RawExtension `json:"transforms,omitempty"`
	// +kubebuilder:pruning:PreserveUnknownFields
	Sinks *runtime.RawExtension `json:"sinks,omitempty"`
}

Sinks 居然使用了 runtime.RawExtension 类型,而不是一个清晰定义的结构体。

  • vector operator 在写入 secret 时对 yaml 进行了检查,发现某个地方配置错误了,于是使用空的配置写入 secret

我阅读了源码,找到了位置:

// github.com/kaasops/vector-operator/internal/pipeline/pipeline.go
func GetValidPipelines(ctx context.Context, client client.Client, filter FilterPipelines) ([]Pipeline, error) {
	var validPipelines []Pipeline

	matchLabels := map[string]string{}
	if filter.Selector != nil && filter.Selector.MatchLabels != nil {
		matchLabels = filter.Selector.MatchLabels
	}

	if filter.Scope == AllPipelines || filter.Scope == NamespacedPipeline {

		if filter.Scope == NamespacedPipeline && filter.Namespace == "" {
			return nil, fmt.Errorf("namespace not specified")
		}
		// 这里得到 pipeline 的配置
		// 查询对象 v1alpha1.VectorPipelineList{}
		vps, err := GetVectorPipelines(ctx, client)
		if err != nil {
			return nil, err
		}
		if len(vps) != 0 {
			for _, vp := range vps {
				if !vp.IsDeleted() &&
					vp.IsValid() &&  // vp.IsValid() 类似这种配置校验不通过的情况,应该清晰的给个报错,而不是就此放过
					vp.GetRole() == filter.Role &&
					(filter.Scope == AllPipelines || vp.Namespace == filter.Namespace) &&
					MatchLabels(matchLabels, vp.Labels) {
					validPipelines = append(validPipelines, vp.DeepCopy())
				}
			}
		}
	}
    // 当配置有错的时候,if len(validPipelines)!=len(vps) 的时候应该报错。否则无法给出准确的校验!!!

    // more ...
}

总结

"傲娇女朋友法则:你如果不知道为什么我会生气,那么我就不告诉你我为什么生气……"

—— 你的配置写错了,你只知道你写错了,为什么写错的我是不会告诉你的!!!

什么狗屎玩意儿,瞎折腾人!

我消耗了至少 8 小时的生命在这个问题上,生气。

已经提了一个 issue

posted on 2025-11-20 13:21  ahfuzhang  阅读(19)  评论(0)    收藏  举报