diff --git a/config/bundle.yaml b/config/bundle.yaml index 90d3f29..e1f4b01 100644 --- a/config/bundle.yaml +++ b/config/bundle.yaml @@ -13,14 +13,41 @@ data: string: '%{[log.file.path]} %{[message]}' logging.level: warning sidecar.yaml: |- - container: + filebeatContainer: image: elastic/filebeat:6.7.0 imagePullPolicy: IfNotPresent resources: {} + vectorContainer: + image: timberio/vector:0.34.1-debian + imagePullPolicy: IfNotPresent + resources: {} initContainer: image: alpine:3.9 imagePullPolicy: IfNotPresent resources: {} + vector.yaml: |- + data_dir: /etc/logsidecar + sources: + logs: + include: + {{range .Paths}} + - {{.}} + {{end}} + max_line_bytes: 1048576 + type: file + sinks: + console: + encoding: + codec: csv + csv: + delimiter: ' ' + fields: + - file + - message + quote_style: never + inputs: + - logs + type: console kind: ConfigMap metadata: name: logsidecar-injector-configmap diff --git a/config/configmap.yaml b/config/configmap.yaml index 9ca28db..093463f 100644 --- a/config/configmap.yaml +++ b/config/configmap.yaml @@ -1,6 +1,27 @@ apiVersion: v1 kind: ConfigMap data: + vector.yaml: |- + data_dir: /etc/logsidecar + sources: + logs: + include: + {{range .Paths}} + - {{.}} + {{end}} + max_line_bytes: 1048576 + type: file + sinks: + console: + encoding: + codec: csv + csv: + delimiter: ' ' + fields: + - message + inputs: + - logs + type: console filebeat.yaml: |- filebeat.inputs: - type: log @@ -14,10 +35,14 @@ data: string: '%{[log.file.path]} %{[message]}' logging.level: warning sidecar.yaml: |- - container: + filebeatContainer: image: elastic/filebeat:6.7.0 imagePullPolicy: IfNotPresent resources: {} + vectorContainer: + image: timberio/vector:0.34.1-debian + imagePullPolicy: IfNotPresent + resources: {} initContainer: image: alpine:3.9 imagePullPolicy: IfNotPresent diff --git a/injector/config.go b/injector/config.go index 2708a31..ff64bd2 100644 --- a/injector/config.go +++ b/injector/config.go @@ -13,16 +13,22 @@ import ( ) const ( - SidecarContainerDefaultImage = "elastic/filebeat:6.7.0" - SidecarInitContainerDefaultImage = "alpine:3.9" + SidecarTypeFilebeat = "filebeat" + SidecarTypeVector = "vector" + SidecarContainerDefaultFilebeatImage = "elastic/filebeat:6.7.0" + SidecarContainerDefaultVectorImage = "timberio/vector:0.34.1-distroless-static" + SidecarInitContainerDefaultImage = "alpine:3.9" ) type Config struct { CertFile string KeyFile string + SidecarType string + FilebeatConfigFile string SidecarConfigFile string + VectorConfigFile string } type ContainerConfig struct { @@ -32,13 +38,16 @@ type ContainerConfig struct { } type SidecarConfig struct { - InitContainer ContainerConfig `json:"initContainer" yaml:"initContainer"` - Container ContainerConfig `json:"container" yaml:"container"` + InitContainer ContainerConfig `json:"initContainer" yaml:"initContainer"` + FilebeatContainer ContainerConfig `json:"filebeatContainer,omitempty" yaml:"filebeatContainer,omitempty"` + VectorContainer ContainerConfig `json:"vectorContainer,omitempty" yaml:"vectorContainer,omitempty"` } type InjectorConfig struct { + SidecarType string SidecarConfig SidecarConfig FilebeatConfigTemplate *template.Template + VectorConfigTemplate *template.Template } func (c *Config) AddFlags() { @@ -46,11 +55,13 @@ func (c *Config) AddFlags() { "File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert).") flag.StringVar(&c.KeyFile, "tls-private-key-file", "/etc/logsidecar-injector/certs/server.key", "File containing the default x509 private key matching --tls-cert-file.") - + flag.StringVar(&c.SidecarType, "sidecar-type", SidecarTypeVector, "Type of sidecar to inject. Supported values: filebeat, vector") flag.StringVar(&c.SidecarConfigFile, "sidecar-config-file", "/etc/logsidecar-injector/config/sidecar.yaml", "File containing config of injected containers etc.") flag.StringVar(&c.FilebeatConfigFile, "filebeat-config-file", "/etc/logsidecar-injector/config/filebeat.yaml", "File containing filebeat config") + flag.StringVar(&c.VectorConfigFile, "vector-config-file", "/etc/logsidecar-injector/config/vector.yaml", + "File containing vector config") } func (c *Config) TLSConfig(stop <-chan struct{}, reloadCh <-chan chan error) (*tls.Config, error) { @@ -99,7 +110,9 @@ func sidecarConfig(sidecarConfigFile string) (*SidecarConfig, error) { } func (c *Config) InjectorConfig() (*InjectorConfig, error) { - ic := &InjectorConfig{} + ic := &InjectorConfig{ + SidecarType: c.SidecarType, + } sc, err := sidecarConfig(c.SidecarConfigFile) if err != nil { @@ -107,16 +120,31 @@ func (c *Config) InjectorConfig() (*InjectorConfig, error) { } ic.SidecarConfig = *sc - tmpl, err := template.ParseFiles(c.FilebeatConfigFile) - if err != nil { - return nil, fmt.Errorf("error to parse %s to tempalte: %v", c.FilebeatConfigFile, err) - } - ic.FilebeatConfigTemplate = tmpl - if ic.SidecarConfig.Container.Image == "" { - ic.SidecarConfig.Container.Image = SidecarContainerDefaultImage + if c.SidecarType == SidecarTypeVector { + vectorTmpl, err := template.ParseFiles(c.VectorConfigFile) + if err != nil { + return nil, fmt.Errorf("error to parse %s to tempalte: %v", c.VectorConfigFile, err) + } + ic.VectorConfigTemplate = vectorTmpl + if ic.SidecarConfig.VectorContainer.Image == "" { + ic.SidecarConfig.VectorContainer.Image = SidecarContainerDefaultVectorImage + } + } else if c.SidecarType == SidecarTypeFilebeat { + filebeatTmpl, err := template.ParseFiles(c.FilebeatConfigFile) + if err != nil { + return nil, fmt.Errorf("error to parse %s to tempalte: %v", c.FilebeatConfigFile, err) + } + ic.FilebeatConfigTemplate = filebeatTmpl + if ic.SidecarConfig.FilebeatContainer.Image == "" { + ic.SidecarConfig.FilebeatContainer.Image = SidecarContainerDefaultFilebeatImage + } + } else { + return nil, fmt.Errorf("sidecar type %s not supported", c.SidecarType) } + if ic.SidecarConfig.InitContainer.Image == "" { ic.SidecarConfig.InitContainer.Image = SidecarInitContainerDefaultImage } + return ic, nil } diff --git a/injector/logsidecar_pods.go b/injector/logsidecar_pods.go index 83bf651..3c6b1c2 100644 --- a/injector/logsidecar_pods.go +++ b/injector/logsidecar_pods.go @@ -17,6 +17,7 @@ import ( const ( logsidecarAnnotationName = "logging.kubesphere.io/logsidecar-config" logsidecarFilebeatPatchAnnotationName = "logging.kubesphere.io/logsidecar-filebeat-config-jsonpatch" + logsidecarVectorPatchAnnotationName = "logging.kubesphere.io/logsidecar-vector-config-jsonpatch" logsidecarInitContainerName = "logsidecar-init-container-logging-kubesphere-io" logsidecarContainerName = "logsidecar-container-logging-kubesphere-io" logsidecarVolumeName = "logsidecar-config-volume-logging-kubesphere-io" @@ -54,9 +55,8 @@ func MutateLogsidecarPods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse klog.Error(err) return toAdmissionResponse(err) } - filebeatJsonPatch, _ := pod.Annotations[logsidecarFilebeatPatchAnnotationName] - if err = addLogsidecarPart(podSpec, lscConfig, filebeatJsonPatch); err != nil { + if err = addLogsidecarPart(&pod, lscConfig); err != nil { err = fmt.Errorf("faild to inject logsidecar into pod %s: %v", podNN, err) klog.Error(err) return toAdmissionResponse(err) @@ -115,11 +115,12 @@ func removeLogsidecarPart(podSpec *corev1.PodSpec) { const ( logsidecarConfigDir = "/etc/logsidecar" filebeatConfigFileName = "filebeat.yaml" + vectorConfigFileName = "vector.yaml" ) -func addLogsidecarPart(podSpec *corev1.PodSpec, conf *LogsidecarConfig, filebeatJsonPatch string) error { +func addLogsidecarPart(pod *corev1.Pod, conf *LogsidecarConfig) error { cvmMap := make(map[string]map[string]string) // containerName: volumeName: mountPath - for _, c := range podSpec.Containers { + for _, c := range pod.Spec.Containers { if len(c.VolumeMounts) == 0 { continue } @@ -157,24 +158,32 @@ func addLogsidecarPart(podSpec *corev1.PodSpec, conf *LogsidecarConfig, filebeat } iconfig := GetInjectorConfig() + tmpl := iconfig.VectorConfigTemplate + jsonPatch, _ := pod.Annotations[logsidecarVectorPatchAnnotationName] + configFile := vectorConfigFileName + if iconfig.SidecarType == SidecarTypeFilebeat { + tmpl = iconfig.FilebeatConfigTemplate + jsonPatch, _ = pod.Annotations[logsidecarFilebeatPatchAnnotationName] + configFile = filebeatConfigFileName + } // echo command writes filebeat config to volume shared by filebeat container var buffer bytes.Buffer - if err := iconfig.FilebeatConfigTemplate.Execute(&buffer, struct { + if err := tmpl.Execute(&buffer, struct { Paths []string }{filebeatLogPaths}); err != nil { return err } - fbConfigYaml := buffer.String() - if filebeatJsonPatch = strings.TrimSpace(filebeatJsonPatch); filebeatJsonPatch != "" { - newYaml, err := PatchYaml(fbConfigYaml, filebeatJsonPatch) + configYaml := buffer.String() + if jsonPatch = strings.TrimSpace(jsonPatch); jsonPatch != "" { + newYaml, err := PatchYaml(configYaml, jsonPatch) if err != nil { return err } - fbConfigYaml = newYaml + configYaml = newYaml } - fbConfigEcho := JoinLines(fbConfigYaml, "echo \"", - fmt.Sprintf("\" >> %s/%s ; ", logsidecarConfigDir, filebeatConfigFileName)) + configEcho := JoinLines(configYaml, "echo \"", + fmt.Sprintf("\" >> %s/%s ; ", logsidecarConfigDir, configFile)) logsidecarVolume := corev1.Volume{ Name: logsidecarVolumeName, @@ -184,22 +193,30 @@ func addLogsidecarPart(podSpec *corev1.PodSpec, conf *LogsidecarConfig, filebeat Name: logsidecarVolumeName, MountPath: logsidecarConfigDir, } - podSpec.Volumes = append(podSpec.Volumes, logsidecarVolume) - podSpec.InitContainers = append(podSpec.InitContainers, corev1.Container{ + pod.Spec.Volumes = append(pod.Spec.Volumes, logsidecarVolume) + pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{ Name: logsidecarInitContainerName, Image: iconfig.SidecarConfig.InitContainer.Image, ImagePullPolicy: iconfig.SidecarConfig.InitContainer.ImagePullPolicy, Resources: iconfig.SidecarConfig.InitContainer.Resources, Command: []string{"/bin/sh"}, - Args: []string{"-c", fbConfigEcho}, + Args: []string{"-c", configEcho}, VolumeMounts: []corev1.VolumeMount{logsidecarVolumeMount}, }) - podSpec.Containers = append(podSpec.Containers, corev1.Container{ + image := iconfig.SidecarConfig.VectorContainer.Image + imagePullPolicy := iconfig.SidecarConfig.VectorContainer.ImagePullPolicy + resources := iconfig.SidecarConfig.VectorContainer.Resources + if iconfig.SidecarType == SidecarTypeFilebeat { + image = iconfig.SidecarConfig.FilebeatContainer.Image + imagePullPolicy = iconfig.SidecarConfig.FilebeatContainer.ImagePullPolicy + resources = iconfig.SidecarConfig.FilebeatContainer.Resources + } + pod.Spec.Containers = append(pod.Spec.Containers, corev1.Container{ Name: logsidecarContainerName, - Image: iconfig.SidecarConfig.Container.Image, - ImagePullPolicy: iconfig.SidecarConfig.Container.ImagePullPolicy, - Resources: iconfig.SidecarConfig.Container.Resources, - Args: []string{"-c", fmt.Sprintf("%s/%s", logsidecarConfigDir, filebeatConfigFileName)}, + Image: image, + ImagePullPolicy: imagePullPolicy, + Resources: resources, + Args: []string{"-c", fmt.Sprintf("%s/%s", logsidecarConfigDir, configFile)}, VolumeMounts: append(volumeMounts, logsidecarVolumeMount), }) return nil