【发现一个问题】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

浙公网安备 33010602011771号