From 67e79a53a3023239bc800b15b4a49b60b0487489 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 6 Nov 2023 16:29:35 +0100 Subject: [PATCH 01/28] Loggingspec: move fluentdspec setdefaults() to fluentd level Signed-off-by: Szilard Parrag --- pkg/resources/fluentd/service.go | 2 +- pkg/sdk/logging/api/v1beta1/fluentd_types.go | 266 +++++++++++++++++++ pkg/sdk/logging/api/v1beta1/logging_types.go | 265 +----------------- 3 files changed, 272 insertions(+), 261 deletions(-) diff --git a/pkg/resources/fluentd/service.go b/pkg/resources/fluentd/service.go index 73659d9e4..1ec6cdff8 100644 --- a/pkg/resources/fluentd/service.go +++ b/pkg/resources/fluentd/service.go @@ -101,7 +101,7 @@ func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.Desired PodTargetLabels: nil, Endpoints: []v1.Endpoint{{ Port: "http-metrics", - Path: r.Logging.GetFluentdMetricsPath(), + Path: r.Logging.Spec.FluentdSpec.GetFluentdMetricsPath(), Interval: v1.Duration(r.Logging.Spec.FluentdSpec.Metrics.Interval), ScrapeTimeout: v1.Duration(r.Logging.Spec.FluentdSpec.Metrics.Timeout), HonorLabels: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.HonorLabels, diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index d0accdce6..8cf3de5a1 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -15,9 +15,16 @@ package v1beta1 import ( + "errors" + "fmt" + "github.com/cisco-open/operator-tools/pkg/typeoverride" + util "github.com/cisco-open/operator-tools/pkg/utils" "github.com/cisco-open/operator-tools/pkg/volume" + "github.com/spf13/cast" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/input" ) @@ -110,6 +117,265 @@ type FluentOutLogrotate struct { Size string `json:"size,omitempty"` } +// GetFluentdMetricsPath returns the right Fluentd metrics endpoint +// depending on the number of workers and the user configuration +func (f *FluentdSpec) GetFluentdMetricsPath() string { + if f.Metrics.Path == "" { + if f.Workers > 1 { + return "/aggregated_metrics" + } + return "/metrics" + } + return f.Metrics.Path +} + +func (f *FluentdSpec) SetDefaults() error { + if f != nil { // nolint:nestif + if f.FluentdPvcSpec != nil { + return errors.New("`fluentdPvcSpec` field is deprecated, use: `bufferStorageVolume`") + } + if f.Image.Repository == "" { + f.Image.Repository = DefaultFluentdImageRepository + } + if f.Image.Tag == "" { + f.Image.Tag = DefaultFluentdImageTag + } + if f.Image.PullPolicy == "" { + f.Image.PullPolicy = "IfNotPresent" + } + if f.Annotations == nil { + f.Annotations = make(map[string]string) + } + if f.Security == nil { + f.Security = &Security{} + } + if f.Security.RoleBasedAccessControlCreate == nil { + f.Security.RoleBasedAccessControlCreate = util.BoolPointer(true) + } + if f.Security.SecurityContext == nil { + f.Security.SecurityContext = &v1.SecurityContext{} + } + if f.Security.PodSecurityContext == nil { + f.Security.PodSecurityContext = &v1.PodSecurityContext{} + } + if f.Security.PodSecurityContext.FSGroup == nil { + f.Security.PodSecurityContext.FSGroup = util.IntPointer64(101) + } + if f.Workers <= 0 { + f.Workers = 1 + } + if f.Metrics != nil { + if f.Metrics.Port == 0 { + f.Metrics.Port = 24231 + } + if f.Metrics.Timeout == "" { + f.Metrics.Timeout = "5s" + } + if f.Metrics.Interval == "" { + f.Metrics.Interval = "15s" + } + if f.Metrics.PrometheusAnnotations { + f.Annotations["prometheus.io/scrape"] = "true" + f.Annotations["prometheus.io/path"] = f.GetFluentdMetricsPath() + f.Annotations["prometheus.io/port"] = fmt.Sprintf("%d", f.Metrics.Port) + } + } + if f.LogLevel == "" { + f.LogLevel = "info" + } + if !f.DisablePvc { + if f.BufferStorageVolume.PersistentVolumeClaim == nil { + f.BufferStorageVolume.PersistentVolumeClaim = &volume.PersistentVolumeClaim{ + PersistentVolumeClaimSpec: v1.PersistentVolumeClaimSpec{}, + } + } + if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes == nil { + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes = []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + } + } + if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests == nil { + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests = map[v1.ResourceName]resource.Quantity{ + "storage": resource.MustParse("20Gi"), + } + } + if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode == nil { + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode = persistentVolumeModePointer(v1.PersistentVolumeFilesystem) + } + if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName == "" { + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName = DefaultFluentdBufferStorageVolumeName + } + } + if f.VolumeModImage.Repository == "" { + f.VolumeModImage.Repository = DefaultFluentdVolumeModeImageRepository + } + if f.VolumeModImage.Tag == "" { + f.VolumeModImage.Tag = DefaultFluentdVolumeModeImageTag + } + if f.VolumeModImage.PullPolicy == "" { + f.VolumeModImage.PullPolicy = "IfNotPresent" + } + if f.ConfigReloaderImage.Repository == "" { + f.ConfigReloaderImage.Repository = DefaultFluentdConfigReloaderImageRepository + } + if f.ConfigReloaderImage.Tag == "" { + f.ConfigReloaderImage.Tag = DefaultFluentdConfigReloaderImageTag + } + if f.ConfigReloaderImage.PullPolicy == "" { + f.ConfigReloaderImage.PullPolicy = "IfNotPresent" + } + if f.BufferVolumeImage.Repository == "" { + f.BufferVolumeImage.Repository = DefaultFluentdBufferVolumeImageRepository + } + if f.BufferVolumeImage.Tag == "" { + f.BufferVolumeImage.Tag = DefaultFluentdBufferVolumeImageTag + } + if f.BufferVolumeImage.PullPolicy == "" { + f.BufferVolumeImage.PullPolicy = "IfNotPresent" + } + if f.BufferVolumeResources.Limits == nil { + f.BufferVolumeResources.Limits = v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("10M"), + v1.ResourceCPU: resource.MustParse("50m"), + } + } + if f.BufferVolumeResources.Requests == nil { + f.BufferVolumeResources.Requests = v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("10M"), + v1.ResourceCPU: resource.MustParse("1m"), + } + } + if f.Resources.Limits == nil { + f.Resources.Limits = v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("400M"), + v1.ResourceCPU: resource.MustParse("1000m"), + } + } + if f.Resources.Requests == nil { + f.Resources.Requests = v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("100M"), + v1.ResourceCPU: resource.MustParse("500m"), + } + } + if f.Port == 0 { + f.Port = 24240 + } + if f.Scaling == nil { + f.Scaling = new(FluentdScaling) + } + if f.Scaling.PodManagementPolicy == "" { + f.Scaling.PodManagementPolicy = "OrderedReady" + } + if f.Scaling.Drain.Image.Repository == "" { + f.Scaling.Drain.Image.Repository = DefaultFluentdDrainWatchImageRepository + } + if f.Scaling.Drain.Image.Tag == "" { + f.Scaling.Drain.Image.Tag = DefaultFluentdDrainWatchImageTag + } + if f.Scaling.Drain.Image.PullPolicy == "" { + f.Scaling.Drain.Image.PullPolicy = "IfNotPresent" + } + if f.Scaling.Drain.PauseImage.Repository == "" { + f.Scaling.Drain.PauseImage.Repository = DefaultFluentdDrainPauseImageRepository + } + if f.Scaling.Drain.PauseImage.Tag == "" { + f.Scaling.Drain.PauseImage.Tag = DefaultFluentdDrainPauseImageTag + } + if f.Scaling.Drain.PauseImage.PullPolicy == "" { + f.Scaling.Drain.PauseImage.PullPolicy = "IfNotPresent" + } + if f.Scaling.Drain.Resources == nil { + f.Scaling.Drain.Resources = &v1.ResourceRequirements{ + Limits: v1.ResourceList{ + v1.ResourceMemory: resource.MustParse("50M"), + }, + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("20m"), + }, + } + } + if f.Scaling.Drain.SecurityContext == nil { + f.Scaling.Drain.SecurityContext = f.Security.SecurityContext.DeepCopy() + } + if f.FluentLogDestination == "" { + f.FluentLogDestination = "null" + } + if f.FluentOutLogrotate == nil { + f.FluentOutLogrotate = &FluentOutLogrotate{ + Enabled: false, + } + } + if _, ok := f.Annotations["fluentbit.io/exclude"]; !ok { + f.Annotations["fluentbit.io/exclude"] = "true" + } + if f.FluentOutLogrotate.Path == "" { + f.FluentOutLogrotate.Path = "/fluentd/log/out" + } + if f.FluentOutLogrotate.Age == "" { + f.FluentOutLogrotate.Age = "10" + } + if f.FluentOutLogrotate.Size == "" { + f.FluentOutLogrotate.Size = cast.ToString(1024 * 1024 * 10) + } + if f.LivenessProbe == nil { + if f.LivenessDefaultCheck { + f.LivenessProbe = &v1.Probe{ + ProbeHandler: v1.ProbeHandler{ + Exec: &v1.ExecAction{Command: []string{"/bin/healthy.sh"}}, + }, + InitialDelaySeconds: 600, + TimeoutSeconds: 0, + PeriodSeconds: 60, + SuccessThreshold: 0, + FailureThreshold: 0, + } + } + } + if f.ReadinessDefaultCheck.BufferFreeSpace { + if f.ReadinessDefaultCheck.BufferFreeSpaceThreshold == 0 { + f.ReadinessDefaultCheck.BufferFreeSpaceThreshold = 90 + } + } + + if f.ReadinessDefaultCheck.BufferFileNumber { + if f.ReadinessDefaultCheck.BufferFileNumberMax == 0 { + f.ReadinessDefaultCheck.BufferFileNumberMax = 5000 + } + } + if f.ReadinessDefaultCheck.InitialDelaySeconds == 0 { + f.ReadinessDefaultCheck.InitialDelaySeconds = 5 + } + if f.ReadinessDefaultCheck.TimeoutSeconds == 0 { + f.ReadinessDefaultCheck.TimeoutSeconds = 3 + } + if f.ReadinessDefaultCheck.PeriodSeconds == 0 { + f.ReadinessDefaultCheck.PeriodSeconds = 30 + } + if f.ReadinessDefaultCheck.SuccessThreshold == 0 { + f.ReadinessDefaultCheck.SuccessThreshold = 3 + } + if f.ReadinessDefaultCheck.FailureThreshold == 0 { + f.ReadinessDefaultCheck.FailureThreshold = 1 + } + for i := range f.ExtraVolumes { + e := &f.ExtraVolumes[i] + if e.ContainerName == "" { + e.ContainerName = "fluentd" + } + if e.VolumeName == "" { + e.VolumeName = fmt.Sprintf("extravolume-%d", i) + } + if e.Path == "" { + e.Path = "/tmp" + } + if e.Volume == nil { + e.Volume = &volume.KubernetesVolume{} + } + } + } + return nil +} + // +kubebuilder:object:generate=true // ExtraVolume defines the fluentd extra volumes diff --git a/pkg/sdk/logging/api/v1beta1/logging_types.go b/pkg/sdk/logging/api/v1beta1/logging_types.go index abf929771..c5641ecfe 100644 --- a/pkg/sdk/logging/api/v1beta1/logging_types.go +++ b/pkg/sdk/logging/api/v1beta1/logging_types.go @@ -19,8 +19,6 @@ import ( "fmt" util "github.com/cisco-open/operator-tools/pkg/utils" - "github.com/cisco-open/operator-tools/pkg/volume" - "github.com/spf13/cast" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -189,253 +187,12 @@ func (l *Logging) SetDefaults() error { if !l.Spec.FlowConfigCheckDisabled && l.Status.ConfigCheckResults == nil { l.Status.ConfigCheckResults = make(map[string]bool) } - if l.Spec.FluentdSpec != nil { // nolint:nestif - if l.Spec.FluentdSpec.FluentdPvcSpec != nil { - return errors.New("`fluentdPvcSpec` field is deprecated, use: `bufferStorageVolume`") - } - if l.Spec.FluentdSpec.Image.Repository == "" { - l.Spec.FluentdSpec.Image.Repository = DefaultFluentdImageRepository - } - if l.Spec.FluentdSpec.Image.Tag == "" { - l.Spec.FluentdSpec.Image.Tag = DefaultFluentdImageTag - } - if l.Spec.FluentdSpec.Image.PullPolicy == "" { - l.Spec.FluentdSpec.Image.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.Annotations == nil { - l.Spec.FluentdSpec.Annotations = make(map[string]string) - } - if l.Spec.FluentdSpec.Security == nil { - l.Spec.FluentdSpec.Security = &Security{} - } - if l.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate == nil { - l.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate = util.BoolPointer(true) - } - if l.Spec.FluentdSpec.Security.SecurityContext == nil { - l.Spec.FluentdSpec.Security.SecurityContext = &v1.SecurityContext{} - } - if l.Spec.FluentdSpec.Security.PodSecurityContext == nil { - l.Spec.FluentdSpec.Security.PodSecurityContext = &v1.PodSecurityContext{} - } - if l.Spec.FluentdSpec.Security.PodSecurityContext.FSGroup == nil { - l.Spec.FluentdSpec.Security.PodSecurityContext.FSGroup = util.IntPointer64(101) - } - if l.Spec.FluentdSpec.Workers <= 0 { - l.Spec.FluentdSpec.Workers = 1 - } - if l.Spec.FluentdSpec.Metrics != nil { - if l.Spec.FluentdSpec.Metrics.Port == 0 { - l.Spec.FluentdSpec.Metrics.Port = 24231 - } - if l.Spec.FluentdSpec.Metrics.Timeout == "" { - l.Spec.FluentdSpec.Metrics.Timeout = "5s" - } - if l.Spec.FluentdSpec.Metrics.Interval == "" { - l.Spec.FluentdSpec.Metrics.Interval = "15s" - } - if l.Spec.FluentdSpec.Metrics.PrometheusAnnotations { - l.Spec.FluentdSpec.Annotations["prometheus.io/scrape"] = "true" - l.Spec.FluentdSpec.Annotations["prometheus.io/path"] = l.GetFluentdMetricsPath() - l.Spec.FluentdSpec.Annotations["prometheus.io/port"] = fmt.Sprintf("%d", l.Spec.FluentdSpec.Metrics.Port) - } - } - if l.Spec.FluentdSpec.LogLevel == "" { - l.Spec.FluentdSpec.LogLevel = "info" - } - if !l.Spec.FluentdSpec.DisablePvc { - if l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim == nil { - l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim = &volume.PersistentVolumeClaim{ - PersistentVolumeClaimSpec: v1.PersistentVolumeClaimSpec{}, - } - } - if l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes == nil { - l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes = []v1.PersistentVolumeAccessMode{ - v1.ReadWriteOnce, - } - } - if l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests == nil { - l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests = map[v1.ResourceName]resource.Quantity{ - "storage": resource.MustParse("20Gi"), - } - } - if l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode == nil { - l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode = persistentVolumeModePointer(v1.PersistentVolumeFilesystem) - } - if l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName == "" { - l.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName = DefaultFluentdBufferStorageVolumeName - } - } - if l.Spec.FluentdSpec.VolumeModImage.Repository == "" { - l.Spec.FluentdSpec.VolumeModImage.Repository = DefaultFluentdVolumeModeImageRepository - } - if l.Spec.FluentdSpec.VolumeModImage.Tag == "" { - l.Spec.FluentdSpec.VolumeModImage.Tag = DefaultFluentdVolumeModeImageTag - } - if l.Spec.FluentdSpec.VolumeModImage.PullPolicy == "" { - l.Spec.FluentdSpec.VolumeModImage.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.ConfigReloaderImage.Repository == "" { - l.Spec.FluentdSpec.ConfigReloaderImage.Repository = DefaultFluentdConfigReloaderImageRepository - } - if l.Spec.FluentdSpec.ConfigReloaderImage.Tag == "" { - l.Spec.FluentdSpec.ConfigReloaderImage.Tag = DefaultFluentdConfigReloaderImageTag - } - if l.Spec.FluentdSpec.ConfigReloaderImage.PullPolicy == "" { - l.Spec.FluentdSpec.ConfigReloaderImage.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.BufferVolumeImage.Repository == "" { - l.Spec.FluentdSpec.BufferVolumeImage.Repository = DefaultFluentdBufferVolumeImageRepository - } - if l.Spec.FluentdSpec.BufferVolumeImage.Tag == "" { - l.Spec.FluentdSpec.BufferVolumeImage.Tag = DefaultFluentdBufferVolumeImageTag - } - if l.Spec.FluentdSpec.BufferVolumeImage.PullPolicy == "" { - l.Spec.FluentdSpec.BufferVolumeImage.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.BufferVolumeResources.Limits == nil { - l.Spec.FluentdSpec.BufferVolumeResources.Limits = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("10M"), - v1.ResourceCPU: resource.MustParse("50m"), - } - } - if l.Spec.FluentdSpec.BufferVolumeResources.Requests == nil { - l.Spec.FluentdSpec.BufferVolumeResources.Requests = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("10M"), - v1.ResourceCPU: resource.MustParse("1m"), - } - } - if l.Spec.FluentdSpec.Resources.Limits == nil { - l.Spec.FluentdSpec.Resources.Limits = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("400M"), - v1.ResourceCPU: resource.MustParse("1000m"), - } - } - if l.Spec.FluentdSpec.Resources.Requests == nil { - l.Spec.FluentdSpec.Resources.Requests = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("100M"), - v1.ResourceCPU: resource.MustParse("500m"), - } - } - if l.Spec.FluentdSpec.Port == 0 { - l.Spec.FluentdSpec.Port = 24240 - } - if l.Spec.FluentdSpec.Scaling == nil { - l.Spec.FluentdSpec.Scaling = new(FluentdScaling) - } - if l.Spec.FluentdSpec.Scaling.PodManagementPolicy == "" { - l.Spec.FluentdSpec.Scaling.PodManagementPolicy = "OrderedReady" - } - if l.Spec.FluentdSpec.Scaling.Drain.Image.Repository == "" { - l.Spec.FluentdSpec.Scaling.Drain.Image.Repository = DefaultFluentdDrainWatchImageRepository - } - if l.Spec.FluentdSpec.Scaling.Drain.Image.Tag == "" { - l.Spec.FluentdSpec.Scaling.Drain.Image.Tag = DefaultFluentdDrainWatchImageTag - } - if l.Spec.FluentdSpec.Scaling.Drain.Image.PullPolicy == "" { - l.Spec.FluentdSpec.Scaling.Drain.Image.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.Scaling.Drain.PauseImage.Repository == "" { - l.Spec.FluentdSpec.Scaling.Drain.PauseImage.Repository = DefaultFluentdDrainPauseImageRepository - } - if l.Spec.FluentdSpec.Scaling.Drain.PauseImage.Tag == "" { - l.Spec.FluentdSpec.Scaling.Drain.PauseImage.Tag = DefaultFluentdDrainPauseImageTag - } - if l.Spec.FluentdSpec.Scaling.Drain.PauseImage.PullPolicy == "" { - l.Spec.FluentdSpec.Scaling.Drain.PauseImage.PullPolicy = "IfNotPresent" - } - if l.Spec.FluentdSpec.Scaling.Drain.Resources == nil { - l.Spec.FluentdSpec.Scaling.Drain.Resources = &v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("50M"), - }, - Requests: v1.ResourceList{ - v1.ResourceCPU: resource.MustParse("20m"), - }, - } - } - if l.Spec.FluentdSpec.Scaling.Drain.SecurityContext == nil { - l.Spec.FluentdSpec.Scaling.Drain.SecurityContext = l.Spec.FluentdSpec.Security.SecurityContext.DeepCopy() - } - if l.Spec.FluentdSpec.FluentLogDestination == "" { - l.Spec.FluentdSpec.FluentLogDestination = "null" - } - if l.Spec.FluentdSpec.FluentOutLogrotate == nil { - l.Spec.FluentdSpec.FluentOutLogrotate = &FluentOutLogrotate{ - Enabled: false, - } - } - if _, ok := l.Spec.FluentdSpec.Annotations["fluentbit.io/exclude"]; !ok { - l.Spec.FluentdSpec.Annotations["fluentbit.io/exclude"] = "true" - } - if l.Spec.FluentdSpec.FluentOutLogrotate.Path == "" { - l.Spec.FluentdSpec.FluentOutLogrotate.Path = "/fluentd/log/out" - } - if l.Spec.FluentdSpec.FluentOutLogrotate.Age == "" { - l.Spec.FluentdSpec.FluentOutLogrotate.Age = "10" - } - if l.Spec.FluentdSpec.FluentOutLogrotate.Size == "" { - l.Spec.FluentdSpec.FluentOutLogrotate.Size = cast.ToString(1024 * 1024 * 10) - } - if l.Spec.FluentdSpec.LivenessProbe == nil { - if l.Spec.FluentdSpec.LivenessDefaultCheck { - l.Spec.FluentdSpec.LivenessProbe = &v1.Probe{ - ProbeHandler: v1.ProbeHandler{ - Exec: &v1.ExecAction{Command: []string{"/bin/healthy.sh"}}, - }, - InitialDelaySeconds: 600, - TimeoutSeconds: 0, - PeriodSeconds: 60, - SuccessThreshold: 0, - FailureThreshold: 0, - } - } - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFreeSpace { - if l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFreeSpaceThreshold == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFreeSpaceThreshold = 90 - } - } - - if l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFileNumber { - if l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFileNumberMax == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.BufferFileNumberMax = 5000 - } - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.InitialDelaySeconds == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.InitialDelaySeconds = 5 - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.TimeoutSeconds == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.TimeoutSeconds = 3 - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.PeriodSeconds == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.PeriodSeconds = 30 - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.SuccessThreshold == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.SuccessThreshold = 3 - } - if l.Spec.FluentdSpec.ReadinessDefaultCheck.FailureThreshold == 0 { - l.Spec.FluentdSpec.ReadinessDefaultCheck.FailureThreshold = 1 - } - for i := range l.Spec.FluentdSpec.ExtraVolumes { - e := &l.Spec.FluentdSpec.ExtraVolumes[i] - if e.ContainerName == "" { - e.ContainerName = "fluentd" - } - if e.VolumeName == "" { - e.VolumeName = fmt.Sprintf("extravolume-%d", i) - } - if e.Path == "" { - e.Path = "/tmp" - } - if e.Volume == nil { - e.Volume = &volume.KubernetesVolume{} - } - } - if l.Spec.ConfigCheck.TimeoutSeconds == 0 { - l.Spec.ConfigCheck.TimeoutSeconds = 10 - } + if err := l.Spec.FluentdSpec.SetDefaults(); err != nil { + return err + } + if l.Spec.ConfigCheck.TimeoutSeconds == 0 { + l.Spec.ConfigCheck.TimeoutSeconds = 10 } - if l.Spec.SyslogNGSpec != nil { // if l.Spec.SyslogNGSpec.MaxConnections == 0 { // max connections is now configured dynamically if not set @@ -762,15 +519,3 @@ func (l *Logging) GetSyslogNGLabels(component string) map[string]string { func GenerateLoggingRefLabels(loggingRef string) map[string]string { return map[string]string{"app.kubernetes.io/managed-by": loggingRef} } - -// GetFluentdMetricsPath returns the right Fluentd metrics endpoint -// depending on the number of workers and the user configuration -func (l *Logging) GetFluentdMetricsPath() string { - if l.Spec.FluentdSpec.Metrics.Path == "" { - if l.Spec.FluentdSpec.Workers > 1 { - return "/aggregated_metrics" - } - return "/metrics" - } - return l.Spec.FluentdSpec.Metrics.Path -} From 5b247f831073156b4b33f1415d942cc1a9b9e070 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 6 Nov 2023 16:47:59 +0100 Subject: [PATCH 02/28] fluentd: introduce fluentdspecref (detached fluentd) Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_loggings.yaml | 2 + .../logging.banzaicloud.io_loggings.yaml | 2 + controllers/logging/logging_controller.go | 7 +- docs/configuration/crds/v1beta1/_index.md | 2 +- .../crds/v1beta1/fluentd_types.md | 45 +++++++++ .../crds/v1beta1/logging_types.md | 5 + pkg/sdk/logging/api/v1beta1/fluentd_types.go | 97 +++++++++++++------ pkg/sdk/logging/api/v1beta1/logging_types.go | 6 ++ .../api/v1beta1/zz_generated.deepcopy.go | 74 ++++++++++++++ 9 files changed, 209 insertions(+), 31 deletions(-) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml index 0f7503156..c9105b7bf 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml @@ -6106,6 +6106,8 @@ spec: format: int32 type: integer type: object + fluentdRef: + type: string globalFilters: items: properties: diff --git a/config/crd/bases/logging.banzaicloud.io_loggings.yaml b/config/crd/bases/logging.banzaicloud.io_loggings.yaml index 0f7503156..c9105b7bf 100644 --- a/config/crd/bases/logging.banzaicloud.io_loggings.yaml +++ b/config/crd/bases/logging.banzaicloud.io_loggings.yaml @@ -6106,6 +6106,8 @@ spec: format: int32 type: integer type: object + fluentdRef: + type: string globalFilters: items: properties: diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index 6f3cad00f..dec045570 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -169,7 +169,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct ), } - if logging.Spec.FluentdSpec != nil && logging.Spec.SyslogNGSpec != nil { + if logging.AreMultipleAggregatorsSet() { return ctrl.Result{}, errors.New("fluentd and syslogNG cannot be enabled simultaneously") } @@ -433,6 +433,8 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.LoggingRef) case *loggingv1beta1.LoggingRoute: return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.Source) + case *loggingv1beta1.FluentdConfig: + return reconcileRequestsForLoggingRef(loggingList.Items, o.LoggingRef) case *corev1.Secret: r := regexp.MustCompile(`^logging\.banzaicloud\.io/(.*)`) var requestList []reconcile.Request @@ -482,7 +484,8 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder Watches(&loggingv1beta1.SyslogNGOutput{}, requestMapper). Watches(&loggingv1beta1.SyslogNGFlow{}, requestMapper). Watches(&corev1.Secret{}, requestMapper). - Watches(&loggingv1beta1.LoggingRoute{}, requestMapper) + Watches(&loggingv1beta1.LoggingRoute{}, requestMapper). + Watches(&loggingv1beta1.FluentdConfig{}, requestMapper) // TODO remove with the next major release if os.Getenv("ENABLE_NODEAGENT_CRD") != "" { diff --git a/docs/configuration/crds/v1beta1/_index.md b/docs/configuration/crds/v1beta1/_index.md index c34ea5e99..a3a2a2a18 100644 --- a/docs/configuration/crds/v1beta1/_index.md +++ b/docs/configuration/crds/v1beta1/_index.md @@ -18,7 +18,7 @@ For more information please click on the name | **[](conversion/)** | | v1beta1 | | **[FlowSpec](flow_types/)** | FlowSpec is the Kubernetes spec for Flows | v1beta1 | | **[FluentbitSpec](fluentbit_types/)** | FluentbitSpec defines the desired state of FluentbitAgent | v1beta1 | -| **[FluentdSpec](fluentd_types/)** | FluentdSpec defines the desired state of Fluentd | v1beta1 | +| **[FluentdConfig](fluentd_types/)** | FluentdConfig is a reference to the desired Fluentd state | v1beta1 | | **[Logging](logging_types/)** | Logging system configuration | v1beta1 | | **[LoggingRouteSpec](loggingroute_types/)** | LoggingRouteSpec defines the desired state of LoggingRoute | v1beta1 | | **[_hugoNodeAgent](node_agent_types/)** | | v1beta1 | diff --git a/docs/configuration/crds/v1beta1/fluentd_types.md b/docs/configuration/crds/v1beta1/fluentd_types.md index 4553801aa..28b9ca095 100644 --- a/docs/configuration/crds/v1beta1/fluentd_types.md +++ b/docs/configuration/crds/v1beta1/fluentd_types.md @@ -170,6 +170,51 @@ Fluentd port inside the container (24240 by default). The headless service port +--- +title: FluentdConfig +weight: 200 +generated_file: true +--- + +## FluentdConfig + +NodeAgent + +### (metav1.TypeMeta, required) {#fluentdconfig-} + + +### metadata (metav1.ObjectMeta, optional) {#fluentdconfig-metadata} + + +### loggingRef (string, optional) {#fluentdconfig-loggingref} + + +### spec (FluentdSpec, optional) {#fluentdconfig-spec} + + +### status (NodeAgentStatus, optional) {#fluentdconfig-status} + + + +## FluentdConfigStatus + +FluentdConfigStatus + + +## FluentdConfigList + +FluentdConfigList + +### (metav1.TypeMeta, required) {#fluentdconfiglist-} + + +### metadata (metav1.ListMeta, optional) {#fluentdconfiglist-metadata} + + +### items ([]FluentdConfig, required) {#fluentdconfiglist-items} + + + ## FluentOutLogrotate ### age (string, optional) {#fluentoutlogrotate-age} diff --git a/docs/configuration/crds/v1beta1/logging_types.md b/docs/configuration/crds/v1beta1/logging_types.md index 5e007a2e7..86297c83d 100644 --- a/docs/configuration/crds/v1beta1/logging_types.md +++ b/docs/configuration/crds/v1beta1/logging_types.md @@ -59,6 +59,11 @@ Override generated config. This is a *raw* configuration string for troubleshoot FluentbitAgent daemonset configuration. Deprecated, will be removed with next major version Migrate to the standalone NodeAgent resource +### fluentdRef (string, optional) {#loggingspec-fluentdref} + +Fluentd statefulset configuration reference by name + + ### fluentd (*FluentdSpec, optional) {#loggingspec-fluentd} Fluentd statefulset configuration diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index 8cf3de5a1..6ff7e3d13 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -23,8 +23,8 @@ import ( "github.com/cisco-open/operator-tools/pkg/volume" "github.com/spf13/cast" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/input" ) @@ -108,6 +108,47 @@ type FluentdSpec struct { SidecarContainers []corev1.Container `json:"sidecarContainers,omitempty"` } +// +name:"FluentdConfig" +// +weight:"200" +type _hugoFluentdConfig interface{} //nolint:deadcode,unused + +// +name:"FluentdConfig" +// +version:"v1beta1" +// +description:"FluentdConfig is a reference to the desired Fluentd state" +type _metaFluentdConfig interface{} //nolint:deadcode,unused + +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=logging-all +// +kubebuilder:subresource:status +// +kubebuilder:storageversion + +// NodeAgent +type FluentdConfig struct { + LoggingRef string `json:"loggingRef,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec FluentdSpec `json:"spec,omitempty"` + Status NodeAgentStatus `json:"status,omitempty"` +} + +// FluentdConfigStatus +type FluentdConfigStatus struct { +} + +// +kubebuilder:object:root=true + +// FluentdConfigList +type FluentdConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []FluentdConfig `json:"items"` +} + +func init() { + SchemeBuilder.Register(&FluentdConfig{}, &FluentdConfigList{}) +} + // +kubebuilder:object:generate=true type FluentOutLogrotate struct { @@ -153,10 +194,10 @@ func (f *FluentdSpec) SetDefaults() error { f.Security.RoleBasedAccessControlCreate = util.BoolPointer(true) } if f.Security.SecurityContext == nil { - f.Security.SecurityContext = &v1.SecurityContext{} + f.Security.SecurityContext = &corev1.SecurityContext{} } if f.Security.PodSecurityContext == nil { - f.Security.PodSecurityContext = &v1.PodSecurityContext{} + f.Security.PodSecurityContext = &corev1.PodSecurityContext{} } if f.Security.PodSecurityContext.FSGroup == nil { f.Security.PodSecurityContext.FSGroup = util.IntPointer64(101) @@ -186,21 +227,21 @@ func (f *FluentdSpec) SetDefaults() error { if !f.DisablePvc { if f.BufferStorageVolume.PersistentVolumeClaim == nil { f.BufferStorageVolume.PersistentVolumeClaim = &volume.PersistentVolumeClaim{ - PersistentVolumeClaimSpec: v1.PersistentVolumeClaimSpec{}, + PersistentVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{}, } } if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes == nil { - f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes = []v1.PersistentVolumeAccessMode{ - v1.ReadWriteOnce, + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.AccessModes = []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, } } if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests == nil { - f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests = map[v1.ResourceName]resource.Quantity{ + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ "storage": resource.MustParse("20Gi"), } } if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode == nil { - f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode = persistentVolumeModePointer(v1.PersistentVolumeFilesystem) + f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeClaimSpec.VolumeMode = persistentVolumeModePointer(corev1.PersistentVolumeFilesystem) } if f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName == "" { f.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName = DefaultFluentdBufferStorageVolumeName @@ -234,27 +275,27 @@ func (f *FluentdSpec) SetDefaults() error { f.BufferVolumeImage.PullPolicy = "IfNotPresent" } if f.BufferVolumeResources.Limits == nil { - f.BufferVolumeResources.Limits = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("10M"), - v1.ResourceCPU: resource.MustParse("50m"), + f.BufferVolumeResources.Limits = corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("10M"), + corev1.ResourceCPU: resource.MustParse("50m"), } } if f.BufferVolumeResources.Requests == nil { - f.BufferVolumeResources.Requests = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("10M"), - v1.ResourceCPU: resource.MustParse("1m"), + f.BufferVolumeResources.Requests = corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("10M"), + corev1.ResourceCPU: resource.MustParse("1m"), } } if f.Resources.Limits == nil { - f.Resources.Limits = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("400M"), - v1.ResourceCPU: resource.MustParse("1000m"), + f.Resources.Limits = corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("400M"), + corev1.ResourceCPU: resource.MustParse("1000m"), } } if f.Resources.Requests == nil { - f.Resources.Requests = v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("100M"), - v1.ResourceCPU: resource.MustParse("500m"), + f.Resources.Requests = corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("100M"), + corev1.ResourceCPU: resource.MustParse("500m"), } } if f.Port == 0 { @@ -285,12 +326,12 @@ func (f *FluentdSpec) SetDefaults() error { f.Scaling.Drain.PauseImage.PullPolicy = "IfNotPresent" } if f.Scaling.Drain.Resources == nil { - f.Scaling.Drain.Resources = &v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceMemory: resource.MustParse("50M"), + f.Scaling.Drain.Resources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("50M"), }, - Requests: v1.ResourceList{ - v1.ResourceCPU: resource.MustParse("20m"), + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("20m"), }, } } @@ -319,9 +360,9 @@ func (f *FluentdSpec) SetDefaults() error { } if f.LivenessProbe == nil { if f.LivenessDefaultCheck { - f.LivenessProbe = &v1.Probe{ - ProbeHandler: v1.ProbeHandler{ - Exec: &v1.ExecAction{Command: []string{"/bin/healthy.sh"}}, + f.LivenessProbe = &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{Command: []string{"/bin/healthy.sh"}}, }, InitialDelaySeconds: 600, TimeoutSeconds: 0, diff --git a/pkg/sdk/logging/api/v1beta1/logging_types.go b/pkg/sdk/logging/api/v1beta1/logging_types.go index c5641ecfe..897fc1d0b 100644 --- a/pkg/sdk/logging/api/v1beta1/logging_types.go +++ b/pkg/sdk/logging/api/v1beta1/logging_types.go @@ -55,6 +55,8 @@ type LoggingSpec struct { FluentbitSpec *FluentbitSpec `json:"fluentbit,omitempty"` // Fluentd statefulset configuration FluentdSpec *FluentdSpec `json:"fluentd,omitempty"` + // Fluentd statefulset configuration reference by name + FluentdRef string `json:"fluentdRef,omitempty"` // Syslog-NG statefulset configuration SyslogNGSpec *SyslogNGSpec `json:"syslogNG,omitempty"` // Default flow for unmatched logs. This Flow configuration collects all logs that didn't matched any other Flow. @@ -519,3 +521,7 @@ func (l *Logging) GetSyslogNGLabels(component string) map[string]string { func GenerateLoggingRefLabels(loggingRef string) map[string]string { return map[string]string{"app.kubernetes.io/managed-by": loggingRef} } + +func (l *Logging) AreMultipleAggregatorsSet() bool { + return l.Spec.SyslogNGSpec != nil && (l.Spec.FluentdSpec != nil || len(l.Spec.FluentdRef) != 0) +} diff --git a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go index dcda008c4..a63bbee26 100644 --- a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go +++ b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go @@ -1297,6 +1297,80 @@ func (in *FluentbitTLS) DeepCopy() *FluentbitTLS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdConfig) DeepCopyInto(out *FluentdConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfig. +func (in *FluentdConfig) DeepCopy() *FluentdConfig { + if in == nil { + return nil + } + out := new(FluentdConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentdConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdConfigList) DeepCopyInto(out *FluentdConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FluentdConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigList. +func (in *FluentdConfigList) DeepCopy() *FluentdConfigList { + if in == nil { + return nil + } + out := new(FluentdConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentdConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdConfigStatus) DeepCopyInto(out *FluentdConfigStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigStatus. +func (in *FluentdConfigStatus) DeepCopy() *FluentdConfigStatus { + if in == nil { + return nil + } + out := new(FluentdConfigStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdDrainConfig) DeepCopyInto(out *FluentdDrainConfig) { *out = *in From 6cb81128fd1951807ee96689ed49e9359ec49dc0 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 20 Nov 2023 09:33:36 +0100 Subject: [PATCH 03/28] logging: add reconcileRequestsForMatchingControlNamespace in controller Signed-off-by: Szilard Parrag --- controllers/logging/logging_controller.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index dec045570..8d7dd74e0 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -434,7 +434,7 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder case *loggingv1beta1.LoggingRoute: return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.Source) case *loggingv1beta1.FluentdConfig: - return reconcileRequestsForLoggingRef(loggingList.Items, o.LoggingRef) + return reconcileRequestsForMatchingControlNamespace(loggingList.Items, o.Namespace) case *corev1.Secret: r := regexp.MustCompile(`^logging\.banzaicloud\.io/(.*)`) var requestList []reconcile.Request @@ -517,6 +517,20 @@ func reconcileRequestsForLoggingRef(loggings []loggingv1beta1.Logging, loggingRe return } +func reconcileRequestsForMatchingControlNamespace(loggings []loggingv1beta1.Logging, ControlNamespace string) (reqs []reconcile.Request) { + for _, l := range loggings { + if l.Spec.ControlNamespace == ControlNamespace { + reqs = append(reqs, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: l.Namespace, // this happens to be empty as long as Logging is cluster scoped + Name: l.Name, + }, + }) + } + } + return +} + func min(a, b int) int { if a < b { return a From adf4e0180eeaa859b54fda289e73c30714e9977b Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Tue, 7 Nov 2023 13:57:44 +0100 Subject: [PATCH 04/28] fluentd: enable detached fluentd Signed-off-by: Szilard Parrag --- controllers/logging/logging_controller.go | 3 ++- pkg/resources/model/repository.go | 25 ++++++++++++++++++++ pkg/resources/model/resources.go | 10 ++++++++ pkg/resources/model/system.go | 13 +++++----- pkg/sdk/logging/api/v1beta1/fluentd_types.go | 1 - 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index 8d7dd74e0..17178c3d8 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -175,7 +175,8 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct var loggingDataProvider loggingdataprovider.LoggingDataProvider - if logging.Spec.FluentdSpec != nil { + fluentdSpec := loggingResources.FluentdSpec() + if fluentdSpec != nil { fluentdConfig, secretList, err := r.clusterConfigurationFluentd(loggingResources) if err != nil { // TODO: move config generation into Fluentd reconciler diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 0af7b8d4c..6e4c53b5f 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -57,6 +57,9 @@ func (r LoggingResourceRepository) LoggingResourcesFor(ctx context.Context, logg res.Fluentd.ClusterOutputs, err = r.ClusterOutputsFor(ctx, logging) errs = errors.Append(errs, err) + res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, logging) + errs = errors.Append(errs, err) + res.SyslogNG.ClusterFlows, err = r.SyslogNGClusterFlowsFor(ctx, logging) errs = errors.Append(errs, err) @@ -335,6 +338,28 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 return res, nil } +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.FluentdConfig, error) { + var list v1beta1.FluentdConfigList + if err := r.Client.List(ctx, &list); err != nil { + return nil, err + } + + var res []v1beta1.FluentdConfig + for _, i := range list.Items { + if i.Name == logging.Spec.FluentdRef { + res = append(res, i) + } + } + if len(res) > 1 { + return nil, errors.New("multiple fluentd configurations found, only one is allowed") + } + if len(res) != 0 { + return &res[0], nil + } else { + return nil, nil + } +} + func (r LoggingResourceRepository) LoggingRoutesFor(ctx context.Context, logging v1beta1.Logging) ([]v1beta1.LoggingRoute, error) { var list v1beta1.LoggingRouteList if err := r.Client.List(ctx, &list); err != nil { diff --git a/pkg/resources/model/resources.go b/pkg/resources/model/resources.go index 3be9ae251..949beb628 100644 --- a/pkg/resources/model/resources.go +++ b/pkg/resources/model/resources.go @@ -29,11 +29,21 @@ type LoggingResources struct { WatchNamespaces []string } +func (l LoggingResources) FluentdSpec() *v1beta1.FluentdSpec { + if l.Fluentd.Configuration != nil { + return &l.Fluentd.Configuration.Spec + } else if l.Logging.Spec.FluentdSpec != nil { + return l.Logging.Spec.FluentdSpec + } + return nil +} + type FluentdLoggingResources struct { ClusterFlows []v1beta1.ClusterFlow ClusterOutputs ClusterOutputs Flows []v1beta1.Flow Outputs Outputs + Configuration *v1beta1.FluentdConfig } type SyslogNGLoggingResources struct { diff --git a/pkg/resources/model/system.go b/pkg/resources/model/system.go index 5a295af46..1439f1bc1 100644 --- a/pkg/resources/model/system.go +++ b/pkg/resources/model/system.go @@ -32,15 +32,16 @@ import ( func CreateSystem(resources LoggingResources, secrets SecretLoaderFactory, logger logr.Logger) (*types.System, error) { logging := resources.Logging + fluentdSpec := resources.FluentdSpec() var forwardInput *input.ForwardInputConfig - if logging.Spec.FluentdSpec != nil && logging.Spec.FluentdSpec.ForwardInputConfig != nil { - forwardInput = logging.Spec.FluentdSpec.ForwardInputConfig + if fluentdSpec != nil && fluentdSpec.ForwardInputConfig != nil { + forwardInput = fluentdSpec.ForwardInputConfig } else { forwardInput = input.NewForwardInputConfig() } - if logging.Spec.FluentdSpec != nil && logging.Spec.FluentdSpec.TLS.Enabled { + if fluentdSpec != nil && fluentdSpec.TLS.Enabled { forwardInput.Transport = &common.Transport{ Version: "TLSv1_2", CaPath: "/fluentd/tls/ca.crt", @@ -50,7 +51,7 @@ func CreateSystem(resources LoggingResources, secrets SecretLoaderFactory, logge } forwardInput.Security = &common.Security{ SelfHostname: "fluentd", - SharedKey: logging.Spec.FluentdSpec.TLS.SharedKey, + SharedKey: fluentdSpec.TLS.SharedKey, } } @@ -60,7 +61,7 @@ func CreateSystem(resources LoggingResources, secrets SecretLoaderFactory, logge } router := types.NewRouter("main", types.Params{ - "metrics": strconv.FormatBool(logging.Spec.FluentdSpec.Metrics != nil), + "metrics": strconv.FormatBool(fluentdSpec.Metrics != nil), }) var globalFilters []types.Filter @@ -151,7 +152,7 @@ func CreateSystem(resources LoggingResources, secrets SecretLoaderFactory, logge } // TODO: wow such hack - if logging.Spec.FluentdSpec.Workers > 1 { + if fluentdSpec.Workers > 1 { for _, flow := range system.Flows { for _, output := range flow.Outputs { unsetBufferPath(output) diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index 6ff7e3d13..57284291a 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -124,7 +124,6 @@ type _metaFluentdConfig interface{} //nolint:deadcode,unused // NodeAgent type FluentdConfig struct { - LoggingRef string `json:"loggingRef,omitempty"` metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` From 3f147efc762f8d7b15d006286257273040f15321 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Tue, 7 Nov 2023 16:29:26 +0100 Subject: [PATCH 05/28] fluentd: use detached fluentd Signed-off-by: Szilard Parrag --- .../templates/clusterrole.yaml | 2 + config/rbac/role.yaml | 2 + controllers/logging/logging_controller.go | 10 +- docs/configuration/crds/v1beta1/_index.md | 2 +- .../crds/v1beta1/fluentd_types.md | 31 +++-- pkg/resources/fluentbit/configsecret.go | 6 +- pkg/resources/fluentbit/tenants.go | 6 +- pkg/resources/fluentd/appconfigmap.go | 65 +++++----- .../fluentd/buffervolumeprometheusrules.go | 4 +- pkg/resources/fluentd/configsecret.go | 23 ++-- pkg/resources/fluentd/dataprovider.go | 9 +- pkg/resources/fluentd/drainjob.go | 42 ++++--- pkg/resources/fluentd/fluentd.go | 51 ++++++-- pkg/resources/fluentd/meta.go | 10 +- pkg/resources/fluentd/placeholderpod.go | 14 ++- pkg/resources/fluentd/prometheusrules.go | 8 +- pkg/resources/fluentd/psp.go | 11 +- pkg/resources/fluentd/rbac.go | 19 ++- pkg/resources/fluentd/service.go | 90 +++++++------ pkg/resources/fluentd/statefulset.go | 118 ++++++++++-------- pkg/resources/model/reconciler.go | 9 ++ pkg/resources/model/repository.go | 10 +- pkg/resources/model/resources.go | 16 ++- pkg/resources/model/system.go | 2 +- pkg/resources/nodeagent/configsecret.go | 6 +- pkg/sdk/logging/api/v1beta1/fluentd_types.go | 30 ++--- pkg/sdk/logging/api/v1beta1/logging_types.go | 14 ++- .../api/v1beta1/zz_generated.deepcopy.go | 104 +++++++-------- 28 files changed, 426 insertions(+), 288 deletions(-) diff --git a/charts/logging-operator/templates/clusterrole.yaml b/charts/logging-operator/templates/clusterrole.yaml index bb8ab56d3..5cd1bcf03 100644 --- a/charts/logging-operator/templates/clusterrole.yaml +++ b/charts/logging-operator/templates/clusterrole.yaml @@ -241,6 +241,7 @@ rules: - clusteroutputs - flows - fluentbitagents + - fluentds - loggings - nodeagents - outputs @@ -259,6 +260,7 @@ rules: - clusteroutputs/status - flows/status - fluentbitagents/status + - fluentds/status - loggings/status - nodeagents/status - outputs/status diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index ad88ef178..c570f6c75 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -241,6 +241,7 @@ rules: - clusteroutputs - flows - fluentbitagents + - fluentds - loggings - nodeagents - outputs @@ -259,6 +260,7 @@ rules: - clusteroutputs/status - flows/status - fluentbitagents/status + - fluentds/status - loggings/status - nodeagents/status - outputs/status diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index 17178c3d8..a0846ca8f 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -64,8 +64,8 @@ type LoggingReconciler struct { Log logr.Logger } -// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents;fluentds,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status;fluentds/status,verbs=get;update;patch // +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows;syslogngclusterflows;syslogngoutputs;syslogngclusteroutputs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows/status;syslogngclusterflows/status;syslogngoutputs/status;syslogngclusteroutputs/status,verbs=get;update;patch // +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete @@ -175,7 +175,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct var loggingDataProvider loggingdataprovider.LoggingDataProvider - fluentdSpec := loggingResources.FluentdSpec() + fluentdSpec := loggingResources.GetFluentdSpec() if fluentdSpec != nil { fluentdConfig, secretList, err := r.clusterConfigurationFluentd(loggingResources) if err != nil { @@ -434,7 +434,7 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.LoggingRef) case *loggingv1beta1.LoggingRoute: return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.Source) - case *loggingv1beta1.FluentdConfig: + case *loggingv1beta1.Fluentd: return reconcileRequestsForMatchingControlNamespace(loggingList.Items, o.Namespace) case *corev1.Secret: r := regexp.MustCompile(`^logging\.banzaicloud\.io/(.*)`) @@ -486,7 +486,7 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder Watches(&loggingv1beta1.SyslogNGFlow{}, requestMapper). Watches(&corev1.Secret{}, requestMapper). Watches(&loggingv1beta1.LoggingRoute{}, requestMapper). - Watches(&loggingv1beta1.FluentdConfig{}, requestMapper) + Watches(&loggingv1beta1.Fluentd{}, requestMapper) // TODO remove with the next major release if os.Getenv("ENABLE_NODEAGENT_CRD") != "" { diff --git a/docs/configuration/crds/v1beta1/_index.md b/docs/configuration/crds/v1beta1/_index.md index a3a2a2a18..b00fee49c 100644 --- a/docs/configuration/crds/v1beta1/_index.md +++ b/docs/configuration/crds/v1beta1/_index.md @@ -18,7 +18,7 @@ For more information please click on the name | **[](conversion/)** | | v1beta1 | | **[FlowSpec](flow_types/)** | FlowSpec is the Kubernetes spec for Flows | v1beta1 | | **[FluentbitSpec](fluentbit_types/)** | FluentbitSpec defines the desired state of FluentbitAgent | v1beta1 | -| **[FluentdConfig](fluentd_types/)** | FluentdConfig is a reference to the desired Fluentd state | v1beta1 | +| **[Fluent](fluentd_types/)** | Fluentd is a reference to the desired Fluentd state | v1beta1 | | **[Logging](logging_types/)** | Logging system configuration | v1beta1 | | **[LoggingRouteSpec](loggingroute_types/)** | LoggingRouteSpec defines the desired state of LoggingRoute | v1beta1 | | **[_hugoNodeAgent](node_agent_types/)** | | v1beta1 | diff --git a/docs/configuration/crds/v1beta1/fluentd_types.md b/docs/configuration/crds/v1beta1/fluentd_types.md index 28b9ca095..1e8062e9d 100644 --- a/docs/configuration/crds/v1beta1/fluentd_types.md +++ b/docs/configuration/crds/v1beta1/fluentd_types.md @@ -171,47 +171,44 @@ Fluentd port inside the container (24240 by default). The headless service port --- -title: FluentdConfig +title: Fluentd weight: 200 generated_file: true --- -## FluentdConfig +## Fluentd -NodeAgent +Fluentd -### (metav1.TypeMeta, required) {#fluentdconfig-} +### (metav1.TypeMeta, required) {#fluentd-} -### metadata (metav1.ObjectMeta, optional) {#fluentdconfig-metadata} +### metadata (metav1.ObjectMeta, optional) {#fluentd-metadata} -### loggingRef (string, optional) {#fluentdconfig-loggingref} +### spec (FluentdSpec, optional) {#fluentd-spec} -### spec (FluentdSpec, optional) {#fluentdconfig-spec} +### status (FluentdStatus, optional) {#fluentd-status} -### status (NodeAgentStatus, optional) {#fluentdconfig-status} +## FluentdStatus +FluentdStatus -## FluentdConfigStatus -FluentdConfigStatus +## FluentdList +FluentdList -## FluentdConfigList +### (metav1.TypeMeta, required) {#fluentdlist-} -FluentdConfigList -### (metav1.TypeMeta, required) {#fluentdconfiglist-} +### metadata (metav1.ListMeta, optional) {#fluentdlist-metadata} -### metadata (metav1.ListMeta, optional) {#fluentdconfiglist-metadata} - - -### items ([]FluentdConfig, required) {#fluentdconfiglist-items} +### items ([]Fluentd, required) {#fluentdlist-items} diff --git a/pkg/resources/fluentbit/configsecret.go b/pkg/resources/fluentbit/configsecret.go index 3bee53e53..b609badec 100644 --- a/pkg/resources/fluentbit/configsecret.go +++ b/pkg/resources/fluentbit/configsecret.go @@ -184,6 +184,10 @@ func newFluentbitNetwork(network v1beta1.FluentbitNetwork) (result FluentbitNetw func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, error) { ctx := context.TODO() + fluentdSpec := r.Logging.Spec.FluentdSpec + if detachedFluentd := fluentd.GetFluentd(ctx, r.resourceReconciler.Client, r.resourceReconciler.Log, r.Logging.Spec.ControlNamespace); detachedFluentd != nil { + fluentdSpec = &detachedFluentd.Spec + } if r.fluentbitSpec.CustomConfigSecret != "" { return &corev1.Secret{ @@ -239,7 +243,7 @@ func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, er } } - if r.Logging.Spec.FluentdSpec != nil { + if fluentdSpec != nil { fluentbitTargetHost := r.fluentbitSpec.TargetHost if fluentbitTargetHost == "" { fluentbitTargetHost = aggregatorEndpoint(r.Logging, fluentd.ServiceName) diff --git a/pkg/resources/fluentbit/tenants.go b/pkg/resources/fluentbit/tenants.go index b65fa2aff..a84ff2b2c 100644 --- a/pkg/resources/fluentbit/tenants.go +++ b/pkg/resources/fluentbit/tenants.go @@ -100,7 +100,11 @@ func (r *Reconciler) configureOutputsForTenants(ctx context.Context, tenants []v if err := r.resourceReconciler.Client.Get(ctx, types.NamespacedName{Name: t.Name}, logging); err != nil { return errors.WrapIf(err, "getting logging resource") } - if logging.Spec.FluentdSpec != nil { + fluentdSpec := logging.Spec.FluentdSpec + if detachedFluentd := fluentd.GetFluentd(ctx, r.resourceReconciler.Client, r.logger, logging.Spec.ControlNamespace); detachedFluentd != nil { + fluentdSpec = &detachedFluentd.Spec + } + if fluentdSpec != nil { if input.FluentForwardOutput == nil { input.FluentForwardOutput = &fluentForwardOutputConfig{} } diff --git a/pkg/resources/fluentd/appconfigmap.go b/pkg/resources/fluentd/appconfigmap.go index 67a2e319c..fa55c2944 100644 --- a/pkg/resources/fluentd/appconfigmap.go +++ b/pkg/resources/fluentd/appconfigmap.go @@ -42,8 +42,9 @@ type ConfigCheckResult struct { func (r *Reconciler) appConfigSecret() (runtime.Object, reconciler.DesiredState, error) { data := make(map[string][]byte) + fluentdSpec := r.GetFluentdSpec(context.TODO()) - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + if fluentdSpec.CompressConfigFile { AppConfigKeyCompress := AppConfigKey + ".gz" data[AppConfigKeyCompress] = compression.CompressString(*r.config, r.Log) } else { @@ -203,11 +204,12 @@ func (r *Reconciler) configCheck(ctx context.Context) (*ConfigCheckResult, error } func (r *Reconciler) newCheckSecret(hashKey string) (*corev1.Secret, error) { + fluentdSpec := r.GetFluentdSpec(context.TODO()) data, err := r.generateConfigSecret() if err != nil { return nil, err } - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + if fluentdSpec.CompressConfigFile { ConfigCheckKeyCompress := ConfigCheckKey + ".gz" data[ConfigCheckKeyCompress] = compression.CompressString(*r.config, r.Log) } else { @@ -222,8 +224,9 @@ func (r *Reconciler) newCheckSecret(hashKey string) (*corev1.Secret, error) { func (r *Reconciler) newCheckSecretAppConfig(hashKey string) (*corev1.Secret, error) { data := make(map[string][]byte) + fluentdSpec := r.GetFluentdSpec(context.TODO()) - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + if fluentdSpec.CompressConfigFile { ConfigCheckKeyCompress := ConfigCheckKey + ".gz" data[ConfigCheckKeyCompress] = compression.CompressString(*r.config, r.Log) } else { @@ -252,38 +255,39 @@ func (r *Reconciler) newCheckPod(hashKey string) *corev1.Pod { volumes := r.volumesCheckPod(hashKey) container := r.containerCheckPod(hashKey) initContainer := r.initContainerCheckPod() + fluentdSpec := r.GetFluentdSpec(context.TODO()) pod := &corev1.Pod{ ObjectMeta: r.configCheckPodObjectMeta(fmt.Sprintf("fluentd-configcheck-%s", hashKey), ComponentConfigCheck), Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, ServiceAccountName: r.getServiceAccount(), - NodeSelector: r.Logging.Spec.FluentdSpec.NodeSelector, - Tolerations: r.Logging.Spec.FluentdSpec.Tolerations, - Affinity: r.Logging.Spec.FluentdSpec.Affinity, - PriorityClassName: r.Logging.Spec.FluentdSpec.PodPriorityClassName, + NodeSelector: fluentdSpec.NodeSelector, + Tolerations: fluentdSpec.Tolerations, + Affinity: fluentdSpec.Affinity, + PriorityClassName: fluentdSpec.PodPriorityClassName, SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsNonRoot, - FSGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.FSGroup, - RunAsUser: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsUser, - RunAsGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsGroup, - SeccompProfile: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.SeccompProfile, + RunAsNonRoot: fluentdSpec.Security.PodSecurityContext.RunAsNonRoot, + FSGroup: fluentdSpec.Security.PodSecurityContext.FSGroup, + RunAsUser: fluentdSpec.Security.PodSecurityContext.RunAsUser, + RunAsGroup: fluentdSpec.Security.PodSecurityContext.RunAsGroup, + SeccompProfile: fluentdSpec.Security.PodSecurityContext.SeccompProfile, }, Volumes: volumes, - ImagePullSecrets: r.Logging.Spec.FluentdSpec.Image.ImagePullSecrets, + ImagePullSecrets: fluentdSpec.Image.ImagePullSecrets, InitContainers: initContainer, Containers: container, }, } - if r.Logging.Spec.FluentdSpec.ConfigCheckAnnotations != nil { - pod.Annotations = r.Logging.Spec.FluentdSpec.ConfigCheckAnnotations + if fluentdSpec.ConfigCheckAnnotations != nil { + pod.Annotations = fluentdSpec.ConfigCheckAnnotations } - if r.Logging.Spec.FluentdSpec.TLS.Enabled { + if fluentdSpec.TLS.Enabled { tlsVolume := corev1.Volume{ Name: "fluentd-tls", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: r.Logging.Spec.FluentdSpec.TLS.SecretName, + SecretName: fluentdSpec.TLS.SecretName, }, }, } @@ -294,7 +298,7 @@ func (r *Reconciler) newCheckPod(hashKey string) *corev1.Pod { } pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, volumeMount) } - for _, n := range r.Logging.Spec.FluentdSpec.ExtraVolumes { + for _, n := range fluentdSpec.ExtraVolumes { if err := n.ApplyVolumeForPodSpec(&pod.Spec); err != nil { r.Log.Error(err, "Fluentd Config check pod extraVolume attachment failed.") } @@ -304,6 +308,7 @@ func (r *Reconciler) newCheckPod(hashKey string) *corev1.Pod { } func (r *Reconciler) volumesCheckPod(hashKey string) (v []corev1.Volume) { + fluentdSpec := r.GetFluentdSpec(context.TODO()) v = []corev1.Volume{ { Name: "config", @@ -323,7 +328,7 @@ func (r *Reconciler) volumesCheckPod(hashKey string) (v []corev1.Volume) { }, } - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + if fluentdSpec.CompressConfigFile { v = append(v, corev1.Volume{ Name: "app-config", VolumeSource: corev1.VolumeSource{ @@ -372,15 +377,16 @@ func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { } } - containerArgs = append(containerArgs, r.Logging.Spec.FluentdSpec.ExtraArgs...) + fluentdSpec := r.GetFluentdSpec(context.TODO()) + containerArgs = append(containerArgs, fluentdSpec.ExtraArgs...) container := []corev1.Container{ { Name: "fluentd", - Image: r.Logging.Spec.FluentdSpec.Image.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.Image.PullPolicy), + Image: fluentdSpec.Image.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Image.PullPolicy), Args: containerArgs, - Env: r.Logging.Spec.FluentdSpec.EnvVars, + Env: fluentdSpec.EnvVars, VolumeMounts: []corev1.VolumeMount{ { Name: "config", @@ -395,8 +401,8 @@ func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { MountPath: OutputSecretPath, }, }, - SecurityContext: r.Logging.Spec.FluentdSpec.Security.SecurityContext, - Resources: r.Logging.Spec.FluentdSpec.ConfigCheckResources, + SecurityContext: fluentdSpec.Security.SecurityContext, + Resources: fluentdSpec.ConfigCheckResources, }, } @@ -405,13 +411,14 @@ func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { func (r *Reconciler) initContainerCheckPod() []corev1.Container { var initContainer []corev1.Container - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if fluentdSpec.CompressConfigFile { initContainer = []corev1.Container{ { Name: "config-reloader", - Image: r.Logging.Spec.FluentdSpec.ConfigReloaderImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.Image.PullPolicy), - Resources: r.Logging.Spec.FluentdSpec.ConfigReloaderResources, + Image: fluentdSpec.ConfigReloaderImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Image.PullPolicy), + Resources: fluentdSpec.ConfigReloaderResources, Args: []string{ "--init-mode=true", "--volume-dir-archive=/tmp/archive", diff --git a/pkg/resources/fluentd/buffervolumeprometheusrules.go b/pkg/resources/fluentd/buffervolumeprometheusrules.go index 5339be695..6a204a16f 100644 --- a/pkg/resources/fluentd/buffervolumeprometheusrules.go +++ b/pkg/resources/fluentd/buffervolumeprometheusrules.go @@ -15,6 +15,7 @@ package fluentd import ( + "context" "fmt" "github.com/cisco-open/operator-tools/pkg/reconciler" @@ -30,8 +31,9 @@ func (r *Reconciler) bufferVolumePrometheusRules() (runtime.Object, reconciler.D ObjectMeta: r.FluentdObjectMeta(ServiceName+"-buffer-metrics", ComponentFluentd), } state := reconciler.StateAbsent + fluentdSpec := r.GetFluentdSpec(context.TODO()) - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics != nil && r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.PrometheusRules { + if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.PrometheusRules { nsJobLabel := fmt.Sprintf(`job="%s", namespace="%s"`, obj.Name, obj.Namespace) state = reconciler.StatePresent const ruleGroupName = "fluentd-buffervolume" diff --git a/pkg/resources/fluentd/configsecret.go b/pkg/resources/fluentd/configsecret.go index 8332d8b68..44b3b6619 100644 --- a/pkg/resources/fluentd/configsecret.go +++ b/pkg/resources/fluentd/configsecret.go @@ -16,6 +16,7 @@ package fluentd import ( "bytes" + "context" "fmt" "html/template" @@ -53,23 +54,24 @@ func generateConfig(input fluentdConfig) (string, error) { } func (r *Reconciler) generateConfigSecret() (map[string][]byte, error) { + fluentdSpec := r.GetFluentdSpec(context.TODO()) input := fluentdConfig{ - IgnoreSameLogInterval: r.Logging.Spec.FluentdSpec.IgnoreSameLogInterval, - IgnoreRepeatedLogInterval: r.Logging.Spec.FluentdSpec.IgnoreRepeatedLogInterval, - EnableMsgpackTimeSupport: r.Logging.Spec.FluentdSpec.EnableMsgpackTimeSupport, - Workers: r.Logging.Spec.FluentdSpec.Workers, - LogLevel: r.Logging.Spec.FluentdSpec.LogLevel, + IgnoreSameLogInterval: fluentdSpec.IgnoreSameLogInterval, + IgnoreRepeatedLogInterval: fluentdSpec.IgnoreRepeatedLogInterval, + EnableMsgpackTimeSupport: fluentdSpec.EnableMsgpackTimeSupport, + Workers: fluentdSpec.Workers, + LogLevel: fluentdSpec.LogLevel, } - input.RootDir = r.Logging.Spec.FluentdSpec.RootDir + input.RootDir = fluentdSpec.RootDir if input.RootDir == "" { input.RootDir = bufferPath } - if r.Logging.Spec.FluentdSpec.Metrics != nil { + if fluentdSpec.Metrics != nil { input.Monitor.Enabled = true - input.Monitor.Port = r.Logging.Spec.FluentdSpec.Metrics.Port - input.Monitor.Path = r.Logging.Spec.FluentdSpec.Metrics.Path + input.Monitor.Port = fluentdSpec.Metrics.Port + input.Monitor.Path = fluentdSpec.Metrics.Path } inputConfig, err := generateConfig(input) @@ -87,10 +89,11 @@ func (r *Reconciler) generateConfigSecret() (map[string][]byte, error) { func (r *Reconciler) secretConfig() (runtime.Object, reconciler.DesiredState, error) { configMap, err := r.generateConfigSecret() + fluentdSpec := r.GetFluentdSpec(context.TODO()) if err != nil { return nil, nil, err } - configMap["fluentlog.conf"] = []byte(fmt.Sprintf(fluentLog, r.Logging.Spec.FluentdSpec.FluentLogDestination)) + configMap["fluentlog.conf"] = []byte(fmt.Sprintf(fluentLog, fluentdSpec.FluentLogDestination)) configs := &corev1.Secret{ ObjectMeta: r.FluentdObjectMeta(SecretConfigName, ComponentFluentd), Data: configMap, diff --git a/pkg/resources/fluentd/dataprovider.go b/pkg/resources/fluentd/dataprovider.go index b933a2346..423b48377 100644 --- a/pkg/resources/fluentd/dataprovider.go +++ b/pkg/resources/fluentd/dataprovider.go @@ -18,6 +18,7 @@ import ( "context" "emperror.dev/errors" + "github.com/go-logr/logr" "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" v1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/types" @@ -37,9 +38,13 @@ func NewDataProvider(client client.Client, logging *v1beta1.Logging) *DataProvid } func (p *DataProvider) GetReplicaCount(ctx context.Context) (*int32, error) { - if p.logging.Spec.FluentdSpec != nil { + fluentdSpec := p.logging.Spec.FluentdSpec + if detachedFluentd := GetFluentd(ctx, p.client, logr.Logger{}, p.logging.Spec.ControlNamespace); detachedFluentd != nil { + fluentdSpec = &detachedFluentd.Spec + } + if fluentdSpec != nil { sts := &v1.StatefulSet{} - om := p.logging.FluentdObjectMeta(StatefulSetName, ComponentFluentd) + om := p.logging.FluentdObjectMeta(StatefulSetName, ComponentFluentd, *fluentdSpec) err := p.client.Get(ctx, types.NamespacedName{Namespace: om.Namespace, Name: om.Name}, sts) if err != nil { return nil, errors.WrapIf(client.IgnoreNotFound(err), "getting fluentd statefulset") diff --git a/pkg/resources/fluentd/drainjob.go b/pkg/resources/fluentd/drainjob.go index 4eb09ce78..56dbc3666 100644 --- a/pkg/resources/fluentd/drainjob.go +++ b/pkg/resources/fluentd/drainjob.go @@ -15,6 +15,7 @@ package fluentd import ( + "context" "strings" batchv1 "k8s.io/api/batch/v1" @@ -25,23 +26,24 @@ import ( ) func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim) (*batchv1.Job, error) { - bufVolName := r.Logging.QualifiedName(r.Logging.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) + fluentdSpec := r.GetFluentdSpec(context.TODO()) + bufVolName := r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) - fluentdContainer := fluentContainer(withoutFluentOutLogrotate(r.Logging.Spec.FluentdSpec)) + fluentdContainer := fluentContainer(withoutFluentOutLogrotate(fluentdSpec)) fluentdContainer.VolumeMounts = append(fluentdContainer.VolumeMounts, corev1.VolumeMount{ Name: bufVolName, MountPath: bufferPath, }) containers := []corev1.Container{ fluentdContainer, - drainWatchContainer(&r.Logging.Spec.FluentdSpec.Scaling.Drain, bufVolName), + drainWatchContainer(&fluentdSpec.Scaling.Drain, bufVolName), } if c := r.bufferMetricsSidecarContainer(); c != nil { containers = append(containers, *c) } var initContainers []corev1.Container - if i := generateInitContainer(r.Logging.Spec.FluentdSpec); i != nil { + if i := generateInitContainer(fluentdSpec); i != nil { initContainers = append(initContainers, *i) } if c := r.tmpDirHackContainer(); c != nil { @@ -52,25 +54,25 @@ func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim) (*batchv1.J Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: r.getDrainerLabels(), - Annotations: r.Logging.Spec.FluentdSpec.Scaling.Drain.Annotations, + Annotations: fluentdSpec.Scaling.Drain.Annotations, }, Spec: corev1.PodSpec{ Volumes: r.generateVolume(), ServiceAccountName: r.getServiceAccount(), - ImagePullSecrets: r.Logging.Spec.FluentdSpec.Image.ImagePullSecrets, + ImagePullSecrets: fluentdSpec.Image.ImagePullSecrets, InitContainers: initContainers, Containers: containers, - NodeSelector: r.Logging.Spec.FluentdSpec.NodeSelector, - Tolerations: r.Logging.Spec.FluentdSpec.Tolerations, - Affinity: r.Logging.Spec.FluentdSpec.Affinity, - TopologySpreadConstraints: r.Logging.Spec.FluentdSpec.TopologySpreadConstraints, - PriorityClassName: r.Logging.Spec.FluentdSpec.PodPriorityClassName, + NodeSelector: fluentdSpec.NodeSelector, + Tolerations: fluentdSpec.Tolerations, + Affinity: fluentdSpec.Affinity, + TopologySpreadConstraints: fluentdSpec.TopologySpreadConstraints, + PriorityClassName: fluentdSpec.PodPriorityClassName, SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsNonRoot, - FSGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.FSGroup, - RunAsUser: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsUser, - RunAsGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsGroup, - SeccompProfile: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.SeccompProfile, + RunAsNonRoot: fluentdSpec.Security.PodSecurityContext.RunAsNonRoot, + FSGroup: fluentdSpec.Security.PodSecurityContext.FSGroup, + RunAsUser: fluentdSpec.Security.PodSecurityContext.RunAsUser, + RunAsGroup: fluentdSpec.Security.PodSecurityContext.RunAsGroup, + SeccompProfile: fluentdSpec.Security.PodSecurityContext.SeccompProfile, }, RestartPolicy: corev1.RestartPolicyNever, }, @@ -85,7 +87,7 @@ func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim) (*batchv1.J }, }, }) - for _, n := range r.Logging.Spec.FluentdSpec.ExtraVolumes { + for _, n := range fluentdSpec.ExtraVolumes { if err := n.ApplyVolumeForPodSpec(&spec.Template.Spec); err != nil { return nil, err } @@ -130,9 +132,11 @@ func withoutFluentOutLogrotate(spec *v1beta1.FluentdSpec) *v1beta1.FluentdSpec { } func (r *Reconciler) getDrainerLabels() map[string]string { - labels := r.Logging.GetFluentdLabels(ComponentDrainer) + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + labels := r.Logging.GetFluentdLabels(ComponentDrainer, *fluentdSpec) - for key, value := range r.Logging.Spec.FluentdSpec.Scaling.Drain.Labels { + for key, value := range fluentdSpec.Scaling.Drain.Labels { labels[key] = value } diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index d9a4ca65f..f6fca6ca9 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -82,9 +82,40 @@ type Desire struct { BeforeUpdateHook func(runtime.Object) (reconciler.DesiredState, error) } +func GetFluentd(ctx context.Context, Client client.Client, log logr.Logger, controlNamespace string) *v1beta1.Fluentd { + fluentdList := v1beta1.FluentdList{} + // Detached fluentd must be in the `control namespace` + nsOpt := client.InNamespace(controlNamespace) + + if err := Client.List(ctx, &fluentdList, nsOpt); err != nil { + log.Error(err, "listing fluentd configuration") + return nil + } + + if len(fluentdList.Items) > 1 { + log.Error(errors.New("multiple fluentd configurations found"), fmt.Sprintf("number of configurations: %d", len(fluentdList.Items))) + return nil + } + + if len(fluentdList.Items) == 1 { + return &fluentdList.Items[0] + } + return nil +} + +func (r *Reconciler) GetFluentdSpec(ctx context.Context) *v1beta1.FluentdSpec { + fluentdSpec := r.Logging.Spec.FluentdSpec + if detachedFluentd := GetFluentd(ctx, r.Client, r.Log, r.Logging.Spec.ControlNamespace); detachedFluentd != nil { + fluentdSpec = &detachedFluentd.Spec + } + return fluentdSpec +} + func (r *Reconciler) getServiceAccount() string { - if r.Logging.Spec.FluentdSpec.Security.ServiceAccount != "" { - return r.Logging.Spec.FluentdSpec.Security.ServiceAccount + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.Security.ServiceAccount != "" { + return fluentdSpec.Security.ServiceAccount } return r.Logging.QualifiedName(defaultServiceAccountName) } @@ -103,6 +134,11 @@ func New(client client.Client, log logr.Logger, func (r *Reconciler) Reconcile(ctx context.Context) (*reconcile.Result, error) { patchBase := client.MergeFrom(r.Logging.DeepCopy()) + fluentdSpec := r.GetFluentdSpec(ctx) + if err := fluentdSpec.SetDefaults(); err != nil { + return &reconcile.Result{}, err + } + objects := []resources.Resource{ r.serviceAccount, r.role, @@ -265,13 +301,14 @@ func (r *Reconciler) statusUpdate(ctx context.Context, patchBase client.Patch, r } func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, error) { - if r.Logging.Spec.FluentdSpec.DisablePvc || !r.Logging.Spec.FluentdSpec.Scaling.Drain.Enabled { + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.DisablePvc || !fluentdSpec.Scaling.Drain.Enabled { r.Log.Info("fluentd buffer draining is disabled") return nil, nil } nsOpt := client.InNamespace(r.Logging.Spec.ControlNamespace) - fluentdLabelSet := r.Logging.GetFluentdLabels(ComponentFluentd) + fluentdLabelSet := r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec) var pvcList corev1.PersistentVolumeClaimList if err := r.Client.List(ctx, &pvcList, nsOpt, @@ -286,7 +323,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err return nil, errors.WrapIf(err, "listing StatefulSet pods") } - bufVolName := r.Logging.QualifiedName(r.Logging.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) + bufVolName := r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) pvcsInUse := make(map[string]bool) for _, pod := range stsPods.Items { @@ -306,7 +343,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err } var jobList batchv1.JobList - if err := r.Client.List(ctx, &jobList, nsOpt, client.MatchingLabels(r.Logging.GetFluentdLabels(ComponentDrainer))); err != nil { + if err := r.Client.List(ctx, &jobList, nsOpt, client.MatchingLabels(r.Logging.GetFluentdLabels(ComponentDrainer, *fluentdSpec))); err != nil { return nil, errors.WrapIf(err, "listing buffer drainer jobs") } @@ -350,7 +387,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err continue } - if r.Logging.Spec.FluentdSpec.Scaling.Drain.DeleteVolume { + if fluentdSpec.Scaling.Drain.DeleteVolume { if err := client.IgnoreNotFound(r.Client.Delete(ctx, &pvc, client.PropagationPolicy(v1.DeletePropagationBackground))); err != nil { cr.CombineErr(errors.WrapIfWithDetails(err, "deleting drained PVC", "pvc", pvc.Name)) continue diff --git a/pkg/resources/fluentd/meta.go b/pkg/resources/fluentd/meta.go index a5a26b7d2..73a49aeaf 100644 --- a/pkg/resources/fluentd/meta.go +++ b/pkg/resources/fluentd/meta.go @@ -15,16 +15,20 @@ package fluentd import ( + "context" + util "github.com/cisco-open/operator-tools/pkg/utils" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // FluentdObjectMeta creates an objectMeta for resource fluentd func (r *Reconciler) FluentdObjectMeta(name, component string) metav1.ObjectMeta { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) o := metav1.ObjectMeta{ Name: r.Logging.QualifiedName(name), Namespace: r.Logging.Spec.ControlNamespace, - Labels: r.Logging.GetFluentdLabels(component), + Labels: r.Logging.GetFluentdLabels(component, *fluentdSpec), OwnerReferences: []metav1.OwnerReference{ { APIVersion: r.Logging.APIVersion, @@ -40,9 +44,11 @@ func (r *Reconciler) FluentdObjectMeta(name, component string) metav1.ObjectMeta // FluentdObjectMetaClusterScope creates an objectMeta for resource fluentd func (r *Reconciler) FluentdObjectMetaClusterScope(name, component string) metav1.ObjectMeta { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) o := metav1.ObjectMeta{ Name: r.Logging.QualifiedName(name), - Labels: r.Logging.GetFluentdLabels(component), + Labels: r.Logging.GetFluentdLabels(component, *fluentdSpec), OwnerReferences: []metav1.OwnerReference{ { APIVersion: r.Logging.APIVersion, diff --git a/pkg/resources/fluentd/placeholderpod.go b/pkg/resources/fluentd/placeholderpod.go index 89b90d9e9..369e3a249 100644 --- a/pkg/resources/fluentd/placeholderpod.go +++ b/pkg/resources/fluentd/placeholderpod.go @@ -15,6 +15,7 @@ package fluentd import ( + "context" "strings" "github.com/cisco-open/operator-tools/pkg/utils" @@ -22,20 +23,21 @@ import ( ) func (r *Reconciler) placeholderPodFor(pvc corev1.PersistentVolumeClaim) *corev1.Pod { + fluentdSpec := r.GetFluentdSpec(context.TODO()) return &corev1.Pod{ ObjectMeta: r.FluentdObjectMeta(StatefulSetName+pvc.Name[strings.LastIndex(pvc.Name, "-"):], ComponentPlaceholder), Spec: corev1.PodSpec{ Containers: []corev1.Container{ { Name: "pause", - Image: r.Logging.Spec.FluentdSpec.Scaling.Drain.PauseImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.Scaling.Drain.PauseImage.PullPolicy), + Image: fluentdSpec.Scaling.Drain.PauseImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Scaling.Drain.PauseImage.PullPolicy), }, }, - NodeSelector: r.Logging.Spec.FluentdSpec.NodeSelector, - Tolerations: r.Logging.Spec.FluentdSpec.Tolerations, - Affinity: r.Logging.Spec.FluentdSpec.Affinity, - PriorityClassName: r.Logging.Spec.FluentdSpec.PodPriorityClassName, + NodeSelector: fluentdSpec.NodeSelector, + Tolerations: fluentdSpec.Tolerations, + Affinity: fluentdSpec.Affinity, + PriorityClassName: fluentdSpec.PodPriorityClassName, RestartPolicy: corev1.RestartPolicyNever, TerminationGracePeriodSeconds: utils.IntPointer64(0), // terminate immediately }, diff --git a/pkg/resources/fluentd/prometheusrules.go b/pkg/resources/fluentd/prometheusrules.go index acd04fa41..4ba48131e 100644 --- a/pkg/resources/fluentd/prometheusrules.go +++ b/pkg/resources/fluentd/prometheusrules.go @@ -15,14 +15,14 @@ package fluentd import ( + "context" "fmt" "github.com/cisco-open/operator-tools/pkg/reconciler" + prometheus_operator "github.com/kube-logging/logging-operator/pkg/resources/prometheus-operator" v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - - "github.com/kube-logging/logging-operator/pkg/resources/prometheus-operator" ) func (r *Reconciler) prometheusRules() (runtime.Object, reconciler.DesiredState, error) { @@ -31,7 +31,9 @@ func (r *Reconciler) prometheusRules() (runtime.Object, reconciler.DesiredState, } state := reconciler.StateAbsent - if r.Logging.Spec.FluentdSpec.Metrics != nil && r.Logging.Spec.FluentdSpec.Metrics.PrometheusRules { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + + if fluentdSpec.Metrics != nil && fluentdSpec.Metrics.PrometheusRules { nsJobLabel := fmt.Sprintf(`job="%s", namespace="%s"`, obj.Name, obj.Namespace) state = reconciler.StatePresent const ruleGroupName = "fluentd" diff --git a/pkg/resources/fluentd/psp.go b/pkg/resources/fluentd/psp.go index 3528dd6f9..02f5e70f1 100644 --- a/pkg/resources/fluentd/psp.go +++ b/pkg/resources/fluentd/psp.go @@ -15,6 +15,8 @@ package fluentd import ( + "context" + "github.com/cisco-open/operator-tools/pkg/reconciler" util "github.com/cisco-open/operator-tools/pkg/utils" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -24,7 +26,8 @@ import ( ) func (r *Reconciler) clusterPodSecurityPolicy() (runtime.Object, reconciler.DesiredState, error) { - if r.Logging.Spec.FluentdSpec.Security.PodSecurityPolicyCreate { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if fluentdSpec.Security.PodSecurityPolicyCreate { return &policyv1beta1.PodSecurityPolicy{ ObjectMeta: r.FluentdObjectMetaClusterScope(PodSecurityPolicyName, ComponentFluentd), Spec: policyv1beta1.PodSecurityPolicySpec{ @@ -59,7 +62,8 @@ func (r *Reconciler) clusterPodSecurityPolicy() (runtime.Object, reconciler.Desi } func (r *Reconciler) pspRole() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate && r.Logging.Spec.FluentdSpec.Security.PodSecurityPolicyCreate { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.PodSecurityPolicyCreate { return &rbacv1.Role{ ObjectMeta: r.FluentdObjectMeta(roleName+"-psp", ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -78,7 +82,8 @@ func (r *Reconciler) pspRole() (runtime.Object, reconciler.DesiredState, error) } func (r *Reconciler) pspRoleBinding() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate && r.Logging.Spec.FluentdSpec.Security.PodSecurityPolicyCreate { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.PodSecurityPolicyCreate { return &rbacv1.RoleBinding{ ObjectMeta: r.FluentdObjectMeta(roleBindingName+"-psp", ComponentFluentd), RoleRef: rbacv1.RoleRef{ diff --git a/pkg/resources/fluentd/rbac.go b/pkg/resources/fluentd/rbac.go index f00b5075a..84bfde3fc 100644 --- a/pkg/resources/fluentd/rbac.go +++ b/pkg/resources/fluentd/rbac.go @@ -15,6 +15,8 @@ package fluentd import ( + "context" + "emperror.dev/errors" "github.com/cisco-open/operator-tools/pkg/merge" "github.com/cisco-open/operator-tools/pkg/reconciler" @@ -24,7 +26,8 @@ import ( ) func (r *Reconciler) role() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate { return &rbacv1.Role{ ObjectMeta: r.FluentdObjectMeta(roleName, ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -42,7 +45,8 @@ func (r *Reconciler) role() (runtime.Object, reconciler.DesiredState, error) { } func (r *Reconciler) roleBinding() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate { return &rbacv1.RoleBinding{ ObjectMeta: r.FluentdObjectMeta(roleBindingName, ComponentFluentd), RoleRef: rbacv1.RoleRef{ @@ -74,7 +78,8 @@ func (r *Reconciler) isEnhanceK8sFilter() bool { } func (r *Reconciler) clusterRole() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { return &rbacv1.ClusterRole{ ObjectMeta: r.FluentdObjectMetaClusterScope(clusterRoleName, ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -115,7 +120,8 @@ func (r *Reconciler) clusterRole() (runtime.Object, reconciler.DesiredState, err } func (r *Reconciler) clusterRoleBinding() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { return &rbacv1.ClusterRoleBinding{ ObjectMeta: r.FluentdObjectMetaClusterScope(clusterRoleBindingName, ComponentFluentd), RoleRef: rbacv1.RoleRef{ @@ -138,11 +144,12 @@ func (r *Reconciler) clusterRoleBinding() (runtime.Object, reconciler.DesiredSta } func (r *Reconciler) serviceAccount() (runtime.Object, reconciler.DesiredState, error) { - if *r.Logging.Spec.FluentdSpec.Security.RoleBasedAccessControlCreate && r.Logging.Spec.FluentdSpec.Security.ServiceAccount == "" { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.ServiceAccount == "" { desired := &corev1.ServiceAccount{ ObjectMeta: r.FluentdObjectMeta(defaultServiceAccountName, ComponentFluentd), } - err := merge.Merge(desired, r.Logging.Spec.FluentdSpec.ServiceAccountOverrides) + err := merge.Merge(desired, fluentdSpec.ServiceAccountOverrides) if err != nil { return desired, reconciler.StatePresent, errors.WrapIf(err, "unable to merge overrides to base object") } diff --git a/pkg/resources/fluentd/service.go b/pkg/resources/fluentd/service.go index 1ec6cdff8..58786908f 100644 --- a/pkg/resources/fluentd/service.go +++ b/pkg/resources/fluentd/service.go @@ -15,6 +15,8 @@ package fluentd import ( + "context" + "emperror.dev/errors" "github.com/cisco-open/operator-tools/pkg/reconciler" v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -25,6 +27,8 @@ import ( ) func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) desired := &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName, ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -33,16 +37,16 @@ func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) Name: "tcp-fluentd", Protocol: corev1.ProtocolTCP, Port: ServicePort, - TargetPort: intstr.IntOrString{IntVal: r.Logging.Spec.FluentdSpec.Port}, + TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Port}, }, { Name: "udp-fluentd", Protocol: corev1.ProtocolUDP, Port: ServicePort, - TargetPort: intstr.IntOrString{IntVal: r.Logging.Spec.FluentdSpec.Port}, + TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), Type: corev1.ServiceTypeClusterIP, }, } @@ -60,7 +64,9 @@ func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) } func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, error) { - if r.Logging.Spec.FluentdSpec.Metrics != nil { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.Metrics != nil { return &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName+"-metrics", ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -68,11 +74,11 @@ func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, { Protocol: corev1.ProtocolTCP, Name: "http-metrics", - Port: r.Logging.Spec.FluentdSpec.Metrics.Port, - TargetPort: intstr.IntOrString{IntVal: r.Logging.Spec.FluentdSpec.Metrics.Port}, + Port: fluentdSpec.Metrics.Port, + TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Metrics.Port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: "None", }, @@ -85,10 +91,12 @@ func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.DesiredState, error) { var SampleLimit uint64 = 0 - if r.Logging.Spec.FluentdSpec.Metrics != nil && r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitor { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.Metrics != nil && fluentdSpec.Metrics.ServiceMonitor { objectMetadata := r.FluentdObjectMeta(ServiceName+"-metrics", ComponentFluentd) - if r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels != nil { - for k, v := range r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels { + if fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels != nil { + for k, v := range fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels { objectMetadata.Labels[k] = v } } @@ -101,16 +109,16 @@ func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.Desired PodTargetLabels: nil, Endpoints: []v1.Endpoint{{ Port: "http-metrics", - Path: r.Logging.Spec.FluentdSpec.GetFluentdMetricsPath(), - Interval: v1.Duration(r.Logging.Spec.FluentdSpec.Metrics.Interval), - ScrapeTimeout: v1.Duration(r.Logging.Spec.FluentdSpec.Metrics.Timeout), - HonorLabels: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.HonorLabels, - RelabelConfigs: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.Relabelings, - MetricRelabelConfigs: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.MetricsRelabelings, - Scheme: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.Scheme, - TLSConfig: r.Logging.Spec.FluentdSpec.Metrics.ServiceMonitorConfig.TLSConfig, + Path: fluentdSpec.GetFluentdMetricsPath(), + Interval: v1.Duration(fluentdSpec.Metrics.Interval), + ScrapeTimeout: v1.Duration(fluentdSpec.Metrics.Timeout), + HonorLabels: fluentdSpec.Metrics.ServiceMonitorConfig.HonorLabels, + RelabelConfigs: fluentdSpec.Metrics.ServiceMonitorConfig.Relabelings, + MetricRelabelConfigs: fluentdSpec.Metrics.ServiceMonitorConfig.MetricsRelabelings, + Scheme: fluentdSpec.Metrics.ServiceMonitorConfig.Scheme, + TLSConfig: fluentdSpec.Metrics.ServiceMonitorConfig.TLSConfig, }}, - Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd)}, + Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec)}, NamespaceSelector: v1.NamespaceSelector{MatchNames: []string{r.Logging.Spec.ControlNamespace}}, SampleLimit: &SampleLimit, }, @@ -123,10 +131,12 @@ func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.Desired } func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredState, error) { - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics != nil { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.BufferVolumeMetrics != nil { port := int32(defaultBufferVolumeMetricsPort) - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics != nil && r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Port != 0 { - port = r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Port + if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.Port != 0 { + port = fluentdSpec.BufferVolumeMetrics.Port } return &corev1.Service{ @@ -140,7 +150,7 @@ func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredS TargetPort: intstr.IntOrString{IntVal: port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: "None", }, @@ -153,10 +163,12 @@ func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredS func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.DesiredState, error) { var SampleLimit uint64 = 0 - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics != nil && r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitor { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.ServiceMonitor { objectMetadata := r.FluentdObjectMeta(ServiceName+"-buffer-metrics", ComponentFluentd) - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels != nil { - for k, v := range r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels { + if fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels != nil { + for k, v := range fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels { objectMetadata.Labels[k] = v } } @@ -168,16 +180,16 @@ func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.D PodTargetLabels: nil, Endpoints: []v1.Endpoint{{ Port: "buffer-metrics", - Path: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Path, - Interval: v1.Duration(r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Interval), - ScrapeTimeout: v1.Duration(r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Timeout), - HonorLabels: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.HonorLabels, - RelabelConfigs: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Relabelings, - MetricRelabelConfigs: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.MetricsRelabelings, - Scheme: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Scheme, - TLSConfig: r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.TLSConfig, + Path: fluentdSpec.BufferVolumeMetrics.Path, + Interval: v1.Duration(fluentdSpec.BufferVolumeMetrics.Interval), + ScrapeTimeout: v1.Duration(fluentdSpec.BufferVolumeMetrics.Timeout), + HonorLabels: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.HonorLabels, + RelabelConfigs: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Relabelings, + MetricRelabelConfigs: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.MetricsRelabelings, + Scheme: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Scheme, + TLSConfig: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.TLSConfig, }}, - Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd)}, + Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec)}, NamespaceSelector: v1.NamespaceSelector{MatchNames: []string{r.Logging.Spec.ControlNamespace}}, SampleLimit: &SampleLimit, }, @@ -190,6 +202,8 @@ func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.D } func (r *Reconciler) headlessService() (runtime.Object, reconciler.DesiredState, error) { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) desired := &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName+"-headless", ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -199,17 +213,17 @@ func (r *Reconciler) headlessService() (runtime.Object, reconciler.DesiredState, Protocol: corev1.ProtocolTCP, // This port should match the containerport and targetPort will be automatically set to the same // https://github.com/kubernetes/kubernetes/issues/20488 - Port: r.Logging.Spec.FluentdSpec.Port, + Port: fluentdSpec.Port, }, { Name: "udp-fluentd", Protocol: corev1.ProtocolUDP, // This port should match the containerport and targetPort will be automatically set to the same // https://github.com/kubernetes/kubernetes/issues/20488 - Port: r.Logging.Spec.FluentdSpec.Port, + Port: fluentdSpec.Port, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: corev1.ClusterIPNone, }, diff --git a/pkg/resources/fluentd/statefulset.go b/pkg/resources/fluentd/statefulset.go index ab1c313db..8c32d9b0e 100644 --- a/pkg/resources/fluentd/statefulset.go +++ b/pkg/resources/fluentd/statefulset.go @@ -15,6 +15,7 @@ package fluentd import ( + "context" "fmt" "strings" @@ -31,24 +32,25 @@ import ( func (r *Reconciler) statefulset() (runtime.Object, reconciler.DesiredState, error) { spec := r.statefulsetSpec() + fluentdSpec := r.GetFluentdSpec(context.TODO()) - r.Logging.Spec.FluentdSpec.BufferStorageVolume.WithDefaultHostPath( + fluentdSpec.BufferStorageVolume.WithDefaultHostPath( fmt.Sprintf(v1beta1.HostPath, r.Logging.Name, r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName)), ) - if !r.Logging.Spec.FluentdSpec.DisablePvc { - err := r.Logging.Spec.FluentdSpec.BufferStorageVolume.ApplyPVCForStatefulSet(containerName, bufferPath, spec, func(name string) metav1.ObjectMeta { + if !fluentdSpec.DisablePvc { + err := fluentdSpec.BufferStorageVolume.ApplyPVCForStatefulSet(containerName, bufferPath, spec, func(name string) metav1.ObjectMeta { return r.FluentdObjectMeta(name, ComponentFluentd) }) if err != nil { return nil, reconciler.StatePresent, err } } else { - err := r.Logging.Spec.FluentdSpec.BufferStorageVolume.ApplyVolumeForPodSpec(r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName), containerName, bufferPath, &spec.Template.Spec) + err := fluentdSpec.BufferStorageVolume.ApplyVolumeForPodSpec(r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName), containerName, bufferPath, &spec.Template.Spec) if err != nil { return nil, reconciler.StatePresent, err } } - for _, n := range r.Logging.Spec.FluentdSpec.ExtraVolumes { + for _, n := range fluentdSpec.ExtraVolumes { if n.Volume != nil && n.Volume.PersistentVolumeClaim != nil { if err := n.Volume.ApplyPVCForStatefulSet(n.ContainerName, n.Path, spec, func(name string) metav1.ObjectMeta { return r.FluentdObjectMeta(name, ComponentFluentd) @@ -67,12 +69,15 @@ func (r *Reconciler) statefulset() (runtime.Object, reconciler.DesiredState, err Spec: *spec, } - desired.Annotations = util.MergeLabels(desired.Annotations, r.Logging.Spec.FluentdSpec.StatefulSetAnnotations) + desired.Annotations = util.MergeLabels(desired.Annotations, fluentdSpec.StatefulSetAnnotations) return desired, reconciler.StatePresent, nil } func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { + ctx := context.TODO() + fluentdSpec := r.GetFluentdSpec(ctx) + var initContainers []corev1.Container if c := r.tmpDirHackContainer(); c != nil { @@ -81,13 +86,13 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { if c := r.volumeMountHackContainer(); c != nil { initContainers = append(initContainers, *c) } - if i := generateInitContainer(r.Logging.Spec.FluentdSpec); i != nil { + if i := generateInitContainer(fluentdSpec); i != nil { initContainers = append(initContainers, *i) } containers := []corev1.Container{ - fluentContainer(r.Logging.Spec.FluentdSpec), - *newConfigMapReloader(r.Logging.Spec.FluentdSpec), + fluentContainer(fluentdSpec), + *newConfigMapReloader(fluentdSpec), } if c := r.bufferMetricsSidecarContainer(); c != nil { containers = append(containers, *c) @@ -97,9 +102,9 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { } sts := &appsv1.StatefulSetSpec{ - PodManagementPolicy: appsv1.PodManagementPolicyType(r.Logging.Spec.FluentdSpec.Scaling.PodManagementPolicy), + PodManagementPolicy: appsv1.PodManagementPolicyType(fluentdSpec.Scaling.PodManagementPolicy), Selector: &metav1.LabelSelector{ - MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd), + MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), }, Template: corev1.PodTemplateSpec{ ObjectMeta: r.generatePodMeta(), @@ -107,29 +112,29 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { Volumes: r.generateVolume(), ServiceAccountName: r.getServiceAccount(), InitContainers: initContainers, - ImagePullSecrets: r.Logging.Spec.FluentdSpec.Image.ImagePullSecrets, + ImagePullSecrets: fluentdSpec.Image.ImagePullSecrets, Containers: containers, - NodeSelector: r.Logging.Spec.FluentdSpec.NodeSelector, - Tolerations: r.Logging.Spec.FluentdSpec.Tolerations, - Affinity: r.Logging.Spec.FluentdSpec.Affinity, - TopologySpreadConstraints: r.Logging.Spec.FluentdSpec.TopologySpreadConstraints, - PriorityClassName: r.Logging.Spec.FluentdSpec.PodPriorityClassName, - DNSPolicy: r.Logging.Spec.FluentdSpec.DNSPolicy, - DNSConfig: r.Logging.Spec.FluentdSpec.DNSConfig, + NodeSelector: fluentdSpec.NodeSelector, + Tolerations: fluentdSpec.Tolerations, + Affinity: fluentdSpec.Affinity, + TopologySpreadConstraints: fluentdSpec.TopologySpreadConstraints, + PriorityClassName: fluentdSpec.PodPriorityClassName, + DNSPolicy: fluentdSpec.DNSPolicy, + DNSConfig: fluentdSpec.DNSConfig, SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsNonRoot, - FSGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.FSGroup, - RunAsUser: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsUser, - RunAsGroup: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.RunAsGroup, - SeccompProfile: r.Logging.Spec.FluentdSpec.Security.PodSecurityContext.SeccompProfile, + RunAsNonRoot: fluentdSpec.Security.PodSecurityContext.RunAsNonRoot, + FSGroup: fluentdSpec.Security.PodSecurityContext.FSGroup, + RunAsUser: fluentdSpec.Security.PodSecurityContext.RunAsUser, + RunAsGroup: fluentdSpec.Security.PodSecurityContext.RunAsGroup, + SeccompProfile: fluentdSpec.Security.PodSecurityContext.SeccompProfile, }, }, }, ServiceName: r.Logging.QualifiedName(ServiceName + "-headless"), } - if r.Logging.Spec.FluentdSpec.Scaling.Replicas > 0 { - sts.Replicas = util.IntPointer(cast.ToInt32(r.Logging.Spec.FluentdSpec.Scaling.Replicas)) + if fluentdSpec.Scaling.Replicas > 0 { + sts.Replicas = util.IntPointer(cast.ToInt32(fluentdSpec.Scaling.Replicas)) } return sts @@ -168,11 +173,12 @@ func fluentContainer(spec *v1beta1.FluentdSpec) corev1.Container { } func (r *Reconciler) generatePodMeta() metav1.ObjectMeta { + fluentdSpec := r.GetFluentdSpec(context.TODO()) meta := metav1.ObjectMeta{ - Labels: r.Logging.GetFluentdLabels(ComponentFluentd), + Labels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), } - if r.Logging.Spec.FluentdSpec.Annotations != nil { - meta.Annotations = r.Logging.Spec.FluentdSpec.Annotations + if fluentdSpec.Annotations != nil { + meta.Annotations = fluentdSpec.Annotations } return meta } @@ -285,6 +291,7 @@ func generateVolumeMounts(spec *v1beta1.FluentdSpec) []corev1.VolumeMount { } func (r *Reconciler) generateVolume() (v []corev1.Volume) { + fluentdSpec := r.GetFluentdSpec(context.TODO()) v = []corev1.Volume{ { Name: "config", @@ -304,14 +311,14 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { }, } - if isFluentdReadOnlyRootFilesystem(r.Logging.Spec.FluentdSpec) { + if isFluentdReadOnlyRootFilesystem(fluentdSpec) { v = append(v, corev1.Volume{ Name: "tmp", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, }) } - if r.Logging.Spec.FluentdSpec.CompressConfigFile { + if fluentdSpec.CompressConfigFile { v = append(v, corev1.Volume{ Name: "app-config", VolumeSource: corev1.VolumeSource{ @@ -337,12 +344,12 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { }) } - if r.Logging.Spec.FluentdSpec.TLS.Enabled { + if fluentdSpec.TLS.Enabled { tlsRelatedVolume := corev1.Volume{ Name: "fluentd-tls", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: r.Logging.Spec.FluentdSpec.TLS.SecretName, + SecretName: fluentdSpec.TLS.SecretName, }, }, } @@ -352,14 +359,15 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { } func (r *Reconciler) tmpDirHackContainer() *corev1.Container { - if isFluentdReadOnlyRootFilesystem(r.Logging.Spec.FluentdSpec) { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if isFluentdReadOnlyRootFilesystem(fluentdSpec) { return &corev1.Container{ Command: []string{"sh", "-c", "mkdir -p /mnt/tmp/fluentd/; chmod +t /mnt/tmp/fluentd"}, - Image: r.Logging.Spec.FluentdSpec.Image.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.Image.PullPolicy), + Image: fluentdSpec.Image.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Image.PullPolicy), Name: "tmp-dir-hack", - Resources: r.Logging.Spec.FluentdSpec.Resources, - SecurityContext: r.Logging.Spec.FluentdSpec.Security.SecurityContext, + Resources: fluentdSpec.Resources, + SecurityContext: fluentdSpec.Security.SecurityContext, VolumeMounts: []corev1.VolumeMount{ { Name: "tmp", @@ -371,11 +379,12 @@ func (r *Reconciler) tmpDirHackContainer() *corev1.Container { } func (r *Reconciler) volumeMountHackContainer() *corev1.Container { - if r.Logging.Spec.FluentdSpec.VolumeMountChmod { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if fluentdSpec.VolumeMountChmod { return &corev1.Container{ Name: "volume-mount-hack", - Image: r.Logging.Spec.FluentdSpec.VolumeModImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.VolumeModImage.PullPolicy), + Image: fluentdSpec.VolumeModImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.VolumeModImage.PullPolicy), Command: []string{"sh", "-c", "chmod -R 777 " + bufferPath}, VolumeMounts: []corev1.VolumeMount{ { @@ -389,15 +398,17 @@ func (r *Reconciler) volumeMountHackContainer() *corev1.Container { } func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics != nil { + fluentdSpec := r.GetFluentdSpec(context.TODO()) + + if fluentdSpec.BufferVolumeMetrics != nil { port := int32(defaultBufferVolumeMetricsPort) - if r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Port != 0 { - port = r.Logging.Spec.FluentdSpec.BufferVolumeMetrics.Port + if fluentdSpec.BufferVolumeMetrics.Port != 0 { + port = fluentdSpec.BufferVolumeMetrics.Port } portParam := fmt.Sprintf("--web.listen-address=:%d", port) args := []string{portParam} - if len(r.Logging.Spec.FluentdSpec.BufferVolumeArgs) != 0 { - args = append(args, r.Logging.Spec.FluentdSpec.BufferVolumeArgs...) + if len(fluentdSpec.BufferVolumeArgs) != 0 { + args = append(args, fluentdSpec.BufferVolumeArgs...) } else { args = append(args, "--collector.disable-defaults", "--collector.filesystem", "--collector.textfile", "--collector.textfile.directory=/prometheus/node_exporter/textfile_collector/") } @@ -407,8 +418,8 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { return &corev1.Container{ Name: "buffer-metrics-sidecar", - Image: r.Logging.Spec.FluentdSpec.BufferVolumeImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(r.Logging.Spec.FluentdSpec.BufferVolumeImage.PullPolicy), + Image: fluentdSpec.BufferVolumeImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(fluentdSpec.BufferVolumeImage.PullPolicy), Args: []string{ "--exec", nodeExporterCmd, "--exec", bufferSizeCmd, @@ -419,15 +430,15 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { Value: bufferPath, }, }, - Ports: generatePortsBufferVolumeMetrics(r.Logging.Spec.FluentdSpec), + Ports: generatePortsBufferVolumeMetrics(fluentdSpec), VolumeMounts: []corev1.VolumeMount{ { Name: r.bufferVolumeName(), MountPath: bufferPath, }, }, - Resources: r.Logging.Spec.FluentdSpec.BufferVolumeResources, - SecurityContext: r.Logging.Spec.FluentdSpec.Security.SecurityContext, + Resources: fluentdSpec.BufferVolumeResources, + SecurityContext: fluentdSpec.Security.SecurityContext, } } return nil @@ -435,8 +446,9 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { func (r *Reconciler) bufferVolumeName() string { volumeName := r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName) - if r.Logging.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim != nil { - volumeName = r.Logging.QualifiedName(r.Logging.Spec.FluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) + fluentdSpec := r.GetFluentdSpec(context.TODO()) + if fluentdSpec.BufferStorageVolume.PersistentVolumeClaim != nil { + volumeName = r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) } return volumeName } diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index f9563d080..0c0023da8 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -158,6 +158,15 @@ func NewValidationReconciler( flow.Status.ProblemsCount = len(flow.Status.Problems) } + if resources.Fluentd.Configuration != nil && resources.Logging.Spec.FluentdSpec != nil { + resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration found is set as well, clearing inline", resources.Fluentd.Configuration.Name)) + resources.Logging.Spec.FluentdSpec = nil + } + + if fluentd := resources.GetFluentd(); fluentd != nil { + registerForPatching(fluentd) + } + for i := range resources.SyslogNG.ClusterFlows { flow := &resources.SyslogNG.ClusterFlows[i] registerForPatching(flow) diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 6e4c53b5f..edff4038b 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -338,13 +338,13 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 return res, nil } -func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.FluentdConfig, error) { - var list v1beta1.FluentdConfigList +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { + var list v1beta1.FluentdList if err := r.Client.List(ctx, &list); err != nil { return nil, err } - var res []v1beta1.FluentdConfig + var res []v1beta1.Fluentd for _, i := range list.Items { if i.Name == logging.Spec.FluentdRef { res = append(res, i) @@ -354,7 +354,9 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging return nil, errors.New("multiple fluentd configurations found, only one is allowed") } if len(res) != 0 { - return &res[0], nil + // Detached fluentd configuration found + err := res[0].Spec.SetDefaults() + return &res[0], err } else { return nil, nil } diff --git a/pkg/resources/model/resources.go b/pkg/resources/model/resources.go index 949beb628..de9e3b5a3 100644 --- a/pkg/resources/model/resources.go +++ b/pkg/resources/model/resources.go @@ -29,21 +29,27 @@ type LoggingResources struct { WatchNamespaces []string } -func (l LoggingResources) FluentdSpec() *v1beta1.FluentdSpec { +func (l LoggingResources) GetFluentd() *v1beta1.Fluentd { if l.Fluentd.Configuration != nil { - return &l.Fluentd.Configuration.Spec - } else if l.Logging.Spec.FluentdSpec != nil { - return l.Logging.Spec.FluentdSpec + return l.Fluentd.Configuration } return nil } +func (l LoggingResources) GetFluentdSpec() *v1beta1.FluentdSpec { + if detachedFluentd := l.GetFluentd(); detachedFluentd != nil { + return &detachedFluentd.Spec + } + + return l.Logging.Spec.FluentdSpec +} + type FluentdLoggingResources struct { ClusterFlows []v1beta1.ClusterFlow ClusterOutputs ClusterOutputs Flows []v1beta1.Flow Outputs Outputs - Configuration *v1beta1.FluentdConfig + Configuration *v1beta1.Fluentd } type SyslogNGLoggingResources struct { diff --git a/pkg/resources/model/system.go b/pkg/resources/model/system.go index 1439f1bc1..5ac622879 100644 --- a/pkg/resources/model/system.go +++ b/pkg/resources/model/system.go @@ -32,7 +32,7 @@ import ( func CreateSystem(resources LoggingResources, secrets SecretLoaderFactory, logger logr.Logger) (*types.System, error) { logging := resources.Logging - fluentdSpec := resources.FluentdSpec() + fluentdSpec := resources.GetFluentdSpec() var forwardInput *input.ForwardInputConfig if fluentdSpec != nil && fluentdSpec.ForwardInputConfig != nil { diff --git a/pkg/resources/nodeagent/configsecret.go b/pkg/resources/nodeagent/configsecret.go index 17fbb95d8..b088bf91b 100644 --- a/pkg/resources/nodeagent/configsecret.go +++ b/pkg/resources/nodeagent/configsecret.go @@ -318,6 +318,10 @@ func generateUpstreamConfig(input fluentBitConfig) (string, error) { } func (n *nodeAgentInstance) generateUpstreamNode(index int32) upstreamNode { + fluentdSpec := n.logging.Spec.FluentdSpec + if detachedFluentd := fluentd.GetFluentd(context.TODO(), n.reconciler.Client, n.reconciler.Log, n.logging.Spec.ControlNamespace); detachedFluentd != nil { + fluentdSpec = &detachedFluentd.Spec + } podName := n.FluentdQualifiedName(fmt.Sprintf("%s-%d", fluentd.ComponentFluentd, index)) return upstreamNode{ Name: podName, @@ -326,6 +330,6 @@ func (n *nodeAgentInstance) generateUpstreamNode(index int32) upstreamNode { n.FluentdQualifiedName(fluentd.ServiceName+"-headless"), n.logging.Spec.ControlNamespace, n.logging.ClusterDomainAsSuffix()), - Port: n.logging.Spec.FluentdSpec.Port, + Port: fluentdSpec.Port, } } diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index 57284291a..91b46eec7 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -108,44 +108,44 @@ type FluentdSpec struct { SidecarContainers []corev1.Container `json:"sidecarContainers,omitempty"` } -// +name:"FluentdConfig" +// +name:"Fluentd" // +weight:"200" -type _hugoFluentdConfig interface{} //nolint:deadcode,unused +type _hugoFluent interface{} //nolint:deadcode,unused -// +name:"FluentdConfig" +// +name:"Fluent" // +version:"v1beta1" -// +description:"FluentdConfig is a reference to the desired Fluentd state" -type _metaFluentdConfig interface{} //nolint:deadcode,unused +// +description:"Fluentd is a reference to the desired Fluentd state" +type _metaFluentd interface{} //nolint:deadcode,unused // +kubebuilder:object:root=true // +kubebuilder:resource:categories=logging-all // +kubebuilder:subresource:status // +kubebuilder:storageversion -// NodeAgent -type FluentdConfig struct { +// Fluentd +type Fluentd struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec FluentdSpec `json:"spec,omitempty"` - Status NodeAgentStatus `json:"status,omitempty"` + Spec FluentdSpec `json:"spec,omitempty"` + Status FluentdStatus `json:"status,omitempty"` } -// FluentdConfigStatus -type FluentdConfigStatus struct { +// FluentdStatus +type FluentdStatus struct { } // +kubebuilder:object:root=true -// FluentdConfigList -type FluentdConfigList struct { +// FluentdList +type FluentdList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []FluentdConfig `json:"items"` + Items []Fluentd `json:"items"` } func init() { - SchemeBuilder.Register(&FluentdConfig{}, &FluentdConfigList{}) + SchemeBuilder.Register(&Fluentd{}, &FluentdList{}) } // +kubebuilder:object:generate=true diff --git a/pkg/sdk/logging/api/v1beta1/logging_types.go b/pkg/sdk/logging/api/v1beta1/logging_types.go index 897fc1d0b..eadfb58d9 100644 --- a/pkg/sdk/logging/api/v1beta1/logging_types.go +++ b/pkg/sdk/logging/api/v1beta1/logging_types.go @@ -189,8 +189,10 @@ func (l *Logging) SetDefaults() error { if !l.Spec.FlowConfigCheckDisabled && l.Status.ConfigCheckResults == nil { l.Status.ConfigCheckResults = make(map[string]bool) } - if err := l.Spec.FluentdSpec.SetDefaults(); err != nil { - return err + if len(l.Spec.FluentdRef) == 0 { + if err := l.Spec.FluentdSpec.SetDefaults(); err != nil { + return err + } } if l.Spec.ConfigCheck.TimeoutSeconds == 0 { l.Spec.ConfigCheck.TimeoutSeconds = 10 @@ -460,11 +462,11 @@ func persistentVolumeModePointer(mode v1.PersistentVolumeMode) *v1.PersistentVol } // FluentdObjectMeta creates an objectMeta for resource fluentd -func (l *Logging) FluentdObjectMeta(name, component string) metav1.ObjectMeta { +func (l *Logging) FluentdObjectMeta(name, component string, f FluentdSpec) metav1.ObjectMeta { o := metav1.ObjectMeta{ Name: l.QualifiedName(name), Namespace: l.Spec.ControlNamespace, - Labels: l.GetFluentdLabels(component), + Labels: l.GetFluentdLabels(component, f), OwnerReferences: []metav1.OwnerReference{ { APIVersion: l.APIVersion, @@ -478,9 +480,9 @@ func (l *Logging) FluentdObjectMeta(name, component string) metav1.ObjectMeta { return o } -func (l *Logging) GetFluentdLabels(component string) map[string]string { +func (l *Logging) GetFluentdLabels(component string, f FluentdSpec) map[string]string { return util.MergeLabels( - l.Spec.FluentdSpec.Labels, + f.Labels, map[string]string{ "app.kubernetes.io/name": "fluentd", "app.kubernetes.io/component": component, diff --git a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go index a63bbee26..9ce8e734a 100644 --- a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go +++ b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go @@ -1298,7 +1298,7 @@ func (in *FluentbitTLS) DeepCopy() *FluentbitTLS { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentdConfig) DeepCopyInto(out *FluentdConfig) { +func (in *Fluentd) DeepCopyInto(out *Fluentd) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -1306,71 +1306,24 @@ func (in *FluentdConfig) DeepCopyInto(out *FluentdConfig) { out.Status = in.Status } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfig. -func (in *FluentdConfig) DeepCopy() *FluentdConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Fluentd. +func (in *Fluentd) DeepCopy() *Fluentd { if in == nil { return nil } - out := new(FluentdConfig) + out := new(Fluentd) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *FluentdConfig) DeepCopyObject() runtime.Object { +func (in *Fluentd) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentdConfigList) DeepCopyInto(out *FluentdConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]FluentdConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigList. -func (in *FluentdConfigList) DeepCopy() *FluentdConfigList { - if in == nil { - return nil - } - out := new(FluentdConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *FluentdConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentdConfigStatus) DeepCopyInto(out *FluentdConfigStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigStatus. -func (in *FluentdConfigStatus) DeepCopy() *FluentdConfigStatus { - if in == nil { - return nil - } - out := new(FluentdConfigStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdDrainConfig) DeepCopyInto(out *FluentdDrainConfig) { *out = *in @@ -1412,6 +1365,38 @@ func (in *FluentdDrainConfig) DeepCopy() *FluentdDrainConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdList) DeepCopyInto(out *FluentdList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Fluentd, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdList. +func (in *FluentdList) DeepCopy() *FluentdList { + if in == nil { + return nil + } + out := new(FluentdList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentdList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdScaling) DeepCopyInto(out *FluentdScaling) { *out = *in @@ -1594,6 +1579,21 @@ func (in *FluentdSpec) DeepCopy() *FluentdSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdStatus) DeepCopyInto(out *FluentdStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdStatus. +func (in *FluentdStatus) DeepCopy() *FluentdStatus { + if in == nil { + return nil + } + out := new(FluentdStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdTLS) DeepCopyInto(out *FluentdTLS) { *out = *in From cfd49b289cf5dc9861cc9a8199bff6b2863ee892 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 8 Nov 2023 16:49:51 +0100 Subject: [PATCH 06/28] conversion: add fluentdRef Signed-off-by: Szilard Parrag --- pkg/sdk/logging/api/v1beta1/conversion.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/sdk/logging/api/v1beta1/conversion.go b/pkg/sdk/logging/api/v1beta1/conversion.go index ca2144fe7..706379e4a 100644 --- a/pkg/sdk/logging/api/v1beta1/conversion.go +++ b/pkg/sdk/logging/api/v1beta1/conversion.go @@ -47,12 +47,13 @@ func APITypes() []runtime.Object { func (l *Logging) Default() { Log.Info("Defaulter called for", "logging", l) - if l.Spec.FluentdSpec != nil { - if l.Spec.FluentdSpec.Scaling == nil { - l.Spec.FluentdSpec.Scaling = new(FluentdScaling) + if l.Spec.FluentdSpec != nil && l.Spec.FluentdRef == "" { + fluentdSpec := l.Spec.FluentdSpec + if fluentdSpec.Scaling == nil { + fluentdSpec.Scaling = new(FluentdScaling) } - if l.Spec.FluentdSpec.Scaling.PodManagementPolicy == "" { - l.Spec.FluentdSpec.Scaling.PodManagementPolicy = string(appsv1.ParallelPodManagement) + if fluentdSpec.Scaling.PodManagementPolicy == "" { + fluentdSpec.Scaling.PodManagementPolicy = string(appsv1.ParallelPodManagement) } } else { Log.Info("l.Spec.FluentdSpec is missing, skipping Defaulter") From 34d7239081036f0dadc799f0e3457a7d1c494b5e Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 20 Nov 2023 09:34:09 +0100 Subject: [PATCH 07/28] e2e: add detached fluentd Signed-off-by: Szilard Parrag --- .../fluentd_aggregator_detached_test.go | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go diff --git a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go new file mode 100644 index 000000000..fc4be7a3d --- /dev/null +++ b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go @@ -0,0 +1,227 @@ +// Copyright © 2021 Cisco Systems, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fluentd_aggregator + +import ( + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/cisco-open/operator-tools/pkg/utils" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/cluster" + + "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" + "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/output" + + "github.com/kube-logging/logging-operator/e2e/common" + "github.com/kube-logging/logging-operator/e2e/common/cond" + "github.com/kube-logging/logging-operator/e2e/common/setup" +) + +var TestTempDir string + +func init() { + var ok bool + TestTempDir, ok = os.LookupEnv("PROJECT_DIR") + if !ok { + TestTempDir = "../.." + } + TestTempDir = filepath.Join(TestTempDir, "build/_test") + err := os.MkdirAll(TestTempDir, os.FileMode(0755)) + if err != nil { + panic(err) + } +} + +func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { + common.Initialize(t) + ns := "testing-1" + releaseNameOverride := "e2e" + testTag := "test.fluentd_aggregator_multiworker_detached" + outputName := "test-output" + flowName := "test-flow" + common.WithCluster("fluentd-1-detached", t, func(t *testing.T, c common.Cluster) { + setup.LoggingOperator(t, c, setup.LoggingOperatorOptionFunc(func(options *setup.LoggingOperatorOptions) { + options.Namespace = ns + options.NameOverride = releaseNameOverride + })) + + ctx := context.Background() + + logging := v1beta1.Logging{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fluentd-aggregator-multiworker-test", + Namespace: ns, + }, + Spec: v1beta1.LoggingSpec{ + EnableRecreateWorkloadOnImmutableFieldChange: true, + ControlNamespace: ns, + FluentbitSpec: &v1beta1.FluentbitSpec{ + Network: &v1beta1.FluentbitNetwork{ + Keepalive: utils.BoolPointer(false), + }, + }, + FluentdRef: "detached-fluentd", + }, + } + common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) + + fluentd := v1beta1.Fluentd{ + ObjectMeta: metav1.ObjectMeta{ + Name: "detached-fluentd", + Namespace: ns, + }, + Spec: v1beta1.FluentdSpec{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("200M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("50M"), + }, + }, + BufferVolumeMetrics: &v1beta1.Metrics{}, + Scaling: &v1beta1.FluentdScaling{ + Replicas: 1, + Drain: v1beta1.FluentdDrainConfig{ + Enabled: true, + }, + }, + Workers: 2, + }, + } + + common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) + t.Logf("fluentd is: %v", fluentd) + tags := "time" + output := v1beta1.Output{ + ObjectMeta: metav1.ObjectMeta{ + Name: outputName, + Namespace: ns, + }, + Spec: v1beta1.OutputSpec{ + HTTPOutput: &output.HTTPOutputConfig{ + Endpoint: fmt.Sprintf("http://%s-test-receiver:8080/%s", releaseNameOverride, testTag), + ContentType: "application/json", + Buffer: &output.Buffer{ + Type: "file", + Tags: &tags, + Timekey: "1s", + TimekeyWait: "0s", + }, + }, + }, + } + + producerLabels := map[string]string{ + "my-unique-label": "log-producer", + } + + common.RequireNoError(t, c.GetClient().Create(ctx, &output)) + flow := v1beta1.Flow{ + ObjectMeta: metav1.ObjectMeta{ + Name: flowName, + Namespace: ns, + }, + Spec: v1beta1.FlowSpec{ + Match: []v1beta1.Match{ + { + Select: &v1beta1.Select{ + Labels: producerLabels, + }, + }, + }, + LocalOutputRefs: []string{output.Name}, + }, + } + common.RequireNoError(t, c.GetClient().Create(ctx, &flow)) + + aggregatorLabels := map[string]string{ + "app.kubernetes.io/name": "fluentd", + "app.kubernetes.io/component": "fluentd", + } + operatorLabels := map[string]string{ + "app.kubernetes.io/name": releaseNameOverride, + } + + go setup.LogProducer(t, c.GetClient(), setup.LogProducerOptionFunc(func(options *setup.LogProducerOptions) { + options.Namespace = ns + options.Labels = producerLabels + })) + + require.Eventually(t, func() bool { + if operatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(operatorLabels))(); !operatorRunning { + t.Log("waiting for the operator") + return false + } + if producerRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(producerLabels))(); !producerRunning { + t.Log("waiting for the producer") + return false + } + if aggregatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(aggregatorLabels)); !aggregatorRunning() { + t.Log("waiting for the aggregator") + return false + } + + cmd := common.CmdEnv(exec.Command("kubectl", + "logs", + "-n", ns, + "-l", fmt.Sprintf("app.kubernetes.io/name=%s-test-receiver", releaseNameOverride)), c) + rawOut, err := cmd.Output() + if err != nil { + t.Logf("failed to get log consumer logs: %v", err) + return false + } + t.Logf("log consumer logs: %s", rawOut) + return strings.Contains(string(rawOut), testTag) + }, 5*time.Minute, 3*time.Second) + + }, func(t *testing.T, c common.Cluster) error { + path := filepath.Join(TestTempDir, fmt.Sprintf("cluster-%s.log", t.Name())) + t.Logf("Printing cluster logs to %s", path) + return c.PrintLogs(common.PrintLogConfig{ + Namespaces: []string{ns, "default"}, + FilePath: path, + Limit: 100 * 1000, + }) + }, func(o *cluster.Options) { + if o.Scheme == nil { + o.Scheme = runtime.NewScheme() + } + common.RequireNoError(t, v1beta1.AddToScheme(o.Scheme)) + common.RequireNoError(t, apiextensionsv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, appsv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, batchv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, corev1.AddToScheme(o.Scheme)) + common.RequireNoError(t, rbacv1.AddToScheme(o.Scheme)) + }) +} From 00b0f44ab1b1938a3247b6e7d9464346540546a0 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Fri, 10 Nov 2023 15:37:15 +0100 Subject: [PATCH 08/28] fluentd: allow nameless case, or multiple, but named Signed-off-by: Szilard Parrag --- ...entd_aggregator_detached_single_unnamed.go | 226 ++++++++++++++++++ pkg/resources/model/repository.go | 27 ++- 2 files changed, 241 insertions(+), 12 deletions(-) create mode 100644 e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go new file mode 100644 index 000000000..a3b056e26 --- /dev/null +++ b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go @@ -0,0 +1,226 @@ +// Copyright © 2021 Cisco Systems, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fluentd_aggregator + +import ( + "context" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/cisco-open/operator-tools/pkg/utils" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/cluster" + + "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" + "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/output" + + "github.com/kube-logging/logging-operator/e2e/common" + "github.com/kube-logging/logging-operator/e2e/common/cond" + "github.com/kube-logging/logging-operator/e2e/common/setup" +) + +var TestTempDirUnnamed string + +func init() { + var ok bool + TestTempDirUnnamed, ok = os.LookupEnv("PROJECT_DIR") + if !ok { + TestTempDirUnnamed = "../.." + } + TestTempDirUnnamed = filepath.Join(TestTempDirUnnamed, "build/_test") + err := os.MkdirAll(TestTempDirUnnamed, os.FileMode(0755)) + if err != nil { + panic(err) + } +} + +func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { + common.Initialize(t) + ns := "testing-1" + releaseNameOverride := "e2e" + testTag := "test.fluentd_aggregator_multiworker_multiple_detached" + outputName := "test-output" + flowName := "test-flow" + common.WithCluster("fluentd-1-detached-unnamed", t, func(t *testing.T, c common.Cluster) { + setup.LoggingOperator(t, c, setup.LoggingOperatorOptionFunc(func(options *setup.LoggingOperatorOptions) { + options.Namespace = ns + options.NameOverride = releaseNameOverride + })) + + ctx := context.Background() + + logging := v1beta1.Logging{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fluentd-aggregator-multiworker-test", + Namespace: ns, + }, + Spec: v1beta1.LoggingSpec{ + EnableRecreateWorkloadOnImmutableFieldChange: true, + ControlNamespace: ns, + FluentbitSpec: &v1beta1.FluentbitSpec{ + Network: &v1beta1.FluentbitNetwork{ + Keepalive: utils.BoolPointer(false), + }, + }, + }, + } + common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) + + fluentd := v1beta1.Fluentd{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name-not-to-be-used", + Namespace: ns, + }, + Spec: v1beta1.FluentdSpec{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("200M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("50M"), + }, + }, + BufferVolumeMetrics: &v1beta1.Metrics{}, + Scaling: &v1beta1.FluentdScaling{ + Replicas: 1, + Drain: v1beta1.FluentdDrainConfig{ + Enabled: true, + }, + }, + Workers: 2, + }, + } + + common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) + t.Logf("fluentd is: %v", fluentd) + tags := "time" + output := v1beta1.Output{ + ObjectMeta: metav1.ObjectMeta{ + Name: outputName, + Namespace: ns, + }, + Spec: v1beta1.OutputSpec{ + HTTPOutput: &output.HTTPOutputConfig{ + Endpoint: fmt.Sprintf("http://%s-test-receiver:8080/%s", releaseNameOverride, testTag), + ContentType: "application/json", + Buffer: &output.Buffer{ + Type: "file", + Tags: &tags, + Timekey: "1s", + TimekeyWait: "0s", + }, + }, + }, + } + + producerLabels := map[string]string{ + "my-unique-label": "log-producer", + } + + common.RequireNoError(t, c.GetClient().Create(ctx, &output)) + flow := v1beta1.Flow{ + ObjectMeta: metav1.ObjectMeta{ + Name: flowName, + Namespace: ns, + }, + Spec: v1beta1.FlowSpec{ + Match: []v1beta1.Match{ + { + Select: &v1beta1.Select{ + Labels: producerLabels, + }, + }, + }, + LocalOutputRefs: []string{output.Name}, + }, + } + common.RequireNoError(t, c.GetClient().Create(ctx, &flow)) + + aggregatorLabels := map[string]string{ + "app.kubernetes.io/name": "fluentd", + "app.kubernetes.io/component": "fluentd", + } + operatorLabels := map[string]string{ + "app.kubernetes.io/name": releaseNameOverride, + } + + go setup.LogProducer(t, c.GetClient(), setup.LogProducerOptionFunc(func(options *setup.LogProducerOptions) { + options.Namespace = ns + options.Labels = producerLabels + })) + + require.Eventually(t, func() bool { + if operatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(operatorLabels))(); !operatorRunning { + t.Log("waiting for the operator") + return false + } + if producerRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(producerLabels))(); !producerRunning { + t.Log("waiting for the producer") + return false + } + if aggregatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(aggregatorLabels)); !aggregatorRunning() { + t.Log("waiting for the aggregator") + return false + } + + cmd := common.CmdEnv(exec.Command("kubectl", + "logs", + "-n", ns, + "-l", fmt.Sprintf("app.kubernetes.io/name=%s-test-receiver", releaseNameOverride)), c) + rawOut, err := cmd.Output() + if err != nil { + t.Logf("failed to get log consumer logs: %v", err) + return false + } + t.Logf("log consumer logs: %s", rawOut) + return strings.Contains(string(rawOut), testTag) + }, 5*time.Minute, 3*time.Second) + + }, func(t *testing.T, c common.Cluster) error { + path := filepath.Join(TestTempDirUnnamed, fmt.Sprintf("cluster-%s.log", t.Name())) + t.Logf("Printing cluster logs to %s", path) + return c.PrintLogs(common.PrintLogConfig{ + Namespaces: []string{ns, "default"}, + FilePath: path, + Limit: 100 * 1000, + }) + }, func(o *cluster.Options) { + if o.Scheme == nil { + o.Scheme = runtime.NewScheme() + } + common.RequireNoError(t, v1beta1.AddToScheme(o.Scheme)) + common.RequireNoError(t, apiextensionsv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, appsv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, batchv1.AddToScheme(o.Scheme)) + common.RequireNoError(t, corev1.AddToScheme(o.Scheme)) + common.RequireNoError(t, rbacv1.AddToScheme(o.Scheme)) + }) +} diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index edff4038b..0cd0a0c4f 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -345,21 +345,24 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging } var res []v1beta1.Fluentd - for _, i := range list.Items { - if i.Name == logging.Spec.FluentdRef { - res = append(res, i) - } + res = append(res, list.Items...) + if len(res) < 1 { + return nil, nil } + + // Multiple detached fluentds if len(res) > 1 { - return nil, errors.New("multiple fluentd configurations found, only one is allowed") - } - if len(res) != 0 { - // Detached fluentd configuration found - err := res[0].Spec.SetDefaults() - return &res[0], err - } else { - return nil, nil + for _, i := range res { + // Explicit reference is set and found + if i.Name == logging.Spec.FluentdRef { + err := i.Spec.SetDefaults() + return &i, err + } + } + return nil, errors.New("multiple fluentd configurations found, could't associate it with logging") } + err := res[0].Spec.SetDefaults() + return &res[0], err } func (r LoggingResourceRepository) LoggingRoutesFor(ctx context.Context, logging v1beta1.Logging) ([]v1beta1.LoggingRoute, error) { From 5313a19117b82c1fbc9ca0b49e8978c3271da99a Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 20 Nov 2023 09:35:28 +0100 Subject: [PATCH 09/28] add generated files Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_fluentds.yaml | 2284 +++++++++++++++++ .../logging.banzaicloud.io_fluentds.yaml | 2284 +++++++++++++++++ 2 files changed, 4568 insertions(+) create mode 100644 charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml create mode 100644 config/crd/bases/logging.banzaicloud.io_fluentds.yaml diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml new file mode 100644 index 000000000..2903d321f --- /dev/null +++ b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml @@ -0,0 +1,2284 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.0 + creationTimestamp: null + name: fluentds.logging.banzaicloud.io +spec: + group: logging.banzaicloud.io + names: + categories: + - logging-all + kind: Fluentd + listKind: FluentdList + plural: fluentds + singular: fluentd + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + additionalProperties: + type: string + type: object + bufferStorageVolume: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + bufferVolumeArgs: + items: + type: string + type: array + bufferVolumeImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + bufferVolumeMetrics: + properties: + interval: + type: string + path: + type: string + port: + format: int32 + type: integer + prometheusAnnotations: + type: boolean + prometheusRules: + type: boolean + serviceMonitor: + type: boolean + serviceMonitorConfig: + properties: + additionalLabels: + additionalProperties: + type: string + type: object + honorLabels: + type: boolean + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + serverName: + type: string + type: object + type: object + timeout: + type: string + type: object + bufferVolumeResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + compressConfigFile: + type: boolean + configCheckAnnotations: + additionalProperties: + type: string + type: object + configCheckResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + configReloaderImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + configReloaderResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + disablePvc: + type: boolean + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + searches: + items: + type: string + type: array + type: object + dnsPolicy: + type: string + enableMsgpackTimeSupport: + type: boolean + envVars: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + extraArgs: + items: + type: string + type: array + extraVolumes: + items: + properties: + containerName: + type: string + path: + type: string + volume: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + volumeName: + type: string + type: object + type: array + fluentLogDestination: + type: string + fluentOutLogrotate: + properties: + age: + type: string + enabled: + type: boolean + path: + type: string + size: + type: string + required: + - enabled + type: object + fluentdPvcSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + forwardInputConfig: + properties: + add_tag_prefix: + type: string + bind: + type: string + chunk_size_limit: + type: string + chunk_size_warn_limit: + type: string + deny_keepalive: + type: boolean + linger_timeout: + type: integer + port: + type: string + resolve_hostname: + type: boolean + security: + properties: + allow_anonymous_source: + type: boolean + self_hostname: + type: string + shared_key: + type: string + user_auth: + type: boolean + required: + - self_hostname + - shared_key + type: object + send_keepalive_packet: + type: boolean + skip_invalid_event: + type: boolean + source_address_key: + type: string + sourceHostnameKey: + type: string + tag: + type: string + transport: + properties: + ca_cert_path: + type: string + ca_path: + type: string + ca_private_key_passphrase: + type: string + ca_private_key_path: + type: string + cert_path: + type: string + ciphers: + type: string + client_cert_auth: + type: boolean + insecure: + type: boolean + private_key_passphrase: + type: string + private_key_path: + type: string + protocol: + type: string + version: + type: string + type: object + type: object + ignoreRepeatedLogInterval: + type: string + ignoreSameLogInterval: + type: string + image: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + livenessDefaultCheck: + type: boolean + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + logLevel: + type: string + metrics: + properties: + interval: + type: string + path: + type: string + port: + format: int32 + type: integer + prometheusAnnotations: + type: boolean + prometheusRules: + type: boolean + serviceMonitor: + type: boolean + serviceMonitorConfig: + properties: + additionalLabels: + additionalProperties: + type: string + type: object + honorLabels: + type: boolean + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + serverName: + type: string + type: object + type: object + timeout: + type: string + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podPriorityClassName: + type: string + port: + format: int32 + type: integer + readinessDefaultCheck: + properties: + bufferFileNumber: + type: boolean + bufferFileNumberMax: + format: int32 + type: integer + bufferFreeSpace: + type: boolean + bufferFreeSpaceThreshold: + format: int32 + type: integer + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + rootDir: + type: string + scaling: + properties: + drain: + properties: + annotations: + additionalProperties: + type: string + type: object + deleteVolume: + type: boolean + enabled: + type: boolean + image: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + pauseImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + type: object + podManagementPolicy: + type: string + replicas: + type: integer + type: object + security: + properties: + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + podSecurityPolicyCreate: + type: boolean + roleBasedAccessControlCreate: + type: boolean + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + type: object + serviceAccount: + properties: + automountServiceAccountToken: + type: boolean + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + secrets: + items: + properties: + apiVersion: + type: string + fieldPath: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + type: array + type: object + statefulsetAnnotations: + additionalProperties: + type: string + type: object + tls: + properties: + enabled: + type: boolean + secretName: + type: string + sharedKey: + type: string + required: + - enabled + type: object + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeModImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + volumeMountChmod: + type: boolean + workers: + format: int32 + type: integer + type: object + status: + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml new file mode 100644 index 000000000..2903d321f --- /dev/null +++ b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml @@ -0,0 +1,2284 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.0 + creationTimestamp: null + name: fluentds.logging.banzaicloud.io +spec: + group: logging.banzaicloud.io + names: + categories: + - logging-all + kind: Fluentd + listKind: FluentdList + plural: fluentds + singular: fluentd + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + annotations: + additionalProperties: + type: string + type: object + bufferStorageVolume: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + bufferVolumeArgs: + items: + type: string + type: array + bufferVolumeImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + bufferVolumeMetrics: + properties: + interval: + type: string + path: + type: string + port: + format: int32 + type: integer + prometheusAnnotations: + type: boolean + prometheusRules: + type: boolean + serviceMonitor: + type: boolean + serviceMonitorConfig: + properties: + additionalLabels: + additionalProperties: + type: string + type: object + honorLabels: + type: boolean + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + serverName: + type: string + type: object + type: object + timeout: + type: string + type: object + bufferVolumeResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + compressConfigFile: + type: boolean + configCheckAnnotations: + additionalProperties: + type: string + type: object + configCheckResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + configReloaderImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + configReloaderResources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + disablePvc: + type: boolean + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + searches: + items: + type: string + type: array + type: object + dnsPolicy: + type: string + enableMsgpackTimeSupport: + type: boolean + envVars: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + extraArgs: + items: + type: string + type: array + extraVolumes: + items: + properties: + containerName: + type: string + path: + type: string + volume: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + volumeName: + type: string + type: object + type: array + fluentLogDestination: + type: string + fluentOutLogrotate: + properties: + age: + type: string + enabled: + type: boolean + path: + type: string + size: + type: string + required: + - enabled + type: object + fluentdPvcSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + host_path: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + pvc: + properties: + source: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + storageClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + optional: + type: boolean + secretName: + type: string + type: object + type: object + forwardInputConfig: + properties: + add_tag_prefix: + type: string + bind: + type: string + chunk_size_limit: + type: string + chunk_size_warn_limit: + type: string + deny_keepalive: + type: boolean + linger_timeout: + type: integer + port: + type: string + resolve_hostname: + type: boolean + security: + properties: + allow_anonymous_source: + type: boolean + self_hostname: + type: string + shared_key: + type: string + user_auth: + type: boolean + required: + - self_hostname + - shared_key + type: object + send_keepalive_packet: + type: boolean + skip_invalid_event: + type: boolean + source_address_key: + type: string + sourceHostnameKey: + type: string + tag: + type: string + transport: + properties: + ca_cert_path: + type: string + ca_path: + type: string + ca_private_key_passphrase: + type: string + ca_private_key_path: + type: string + cert_path: + type: string + ciphers: + type: string + client_cert_auth: + type: boolean + insecure: + type: boolean + private_key_passphrase: + type: string + private_key_path: + type: string + protocol: + type: string + version: + type: string + type: object + type: object + ignoreRepeatedLogInterval: + type: string + ignoreSameLogInterval: + type: string + image: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + livenessDefaultCheck: + type: boolean + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + logLevel: + type: string + metrics: + properties: + interval: + type: string + path: + type: string + port: + format: int32 + type: integer + prometheusAnnotations: + type: boolean + prometheusRules: + type: boolean + serviceMonitor: + type: boolean + serviceMonitorConfig: + properties: + additionalLabels: + additionalProperties: + type: string + type: object + honorLabels: + type: boolean + metricRelabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + relabelings: + items: + properties: + action: + default: replace + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + format: int64 + type: integer + regex: + type: string + replacement: + type: string + separator: + type: string + sourceLabels: + items: + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + type: string + type: object + type: array + scheme: + type: string + tlsConfig: + properties: + ca: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + caFile: + type: string + cert: + properties: + configMap: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + secret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + certFile: + type: string + insecureSkipVerify: + type: boolean + keyFile: + type: string + keySecret: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + serverName: + type: string + type: object + type: object + timeout: + type: string + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podPriorityClassName: + type: string + port: + format: int32 + type: integer + readinessDefaultCheck: + properties: + bufferFileNumber: + type: boolean + bufferFileNumberMax: + format: int32 + type: integer + bufferFreeSpace: + type: boolean + bufferFreeSpaceThreshold: + format: int32 + type: integer + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + rootDir: + type: string + scaling: + properties: + drain: + properties: + annotations: + additionalProperties: + type: string + type: object + deleteVolume: + type: boolean + enabled: + type: boolean + image: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + pauseImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + type: object + podManagementPolicy: + type: string + replicas: + type: integer + type: object + security: + properties: + podSecurityContext: + properties: + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + podSecurityPolicyCreate: + type: boolean + roleBasedAccessControlCreate: + type: boolean + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + type: object + serviceAccount: + properties: + automountServiceAccountToken: + type: boolean + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + secrets: + items: + properties: + apiVersion: + type: string + fieldPath: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + type: array + type: object + statefulsetAnnotations: + additionalProperties: + type: string + type: object + tls: + properties: + enabled: + type: boolean + secretName: + type: string + sharedKey: + type: string + required: + - enabled + type: object + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeModImage: + properties: + imagePullSecrets: + items: + properties: + name: + type: string + type: object + type: array + pullPolicy: + type: string + repository: + type: string + tag: + type: string + type: object + volumeMountChmod: + type: boolean + workers: + format: int32 + type: integer + type: object + status: + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] From 65caf04c919f8faaead96a68ed15306dafb691e8 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Tue, 14 Nov 2023 09:57:43 +0100 Subject: [PATCH 10/28] fluentd: store detached fluentd in reconciler Signed-off-by: Szilard Parrag --- controllers/logging/logging_controller.go | 6 +- pkg/resources/fluentbit/configsecret.go | 2 +- pkg/resources/fluentbit/tenants.go | 6 +- pkg/resources/fluentd/appconfigmap.go | 39 +++--- .../fluentd/buffervolumeprometheusrules.go | 4 +- pkg/resources/fluentd/configsecret.go | 10 +- pkg/resources/fluentd/dataprovider.go | 21 ++- pkg/resources/fluentd/drainjob.go | 14 +- pkg/resources/fluentd/fluentd.go | 34 ++--- pkg/resources/fluentd/meta.go | 10 +- pkg/resources/fluentd/placeholderpod.go | 14 +- pkg/resources/fluentd/prometheusrules.go | 5 +- pkg/resources/fluentd/psp.go | 11 +- pkg/resources/fluentd/rbac.go | 19 +-- pkg/resources/fluentd/service.go | 90 ++++++------- pkg/resources/fluentd/statefulset.go | 120 ++++++++---------- 16 files changed, 164 insertions(+), 241 deletions(-) diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index a0846ca8f..3ee10ac40 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -186,9 +186,9 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct } else { log.V(1).Info("flow configuration", "config", fluentdConfig) - reconcilers = append(reconcilers, fluentd.New(r.Client, r.Log, &logging, &fluentdConfig, secretList, reconcilerOpts).Reconcile) + reconcilers = append(reconcilers, fluentd.New(r.Client, r.Log, &logging, fluentdSpec, &fluentdConfig, secretList, reconcilerOpts).Reconcile) } - loggingDataProvider = fluentd.NewDataProvider(r.Client, &logging) + loggingDataProvider = fluentd.NewDataProvider(r.Client, &logging, fluentdSpec) } if logging.Spec.SyslogNGSpec != nil { @@ -258,7 +258,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct log.Error(errors.New("nodeagent definition conflict"), problem) } } - reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging)).Reconcile) + reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging, fluentdSpec)).Reconcile) } for _, rec := range reconcilers { diff --git a/pkg/resources/fluentbit/configsecret.go b/pkg/resources/fluentbit/configsecret.go index b609badec..6688257a4 100644 --- a/pkg/resources/fluentbit/configsecret.go +++ b/pkg/resources/fluentbit/configsecret.go @@ -370,7 +370,7 @@ func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, er for _, a := range r.loggingRoutes { tenants = append(tenants, a.Status.Tenants...) } - if err := r.configureOutputsForTenants(ctx, tenants, &input); err != nil { + if err := r.configureOutputsForTenants(ctx, tenants, &input, fluentdSpec); err != nil { return nil, nil, errors.WrapIf(err, "configuring outputs for target tenants") } } else { diff --git a/pkg/resources/fluentbit/tenants.go b/pkg/resources/fluentbit/tenants.go index a84ff2b2c..5800f7c56 100644 --- a/pkg/resources/fluentbit/tenants.go +++ b/pkg/resources/fluentbit/tenants.go @@ -88,7 +88,7 @@ func FindTenants(ctx context.Context, target metav1.LabelSelector, reader client return tenants, nil } -func (r *Reconciler) configureOutputsForTenants(ctx context.Context, tenants []v1beta1.Tenant, input *fluentBitConfig) error { +func (r *Reconciler) configureOutputsForTenants(ctx context.Context, tenants []v1beta1.Tenant, input *fluentBitConfig, fluentdSpec *v1beta1.FluentdSpec) error { var errs error for _, t := range tenants { allNamespaces := len(t.Namespaces) == 0 @@ -100,10 +100,6 @@ func (r *Reconciler) configureOutputsForTenants(ctx context.Context, tenants []v if err := r.resourceReconciler.Client.Get(ctx, types.NamespacedName{Name: t.Name}, logging); err != nil { return errors.WrapIf(err, "getting logging resource") } - fluentdSpec := logging.Spec.FluentdSpec - if detachedFluentd := fluentd.GetFluentd(ctx, r.resourceReconciler.Client, r.logger, logging.Spec.ControlNamespace); detachedFluentd != nil { - fluentdSpec = &detachedFluentd.Spec - } if fluentdSpec != nil { if input.FluentForwardOutput == nil { input.FluentForwardOutput = &fluentForwardOutputConfig{} diff --git a/pkg/resources/fluentd/appconfigmap.go b/pkg/resources/fluentd/appconfigmap.go index fa55c2944..1dac41421 100644 --- a/pkg/resources/fluentd/appconfigmap.go +++ b/pkg/resources/fluentd/appconfigmap.go @@ -42,9 +42,8 @@ type ConfigCheckResult struct { func (r *Reconciler) appConfigSecret() (runtime.Object, reconciler.DesiredState, error) { data := make(map[string][]byte) - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if fluentdSpec.CompressConfigFile { + if r.fluentdSpec.CompressConfigFile { AppConfigKeyCompress := AppConfigKey + ".gz" data[AppConfigKeyCompress] = compression.CompressString(*r.config, r.Log) } else { @@ -66,9 +65,9 @@ func (r *Reconciler) configHash() (string, error) { return fmt.Sprintf("%x", hasher.Sum32()), nil } -func (r *Reconciler) hasConfigCheckPod(ctx context.Context, hashKey string) (bool, error) { +func (r *Reconciler) hasConfigCheckPod(ctx context.Context, hashKey string, fluentdSpec v1beta1.FluentdSpec) (bool, error) { var err error - pod := r.newCheckPod(hashKey) + pod := r.newCheckPod(hashKey, fluentdSpec) p := &corev1.Pod{} err = r.Client.Get(ctx, client.ObjectKeyFromObject(pod), p) @@ -99,12 +98,12 @@ func (r *Reconciler) configCheck(ctx context.Context) (*ConfigCheckResult, error return nil, err } - checkSecret, err := r.newCheckSecret(hashKey) + checkSecret, err := r.newCheckSecret(hashKey, *r.fluentdSpec) if err != nil { return nil, err } configcheck.WithHashLabel(checkSecret, hashKey) - checkSecretAppConfig, err := r.newCheckSecretAppConfig(hashKey) + checkSecretAppConfig, err := r.newCheckSecretAppConfig(hashKey, *r.fluentdSpec) if err != nil { return nil, err } @@ -139,7 +138,7 @@ func (r *Reconciler) configCheck(ctx context.Context) (*ConfigCheckResult, error return res, errors.WrapIf(err, "failed to find output secret for fluentd configcheck") } - pod := r.newCheckPod(hashKey) + pod := r.newCheckPod(hashKey, *r.fluentdSpec) configcheck.WithHashLabel(pod, hashKey) existingPods := &corev1.PodList{} @@ -203,9 +202,8 @@ func (r *Reconciler) configCheck(ctx context.Context) (*ConfigCheckResult, error return &ConfigCheckResult{}, nil } -func (r *Reconciler) newCheckSecret(hashKey string) (*corev1.Secret, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - data, err := r.generateConfigSecret() +func (r *Reconciler) newCheckSecret(hashKey string, fluentdSpec v1beta1.FluentdSpec) (*corev1.Secret, error) { + data, err := r.generateConfigSecret(fluentdSpec) if err != nil { return nil, err } @@ -222,9 +220,8 @@ func (r *Reconciler) newCheckSecret(hashKey string) (*corev1.Secret, error) { }, nil } -func (r *Reconciler) newCheckSecretAppConfig(hashKey string) (*corev1.Secret, error) { +func (r *Reconciler) newCheckSecretAppConfig(hashKey string, fluentdSpec v1beta1.FluentdSpec) (*corev1.Secret, error) { data := make(map[string][]byte) - fluentdSpec := r.GetFluentdSpec(context.TODO()) if fluentdSpec.CompressConfigFile { ConfigCheckKeyCompress := ConfigCheckKey + ".gz" @@ -250,12 +247,11 @@ func (r *Reconciler) newCheckOutputSecret(hashKey string) (*corev1.Secret, error return nil, errors.New("output secret is invalid, unable to create output secret for config check") } -func (r *Reconciler) newCheckPod(hashKey string) *corev1.Pod { +func (r *Reconciler) newCheckPod(hashKey string, fluentdSpec v1beta1.FluentdSpec) *corev1.Pod { - volumes := r.volumesCheckPod(hashKey) - container := r.containerCheckPod(hashKey) - initContainer := r.initContainerCheckPod() - fluentdSpec := r.GetFluentdSpec(context.TODO()) + volumes := r.volumesCheckPod(hashKey, fluentdSpec) + container := r.containerCheckPod(hashKey, fluentdSpec) + initContainer := r.initContainerCheckPod(fluentdSpec) pod := &corev1.Pod{ ObjectMeta: r.configCheckPodObjectMeta(fmt.Sprintf("fluentd-configcheck-%s", hashKey), ComponentConfigCheck), @@ -307,8 +303,7 @@ func (r *Reconciler) newCheckPod(hashKey string) *corev1.Pod { return pod } -func (r *Reconciler) volumesCheckPod(hashKey string) (v []corev1.Volume) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) +func (r *Reconciler) volumesCheckPod(hashKey string, fluentdSpec v1beta1.FluentdSpec) (v []corev1.Volume) { v = []corev1.Volume{ { Name: "config", @@ -357,7 +352,7 @@ func (r *Reconciler) volumesCheckPod(hashKey string) (v []corev1.Volume) { return v } -func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { +func (r *Reconciler) containerCheckPod(hashKey string, fluentdSpec v1beta1.FluentdSpec) []corev1.Container { var containerArgs []string switch r.Logging.Spec.ConfigCheck.Strategy { @@ -377,7 +372,6 @@ func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { } } - fluentdSpec := r.GetFluentdSpec(context.TODO()) containerArgs = append(containerArgs, fluentdSpec.ExtraArgs...) container := []corev1.Container{ @@ -409,9 +403,8 @@ func (r *Reconciler) containerCheckPod(hashKey string) []corev1.Container { return container } -func (r *Reconciler) initContainerCheckPod() []corev1.Container { +func (r *Reconciler) initContainerCheckPod(fluentdSpec v1beta1.FluentdSpec) []corev1.Container { var initContainer []corev1.Container - fluentdSpec := r.GetFluentdSpec(context.TODO()) if fluentdSpec.CompressConfigFile { initContainer = []corev1.Container{ { diff --git a/pkg/resources/fluentd/buffervolumeprometheusrules.go b/pkg/resources/fluentd/buffervolumeprometheusrules.go index 6a204a16f..46898970c 100644 --- a/pkg/resources/fluentd/buffervolumeprometheusrules.go +++ b/pkg/resources/fluentd/buffervolumeprometheusrules.go @@ -15,7 +15,6 @@ package fluentd import ( - "context" "fmt" "github.com/cisco-open/operator-tools/pkg/reconciler" @@ -31,9 +30,8 @@ func (r *Reconciler) bufferVolumePrometheusRules() (runtime.Object, reconciler.D ObjectMeta: r.FluentdObjectMeta(ServiceName+"-buffer-metrics", ComponentFluentd), } state := reconciler.StateAbsent - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.PrometheusRules { + if r.fluentdSpec.BufferVolumeMetrics != nil && r.fluentdSpec.BufferVolumeMetrics.PrometheusRules { nsJobLabel := fmt.Sprintf(`job="%s", namespace="%s"`, obj.Name, obj.Namespace) state = reconciler.StatePresent const ruleGroupName = "fluentd-buffervolume" diff --git a/pkg/resources/fluentd/configsecret.go b/pkg/resources/fluentd/configsecret.go index 44b3b6619..ff7e63550 100644 --- a/pkg/resources/fluentd/configsecret.go +++ b/pkg/resources/fluentd/configsecret.go @@ -16,12 +16,12 @@ package fluentd import ( "bytes" - "context" "fmt" "html/template" "emperror.dev/errors" "github.com/cisco-open/operator-tools/pkg/reconciler" + "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -53,8 +53,7 @@ func generateConfig(input fluentdConfig) (string, error) { return output.String(), nil } -func (r *Reconciler) generateConfigSecret() (map[string][]byte, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) +func (r *Reconciler) generateConfigSecret(fluentdSpec v1beta1.FluentdSpec) (map[string][]byte, error) { input := fluentdConfig{ IgnoreSameLogInterval: fluentdSpec.IgnoreSameLogInterval, IgnoreRepeatedLogInterval: fluentdSpec.IgnoreRepeatedLogInterval, @@ -88,12 +87,11 @@ func (r *Reconciler) generateConfigSecret() (map[string][]byte, error) { } func (r *Reconciler) secretConfig() (runtime.Object, reconciler.DesiredState, error) { - configMap, err := r.generateConfigSecret() - fluentdSpec := r.GetFluentdSpec(context.TODO()) + configMap, err := r.generateConfigSecret(*r.fluentdSpec) if err != nil { return nil, nil, err } - configMap["fluentlog.conf"] = []byte(fmt.Sprintf(fluentLog, fluentdSpec.FluentLogDestination)) + configMap["fluentlog.conf"] = []byte(fmt.Sprintf(fluentLog, r.fluentdSpec.FluentLogDestination)) configs := &corev1.Secret{ ObjectMeta: r.FluentdObjectMeta(SecretConfigName, ComponentFluentd), Data: configMap, diff --git a/pkg/resources/fluentd/dataprovider.go b/pkg/resources/fluentd/dataprovider.go index 423b48377..ccba81e86 100644 --- a/pkg/resources/fluentd/dataprovider.go +++ b/pkg/resources/fluentd/dataprovider.go @@ -18,7 +18,6 @@ import ( "context" "emperror.dev/errors" - "github.com/go-logr/logr" "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" v1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/types" @@ -26,25 +25,23 @@ import ( ) type DataProvider struct { - client client.Client - logging *v1beta1.Logging + client client.Client + logging *v1beta1.Logging + fluentdSpec *v1beta1.FluentdSpec } -func NewDataProvider(client client.Client, logging *v1beta1.Logging) *DataProvider { +func NewDataProvider(client client.Client, logging *v1beta1.Logging, fluentdSpec *v1beta1.FluentdSpec) *DataProvider { return &DataProvider{ - client: client, - logging: logging, + client: client, + logging: logging, + fluentdSpec: fluentdSpec, } } func (p *DataProvider) GetReplicaCount(ctx context.Context) (*int32, error) { - fluentdSpec := p.logging.Spec.FluentdSpec - if detachedFluentd := GetFluentd(ctx, p.client, logr.Logger{}, p.logging.Spec.ControlNamespace); detachedFluentd != nil { - fluentdSpec = &detachedFluentd.Spec - } - if fluentdSpec != nil { + if p.fluentdSpec != nil { sts := &v1.StatefulSet{} - om := p.logging.FluentdObjectMeta(StatefulSetName, ComponentFluentd, *fluentdSpec) + om := p.logging.FluentdObjectMeta(StatefulSetName, ComponentFluentd, *p.fluentdSpec) err := p.client.Get(ctx, types.NamespacedName{Namespace: om.Namespace, Name: om.Name}, sts) if err != nil { return nil, errors.WrapIf(client.IgnoreNotFound(err), "getting fluentd statefulset") diff --git a/pkg/resources/fluentd/drainjob.go b/pkg/resources/fluentd/drainjob.go index 56dbc3666..7d7a29c7b 100644 --- a/pkg/resources/fluentd/drainjob.go +++ b/pkg/resources/fluentd/drainjob.go @@ -15,7 +15,6 @@ package fluentd import ( - "context" "strings" batchv1 "k8s.io/api/batch/v1" @@ -25,11 +24,10 @@ import ( "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" ) -func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim) (*batchv1.Job, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) +func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim, fluentdSpec v1beta1.FluentdSpec) (*batchv1.Job, error) { bufVolName := r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) - fluentdContainer := fluentContainer(withoutFluentOutLogrotate(fluentdSpec)) + fluentdContainer := fluentContainer(withoutFluentOutLogrotate(&fluentdSpec)) fluentdContainer.VolumeMounts = append(fluentdContainer.VolumeMounts, corev1.VolumeMount{ Name: bufVolName, MountPath: bufferPath, @@ -53,7 +51,7 @@ func (r *Reconciler) drainerJobFor(pvc corev1.PersistentVolumeClaim) (*batchv1.J spec := batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: r.getDrainerLabels(), + Labels: r.getDrainerLabels(fluentdSpec), Annotations: fluentdSpec.Scaling.Drain.Annotations, }, Spec: corev1.PodSpec{ @@ -131,10 +129,8 @@ func withoutFluentOutLogrotate(spec *v1beta1.FluentdSpec) *v1beta1.FluentdSpec { return res } -func (r *Reconciler) getDrainerLabels() map[string]string { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - labels := r.Logging.GetFluentdLabels(ComponentDrainer, *fluentdSpec) +func (r *Reconciler) getDrainerLabels(fluentdSpec v1beta1.FluentdSpec) map[string]string { + labels := r.Logging.GetFluentdLabels(ComponentDrainer, fluentdSpec) for key, value := range fluentdSpec.Scaling.Drain.Labels { labels[key] = value diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index f6fca6ca9..378bc1907 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -68,7 +68,8 @@ const ( // Reconciler holds info what resource to reconcile type Reconciler struct { - Logging *v1beta1.Logging + Logging *v1beta1.Logging + fluentdSpec *v1beta1.FluentdSpec *reconciler.GenericResourceReconciler config *string secrets *secret.MountSecrets @@ -112,18 +113,17 @@ func (r *Reconciler) GetFluentdSpec(ctx context.Context) *v1beta1.FluentdSpec { } func (r *Reconciler) getServiceAccount() string { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.Security.ServiceAccount != "" { - return fluentdSpec.Security.ServiceAccount + if r.fluentdSpec.Security.ServiceAccount != "" { + return r.fluentdSpec.Security.ServiceAccount } return r.Logging.QualifiedName(defaultServiceAccountName) } func New(client client.Client, log logr.Logger, - logging *v1beta1.Logging, config *string, secrets *secret.MountSecrets, opts reconciler.ReconcilerOpts) *Reconciler { + logging *v1beta1.Logging, fluentdSpec *v1beta1.FluentdSpec, config *string, secrets *secret.MountSecrets, opts reconciler.ReconcilerOpts) *Reconciler { return &Reconciler{ Logging: logging, + fluentdSpec: fluentdSpec, GenericResourceReconciler: reconciler.NewGenericReconciler(client, log, opts), config: config, secrets: secrets, @@ -134,11 +134,6 @@ func New(client client.Client, log logr.Logger, func (r *Reconciler) Reconcile(ctx context.Context) (*reconcile.Result, error) { patchBase := client.MergeFrom(r.Logging.DeepCopy()) - fluentdSpec := r.GetFluentdSpec(ctx) - if err := fluentdSpec.SetDefaults(); err != nil { - return &reconcile.Result{}, err - } - objects := []resources.Resource{ r.serviceAccount, r.role, @@ -176,7 +171,7 @@ func (r *Reconciler) Reconcile(ctx context.Context) (*reconcile.Result, error) { // Fail when the current config is invalid if result, ok := r.Logging.Status.ConfigCheckResults[hash]; ok && !result { - if hasPod, err := r.hasConfigCheckPod(ctx, hash); hasPod { + if hasPod, err := r.hasConfigCheckPod(ctx, hash, *r.fluentdSpec); hasPod { return nil, errors.WrapIf(err, "current config is invalid") } // clean the status so that we can rerun the check @@ -301,14 +296,13 @@ func (r *Reconciler) statusUpdate(ctx context.Context, patchBase client.Patch, r } func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, error) { - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.DisablePvc || !fluentdSpec.Scaling.Drain.Enabled { + if r.fluentdSpec.DisablePvc || !r.fluentdSpec.Scaling.Drain.Enabled { r.Log.Info("fluentd buffer draining is disabled") return nil, nil } nsOpt := client.InNamespace(r.Logging.Spec.ControlNamespace) - fluentdLabelSet := r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec) + fluentdLabelSet := r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec) var pvcList corev1.PersistentVolumeClaimList if err := r.Client.List(ctx, &pvcList, nsOpt, @@ -323,7 +317,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err return nil, errors.WrapIf(err, "listing StatefulSet pods") } - bufVolName := r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) + bufVolName := r.Logging.QualifiedName(r.fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) pvcsInUse := make(map[string]bool) for _, pod := range stsPods.Items { @@ -332,7 +326,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err } } - replicaCount, err := NewDataProvider(r.Client, r.Logging).GetReplicaCount(ctx) + replicaCount, err := NewDataProvider(r.Client, r.Logging, r.fluentdSpec).GetReplicaCount(ctx) if err != nil { return nil, errors.WrapIf(err, "get replica count for fluentd") } @@ -343,7 +337,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err } var jobList batchv1.JobList - if err := r.Client.List(ctx, &jobList, nsOpt, client.MatchingLabels(r.Logging.GetFluentdLabels(ComponentDrainer, *fluentdSpec))); err != nil { + if err := r.Client.List(ctx, &jobList, nsOpt, client.MatchingLabels(r.Logging.GetFluentdLabels(ComponentDrainer, *r.fluentdSpec))); err != nil { return nil, errors.WrapIf(err, "listing buffer drainer jobs") } @@ -387,7 +381,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err continue } - if fluentdSpec.Scaling.Drain.DeleteVolume { + if r.fluentdSpec.Scaling.Drain.DeleteVolume { if err := client.IgnoreNotFound(r.Client.Delete(ctx, &pvc, client.PropagationPolicy(v1.DeletePropagationBackground))); err != nil { cr.CombineErr(errors.WrapIfWithDetails(err, "deleting drained PVC", "pvc", pvc.Name)) continue @@ -434,7 +428,7 @@ func (r *Reconciler) reconcileDrain(ctx context.Context) (*reconcile.Result, err continue } - if job, err := r.drainerJobFor(pvc); err != nil { + if job, err := r.drainerJobFor(pvc, *r.fluentdSpec); err != nil { cr.CombineErr(errors.WrapIf(err, "assembling drainer job")) } else { cr.Combine(r.ReconcileResource(job, reconciler.StatePresent)) diff --git a/pkg/resources/fluentd/meta.go b/pkg/resources/fluentd/meta.go index 73a49aeaf..9833736ce 100644 --- a/pkg/resources/fluentd/meta.go +++ b/pkg/resources/fluentd/meta.go @@ -15,20 +15,16 @@ package fluentd import ( - "context" - util "github.com/cisco-open/operator-tools/pkg/utils" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // FluentdObjectMeta creates an objectMeta for resource fluentd func (r *Reconciler) FluentdObjectMeta(name, component string) metav1.ObjectMeta { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) o := metav1.ObjectMeta{ Name: r.Logging.QualifiedName(name), Namespace: r.Logging.Spec.ControlNamespace, - Labels: r.Logging.GetFluentdLabels(component, *fluentdSpec), + Labels: r.Logging.GetFluentdLabels(component, *r.fluentdSpec), OwnerReferences: []metav1.OwnerReference{ { APIVersion: r.Logging.APIVersion, @@ -44,11 +40,9 @@ func (r *Reconciler) FluentdObjectMeta(name, component string) metav1.ObjectMeta // FluentdObjectMetaClusterScope creates an objectMeta for resource fluentd func (r *Reconciler) FluentdObjectMetaClusterScope(name, component string) metav1.ObjectMeta { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) o := metav1.ObjectMeta{ Name: r.Logging.QualifiedName(name), - Labels: r.Logging.GetFluentdLabels(component, *fluentdSpec), + Labels: r.Logging.GetFluentdLabels(component, *r.fluentdSpec), OwnerReferences: []metav1.OwnerReference{ { APIVersion: r.Logging.APIVersion, diff --git a/pkg/resources/fluentd/placeholderpod.go b/pkg/resources/fluentd/placeholderpod.go index 369e3a249..0d07e1f55 100644 --- a/pkg/resources/fluentd/placeholderpod.go +++ b/pkg/resources/fluentd/placeholderpod.go @@ -15,7 +15,6 @@ package fluentd import ( - "context" "strings" "github.com/cisco-open/operator-tools/pkg/utils" @@ -23,21 +22,20 @@ import ( ) func (r *Reconciler) placeholderPodFor(pvc corev1.PersistentVolumeClaim) *corev1.Pod { - fluentdSpec := r.GetFluentdSpec(context.TODO()) return &corev1.Pod{ ObjectMeta: r.FluentdObjectMeta(StatefulSetName+pvc.Name[strings.LastIndex(pvc.Name, "-"):], ComponentPlaceholder), Spec: corev1.PodSpec{ Containers: []corev1.Container{ { Name: "pause", - Image: fluentdSpec.Scaling.Drain.PauseImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Scaling.Drain.PauseImage.PullPolicy), + Image: r.fluentdSpec.Scaling.Drain.PauseImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(r.fluentdSpec.Scaling.Drain.PauseImage.PullPolicy), }, }, - NodeSelector: fluentdSpec.NodeSelector, - Tolerations: fluentdSpec.Tolerations, - Affinity: fluentdSpec.Affinity, - PriorityClassName: fluentdSpec.PodPriorityClassName, + NodeSelector: r.fluentdSpec.NodeSelector, + Tolerations: r.fluentdSpec.Tolerations, + Affinity: r.fluentdSpec.Affinity, + PriorityClassName: r.fluentdSpec.PodPriorityClassName, RestartPolicy: corev1.RestartPolicyNever, TerminationGracePeriodSeconds: utils.IntPointer64(0), // terminate immediately }, diff --git a/pkg/resources/fluentd/prometheusrules.go b/pkg/resources/fluentd/prometheusrules.go index 4ba48131e..32b1ee6f1 100644 --- a/pkg/resources/fluentd/prometheusrules.go +++ b/pkg/resources/fluentd/prometheusrules.go @@ -15,7 +15,6 @@ package fluentd import ( - "context" "fmt" "github.com/cisco-open/operator-tools/pkg/reconciler" @@ -31,9 +30,7 @@ func (r *Reconciler) prometheusRules() (runtime.Object, reconciler.DesiredState, } state := reconciler.StateAbsent - fluentdSpec := r.GetFluentdSpec(context.TODO()) - - if fluentdSpec.Metrics != nil && fluentdSpec.Metrics.PrometheusRules { + if r.fluentdSpec.Metrics != nil && r.fluentdSpec.Metrics.PrometheusRules { nsJobLabel := fmt.Sprintf(`job="%s", namespace="%s"`, obj.Name, obj.Namespace) state = reconciler.StatePresent const ruleGroupName = "fluentd" diff --git a/pkg/resources/fluentd/psp.go b/pkg/resources/fluentd/psp.go index 02f5e70f1..85cebfa25 100644 --- a/pkg/resources/fluentd/psp.go +++ b/pkg/resources/fluentd/psp.go @@ -15,8 +15,6 @@ package fluentd import ( - "context" - "github.com/cisco-open/operator-tools/pkg/reconciler" util "github.com/cisco-open/operator-tools/pkg/utils" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -26,8 +24,7 @@ import ( ) func (r *Reconciler) clusterPodSecurityPolicy() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if fluentdSpec.Security.PodSecurityPolicyCreate { + if r.fluentdSpec.Security.PodSecurityPolicyCreate { return &policyv1beta1.PodSecurityPolicy{ ObjectMeta: r.FluentdObjectMetaClusterScope(PodSecurityPolicyName, ComponentFluentd), Spec: policyv1beta1.PodSecurityPolicySpec{ @@ -62,8 +59,7 @@ func (r *Reconciler) clusterPodSecurityPolicy() (runtime.Object, reconciler.Desi } func (r *Reconciler) pspRole() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.PodSecurityPolicyCreate { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate && r.fluentdSpec.Security.PodSecurityPolicyCreate { return &rbacv1.Role{ ObjectMeta: r.FluentdObjectMeta(roleName+"-psp", ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -82,8 +78,7 @@ func (r *Reconciler) pspRole() (runtime.Object, reconciler.DesiredState, error) } func (r *Reconciler) pspRoleBinding() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.PodSecurityPolicyCreate { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate && r.fluentdSpec.Security.PodSecurityPolicyCreate { return &rbacv1.RoleBinding{ ObjectMeta: r.FluentdObjectMeta(roleBindingName+"-psp", ComponentFluentd), RoleRef: rbacv1.RoleRef{ diff --git a/pkg/resources/fluentd/rbac.go b/pkg/resources/fluentd/rbac.go index 84bfde3fc..5dfb8703d 100644 --- a/pkg/resources/fluentd/rbac.go +++ b/pkg/resources/fluentd/rbac.go @@ -15,8 +15,6 @@ package fluentd import ( - "context" - "emperror.dev/errors" "github.com/cisco-open/operator-tools/pkg/merge" "github.com/cisco-open/operator-tools/pkg/reconciler" @@ -26,8 +24,7 @@ import ( ) func (r *Reconciler) role() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate { return &rbacv1.Role{ ObjectMeta: r.FluentdObjectMeta(roleName, ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -45,8 +42,7 @@ func (r *Reconciler) role() (runtime.Object, reconciler.DesiredState, error) { } func (r *Reconciler) roleBinding() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate { return &rbacv1.RoleBinding{ ObjectMeta: r.FluentdObjectMeta(roleBindingName, ComponentFluentd), RoleRef: rbacv1.RoleRef{ @@ -78,8 +74,7 @@ func (r *Reconciler) isEnhanceK8sFilter() bool { } func (r *Reconciler) clusterRole() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { return &rbacv1.ClusterRole{ ObjectMeta: r.FluentdObjectMetaClusterScope(clusterRoleName, ComponentFluentd), Rules: []rbacv1.PolicyRule{ @@ -120,8 +115,7 @@ func (r *Reconciler) clusterRole() (runtime.Object, reconciler.DesiredState, err } func (r *Reconciler) clusterRoleBinding() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate && r.isEnhanceK8sFilter() { return &rbacv1.ClusterRoleBinding{ ObjectMeta: r.FluentdObjectMetaClusterScope(clusterRoleBindingName, ComponentFluentd), RoleRef: rbacv1.RoleRef{ @@ -144,12 +138,11 @@ func (r *Reconciler) clusterRoleBinding() (runtime.Object, reconciler.DesiredSta } func (r *Reconciler) serviceAccount() (runtime.Object, reconciler.DesiredState, error) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if *fluentdSpec.Security.RoleBasedAccessControlCreate && fluentdSpec.Security.ServiceAccount == "" { + if *r.fluentdSpec.Security.RoleBasedAccessControlCreate && r.fluentdSpec.Security.ServiceAccount == "" { desired := &corev1.ServiceAccount{ ObjectMeta: r.FluentdObjectMeta(defaultServiceAccountName, ComponentFluentd), } - err := merge.Merge(desired, fluentdSpec.ServiceAccountOverrides) + err := merge.Merge(desired, r.fluentdSpec.ServiceAccountOverrides) if err != nil { return desired, reconciler.StatePresent, errors.WrapIf(err, "unable to merge overrides to base object") } diff --git a/pkg/resources/fluentd/service.go b/pkg/resources/fluentd/service.go index 58786908f..c89465add 100644 --- a/pkg/resources/fluentd/service.go +++ b/pkg/resources/fluentd/service.go @@ -15,8 +15,6 @@ package fluentd import ( - "context" - "emperror.dev/errors" "github.com/cisco-open/operator-tools/pkg/reconciler" v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -27,8 +25,6 @@ import ( ) func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) desired := &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName, ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -37,16 +33,16 @@ func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) Name: "tcp-fluentd", Protocol: corev1.ProtocolTCP, Port: ServicePort, - TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Port}, + TargetPort: intstr.IntOrString{IntVal: r.fluentdSpec.Port}, }, { Name: "udp-fluentd", Protocol: corev1.ProtocolUDP, Port: ServicePort, - TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Port}, + TargetPort: intstr.IntOrString{IntVal: r.fluentdSpec.Port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), Type: corev1.ServiceTypeClusterIP, }, } @@ -64,9 +60,7 @@ func (r *Reconciler) service() (runtime.Object, reconciler.DesiredState, error) } func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, error) { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.Metrics != nil { + if r.fluentdSpec.Metrics != nil { return &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName+"-metrics", ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -74,11 +68,11 @@ func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, { Protocol: corev1.ProtocolTCP, Name: "http-metrics", - Port: fluentdSpec.Metrics.Port, - TargetPort: intstr.IntOrString{IntVal: fluentdSpec.Metrics.Port}, + Port: r.fluentdSpec.Metrics.Port, + TargetPort: intstr.IntOrString{IntVal: r.fluentdSpec.Metrics.Port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: "None", }, @@ -91,12 +85,10 @@ func (r *Reconciler) serviceMetrics() (runtime.Object, reconciler.DesiredState, func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.DesiredState, error) { var SampleLimit uint64 = 0 - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.Metrics != nil && fluentdSpec.Metrics.ServiceMonitor { + if r.fluentdSpec.Metrics != nil && r.fluentdSpec.Metrics.ServiceMonitor { objectMetadata := r.FluentdObjectMeta(ServiceName+"-metrics", ComponentFluentd) - if fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels != nil { - for k, v := range fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels { + if r.fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels != nil { + for k, v := range r.fluentdSpec.Metrics.ServiceMonitorConfig.AdditionalLabels { objectMetadata.Labels[k] = v } } @@ -109,16 +101,16 @@ func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.Desired PodTargetLabels: nil, Endpoints: []v1.Endpoint{{ Port: "http-metrics", - Path: fluentdSpec.GetFluentdMetricsPath(), - Interval: v1.Duration(fluentdSpec.Metrics.Interval), - ScrapeTimeout: v1.Duration(fluentdSpec.Metrics.Timeout), - HonorLabels: fluentdSpec.Metrics.ServiceMonitorConfig.HonorLabels, - RelabelConfigs: fluentdSpec.Metrics.ServiceMonitorConfig.Relabelings, - MetricRelabelConfigs: fluentdSpec.Metrics.ServiceMonitorConfig.MetricsRelabelings, - Scheme: fluentdSpec.Metrics.ServiceMonitorConfig.Scheme, - TLSConfig: fluentdSpec.Metrics.ServiceMonitorConfig.TLSConfig, + Path: r.fluentdSpec.GetFluentdMetricsPath(), + Interval: v1.Duration(r.fluentdSpec.Metrics.Interval), + ScrapeTimeout: v1.Duration(r.fluentdSpec.Metrics.Timeout), + HonorLabels: r.fluentdSpec.Metrics.ServiceMonitorConfig.HonorLabels, + RelabelConfigs: r.fluentdSpec.Metrics.ServiceMonitorConfig.Relabelings, + MetricRelabelConfigs: r.fluentdSpec.Metrics.ServiceMonitorConfig.MetricsRelabelings, + Scheme: r.fluentdSpec.Metrics.ServiceMonitorConfig.Scheme, + TLSConfig: r.fluentdSpec.Metrics.ServiceMonitorConfig.TLSConfig, }}, - Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec)}, + Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec)}, NamespaceSelector: v1.NamespaceSelector{MatchNames: []string{r.Logging.Spec.ControlNamespace}}, SampleLimit: &SampleLimit, }, @@ -131,12 +123,10 @@ func (r *Reconciler) monitorServiceMetrics() (runtime.Object, reconciler.Desired } func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredState, error) { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.BufferVolumeMetrics != nil { + if r.fluentdSpec.BufferVolumeMetrics != nil { port := int32(defaultBufferVolumeMetricsPort) - if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.Port != 0 { - port = fluentdSpec.BufferVolumeMetrics.Port + if r.fluentdSpec.BufferVolumeMetrics != nil && r.fluentdSpec.BufferVolumeMetrics.Port != 0 { + port = r.fluentdSpec.BufferVolumeMetrics.Port } return &corev1.Service{ @@ -150,7 +140,7 @@ func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredS TargetPort: intstr.IntOrString{IntVal: port}, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: "None", }, @@ -163,12 +153,10 @@ func (r *Reconciler) serviceBufferMetrics() (runtime.Object, reconciler.DesiredS func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.DesiredState, error) { var SampleLimit uint64 = 0 - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - if fluentdSpec.BufferVolumeMetrics != nil && fluentdSpec.BufferVolumeMetrics.ServiceMonitor { + if r.fluentdSpec.BufferVolumeMetrics != nil && r.fluentdSpec.BufferVolumeMetrics.ServiceMonitor { objectMetadata := r.FluentdObjectMeta(ServiceName+"-buffer-metrics", ComponentFluentd) - if fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels != nil { - for k, v := range fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels { + if r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels != nil { + for k, v := range r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.AdditionalLabels { objectMetadata.Labels[k] = v } } @@ -180,16 +168,16 @@ func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.D PodTargetLabels: nil, Endpoints: []v1.Endpoint{{ Port: "buffer-metrics", - Path: fluentdSpec.BufferVolumeMetrics.Path, - Interval: v1.Duration(fluentdSpec.BufferVolumeMetrics.Interval), - ScrapeTimeout: v1.Duration(fluentdSpec.BufferVolumeMetrics.Timeout), - HonorLabels: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.HonorLabels, - RelabelConfigs: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Relabelings, - MetricRelabelConfigs: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.MetricsRelabelings, - Scheme: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Scheme, - TLSConfig: fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.TLSConfig, + Path: r.fluentdSpec.BufferVolumeMetrics.Path, + Interval: v1.Duration(r.fluentdSpec.BufferVolumeMetrics.Interval), + ScrapeTimeout: v1.Duration(r.fluentdSpec.BufferVolumeMetrics.Timeout), + HonorLabels: r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.HonorLabels, + RelabelConfigs: r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Relabelings, + MetricRelabelConfigs: r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.MetricsRelabelings, + Scheme: r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.Scheme, + TLSConfig: r.fluentdSpec.BufferVolumeMetrics.ServiceMonitorConfig.TLSConfig, }}, - Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec)}, + Selector: v12.LabelSelector{MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec)}, NamespaceSelector: v1.NamespaceSelector{MatchNames: []string{r.Logging.Spec.ControlNamespace}}, SampleLimit: &SampleLimit, }, @@ -202,8 +190,6 @@ func (r *Reconciler) monitorBufferServiceMetrics() (runtime.Object, reconciler.D } func (r *Reconciler) headlessService() (runtime.Object, reconciler.DesiredState, error) { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) desired := &corev1.Service{ ObjectMeta: r.FluentdObjectMeta(ServiceName+"-headless", ComponentFluentd), Spec: corev1.ServiceSpec{ @@ -213,17 +199,17 @@ func (r *Reconciler) headlessService() (runtime.Object, reconciler.DesiredState, Protocol: corev1.ProtocolTCP, // This port should match the containerport and targetPort will be automatically set to the same // https://github.com/kubernetes/kubernetes/issues/20488 - Port: fluentdSpec.Port, + Port: r.fluentdSpec.Port, }, { Name: "udp-fluentd", Protocol: corev1.ProtocolUDP, // This port should match the containerport and targetPort will be automatically set to the same // https://github.com/kubernetes/kubernetes/issues/20488 - Port: fluentdSpec.Port, + Port: r.fluentdSpec.Port, }, }, - Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + Selector: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), Type: corev1.ServiceTypeClusterIP, ClusterIP: corev1.ClusterIPNone, }, diff --git a/pkg/resources/fluentd/statefulset.go b/pkg/resources/fluentd/statefulset.go index 8c32d9b0e..57f0283d5 100644 --- a/pkg/resources/fluentd/statefulset.go +++ b/pkg/resources/fluentd/statefulset.go @@ -15,7 +15,6 @@ package fluentd import ( - "context" "fmt" "strings" @@ -32,25 +31,24 @@ import ( func (r *Reconciler) statefulset() (runtime.Object, reconciler.DesiredState, error) { spec := r.statefulsetSpec() - fluentdSpec := r.GetFluentdSpec(context.TODO()) - fluentdSpec.BufferStorageVolume.WithDefaultHostPath( + r.fluentdSpec.BufferStorageVolume.WithDefaultHostPath( fmt.Sprintf(v1beta1.HostPath, r.Logging.Name, r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName)), ) - if !fluentdSpec.DisablePvc { - err := fluentdSpec.BufferStorageVolume.ApplyPVCForStatefulSet(containerName, bufferPath, spec, func(name string) metav1.ObjectMeta { + if !r.fluentdSpec.DisablePvc { + err := r.fluentdSpec.BufferStorageVolume.ApplyPVCForStatefulSet(containerName, bufferPath, spec, func(name string) metav1.ObjectMeta { return r.FluentdObjectMeta(name, ComponentFluentd) }) if err != nil { return nil, reconciler.StatePresent, err } } else { - err := fluentdSpec.BufferStorageVolume.ApplyVolumeForPodSpec(r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName), containerName, bufferPath, &spec.Template.Spec) + err := r.fluentdSpec.BufferStorageVolume.ApplyVolumeForPodSpec(r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName), containerName, bufferPath, &spec.Template.Spec) if err != nil { return nil, reconciler.StatePresent, err } } - for _, n := range fluentdSpec.ExtraVolumes { + for _, n := range r.fluentdSpec.ExtraVolumes { if n.Volume != nil && n.Volume.PersistentVolumeClaim != nil { if err := n.Volume.ApplyPVCForStatefulSet(n.ContainerName, n.Path, spec, func(name string) metav1.ObjectMeta { return r.FluentdObjectMeta(name, ComponentFluentd) @@ -69,15 +67,12 @@ func (r *Reconciler) statefulset() (runtime.Object, reconciler.DesiredState, err Spec: *spec, } - desired.Annotations = util.MergeLabels(desired.Annotations, fluentdSpec.StatefulSetAnnotations) + desired.Annotations = util.MergeLabels(desired.Annotations, r.fluentdSpec.StatefulSetAnnotations) return desired, reconciler.StatePresent, nil } func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { - ctx := context.TODO() - fluentdSpec := r.GetFluentdSpec(ctx) - var initContainers []corev1.Container if c := r.tmpDirHackContainer(); c != nil { @@ -86,13 +81,13 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { if c := r.volumeMountHackContainer(); c != nil { initContainers = append(initContainers, *c) } - if i := generateInitContainer(fluentdSpec); i != nil { + if i := generateInitContainer(*r.fluentdSpec); i != nil { initContainers = append(initContainers, *i) } containers := []corev1.Container{ - fluentContainer(fluentdSpec), - *newConfigMapReloader(fluentdSpec), + fluentContainer(r.fluentdSpec), + *newConfigMapReloader(r.fluentdSpec), } if c := r.bufferMetricsSidecarContainer(); c != nil { containers = append(containers, *c) @@ -102,9 +97,9 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { } sts := &appsv1.StatefulSetSpec{ - PodManagementPolicy: appsv1.PodManagementPolicyType(fluentdSpec.Scaling.PodManagementPolicy), + PodManagementPolicy: appsv1.PodManagementPolicyType(r.fluentdSpec.Scaling.PodManagementPolicy), Selector: &metav1.LabelSelector{ - MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + MatchLabels: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), }, Template: corev1.PodTemplateSpec{ ObjectMeta: r.generatePodMeta(), @@ -112,29 +107,29 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { Volumes: r.generateVolume(), ServiceAccountName: r.getServiceAccount(), InitContainers: initContainers, - ImagePullSecrets: fluentdSpec.Image.ImagePullSecrets, + ImagePullSecrets: r.fluentdSpec.Image.ImagePullSecrets, Containers: containers, - NodeSelector: fluentdSpec.NodeSelector, - Tolerations: fluentdSpec.Tolerations, - Affinity: fluentdSpec.Affinity, - TopologySpreadConstraints: fluentdSpec.TopologySpreadConstraints, - PriorityClassName: fluentdSpec.PodPriorityClassName, - DNSPolicy: fluentdSpec.DNSPolicy, - DNSConfig: fluentdSpec.DNSConfig, + NodeSelector: r.fluentdSpec.NodeSelector, + Tolerations: r.fluentdSpec.Tolerations, + Affinity: r.fluentdSpec.Affinity, + TopologySpreadConstraints: r.fluentdSpec.TopologySpreadConstraints, + PriorityClassName: r.fluentdSpec.PodPriorityClassName, + DNSPolicy: r.fluentdSpec.DNSPolicy, + DNSConfig: r.fluentdSpec.DNSConfig, SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: fluentdSpec.Security.PodSecurityContext.RunAsNonRoot, - FSGroup: fluentdSpec.Security.PodSecurityContext.FSGroup, - RunAsUser: fluentdSpec.Security.PodSecurityContext.RunAsUser, - RunAsGroup: fluentdSpec.Security.PodSecurityContext.RunAsGroup, - SeccompProfile: fluentdSpec.Security.PodSecurityContext.SeccompProfile, + RunAsNonRoot: r.fluentdSpec.Security.PodSecurityContext.RunAsNonRoot, + FSGroup: r.fluentdSpec.Security.PodSecurityContext.FSGroup, + RunAsUser: r.fluentdSpec.Security.PodSecurityContext.RunAsUser, + RunAsGroup: r.fluentdSpec.Security.PodSecurityContext.RunAsGroup, + SeccompProfile: r.fluentdSpec.Security.PodSecurityContext.SeccompProfile, }, }, }, ServiceName: r.Logging.QualifiedName(ServiceName + "-headless"), } - if fluentdSpec.Scaling.Replicas > 0 { - sts.Replicas = util.IntPointer(cast.ToInt32(fluentdSpec.Scaling.Replicas)) + if r.fluentdSpec.Scaling.Replicas > 0 { + sts.Replicas = util.IntPointer(cast.ToInt32(r.fluentdSpec.Scaling.Replicas)) } return sts @@ -173,12 +168,11 @@ func fluentContainer(spec *v1beta1.FluentdSpec) corev1.Container { } func (r *Reconciler) generatePodMeta() metav1.ObjectMeta { - fluentdSpec := r.GetFluentdSpec(context.TODO()) meta := metav1.ObjectMeta{ - Labels: r.Logging.GetFluentdLabels(ComponentFluentd, *fluentdSpec), + Labels: r.Logging.GetFluentdLabels(ComponentFluentd, *r.fluentdSpec), } - if fluentdSpec.Annotations != nil { - meta.Annotations = fluentdSpec.Annotations + if r.fluentdSpec.Annotations != nil { + meta.Annotations = r.fluentdSpec.Annotations } return meta } @@ -291,7 +285,6 @@ func generateVolumeMounts(spec *v1beta1.FluentdSpec) []corev1.VolumeMount { } func (r *Reconciler) generateVolume() (v []corev1.Volume) { - fluentdSpec := r.GetFluentdSpec(context.TODO()) v = []corev1.Volume{ { Name: "config", @@ -311,14 +304,14 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { }, } - if isFluentdReadOnlyRootFilesystem(fluentdSpec) { + if isFluentdReadOnlyRootFilesystem(r.fluentdSpec) { v = append(v, corev1.Volume{ Name: "tmp", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, }) } - if fluentdSpec.CompressConfigFile { + if r.fluentdSpec.CompressConfigFile { v = append(v, corev1.Volume{ Name: "app-config", VolumeSource: corev1.VolumeSource{ @@ -344,12 +337,12 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { }) } - if fluentdSpec.TLS.Enabled { + if r.fluentdSpec.TLS.Enabled { tlsRelatedVolume := corev1.Volume{ Name: "fluentd-tls", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: fluentdSpec.TLS.SecretName, + SecretName: r.fluentdSpec.TLS.SecretName, }, }, } @@ -359,15 +352,14 @@ func (r *Reconciler) generateVolume() (v []corev1.Volume) { } func (r *Reconciler) tmpDirHackContainer() *corev1.Container { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if isFluentdReadOnlyRootFilesystem(fluentdSpec) { + if isFluentdReadOnlyRootFilesystem(r.fluentdSpec) { return &corev1.Container{ Command: []string{"sh", "-c", "mkdir -p /mnt/tmp/fluentd/; chmod +t /mnt/tmp/fluentd"}, - Image: fluentdSpec.Image.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(fluentdSpec.Image.PullPolicy), + Image: r.fluentdSpec.Image.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(r.fluentdSpec.Image.PullPolicy), Name: "tmp-dir-hack", - Resources: fluentdSpec.Resources, - SecurityContext: fluentdSpec.Security.SecurityContext, + Resources: r.fluentdSpec.Resources, + SecurityContext: r.fluentdSpec.Security.SecurityContext, VolumeMounts: []corev1.VolumeMount{ { Name: "tmp", @@ -379,12 +371,11 @@ func (r *Reconciler) tmpDirHackContainer() *corev1.Container { } func (r *Reconciler) volumeMountHackContainer() *corev1.Container { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if fluentdSpec.VolumeMountChmod { + if r.fluentdSpec.VolumeMountChmod { return &corev1.Container{ Name: "volume-mount-hack", - Image: fluentdSpec.VolumeModImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(fluentdSpec.VolumeModImage.PullPolicy), + Image: r.fluentdSpec.VolumeModImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(r.fluentdSpec.VolumeModImage.PullPolicy), Command: []string{"sh", "-c", "chmod -R 777 " + bufferPath}, VolumeMounts: []corev1.VolumeMount{ { @@ -398,17 +389,15 @@ func (r *Reconciler) volumeMountHackContainer() *corev1.Container { } func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { - fluentdSpec := r.GetFluentdSpec(context.TODO()) - - if fluentdSpec.BufferVolumeMetrics != nil { + if r.fluentdSpec.BufferVolumeMetrics != nil { port := int32(defaultBufferVolumeMetricsPort) - if fluentdSpec.BufferVolumeMetrics.Port != 0 { - port = fluentdSpec.BufferVolumeMetrics.Port + if r.fluentdSpec.BufferVolumeMetrics.Port != 0 { + port = r.fluentdSpec.BufferVolumeMetrics.Port } portParam := fmt.Sprintf("--web.listen-address=:%d", port) args := []string{portParam} - if len(fluentdSpec.BufferVolumeArgs) != 0 { - args = append(args, fluentdSpec.BufferVolumeArgs...) + if len(r.fluentdSpec.BufferVolumeArgs) != 0 { + args = append(args, r.fluentdSpec.BufferVolumeArgs...) } else { args = append(args, "--collector.disable-defaults", "--collector.filesystem", "--collector.textfile", "--collector.textfile.directory=/prometheus/node_exporter/textfile_collector/") } @@ -418,8 +407,8 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { return &corev1.Container{ Name: "buffer-metrics-sidecar", - Image: fluentdSpec.BufferVolumeImage.RepositoryWithTag(), - ImagePullPolicy: corev1.PullPolicy(fluentdSpec.BufferVolumeImage.PullPolicy), + Image: r.fluentdSpec.BufferVolumeImage.RepositoryWithTag(), + ImagePullPolicy: corev1.PullPolicy(r.fluentdSpec.BufferVolumeImage.PullPolicy), Args: []string{ "--exec", nodeExporterCmd, "--exec", bufferSizeCmd, @@ -430,15 +419,15 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { Value: bufferPath, }, }, - Ports: generatePortsBufferVolumeMetrics(fluentdSpec), + Ports: generatePortsBufferVolumeMetrics(r.fluentdSpec), VolumeMounts: []corev1.VolumeMount{ { Name: r.bufferVolumeName(), MountPath: bufferPath, }, }, - Resources: fluentdSpec.BufferVolumeResources, - SecurityContext: fluentdSpec.Security.SecurityContext, + Resources: r.fluentdSpec.BufferVolumeResources, + SecurityContext: r.fluentdSpec.Security.SecurityContext, } } return nil @@ -446,9 +435,8 @@ func (r *Reconciler) bufferMetricsSidecarContainer() *corev1.Container { func (r *Reconciler) bufferVolumeName() string { volumeName := r.Logging.QualifiedName(v1beta1.DefaultFluentdBufferStorageVolumeName) - fluentdSpec := r.GetFluentdSpec(context.TODO()) - if fluentdSpec.BufferStorageVolume.PersistentVolumeClaim != nil { - volumeName = r.Logging.QualifiedName(fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) + if r.fluentdSpec.BufferStorageVolume.PersistentVolumeClaim != nil { + volumeName = r.Logging.QualifiedName(r.fluentdSpec.BufferStorageVolume.PersistentVolumeClaim.PersistentVolumeSource.ClaimName) } return volumeName } @@ -491,7 +479,7 @@ func generateReadinessCheck(spec *v1beta1.FluentdSpec) *corev1.Probe { return nil } -func generateInitContainer(spec *v1beta1.FluentdSpec) *corev1.Container { +func generateInitContainer(spec v1beta1.FluentdSpec) *corev1.Container { if spec.CompressConfigFile { return &corev1.Container{ Name: "init-config-reloader", From b55e07335ce8c41d46d970174dfd7eaa774f64d5 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Tue, 14 Nov 2023 15:32:27 +0100 Subject: [PATCH 11/28] fluentd: extend fluentd status Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_fluentds.yaml | 22 ++++++++++++++++++- .../logging.banzaicloud.io_fluentds.yaml | 22 ++++++++++++++++++- .../crds/v1beta1/fluentd_types.md | 16 ++++++++++++++ pkg/sdk/logging/api/v1beta1/fluentd_types.go | 6 +++++ .../api/v1beta1/zz_generated.deepcopy.go | 12 +++++++++- 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml index 2903d321f..e2a2ba518 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml @@ -18,7 +18,16 @@ spec: singular: fluentd scope: Namespaced versions: - - name: v1beta1 + - additionalPrinterColumns: + - description: Is the fluentd configuration active? + jsonPath: .status.active + name: Active + type: boolean + - description: Number of problems + jsonPath: .status.problemsCount + name: Problems + type: integer + name: v1beta1 schema: openAPIV3Schema: properties: @@ -2270,6 +2279,17 @@ spec: type: integer type: object status: + properties: + active: + type: boolean + logging: + type: string + problems: + items: + type: string + type: array + problemsCount: + type: integer type: object type: object served: true diff --git a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml index 2903d321f..e2a2ba518 100644 --- a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml +++ b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml @@ -18,7 +18,16 @@ spec: singular: fluentd scope: Namespaced versions: - - name: v1beta1 + - additionalPrinterColumns: + - description: Is the fluentd configuration active? + jsonPath: .status.active + name: Active + type: boolean + - description: Number of problems + jsonPath: .status.problemsCount + name: Problems + type: integer + name: v1beta1 schema: openAPIV3Schema: properties: @@ -2270,6 +2279,17 @@ spec: type: integer type: object status: + properties: + active: + type: boolean + logging: + type: string + problems: + items: + type: string + type: array + problemsCount: + type: integer type: object type: object served: true diff --git a/docs/configuration/crds/v1beta1/fluentd_types.md b/docs/configuration/crds/v1beta1/fluentd_types.md index 1e8062e9d..0075a28b3 100644 --- a/docs/configuration/crds/v1beta1/fluentd_types.md +++ b/docs/configuration/crds/v1beta1/fluentd_types.md @@ -197,6 +197,22 @@ Fluentd FluentdStatus +### logging (string, optional) {#fluentdstatus-logging} + +Default: - + +### active (*bool, optional) {#fluentdstatus-active} + +Default: - + +### problems ([]string, optional) {#fluentdstatus-problems} + +Default: - + +### problemsCount (int, optional) {#fluentdstatus-problemscount} + +Default: - + ## FluentdList diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index 91b46eec7..67cd33b2e 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -120,6 +120,8 @@ type _metaFluentd interface{} //nolint:deadcode,unused // +kubebuilder:object:root=true // +kubebuilder:resource:categories=logging-all // +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Active",type="boolean",JSONPath=".status.active",description="Is the fluentd configuration active?" +// +kubebuilder:printcolumn:name="Problems",type="integer",JSONPath=".status.problemsCount",description="Number of problems" // +kubebuilder:storageversion // Fluentd @@ -133,6 +135,10 @@ type Fluentd struct { // FluentdStatus type FluentdStatus struct { + Logging string `json:"logging,omitempty"` + Active *bool `json:"active,omitempty"` + Problems []string `json:"problems,omitempty"` + ProblemsCount int `json:"problemsCount,omitempty"` } // +kubebuilder:object:root=true diff --git a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go index 9ce8e734a..f217d852d 100644 --- a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go +++ b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go @@ -1303,7 +1303,7 @@ func (in *Fluentd) DeepCopyInto(out *Fluentd) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Fluentd. @@ -1582,6 +1582,16 @@ func (in *FluentdSpec) DeepCopy() *FluentdSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdStatus) DeepCopyInto(out *FluentdStatus) { *out = *in + if in.Active != nil { + in, out := &in.Active, &out.Active + *out = new(bool) + **out = **in + } + if in.Problems != nil { + in, out := &in.Problems, &out.Problems + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdStatus. From 06868c62ac4401d5fa3cd9554b21ff244a6b8f57 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Tue, 14 Nov 2023 16:35:50 +0100 Subject: [PATCH 12/28] fluentd: no longer require explicit fluentdRef in Logging Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_loggings.yaml | 2 + .../logging.banzaicloud.io_loggings.yaml | 2 + .../crds/v1beta1/logging_types.md | 6 +++ ...entd_aggregator_detached_single_unnamed.go | 38 ++++++++++++++++- pkg/resources/model/reconciler.go | 3 ++ pkg/resources/model/repository.go | 42 ++++++++++++------- pkg/sdk/logging/api/v1beta1/logging_types.go | 2 + 7 files changed, 80 insertions(+), 15 deletions(-) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml index c9105b7bf..53fccdbe9 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml @@ -18652,6 +18652,8 @@ spec: additionalProperties: type: boolean type: object + fluentdConfigName: + type: string problems: items: type: string diff --git a/config/crd/bases/logging.banzaicloud.io_loggings.yaml b/config/crd/bases/logging.banzaicloud.io_loggings.yaml index c9105b7bf..53fccdbe9 100644 --- a/config/crd/bases/logging.banzaicloud.io_loggings.yaml +++ b/config/crd/bases/logging.banzaicloud.io_loggings.yaml @@ -18652,6 +18652,8 @@ spec: additionalProperties: type: boolean type: object + fluentdConfigName: + type: string problems: items: type: string diff --git a/docs/configuration/crds/v1beta1/logging_types.md b/docs/configuration/crds/v1beta1/logging_types.md index 86297c83d..8b9c9f55d 100644 --- a/docs/configuration/crds/v1beta1/logging_types.md +++ b/docs/configuration/crds/v1beta1/logging_types.md @@ -132,6 +132,12 @@ LoggingStatus defines the observed state of Logging Result of the config check. Under normal conditions there is a single item in the map with a bool value. +### fluentdConfigName (string, optional) {#loggingstatus-fluentdconfigname} + +Name of the matched detached fluentd configuration object + +Default: - + ### problems ([]string, optional) {#loggingstatus-problems} Problems with the logging resource diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go index a3b056e26..2a5c92a21 100644 --- a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go +++ b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go @@ -118,8 +118,36 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { Workers: 2, }, } - common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) + + fluentdNotUsed := v1beta1.Fluentd{ + ObjectMeta: metav1.ObjectMeta{ + Name: "not-to-be-used-fluentd", + Namespace: ns, + }, + Spec: v1beta1.FluentdSpec{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("200M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("50M"), + }, + }, + BufferVolumeMetrics: &v1beta1.Metrics{}, + Scaling: &v1beta1.FluentdScaling{ + Replicas: 1, + Drain: v1beta1.FluentdDrainConfig{ + Enabled: true, + }, + }, + Workers: 2, + }, + } + common.RequireNoError(t, c.GetClient().Create(ctx, &fluentdNotUsed)) + t.Logf("fluentd is: %v", fluentd) tags := "time" output := v1beta1.Output{ @@ -178,6 +206,14 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { })) require.Eventually(t, func() bool { + if len(fluentdNotUsed.Status.Problems) == 0 { + t.Log("second fluentd instance should have it's problems field filled") + return false + } + if logging.Status.FluentdConfigName != &fluentd.Name { + t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) + return false + } if operatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(operatorLabels))(); !operatorRunning { t.Log("waiting for the operator") return false diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index 0c0023da8..fb54a5c3e 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -158,6 +158,9 @@ func NewValidationReconciler( flow.Status.ProblemsCount = len(flow.Status.Problems) } + if resources.Fluentd.Configuration != nil { + + } if resources.Fluentd.Configuration != nil && resources.Logging.Spec.FluentdSpec != nil { resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration found is set as well, clearing inline", resources.Fluentd.Configuration.Name)) resources.Logging.Spec.FluentdSpec = nil diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 0cd0a0c4f..0d7f1f800 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -20,6 +20,7 @@ import ( "sort" "emperror.dev/errors" + "github.com/cisco-open/operator-tools/pkg/utils" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -338,6 +339,19 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 return res, nil } +func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { + for _, i := range *list { + if logging.Status.FluentdConfigName != "" { + if i.Name != logging.Status.FluentdConfigName { + i.Status.Problems = append(i.Status.Problems, "Logging already has a detached fluentd configuration, remove excess configuration objects") + } + } + } + multipleFluentdErrors := "multiple fluentd configurations found, couldn't associate it with logging" + logging.Status.Problems = append(logging.Status.Problems, multipleFluentdErrors) + return nil, errors.New(multipleFluentdErrors) +} + func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { var list v1beta1.FluentdList if err := r.Client.List(ctx, &list); err != nil { @@ -346,23 +360,23 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging var res []v1beta1.Fluentd res = append(res, list.Items...) - if len(res) < 1 { - return nil, nil - } - // Multiple detached fluentds - if len(res) > 1 { - for _, i := range res { - // Explicit reference is set and found - if i.Name == logging.Spec.FluentdRef { - err := i.Spec.SetDefaults() - return &i, err - } + switch len(res) { + case 0: + return nil, nil + case 1: + // Implicitly associate fluentd configuration object with logging + detachedFluentd := res[0] + err := detachedFluentd.Spec.SetDefaults() + if err != nil { + logging.Status.FluentdConfigName = detachedFluentd.Name + detachedFluentd.Status.Active = utils.BoolPointer(true) + detachedFluentd.Status.Logging = logging.Name } - return nil, errors.New("multiple fluentd configurations found, could't associate it with logging") + return &detachedFluentd, err + default: + return r.handleMultipleDetachedFluentdObjects(&res, logging) } - err := res[0].Spec.SetDefaults() - return &res[0], err } func (r LoggingResourceRepository) LoggingRoutesFor(ctx context.Context, logging v1beta1.Logging) ([]v1beta1.LoggingRoute, error) { diff --git a/pkg/sdk/logging/api/v1beta1/logging_types.go b/pkg/sdk/logging/api/v1beta1/logging_types.go index eadfb58d9..7c44d7156 100644 --- a/pkg/sdk/logging/api/v1beta1/logging_types.go +++ b/pkg/sdk/logging/api/v1beta1/logging_types.go @@ -111,6 +111,8 @@ type ConfigCheck struct { type LoggingStatus struct { // Result of the config check. Under normal conditions there is a single item in the map with a bool value. ConfigCheckResults map[string]bool `json:"configCheckResults,omitempty"` + // Name of the matched detached fluentd configuration object + FluentdConfigName string `json:"fluentdConfigName,omitempty"` // Problems with the logging resource Problems []string `json:"problems,omitempty"` From 6afc649789aeb68d3a4c325a7a0bcd4df1220e2e Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 20 Nov 2023 09:52:11 +0100 Subject: [PATCH 13/28] fluentd: refactor NewValidationReconciler, set associated fields Signed-off-by: Szilard Parrag --- pkg/resources/fluentd/fluentd.go | 5 +++++ pkg/resources/model/reconciler.go | 16 ++++++++-------- pkg/resources/model/repository.go | 8 ++++---- pkg/resources/model/resources.go | 6 +++++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index 378bc1907..ac029e379 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -132,6 +132,11 @@ func New(client client.Client, log logr.Logger, // Reconcile reconciles the fluentd resource func (r *Reconciler) Reconcile(ctx context.Context) (*reconcile.Result, error) { + // No fluentdSpec yet, explicitly ask for a requeue to short circuit the controller loop after the status update + if r.fluentdSpec == nil { + return &reconcile.Result{Requeue: true}, nil + } + patchBase := client.MergeFrom(r.Logging.DeepCopy()) objects := []resources.Resource{ diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index fb54a5c3e..661d74ccd 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -159,15 +159,15 @@ func NewValidationReconciler( } if resources.Fluentd.Configuration != nil { + registerForPatching(resources.Fluentd.Configuration) - } - if resources.Fluentd.Configuration != nil && resources.Logging.Spec.FluentdSpec != nil { - resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration found is set as well, clearing inline", resources.Fluentd.Configuration.Name)) - resources.Logging.Spec.FluentdSpec = nil - } - - if fluentd := resources.GetFluentd(); fluentd != nil { - registerForPatching(fluentd) + if resources.Logging.Spec.FluentdSpec != nil { + resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration is set as well, clearing inline", resources.Fluentd.Configuration.Name)) + resources.Logging.Spec.FluentdSpec = nil + } + resources.Logging.Status.FluentdConfigName = resources.Fluentd.Configuration.Name + resources.Fluentd.Configuration.Status.Active = utils.BoolPointer(true) + resources.Fluentd.Configuration.Status.Logging = resources.Logging.Name } for i := range resources.SyslogNG.ClusterFlows { diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 0d7f1f800..d9838ec42 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -58,7 +58,7 @@ func (r LoggingResourceRepository) LoggingResourcesFor(ctx context.Context, logg res.Fluentd.ClusterOutputs, err = r.ClusterOutputsFor(ctx, logging) errs = errors.Append(errs, err) - res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, logging) + res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, &logging) errs = errors.Append(errs, err) res.SyslogNG.ClusterFlows, err = r.SyslogNGClusterFlowsFor(ctx, logging) @@ -338,8 +338,8 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 }) return res, nil } - -func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { +func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { + // TODO add a bit more verbose error handling for _, i := range *list { if logging.Status.FluentdConfigName != "" { if i.Name != logging.Status.FluentdConfigName { @@ -352,7 +352,7 @@ func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[] return nil, errors.New(multipleFluentdErrors) } -func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { var list v1beta1.FluentdList if err := r.Client.List(ctx, &list); err != nil { return nil, err diff --git a/pkg/resources/model/resources.go b/pkg/resources/model/resources.go index de9e3b5a3..671a4bf24 100644 --- a/pkg/resources/model/resources.go +++ b/pkg/resources/model/resources.go @@ -37,11 +37,15 @@ func (l LoggingResources) GetFluentd() *v1beta1.Fluentd { } func (l LoggingResources) GetFluentdSpec() *v1beta1.FluentdSpec { + if detachedFluentd := l.GetFluentd(); detachedFluentd != nil { return &detachedFluentd.Spec } + if l.Logging.Spec.FluentdSpec != nil { + return l.Logging.Spec.FluentdSpec + } - return l.Logging.Spec.FluentdSpec + return nil } type FluentdLoggingResources struct { From 5c6eadf0aca476c2cd57a30fac508f4c81584884 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 20 Nov 2023 12:20:36 +0100 Subject: [PATCH 14/28] e2e: add followup Signed-off-by: Szilard Parrag --- .../fluentd_aggregator_detached_single_unnamed.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go index 2a5c92a21..af0d6d34a 100644 --- a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go +++ b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go @@ -210,7 +210,7 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { t.Log("second fluentd instance should have it's problems field filled") return false } - if logging.Status.FluentdConfigName != &fluentd.Name { + if logging.Status.FluentdConfigName != fluentd.Name { t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) return false } From 0fab875dcb4039d86da10597d275ee24e7fa7f88 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 22 Nov 2023 10:14:18 +0100 Subject: [PATCH 15/28] logging: remove explicit fluentdRef Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_loggings.yaml | 2 -- config/crd/bases/logging.banzaicloud.io_loggings.yaml | 2 -- docs/configuration/crds/v1beta1/fluentd_types.md | 8 ++------ docs/configuration/crds/v1beta1/logging_types.md | 6 ------ pkg/sdk/logging/api/v1beta1/conversion.go | 2 +- pkg/sdk/logging/api/v1beta1/logging_types.go | 6 ++---- 6 files changed, 5 insertions(+), 21 deletions(-) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml index 53fccdbe9..278d34dca 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_loggings.yaml @@ -6106,8 +6106,6 @@ spec: format: int32 type: integer type: object - fluentdRef: - type: string globalFilters: items: properties: diff --git a/config/crd/bases/logging.banzaicloud.io_loggings.yaml b/config/crd/bases/logging.banzaicloud.io_loggings.yaml index 53fccdbe9..278d34dca 100644 --- a/config/crd/bases/logging.banzaicloud.io_loggings.yaml +++ b/config/crd/bases/logging.banzaicloud.io_loggings.yaml @@ -6106,8 +6106,6 @@ spec: format: int32 type: integer type: object - fluentdRef: - type: string globalFilters: items: properties: diff --git a/docs/configuration/crds/v1beta1/fluentd_types.md b/docs/configuration/crds/v1beta1/fluentd_types.md index 0075a28b3..3008443c5 100644 --- a/docs/configuration/crds/v1beta1/fluentd_types.md +++ b/docs/configuration/crds/v1beta1/fluentd_types.md @@ -197,21 +197,17 @@ Fluentd FluentdStatus -### logging (string, optional) {#fluentdstatus-logging} +### active (*bool, optional) {#fluentdstatus-active} -Default: - -### active (*bool, optional) {#fluentdstatus-active} +### logging (string, optional) {#fluentdstatus-logging} -Default: - ### problems ([]string, optional) {#fluentdstatus-problems} -Default: - ### problemsCount (int, optional) {#fluentdstatus-problemscount} -Default: - ## FluentdList diff --git a/docs/configuration/crds/v1beta1/logging_types.md b/docs/configuration/crds/v1beta1/logging_types.md index 8b9c9f55d..caa158fb3 100644 --- a/docs/configuration/crds/v1beta1/logging_types.md +++ b/docs/configuration/crds/v1beta1/logging_types.md @@ -59,11 +59,6 @@ Override generated config. This is a *raw* configuration string for troubleshoot FluentbitAgent daemonset configuration. Deprecated, will be removed with next major version Migrate to the standalone NodeAgent resource -### fluentdRef (string, optional) {#loggingspec-fluentdref} - -Fluentd statefulset configuration reference by name - - ### fluentd (*FluentdSpec, optional) {#loggingspec-fluentd} Fluentd statefulset configuration @@ -136,7 +131,6 @@ Result of the config check. Under normal conditions there is a single item in th Name of the matched detached fluentd configuration object -Default: - ### problems ([]string, optional) {#loggingstatus-problems} diff --git a/pkg/sdk/logging/api/v1beta1/conversion.go b/pkg/sdk/logging/api/v1beta1/conversion.go index 706379e4a..1265ea2b0 100644 --- a/pkg/sdk/logging/api/v1beta1/conversion.go +++ b/pkg/sdk/logging/api/v1beta1/conversion.go @@ -47,7 +47,7 @@ func APITypes() []runtime.Object { func (l *Logging) Default() { Log.Info("Defaulter called for", "logging", l) - if l.Spec.FluentdSpec != nil && l.Spec.FluentdRef == "" { + if l.Spec.FluentdSpec != nil { fluentdSpec := l.Spec.FluentdSpec if fluentdSpec.Scaling == nil { fluentdSpec.Scaling = new(FluentdScaling) diff --git a/pkg/sdk/logging/api/v1beta1/logging_types.go b/pkg/sdk/logging/api/v1beta1/logging_types.go index 7c44d7156..5353b3249 100644 --- a/pkg/sdk/logging/api/v1beta1/logging_types.go +++ b/pkg/sdk/logging/api/v1beta1/logging_types.go @@ -55,8 +55,6 @@ type LoggingSpec struct { FluentbitSpec *FluentbitSpec `json:"fluentbit,omitempty"` // Fluentd statefulset configuration FluentdSpec *FluentdSpec `json:"fluentd,omitempty"` - // Fluentd statefulset configuration reference by name - FluentdRef string `json:"fluentdRef,omitempty"` // Syslog-NG statefulset configuration SyslogNGSpec *SyslogNGSpec `json:"syslogNG,omitempty"` // Default flow for unmatched logs. This Flow configuration collects all logs that didn't matched any other Flow. @@ -191,7 +189,7 @@ func (l *Logging) SetDefaults() error { if !l.Spec.FlowConfigCheckDisabled && l.Status.ConfigCheckResults == nil { l.Status.ConfigCheckResults = make(map[string]bool) } - if len(l.Spec.FluentdRef) == 0 { + if len(l.Status.FluentdConfigName) == 0 { if err := l.Spec.FluentdSpec.SetDefaults(); err != nil { return err } @@ -527,5 +525,5 @@ func GenerateLoggingRefLabels(loggingRef string) map[string]string { } func (l *Logging) AreMultipleAggregatorsSet() bool { - return l.Spec.SyslogNGSpec != nil && (l.Spec.FluentdSpec != nil || len(l.Spec.FluentdRef) != 0) + return l.Spec.SyslogNGSpec != nil && (l.Spec.FluentdSpec != nil || len(l.Status.FluentdConfigName) != 0) } From b957e74922d049f55f073f1468b0ca8774544003 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 22 Nov 2023 13:34:01 +0100 Subject: [PATCH 16/28] refactor(fluentd): extend reconcilers with fluentdSpec reference Signed-off-by: Szilard Parrag --- controllers/logging/logging_controller.go | 4 +++- pkg/resources/fluentbit/configsecret.go | 9 ++------- pkg/resources/fluentbit/fluentbit.go | 3 +++ pkg/resources/fluentd/fluentd.go | 8 -------- pkg/resources/model/repository.go | 4 ++-- pkg/resources/nodeagent/configsecret.go | 6 +----- pkg/resources/nodeagent/nodeagent.go | 8 ++++++-- 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index 3ee10ac40..fb39e4d26 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -216,6 +216,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct r.Client, log.WithName("fluentbit-legacy"), &logging, + fluentdSpec, reconcilerOpts, logging.Spec.FluentbitSpec, loggingDataProvider, @@ -234,6 +235,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct r.Client, l.WithValues("fluentbitagent", f.Name), &logging, + fluentdSpec, reconcilerOpts, &f.Spec, loggingDataProvider, @@ -258,7 +260,7 @@ func (r *LoggingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct log.Error(errors.New("nodeagent definition conflict"), problem) } } - reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging, fluentdSpec)).Reconcile) + reconcilers = append(reconcilers, nodeagent.New(r.Client, r.Log, &logging, fluentdSpec, agents, reconcilerOpts, fluentd.NewDataProvider(r.Client, &logging, fluentdSpec)).Reconcile) } for _, rec := range reconcilers { diff --git a/pkg/resources/fluentbit/configsecret.go b/pkg/resources/fluentbit/configsecret.go index 6688257a4..d7aef9ab8 100644 --- a/pkg/resources/fluentbit/configsecret.go +++ b/pkg/resources/fluentbit/configsecret.go @@ -184,11 +184,6 @@ func newFluentbitNetwork(network v1beta1.FluentbitNetwork) (result FluentbitNetw func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, error) { ctx := context.TODO() - fluentdSpec := r.Logging.Spec.FluentdSpec - if detachedFluentd := fluentd.GetFluentd(ctx, r.resourceReconciler.Client, r.resourceReconciler.Log, r.Logging.Spec.ControlNamespace); detachedFluentd != nil { - fluentdSpec = &detachedFluentd.Spec - } - if r.fluentbitSpec.CustomConfigSecret != "" { return &corev1.Secret{ ObjectMeta: r.FluentbitObjectMeta(fluentBitSecretConfigName), @@ -243,7 +238,7 @@ func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, er } } - if fluentdSpec != nil { + if r.fluentdSpec != nil { fluentbitTargetHost := r.fluentbitSpec.TargetHost if fluentbitTargetHost == "" { fluentbitTargetHost = aggregatorEndpoint(r.Logging, fluentd.ServiceName) @@ -370,7 +365,7 @@ func (r *Reconciler) configSecret() (runtime.Object, reconciler.DesiredState, er for _, a := range r.loggingRoutes { tenants = append(tenants, a.Status.Tenants...) } - if err := r.configureOutputsForTenants(ctx, tenants, &input, fluentdSpec); err != nil { + if err := r.configureOutputsForTenants(ctx, tenants, &input, r.fluentdSpec); err != nil { return nil, nil, errors.WrapIf(err, "configuring outputs for target tenants") } } else { diff --git a/pkg/resources/fluentbit/fluentbit.go b/pkg/resources/fluentbit/fluentbit.go index 159e37f57..f736b62f8 100644 --- a/pkg/resources/fluentbit/fluentbit.go +++ b/pkg/resources/fluentbit/fluentbit.go @@ -90,6 +90,7 @@ type Reconciler struct { resourceReconciler *reconciler.GenericResourceReconciler logger logr.Logger Logging *v1beta1.Logging + fluentdSpec *v1beta1.FluentdSpec configs map[string][]byte fluentbitSpec *v1beta1.FluentbitSpec loggingDataProvider loggingdataprovider.LoggingDataProvider @@ -101,6 +102,7 @@ type Reconciler struct { func New(client client.Client, logger logr.Logger, logging *v1beta1.Logging, + fluentdSpec *v1beta1.FluentdSpec, opts reconciler.ReconcilerOpts, fluentbitSpec *v1beta1.FluentbitSpec, loggingDataProvider loggingdataprovider.LoggingDataProvider, @@ -108,6 +110,7 @@ func New(client client.Client, loggingRoutes []v1beta1.LoggingRoute) *Reconciler { return &Reconciler{ Logging: logging, + fluentdSpec: fluentdSpec, logger: logger, resourceReconciler: reconciler.NewGenericReconciler(client, logger.WithName("reconciler"), opts), fluentbitSpec: fluentbitSpec, diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index ac029e379..843a4d7db 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -104,14 +104,6 @@ func GetFluentd(ctx context.Context, Client client.Client, log logr.Logger, cont return nil } -func (r *Reconciler) GetFluentdSpec(ctx context.Context) *v1beta1.FluentdSpec { - fluentdSpec := r.Logging.Spec.FluentdSpec - if detachedFluentd := GetFluentd(ctx, r.Client, r.Log, r.Logging.Spec.ControlNamespace); detachedFluentd != nil { - fluentdSpec = &detachedFluentd.Spec - } - return fluentdSpec -} - func (r *Reconciler) getServiceAccount() string { if r.fluentdSpec.Security.ServiceAccount != "" { return r.fluentdSpec.Security.ServiceAccount diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index d9838ec42..e40ed0c26 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -366,14 +366,14 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging return nil, nil case 1: // Implicitly associate fluentd configuration object with logging - detachedFluentd := res[0] + detachedFluentd := &res[0] err := detachedFluentd.Spec.SetDefaults() if err != nil { logging.Status.FluentdConfigName = detachedFluentd.Name detachedFluentd.Status.Active = utils.BoolPointer(true) detachedFluentd.Status.Logging = logging.Name } - return &detachedFluentd, err + return detachedFluentd, err default: return r.handleMultipleDetachedFluentdObjects(&res, logging) } diff --git a/pkg/resources/nodeagent/configsecret.go b/pkg/resources/nodeagent/configsecret.go index b088bf91b..0ce550012 100644 --- a/pkg/resources/nodeagent/configsecret.go +++ b/pkg/resources/nodeagent/configsecret.go @@ -318,10 +318,6 @@ func generateUpstreamConfig(input fluentBitConfig) (string, error) { } func (n *nodeAgentInstance) generateUpstreamNode(index int32) upstreamNode { - fluentdSpec := n.logging.Spec.FluentdSpec - if detachedFluentd := fluentd.GetFluentd(context.TODO(), n.reconciler.Client, n.reconciler.Log, n.logging.Spec.ControlNamespace); detachedFluentd != nil { - fluentdSpec = &detachedFluentd.Spec - } podName := n.FluentdQualifiedName(fmt.Sprintf("%s-%d", fluentd.ComponentFluentd, index)) return upstreamNode{ Name: podName, @@ -330,6 +326,6 @@ func (n *nodeAgentInstance) generateUpstreamNode(index int32) upstreamNode { n.FluentdQualifiedName(fluentd.ServiceName+"-headless"), n.logging.Spec.ControlNamespace, n.logging.ClusterDomainAsSuffix()), - Port: fluentdSpec.Port, + Port: n.fluentdSpec.Port, } } diff --git a/pkg/resources/nodeagent/nodeagent.go b/pkg/resources/nodeagent/nodeagent.go index c2a8623f6..cc7d4ab5e 100644 --- a/pkg/resources/nodeagent/nodeagent.go +++ b/pkg/resources/nodeagent/nodeagent.go @@ -269,7 +269,8 @@ func (n *nodeAgentInstance) getServiceAccount() string { // // Reconciler holds info what resource to reconcile type Reconciler struct { - Logging *v1beta1.Logging + Logging *v1beta1.Logging + fluentdSpec *v1beta1.FluentdSpec *reconciler.GenericResourceReconciler configs map[string][]byte agents map[string]v1beta1.NodeAgentConfig @@ -277,12 +278,13 @@ type Reconciler struct { } // New creates a new NodeAgent reconciler -func New(client client.Client, logger logr.Logger, logging *v1beta1.Logging, agents map[string]v1beta1.NodeAgentConfig, opts reconciler.ReconcilerOpts, fluentdDataProvider loggingdataprovider.LoggingDataProvider) *Reconciler { +func New(client client.Client, logger logr.Logger, logging *v1beta1.Logging, fluentdSpec *v1beta1.FluentdSpec, agents map[string]v1beta1.NodeAgentConfig, opts reconciler.ReconcilerOpts, fluentdDataProvider loggingdataprovider.LoggingDataProvider) *Reconciler { return &Reconciler{ Logging: logging, GenericResourceReconciler: reconciler.NewGenericReconciler(client, logger, opts), agents: agents, fluentdDataProvider: fluentdDataProvider, + fluentdSpec: fluentdSpec, } } @@ -291,6 +293,7 @@ type nodeAgentInstance struct { nodeAgent *v1beta1.NodeAgentConfig reconciler *reconciler.GenericResourceReconciler logging *v1beta1.Logging + fluentdSpec *v1beta1.FluentdSpec configs map[string][]byte loggingDataProvider loggingdataprovider.LoggingDataProvider } @@ -340,6 +343,7 @@ func (r *Reconciler) processAgent(ctx context.Context, name string, userDefinedA reconciler: r.GenericResourceReconciler, logging: r.Logging, loggingDataProvider: r.fluentdDataProvider, + fluentdSpec: r.fluentdSpec, } return instance.Reconcile(ctx) From f13c7af7ee8430ce61e94b2ec526cbe8c6c35a81 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 22 Nov 2023 13:45:47 +0100 Subject: [PATCH 17/28] refactor(fluentd): remove code duplication in case multiple detached fluentd objects are found Signed-off-by: Szilard Parrag --- pkg/resources/model/repository.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index e40ed0c26..2e0f362de 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -20,7 +20,6 @@ import ( "sort" "emperror.dev/errors" - "github.com/cisco-open/operator-tools/pkg/utils" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -339,10 +338,10 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 return res, nil } func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { - // TODO add a bit more verbose error handling for _, i := range *list { if logging.Status.FluentdConfigName != "" { if i.Name != logging.Status.FluentdConfigName { + i.Status.Problems = []string{} i.Status.Problems = append(i.Status.Problems, "Logging already has a detached fluentd configuration, remove excess configuration objects") } } @@ -368,11 +367,6 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging // Implicitly associate fluentd configuration object with logging detachedFluentd := &res[0] err := detachedFluentd.Spec.SetDefaults() - if err != nil { - logging.Status.FluentdConfigName = detachedFluentd.Name - detachedFluentd.Status.Active = utils.BoolPointer(true) - detachedFluentd.Status.Logging = logging.Name - } return detachedFluentd, err default: return r.handleMultipleDetachedFluentdObjects(&res, logging) From 2cec708306ff0b2d175af1b6530e263ff01133ee Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 22 Nov 2023 13:46:54 +0100 Subject: [PATCH 18/28] test(e2e): refine detached fluentd test case Signed-off-by: Szilard Parrag --- ...entd_aggregator_detached_single_unnamed.go | 3 ++- .../fluentd_aggregator_detached_test.go | 6 ++++- pkg/resources/model/reconciler.go | 26 ++++++++++--------- pkg/resources/model/repository.go | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go index af0d6d34a..1b9af7289 100644 --- a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go +++ b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go @@ -210,7 +210,8 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { t.Log("second fluentd instance should have it's problems field filled") return false } - if logging.Status.FluentdConfigName != fluentd.Name { + if len(logging.Status.FluentdConfigName) == 0 || logging.Status.FluentdConfigName != fluentd.Name { + common.RequireNoError(t, c.GetClient().Get(ctx, utils.ObjectKeyFromObjectMeta(&logging), &logging)) t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) return false } diff --git a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go index fc4be7a3d..bbf8795c4 100644 --- a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go +++ b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go @@ -88,7 +88,6 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { Keepalive: utils.BoolPointer(false), }, }, - FluentdRef: "detached-fluentd", }, } common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) @@ -191,6 +190,11 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { t.Log("waiting for the aggregator") return false } + if len(logging.Status.FluentdConfigName) == 0 || logging.Status.FluentdConfigName != fluentd.Name { + common.RequireNoError(t, c.GetClient().Get(ctx, utils.ObjectKeyFromObjectMeta(&logging), &logging)) + t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) + return false + } cmd := common.CmdEnv(exec.Command("kubectl", "logs", diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index 661d74ccd..e1df1647e 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -158,18 +158,6 @@ func NewValidationReconciler( flow.Status.ProblemsCount = len(flow.Status.Problems) } - if resources.Fluentd.Configuration != nil { - registerForPatching(resources.Fluentd.Configuration) - - if resources.Logging.Spec.FluentdSpec != nil { - resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration is set as well, clearing inline", resources.Fluentd.Configuration.Name)) - resources.Logging.Spec.FluentdSpec = nil - } - resources.Logging.Status.FluentdConfigName = resources.Fluentd.Configuration.Name - resources.Fluentd.Configuration.Status.Active = utils.BoolPointer(true) - resources.Fluentd.Configuration.Status.Logging = resources.Logging.Name - } - for i := range resources.SyslogNG.ClusterFlows { flow := &resources.SyslogNG.ClusterFlows[i] registerForPatching(flow) @@ -219,6 +207,20 @@ func NewValidationReconciler( resources.Logging.Status.Problems = nil resources.Logging.Status.WatchNamespaces = nil + if resources.Fluentd.Configuration != nil { + registerForPatching(resources.Fluentd.Configuration) + + if resources.Logging.Spec.FluentdSpec != nil { + resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration is set as well, clearing inline", resources.Fluentd.Configuration.Name)) + resources.Logging.Spec.FluentdSpec = nil + } + logger.Info("found detached fluentd aggregator, making association", "name=", resources.Fluentd.Configuration.Name) + resources.Logging.Status.FluentdConfigName = resources.Fluentd.Configuration.Name + + resources.Fluentd.Configuration.Status.Active = utils.BoolPointer(true) + resources.Fluentd.Configuration.Status.Logging = resources.Logging.Name + } + if !resources.Logging.WatchAllNamespaces() { resources.Logging.Status.WatchNamespaces = resources.WatchNamespaces } diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 2e0f362de..cf165b142 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -339,7 +339,7 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 } func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { for _, i := range *list { - if logging.Status.FluentdConfigName != "" { + if len(logging.Status.FluentdConfigName) != 0 { if i.Name != logging.Status.FluentdConfigName { i.Status.Problems = []string{} i.Status.Problems = append(i.Status.Problems, "Logging already has a detached fluentd configuration, remove excess configuration objects") From e4bb155bd1eaf3adebf12c8f33ae27b929d8826b Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 27 Nov 2023 14:15:28 +0100 Subject: [PATCH 19/28] refactor(fluentd): make sure FluentdConfigFor follows previous conventions by not taking pointers Signed-off-by: Szilard Parrag --- pkg/resources/model/repository.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index cf165b142..d604224d7 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -57,7 +57,7 @@ func (r LoggingResourceRepository) LoggingResourcesFor(ctx context.Context, logg res.Fluentd.ClusterOutputs, err = r.ClusterOutputsFor(ctx, logging) errs = errors.Append(errs, err) - res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, &logging) + res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, logging) errs = errors.Append(errs, err) res.SyslogNG.ClusterFlows, err = r.SyslogNGClusterFlowsFor(ctx, logging) @@ -337,7 +337,7 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 }) return res, nil } -func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { +func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { for _, i := range *list { if len(logging.Status.FluentdConfigName) != 0 { if i.Name != logging.Status.FluentdConfigName { @@ -351,7 +351,7 @@ func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[] return nil, errors.New(multipleFluentdErrors) } -func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging *v1beta1.Logging) (*v1beta1.Fluentd, error) { +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { var list v1beta1.FluentdList if err := r.Client.List(ctx, &list); err != nil { return nil, err @@ -365,9 +365,9 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging return nil, nil case 1: // Implicitly associate fluentd configuration object with logging - detachedFluentd := &res[0] + detachedFluentd := res[0] err := detachedFluentd.Spec.SetDefaults() - return detachedFluentd, err + return &detachedFluentd, err default: return r.handleMultipleDetachedFluentdObjects(&res, logging) } From 19408562a12a095c84997e77f1d49dde44a1e18f Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 27 Nov 2023 14:29:10 +0100 Subject: [PATCH 20/28] fix(reconciler): add note regarding ordering of modification and registerForPatching() call Signed-off-by: Szilard Parrag --- pkg/resources/model/reconciler.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index e1df1647e..3e47f4697 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -41,6 +41,7 @@ func NewValidationReconciler( logger logr.Logger, ) func(ctx context.Context) (*reconcile.Result, error) { return func(ctx context.Context) (*reconcile.Result, error) { + // Make sure that you call registerForPatching() before modifying the object var patchRequests []patchRequest registerForPatching := func(obj client.Object) { patchRequests = append(patchRequests, patchRequest{ From 8ba94073bc970ecafb33f3b926d66abf09039617 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 27 Nov 2023 14:44:23 +0100 Subject: [PATCH 21/28] feat(fluentd): add support for SidecarContainers in detached fluentd Signed-off-by: Szilard Parrag --- .../crds/logging.banzaicloud.io_fluentds.yaml | 614 ++++++++++++++++++ .../logging.banzaicloud.io_fluentds.yaml | 614 ++++++++++++++++++ pkg/resources/fluentd/statefulset.go | 4 +- 3 files changed, 1230 insertions(+), 2 deletions(-) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml index e2a2ba518..a7a2f0d8b 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml @@ -2174,6 +2174,620 @@ spec: type: object type: array type: object + sidecarContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array statefulsetAnnotations: additionalProperties: type: string diff --git a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml index e2a2ba518..a7a2f0d8b 100644 --- a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml +++ b/config/crd/bases/logging.banzaicloud.io_fluentds.yaml @@ -2174,6 +2174,620 @@ spec: type: object type: array type: object + sidecarContainers: + items: + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + type: object + type: array + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + capabilities: + properties: + add: + items: + type: string + type: array + drop: + items: + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + type: string + required: + - name + type: object + type: array statefulsetAnnotations: additionalProperties: type: string diff --git a/pkg/resources/fluentd/statefulset.go b/pkg/resources/fluentd/statefulset.go index 57f0283d5..ddb1c1b6b 100644 --- a/pkg/resources/fluentd/statefulset.go +++ b/pkg/resources/fluentd/statefulset.go @@ -92,8 +92,8 @@ func (r *Reconciler) statefulsetSpec() *appsv1.StatefulSetSpec { if c := r.bufferMetricsSidecarContainer(); c != nil { containers = append(containers, *c) } - if len(r.Logging.Spec.FluentdSpec.SidecarContainers) != 0 { - containers = append(containers, r.Logging.Spec.FluentdSpec.SidecarContainers...) + if len(r.fluentdSpec.SidecarContainers) != 0 { + containers = append(containers, r.fluentdSpec.SidecarContainers...) } sts := &appsv1.StatefulSetSpec{ From 0a58a1237643e71bc1026b6cb59ae620846d186c Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Wed, 29 Nov 2023 16:16:43 +0100 Subject: [PATCH 22/28] fix(fluentd): remove dead code Signed-off-by: Szilard Parrag --- pkg/resources/fluentd/fluentd.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index 843a4d7db..f0997074f 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -124,11 +124,6 @@ func New(client client.Client, log logr.Logger, // Reconcile reconciles the fluentd resource func (r *Reconciler) Reconcile(ctx context.Context) (*reconcile.Result, error) { - // No fluentdSpec yet, explicitly ask for a requeue to short circuit the controller loop after the status update - if r.fluentdSpec == nil { - return &reconcile.Result{Requeue: true}, nil - } - patchBase := client.MergeFrom(r.Logging.DeepCopy()) objects := []resources.Resource{ From 9ed9d0c5c258da0e6a99d9a604f78309a6b7bfbc Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Thu, 30 Nov 2023 15:39:44 +0100 Subject: [PATCH 23/28] fix(e2e): detached fluentd test case rename Signed-off-by: Szilard Parrag --- ...amed.go => fluentd_aggregator_detached_single_unnamed_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename e2e/fluentd-aggregator-detached-single-unnamed/{fluentd_aggregator_detached_single_unnamed.go => fluentd_aggregator_detached_single_unnamed_test.go} (100%) diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go similarity index 100% rename from e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed.go rename to e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go From ff99f64864c41d0e03846aafc1ae6d250553e510 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Thu, 30 Nov 2023 17:02:58 +0100 Subject: [PATCH 24/28] test(e2e): rewrite detached fluentd test case to be a negative test Signed-off-by: Szilard Parrag --- ...aggregator_detached_single_unnamed_test.go | 81 ++++++++----------- pkg/resources/model/reconciler.go | 18 +++++ pkg/resources/model/repository.go | 32 +++++--- pkg/resources/model/resources.go | 1 + 4 files changed, 71 insertions(+), 61 deletions(-) diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go index 1b9af7289..9dd1084f1 100644 --- a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go +++ b/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go @@ -18,9 +18,7 @@ import ( "context" "fmt" "os" - "os/exec" "path/filepath" - "strings" "testing" "time" @@ -34,14 +32,12 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/cluster" "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/output" "github.com/kube-logging/logging-operator/e2e/common" - "github.com/kube-logging/logging-operator/e2e/common/cond" "github.com/kube-logging/logging-operator/e2e/common/setup" ) @@ -60,6 +56,29 @@ func init() { } } +func checkExcessFluentd(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd) bool { + fluentdInstanceName := fluentd.Name + cluster := *c + + if len(fluentd.Status.Problems) == 0 { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's problems field filled", fluentdInstanceName) + return false + } + if fluentd.Status.Logging != "" { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's logging field empty, found: %s", fluentdInstanceName, fluentd.Status.Logging) + return false + } + if *fluentd.Status.Active != false { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's active field set as false, found: %v", fluentdInstanceName, *fluentd.Status.Active) + return false + } + + return true +} + func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { common.Initialize(t) ns := "testing-1" @@ -92,9 +111,9 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { } common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) - fluentd := v1beta1.Fluentd{ + fluentd1 := v1beta1.Fluentd{ ObjectMeta: metav1.ObjectMeta{ - Name: "name-not-to-be-used", + Name: "not-to-be-used-fluentd-1", Namespace: ns, }, Spec: v1beta1.FluentdSpec{ @@ -118,11 +137,11 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { Workers: 2, }, } - common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) + common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd1)) - fluentdNotUsed := v1beta1.Fluentd{ + fluentd2 := v1beta1.Fluentd{ ObjectMeta: metav1.ObjectMeta{ - Name: "not-to-be-used-fluentd", + Name: "not-to-be-used-fluentd-2", Namespace: ns, }, Spec: v1beta1.FluentdSpec{ @@ -146,9 +165,9 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { Workers: 2, }, } - common.RequireNoError(t, c.GetClient().Create(ctx, &fluentdNotUsed)) + common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd2)) - t.Logf("fluentd is: %v", fluentd) + t.Logf("fluentd is: %v", fluentd1) tags := "time" output := v1beta1.Output{ ObjectMeta: metav1.ObjectMeta{ @@ -192,53 +211,19 @@ func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { } common.RequireNoError(t, c.GetClient().Create(ctx, &flow)) - aggregatorLabels := map[string]string{ - "app.kubernetes.io/name": "fluentd", - "app.kubernetes.io/component": "fluentd", - } - operatorLabels := map[string]string{ - "app.kubernetes.io/name": releaseNameOverride, - } - go setup.LogProducer(t, c.GetClient(), setup.LogProducerOptionFunc(func(options *setup.LogProducerOptions) { options.Namespace = ns options.Labels = producerLabels })) require.Eventually(t, func() bool { - if len(fluentdNotUsed.Status.Problems) == 0 { - t.Log("second fluentd instance should have it's problems field filled") + if rv := checkExcessFluentd(t, &c, &ctx, &fluentd1); !rv { return false } - if len(logging.Status.FluentdConfigName) == 0 || logging.Status.FluentdConfigName != fluentd.Name { - common.RequireNoError(t, c.GetClient().Get(ctx, utils.ObjectKeyFromObjectMeta(&logging), &logging)) - t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) - return false - } - if operatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(operatorLabels))(); !operatorRunning { - t.Log("waiting for the operator") - return false - } - if producerRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(producerLabels))(); !producerRunning { - t.Log("waiting for the producer") - return false - } - if aggregatorRunning := cond.AnyPodShouldBeRunning(t, c.GetClient(), client.MatchingLabels(aggregatorLabels)); !aggregatorRunning() { - t.Log("waiting for the aggregator") - return false - } - - cmd := common.CmdEnv(exec.Command("kubectl", - "logs", - "-n", ns, - "-l", fmt.Sprintf("app.kubernetes.io/name=%s-test-receiver", releaseNameOverride)), c) - rawOut, err := cmd.Output() - if err != nil { - t.Logf("failed to get log consumer logs: %v", err) + if rv := checkExcessFluentd(t, &c, &ctx, &fluentd2); !rv { return false } - t.Logf("log consumer logs: %s", rawOut) - return strings.Contains(string(rawOut), testTag) + return true }, 5*time.Minute, 3*time.Second) }, func(t *testing.T, c common.Cluster) error { diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index 3e47f4697..98c0a718f 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -208,6 +208,24 @@ func NewValidationReconciler( resources.Logging.Status.Problems = nil resources.Logging.Status.WatchNamespaces = nil + if len(resources.Fluentd.ExcessFluentds) != 0 { + logger.Info("Excess Fluentd CRDs found") + resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, "multiple fluentd configurations found, couldn't associate it with logging") + for i := range resources.Fluentd.ExcessFluentds { + excessFluentd := &resources.Fluentd.ExcessFluentds[i] + registerForPatching(excessFluentd) + excessFluentd.Status.Problems = nil + excessFluentd.Status.Active = utils.BoolPointer(false) + excessFluentd.Status.Logging = "" + + if len(resources.Logging.Status.FluentdConfigName) == 0 { + excessFluentd.Status.Problems = append(excessFluentd.Status.Problems, "multiple fluentd configurations found, couldn't associate it with logging") + } else if resources.Logging.Status.FluentdConfigName != excessFluentd.Name { + excessFluentd.Status.Problems = append(excessFluentd.Status.Problems, "logging already has a detached fluentd configuration, remove excess configuration objects") + } + excessFluentd.Status.ProblemsCount = len(excessFluentd.Status.Problems) + } + } if resources.Fluentd.Configuration != nil { registerForPatching(resources.Fluentd.Configuration) diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index d604224d7..034e52174 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -57,7 +57,7 @@ func (r LoggingResourceRepository) LoggingResourcesFor(ctx context.Context, logg res.Fluentd.ClusterOutputs, err = r.ClusterOutputsFor(ctx, logging) errs = errors.Append(errs, err) - res.Fluentd.Configuration, err = r.FluentdConfigFor(ctx, logging) + res.Fluentd.Configuration, res.Fluentd.ExcessFluentds, err = r.FluentdConfigFor(ctx, logging) errs = errors.Append(errs, err) res.SyslogNG.ClusterFlows, err = r.SyslogNGClusterFlowsFor(ctx, logging) @@ -337,24 +337,29 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 }) return res, nil } -func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list *[]v1beta1.Fluentd, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { - for _, i := range *list { +func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list []v1beta1.Fluentd, logging v1beta1.Logging) []v1beta1.Fluentd { + + r.Logger.Info("multiple detached Fluentd CRDs found") + + var excessFluentds []v1beta1.Fluentd + for _, i := range list { if len(logging.Status.FluentdConfigName) != 0 { if i.Name != logging.Status.FluentdConfigName { - i.Status.Problems = []string{} - i.Status.Problems = append(i.Status.Problems, "Logging already has a detached fluentd configuration, remove excess configuration objects") + excessFluentds = append(excessFluentds, i) } + } else { + // No association, mark everything as excess + excessFluentds = append(excessFluentds, i) } } - multipleFluentdErrors := "multiple fluentd configurations found, couldn't associate it with logging" - logging.Status.Problems = append(logging.Status.Problems, multipleFluentdErrors) - return nil, errors.New(multipleFluentdErrors) + + return excessFluentds } -func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, error) { +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, []v1beta1.Fluentd, error) { var list v1beta1.FluentdList if err := r.Client.List(ctx, &list); err != nil { - return nil, err + return nil, []v1beta1.Fluentd{}, err } var res []v1beta1.Fluentd @@ -362,14 +367,15 @@ func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging switch len(res) { case 0: - return nil, nil + return nil, []v1beta1.Fluentd{}, nil case 1: // Implicitly associate fluentd configuration object with logging detachedFluentd := res[0] err := detachedFluentd.Spec.SetDefaults() - return &detachedFluentd, err + return &detachedFluentd, []v1beta1.Fluentd{}, err default: - return r.handleMultipleDetachedFluentdObjects(&res, logging) + excessFluentds := r.handleMultipleDetachedFluentdObjects(res, logging) + return nil, excessFluentds, nil } } diff --git a/pkg/resources/model/resources.go b/pkg/resources/model/resources.go index 671a4bf24..5ff8c981d 100644 --- a/pkg/resources/model/resources.go +++ b/pkg/resources/model/resources.go @@ -54,6 +54,7 @@ type FluentdLoggingResources struct { Flows []v1beta1.Flow Outputs Outputs Configuration *v1beta1.Fluentd + ExcessFluentds []v1beta1.Fluentd } type SyslogNGLoggingResources struct { From e53965b6f43cff6bb7b8143967212098dd297c43 Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Fri, 1 Dec 2023 14:29:06 +0100 Subject: [PATCH 25/28] fix(e2e): detached fluentd negative testcase rename Signed-off-by: Szilard Parrag --- .../fluentd_aggregator_detached_multiple_failures_test.go} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename e2e/{fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go => fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go} (98%) diff --git a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go similarity index 98% rename from e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go rename to e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go index 9dd1084f1..41537d743 100644 --- a/e2e/fluentd-aggregator-detached-single-unnamed/fluentd_aggregator_detached_single_unnamed_test.go +++ b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go @@ -79,11 +79,11 @@ func checkExcessFluentd(t *testing.T, c *common.Cluster, ctx *context.Context, f return true } -func TestFluentdAggregator_detached_multiple_MultiWorker(t *testing.T) { +func TestFluentdAggregator_detached_multiple_failure(t *testing.T) { common.Initialize(t) ns := "testing-1" releaseNameOverride := "e2e" - testTag := "test.fluentd_aggregator_multiworker_multiple_detached" + testTag := "test.fluentd_aggregator_multiworker_multiple_detached_failure" outputName := "test-output" flowName := "test-flow" common.WithCluster("fluentd-1-detached-unnamed", t, func(t *testing.T, c common.Cluster) { From ef655a7fe64b8a39bcacc8ec8cefc4c239ec7adc Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Fri, 1 Dec 2023 15:02:17 +0100 Subject: [PATCH 26/28] tests(e2e): refine detached fluentd working testcase Signed-off-by: Szilard Parrag --- e2e/common/cond/conditions.go | 48 +++++++++++++++++++ ...regator_detached_multiple_failures_test.go | 28 ++--------- .../fluentd_aggregator_detached_test.go | 42 ++++++++++++++++ 3 files changed, 93 insertions(+), 25 deletions(-) diff --git a/e2e/common/cond/conditions.go b/e2e/common/cond/conditions.go index 1e65dfc38..fd18af638 100644 --- a/e2e/common/cond/conditions.go +++ b/e2e/common/cond/conditions.go @@ -18,6 +18,9 @@ import ( "context" "testing" + "github.com/cisco-open/operator-tools/pkg/utils" + "github.com/kube-logging/logging-operator/e2e/common" + "github.com/kube-logging/logging-operator/pkg/sdk/logging/api/v1beta1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" @@ -82,3 +85,48 @@ func ResourceShouldBePresent(t *testing.T, cl client.Reader, obj client.Object) return false } } +func CheckFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd, loggingName string) bool { + fluentdInstanceName := fluentd.Name + cluster := *c + + if len(fluentd.Status.Problems) != 0 { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have 0 problems, problems=%v", fluentdInstanceName, fluentd.Status.Problems) + return false + } + if fluentd.Status.Logging != loggingName { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's logging field filled, found: %s, expect:%s", fluentdInstanceName, fluentd.Status.Logging, loggingName) + return false + } + if !*fluentd.Status.Active { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's active field set as true, found: %v", fluentdInstanceName, *fluentd.Status.Active) + return false + } + + return true +} + +func CheckExcessFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd) bool { + fluentdInstanceName := fluentd.Name + cluster := *c + + if len(fluentd.Status.Problems) == 0 { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's problems field filled", fluentdInstanceName) + return false + } + if fluentd.Status.Logging != "" { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's logging field empty, found: %s", fluentdInstanceName, fluentd.Status.Logging) + return false + } + if *fluentd.Status.Active { + common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) + t.Logf("%s should have it's active field set as false, found: %v", fluentdInstanceName, *fluentd.Status.Active) + return false + } + + return true +} diff --git a/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go index 41537d743..ecc9bda37 100644 --- a/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go +++ b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go @@ -38,6 +38,7 @@ import ( "github.com/kube-logging/logging-operator/pkg/sdk/logging/model/output" "github.com/kube-logging/logging-operator/e2e/common" + "github.com/kube-logging/logging-operator/e2e/common/cond" "github.com/kube-logging/logging-operator/e2e/common/setup" ) @@ -56,29 +57,6 @@ func init() { } } -func checkExcessFluentd(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd) bool { - fluentdInstanceName := fluentd.Name - cluster := *c - - if len(fluentd.Status.Problems) == 0 { - common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) - t.Logf("%s should have it's problems field filled", fluentdInstanceName) - return false - } - if fluentd.Status.Logging != "" { - common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) - t.Logf("%s should have it's logging field empty, found: %s", fluentdInstanceName, fluentd.Status.Logging) - return false - } - if *fluentd.Status.Active != false { - common.RequireNoError(t, cluster.GetClient().Get(*ctx, utils.ObjectKeyFromObjectMeta(fluentd), fluentd)) - t.Logf("%s should have it's active field set as false, found: %v", fluentdInstanceName, *fluentd.Status.Active) - return false - } - - return true -} - func TestFluentdAggregator_detached_multiple_failure(t *testing.T) { common.Initialize(t) ns := "testing-1" @@ -217,10 +195,10 @@ func TestFluentdAggregator_detached_multiple_failure(t *testing.T) { })) require.Eventually(t, func() bool { - if rv := checkExcessFluentd(t, &c, &ctx, &fluentd1); !rv { + if rv := cond.CheckExcessFluentdStatus(t, &c, &ctx, &fluentd1); !rv { return false } - if rv := checkExcessFluentd(t, &c, &ctx, &fluentd2); !rv { + if rv := cond.CheckExcessFluentdStatus(t, &c, &ctx, &fluentd2); !rv { return false } return true diff --git a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go index bbf8795c4..e8ff929f1 100644 --- a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go +++ b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go @@ -121,6 +121,32 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) t.Logf("fluentd is: %v", fluentd) + + excessFluentd := v1beta1.Fluentd{ + ObjectMeta: metav1.ObjectMeta{ + Name: "excess-fluentd", + Namespace: ns, + }, + Spec: v1beta1.FluentdSpec{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("200M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("50M"), + }, + }, + BufferVolumeMetrics: &v1beta1.Metrics{}, + Scaling: &v1beta1.FluentdScaling{ + Replicas: 1, + Drain: v1beta1.FluentdDrainConfig{ + Enabled: true, + }, + }, + }, + } tags := "time" output := v1beta1.Output{ ObjectMeta: metav1.ObjectMeta{ @@ -195,6 +221,22 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { t.Logf("logging should use the detached fluentd configuration (name=%s), found: %v", fluentd.Name, logging.Status.FluentdConfigName) return false } + if isValid := cond.CheckFluentdStatus(t, &c, &ctx, &fluentd, logging.Name); !isValid { + t.Log("checking detached fluentd status") + return false + } + var detachedFluentds v1beta1.FluentdList + common.RequireNoError(t, c.GetClient().List(ctx, &detachedFluentds)) + if len(detachedFluentds.Items) != 2 { + // Add a new detached fluentd that is not going to be used + common.RequireNoError(t, c.GetClient().Create(ctx, &excessFluentd)) + t.Log("creating excess detached fluentd") + return false + } else if isValid := cond.CheckExcessFluentdStatus(t, &c, &ctx, &excessFluentd); !isValid && len(detachedFluentds.Items) == 2 { + t.Log("checking excess detached fluentd status") + common.RequireNoError(t, c.GetClient().Get(ctx, utils.ObjectKeyFromObjectMeta(&excessFluentd), &excessFluentd)) + return false + } cmd := common.CmdEnv(exec.Command("kubectl", "logs", From 170bba057dcc77fd311d5e9869ea3de8c4ae280d Mon Sep 17 00:00:00 2001 From: Szilard Parrag Date: Mon, 4 Dec 2023 14:28:29 +0100 Subject: [PATCH 27/28] refactor(fluentd): rename Fluentd CRD to FluentdConfig Signed-off-by: Szilard Parrag --- ...ogging.banzaicloud.io_fluentdconfigs.yaml} | 10 +- .../templates/clusterrole.yaml | 4 +- ...ogging.banzaicloud.io_fluentdconfigs.yaml} | 10 +- config/rbac/role.yaml | 4 +- controllers/logging/logging_controller.go | 8 +- docs/configuration/crds/v1beta1/_index.md | 2 +- .../crds/v1beta1/fluentd_types.md | 36 ++--- e2e/common/cond/conditions.go | 4 +- ...regator_detached_multiple_failures_test.go | 4 +- .../fluentd_aggregator_detached_test.go | 6 +- pkg/resources/fluentd/fluentd.go | 4 +- pkg/resources/model/repository.go | 16 +-- pkg/resources/model/resources.go | 6 +- pkg/sdk/logging/api/v1beta1/fluentd_types.go | 26 ++-- .../api/v1beta1/zz_generated.deepcopy.go | 124 +++++++++--------- 15 files changed, 132 insertions(+), 132 deletions(-) rename charts/logging-operator/crds/{logging.banzaicloud.io_fluentds.yaml => logging.banzaicloud.io_fluentdconfigs.yaml} (99%) rename config/crd/bases/{logging.banzaicloud.io_fluentds.yaml => logging.banzaicloud.io_fluentdconfigs.yaml} (99%) diff --git a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml b/charts/logging-operator/crds/logging.banzaicloud.io_fluentdconfigs.yaml similarity index 99% rename from charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml rename to charts/logging-operator/crds/logging.banzaicloud.io_fluentdconfigs.yaml index a7a2f0d8b..fe993b466 100644 --- a/charts/logging-operator/crds/logging.banzaicloud.io_fluentds.yaml +++ b/charts/logging-operator/crds/logging.banzaicloud.io_fluentdconfigs.yaml @@ -6,16 +6,16 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null - name: fluentds.logging.banzaicloud.io + name: fluentdconfigs.logging.banzaicloud.io spec: group: logging.banzaicloud.io names: categories: - logging-all - kind: Fluentd - listKind: FluentdList - plural: fluentds - singular: fluentd + kind: FluentdConfig + listKind: FluentdConfigList + plural: fluentdconfigs + singular: fluentdconfig scope: Namespaced versions: - additionalPrinterColumns: diff --git a/charts/logging-operator/templates/clusterrole.yaml b/charts/logging-operator/templates/clusterrole.yaml index 5cd1bcf03..66bf6b8d7 100644 --- a/charts/logging-operator/templates/clusterrole.yaml +++ b/charts/logging-operator/templates/clusterrole.yaml @@ -241,7 +241,7 @@ rules: - clusteroutputs - flows - fluentbitagents - - fluentds + - fluentdconfigs - loggings - nodeagents - outputs @@ -260,7 +260,7 @@ rules: - clusteroutputs/status - flows/status - fluentbitagents/status - - fluentds/status + - fluentdconfigs/status - loggings/status - nodeagents/status - outputs/status diff --git a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml b/config/crd/bases/logging.banzaicloud.io_fluentdconfigs.yaml similarity index 99% rename from config/crd/bases/logging.banzaicloud.io_fluentds.yaml rename to config/crd/bases/logging.banzaicloud.io_fluentdconfigs.yaml index a7a2f0d8b..fe993b466 100644 --- a/config/crd/bases/logging.banzaicloud.io_fluentds.yaml +++ b/config/crd/bases/logging.banzaicloud.io_fluentdconfigs.yaml @@ -6,16 +6,16 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null - name: fluentds.logging.banzaicloud.io + name: fluentdconfigs.logging.banzaicloud.io spec: group: logging.banzaicloud.io names: categories: - logging-all - kind: Fluentd - listKind: FluentdList - plural: fluentds - singular: fluentd + kind: FluentdConfig + listKind: FluentdConfigList + plural: fluentdconfigs + singular: fluentdconfig scope: Namespaced versions: - additionalPrinterColumns: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index c570f6c75..16f6a752e 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -241,7 +241,7 @@ rules: - clusteroutputs - flows - fluentbitagents - - fluentds + - fluentdconfigs - loggings - nodeagents - outputs @@ -260,7 +260,7 @@ rules: - clusteroutputs/status - flows/status - fluentbitagents/status - - fluentds/status + - fluentdconfigs/status - loggings/status - nodeagents/status - outputs/status diff --git a/controllers/logging/logging_controller.go b/controllers/logging/logging_controller.go index fb39e4d26..f80afb492 100644 --- a/controllers/logging/logging_controller.go +++ b/controllers/logging/logging_controller.go @@ -64,8 +64,8 @@ type LoggingReconciler struct { Log logr.Logger } -// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents;fluentds,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status;fluentds/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings;fluentbitagents;flows;clusterflows;outputs;clusteroutputs;nodeagents;fluentdconfigs,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=loggings/status;fluentbitagents/status;flows/status;clusterflows/status;outputs/status;clusteroutputs/status;nodeagents/status;fluentdconfigs/status,verbs=get;update;patch // +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows;syslogngclusterflows;syslogngoutputs;syslogngclusteroutputs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=logging.banzaicloud.io,resources=syslogngflows/status;syslogngclusterflows/status;syslogngoutputs/status;syslogngclusteroutputs/status,verbs=get;update;patch // +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete @@ -436,7 +436,7 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.LoggingRef) case *loggingv1beta1.LoggingRoute: return reconcileRequestsForLoggingRef(loggingList.Items, o.Spec.Source) - case *loggingv1beta1.Fluentd: + case *loggingv1beta1.FluentdConfig: return reconcileRequestsForMatchingControlNamespace(loggingList.Items, o.Namespace) case *corev1.Secret: r := regexp.MustCompile(`^logging\.banzaicloud\.io/(.*)`) @@ -488,7 +488,7 @@ func SetupLoggingWithManager(mgr ctrl.Manager, logger logr.Logger) *ctrl.Builder Watches(&loggingv1beta1.SyslogNGFlow{}, requestMapper). Watches(&corev1.Secret{}, requestMapper). Watches(&loggingv1beta1.LoggingRoute{}, requestMapper). - Watches(&loggingv1beta1.Fluentd{}, requestMapper) + Watches(&loggingv1beta1.FluentdConfig{}, requestMapper) // TODO remove with the next major release if os.Getenv("ENABLE_NODEAGENT_CRD") != "" { diff --git a/docs/configuration/crds/v1beta1/_index.md b/docs/configuration/crds/v1beta1/_index.md index b00fee49c..b7dbe3738 100644 --- a/docs/configuration/crds/v1beta1/_index.md +++ b/docs/configuration/crds/v1beta1/_index.md @@ -18,7 +18,7 @@ For more information please click on the name | **[](conversion/)** | | v1beta1 | | **[FlowSpec](flow_types/)** | FlowSpec is the Kubernetes spec for Flows | v1beta1 | | **[FluentbitSpec](fluentbit_types/)** | FluentbitSpec defines the desired state of FluentbitAgent | v1beta1 | -| **[Fluent](fluentd_types/)** | Fluentd is a reference to the desired Fluentd state | v1beta1 | +| **[Fluent](fluentd_types/)** | FluentdConfig is a reference to the desired Fluentd state | v1beta1 | | **[Logging](logging_types/)** | Logging system configuration | v1beta1 | | **[LoggingRouteSpec](loggingroute_types/)** | LoggingRouteSpec defines the desired state of LoggingRoute | v1beta1 | | **[_hugoNodeAgent](node_agent_types/)** | | v1beta1 | diff --git a/docs/configuration/crds/v1beta1/fluentd_types.md b/docs/configuration/crds/v1beta1/fluentd_types.md index 3008443c5..13aedb2c7 100644 --- a/docs/configuration/crds/v1beta1/fluentd_types.md +++ b/docs/configuration/crds/v1beta1/fluentd_types.md @@ -171,56 +171,56 @@ Fluentd port inside the container (24240 by default). The headless service port --- -title: Fluentd +title: FluentdConfig weight: 200 generated_file: true --- -## Fluentd +## FluentdConfig -Fluentd +FluentdConfig -### (metav1.TypeMeta, required) {#fluentd-} +### (metav1.TypeMeta, required) {#fluentdconfig-} -### metadata (metav1.ObjectMeta, optional) {#fluentd-metadata} +### metadata (metav1.ObjectMeta, optional) {#fluentdconfig-metadata} -### spec (FluentdSpec, optional) {#fluentd-spec} +### spec (FluentdSpec, optional) {#fluentdconfig-spec} -### status (FluentdStatus, optional) {#fluentd-status} +### status (FluentdConfigStatus, optional) {#fluentdconfig-status} -## FluentdStatus +## FluentdConfigStatus -FluentdStatus +FluentdConfigStatus -### active (*bool, optional) {#fluentdstatus-active} +### active (*bool, optional) {#fluentdconfigstatus-active} -### logging (string, optional) {#fluentdstatus-logging} +### logging (string, optional) {#fluentdconfigstatus-logging} -### problems ([]string, optional) {#fluentdstatus-problems} +### problems ([]string, optional) {#fluentdconfigstatus-problems} -### problemsCount (int, optional) {#fluentdstatus-problemscount} +### problemsCount (int, optional) {#fluentdconfigstatus-problemscount} -## FluentdList +## FluentdConfigList -FluentdList +FluentdConfigList -### (metav1.TypeMeta, required) {#fluentdlist-} +### (metav1.TypeMeta, required) {#fluentdconfiglist-} -### metadata (metav1.ListMeta, optional) {#fluentdlist-metadata} +### metadata (metav1.ListMeta, optional) {#fluentdconfiglist-metadata} -### items ([]Fluentd, required) {#fluentdlist-items} +### items ([]FluentdConfig, required) {#fluentdconfiglist-items} diff --git a/e2e/common/cond/conditions.go b/e2e/common/cond/conditions.go index fd18af638..5fed3f2c2 100644 --- a/e2e/common/cond/conditions.go +++ b/e2e/common/cond/conditions.go @@ -85,7 +85,7 @@ func ResourceShouldBePresent(t *testing.T, cl client.Reader, obj client.Object) return false } } -func CheckFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd, loggingName string) bool { +func CheckFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.FluentdConfig, loggingName string) bool { fluentdInstanceName := fluentd.Name cluster := *c @@ -108,7 +108,7 @@ func CheckFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, f return true } -func CheckExcessFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.Fluentd) bool { +func CheckExcessFluentdStatus(t *testing.T, c *common.Cluster, ctx *context.Context, fluentd *v1beta1.FluentdConfig) bool { fluentdInstanceName := fluentd.Name cluster := *c diff --git a/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go index ecc9bda37..720be791f 100644 --- a/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go +++ b/e2e/fluentd-aggregator-detached-multiple-failures/fluentd_aggregator_detached_multiple_failures_test.go @@ -89,7 +89,7 @@ func TestFluentdAggregator_detached_multiple_failure(t *testing.T) { } common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) - fluentd1 := v1beta1.Fluentd{ + fluentd1 := v1beta1.FluentdConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "not-to-be-used-fluentd-1", Namespace: ns, @@ -117,7 +117,7 @@ func TestFluentdAggregator_detached_multiple_failure(t *testing.T) { } common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd1)) - fluentd2 := v1beta1.Fluentd{ + fluentd2 := v1beta1.FluentdConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "not-to-be-used-fluentd-2", Namespace: ns, diff --git a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go index e8ff929f1..9b7e0a211 100644 --- a/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go +++ b/e2e/fluentd-aggregator-detached/fluentd_aggregator_detached_test.go @@ -92,7 +92,7 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { } common.RequireNoError(t, c.GetClient().Create(ctx, &logging)) - fluentd := v1beta1.Fluentd{ + fluentd := v1beta1.FluentdConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "detached-fluentd", Namespace: ns, @@ -122,7 +122,7 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { common.RequireNoError(t, c.GetClient().Create(ctx, &fluentd)) t.Logf("fluentd is: %v", fluentd) - excessFluentd := v1beta1.Fluentd{ + excessFluentd := v1beta1.FluentdConfig{ ObjectMeta: metav1.ObjectMeta{ Name: "excess-fluentd", Namespace: ns, @@ -225,7 +225,7 @@ func TestFluentdAggregator_detached_MultiWorker(t *testing.T) { t.Log("checking detached fluentd status") return false } - var detachedFluentds v1beta1.FluentdList + var detachedFluentds v1beta1.FluentdConfigList common.RequireNoError(t, c.GetClient().List(ctx, &detachedFluentds)) if len(detachedFluentds.Items) != 2 { // Add a new detached fluentd that is not going to be used diff --git a/pkg/resources/fluentd/fluentd.go b/pkg/resources/fluentd/fluentd.go index f0997074f..3ca335536 100644 --- a/pkg/resources/fluentd/fluentd.go +++ b/pkg/resources/fluentd/fluentd.go @@ -83,8 +83,8 @@ type Desire struct { BeforeUpdateHook func(runtime.Object) (reconciler.DesiredState, error) } -func GetFluentd(ctx context.Context, Client client.Client, log logr.Logger, controlNamespace string) *v1beta1.Fluentd { - fluentdList := v1beta1.FluentdList{} +func GetFluentd(ctx context.Context, Client client.Client, log logr.Logger, controlNamespace string) *v1beta1.FluentdConfig { + fluentdList := v1beta1.FluentdConfigList{} // Detached fluentd must be in the `control namespace` nsOpt := client.InNamespace(controlNamespace) diff --git a/pkg/resources/model/repository.go b/pkg/resources/model/repository.go index 034e52174..79529932a 100644 --- a/pkg/resources/model/repository.go +++ b/pkg/resources/model/repository.go @@ -337,11 +337,11 @@ func (r LoggingResourceRepository) FluentbitsFor(ctx context.Context, logging v1 }) return res, nil } -func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list []v1beta1.Fluentd, logging v1beta1.Logging) []v1beta1.Fluentd { +func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list []v1beta1.FluentdConfig, logging v1beta1.Logging) []v1beta1.FluentdConfig { r.Logger.Info("multiple detached Fluentd CRDs found") - var excessFluentds []v1beta1.Fluentd + var excessFluentds []v1beta1.FluentdConfig for _, i := range list { if len(logging.Status.FluentdConfigName) != 0 { if i.Name != logging.Status.FluentdConfigName { @@ -356,23 +356,23 @@ func (r LoggingResourceRepository) handleMultipleDetachedFluentdObjects(list []v return excessFluentds } -func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.Fluentd, []v1beta1.Fluentd, error) { - var list v1beta1.FluentdList +func (r LoggingResourceRepository) FluentdConfigFor(ctx context.Context, logging v1beta1.Logging) (*v1beta1.FluentdConfig, []v1beta1.FluentdConfig, error) { + var list v1beta1.FluentdConfigList if err := r.Client.List(ctx, &list); err != nil { - return nil, []v1beta1.Fluentd{}, err + return nil, []v1beta1.FluentdConfig{}, err } - var res []v1beta1.Fluentd + var res []v1beta1.FluentdConfig res = append(res, list.Items...) switch len(res) { case 0: - return nil, []v1beta1.Fluentd{}, nil + return nil, []v1beta1.FluentdConfig{}, nil case 1: // Implicitly associate fluentd configuration object with logging detachedFluentd := res[0] err := detachedFluentd.Spec.SetDefaults() - return &detachedFluentd, []v1beta1.Fluentd{}, err + return &detachedFluentd, []v1beta1.FluentdConfig{}, err default: excessFluentds := r.handleMultipleDetachedFluentdObjects(res, logging) return nil, excessFluentds, nil diff --git a/pkg/resources/model/resources.go b/pkg/resources/model/resources.go index 5ff8c981d..9a9386b90 100644 --- a/pkg/resources/model/resources.go +++ b/pkg/resources/model/resources.go @@ -29,7 +29,7 @@ type LoggingResources struct { WatchNamespaces []string } -func (l LoggingResources) GetFluentd() *v1beta1.Fluentd { +func (l LoggingResources) GetFluentd() *v1beta1.FluentdConfig { if l.Fluentd.Configuration != nil { return l.Fluentd.Configuration } @@ -53,8 +53,8 @@ type FluentdLoggingResources struct { ClusterOutputs ClusterOutputs Flows []v1beta1.Flow Outputs Outputs - Configuration *v1beta1.Fluentd - ExcessFluentds []v1beta1.Fluentd + Configuration *v1beta1.FluentdConfig + ExcessFluentds []v1beta1.FluentdConfig } type SyslogNGLoggingResources struct { diff --git a/pkg/sdk/logging/api/v1beta1/fluentd_types.go b/pkg/sdk/logging/api/v1beta1/fluentd_types.go index 67cd33b2e..a4e225445 100644 --- a/pkg/sdk/logging/api/v1beta1/fluentd_types.go +++ b/pkg/sdk/logging/api/v1beta1/fluentd_types.go @@ -108,14 +108,14 @@ type FluentdSpec struct { SidecarContainers []corev1.Container `json:"sidecarContainers,omitempty"` } -// +name:"Fluentd" +// +name:"FluentdConfig" // +weight:"200" type _hugoFluent interface{} //nolint:deadcode,unused // +name:"Fluent" // +version:"v1beta1" -// +description:"Fluentd is a reference to the desired Fluentd state" -type _metaFluentd interface{} //nolint:deadcode,unused +// +description:"FluentdConfig is a reference to the desired Fluentd state" +type _metaFluentdConfig interface{} //nolint:deadcode,unused // +kubebuilder:object:root=true // +kubebuilder:resource:categories=logging-all @@ -124,17 +124,17 @@ type _metaFluentd interface{} //nolint:deadcode,unused // +kubebuilder:printcolumn:name="Problems",type="integer",JSONPath=".status.problemsCount",description="Number of problems" // +kubebuilder:storageversion -// Fluentd -type Fluentd struct { +// FluentdConfig +type FluentdConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec FluentdSpec `json:"spec,omitempty"` - Status FluentdStatus `json:"status,omitempty"` + Spec FluentdSpec `json:"spec,omitempty"` + Status FluentdConfigStatus `json:"status,omitempty"` } -// FluentdStatus -type FluentdStatus struct { +// FluentdConfigStatus +type FluentdConfigStatus struct { Logging string `json:"logging,omitempty"` Active *bool `json:"active,omitempty"` Problems []string `json:"problems,omitempty"` @@ -143,15 +143,15 @@ type FluentdStatus struct { // +kubebuilder:object:root=true -// FluentdList -type FluentdList struct { +// FluentdConfigList +type FluentdConfigList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []Fluentd `json:"items"` + Items []FluentdConfig `json:"items"` } func init() { - SchemeBuilder.Register(&Fluentd{}, &FluentdList{}) + SchemeBuilder.Register(&FluentdConfig{}, &FluentdConfigList{}) } // +kubebuilder:object:generate=true diff --git a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go index f217d852d..aacd42cb9 100644 --- a/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go +++ b/pkg/sdk/logging/api/v1beta1/zz_generated.deepcopy.go @@ -1298,7 +1298,7 @@ func (in *FluentbitTLS) DeepCopy() *FluentbitTLS { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Fluentd) DeepCopyInto(out *Fluentd) { +func (in *FluentdConfig) DeepCopyInto(out *FluentdConfig) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) @@ -1306,24 +1306,81 @@ func (in *Fluentd) DeepCopyInto(out *Fluentd) { in.Status.DeepCopyInto(&out.Status) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Fluentd. -func (in *Fluentd) DeepCopy() *Fluentd { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfig. +func (in *FluentdConfig) DeepCopy() *FluentdConfig { if in == nil { return nil } - out := new(Fluentd) + out := new(FluentdConfig) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Fluentd) DeepCopyObject() runtime.Object { +func (in *FluentdConfig) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdConfigList) DeepCopyInto(out *FluentdConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FluentdConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigList. +func (in *FluentdConfigList) DeepCopy() *FluentdConfigList { + if in == nil { + return nil + } + out := new(FluentdConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentdConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentdConfigStatus) DeepCopyInto(out *FluentdConfigStatus) { + *out = *in + if in.Active != nil { + in, out := &in.Active, &out.Active + *out = new(bool) + **out = **in + } + if in.Problems != nil { + in, out := &in.Problems, &out.Problems + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdConfigStatus. +func (in *FluentdConfigStatus) DeepCopy() *FluentdConfigStatus { + if in == nil { + return nil + } + out := new(FluentdConfigStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdDrainConfig) DeepCopyInto(out *FluentdDrainConfig) { *out = *in @@ -1365,38 +1422,6 @@ func (in *FluentdDrainConfig) DeepCopy() *FluentdDrainConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentdList) DeepCopyInto(out *FluentdList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Fluentd, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdList. -func (in *FluentdList) DeepCopy() *FluentdList { - if in == nil { - return nil - } - out := new(FluentdList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *FluentdList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdScaling) DeepCopyInto(out *FluentdScaling) { *out = *in @@ -1579,31 +1604,6 @@ func (in *FluentdSpec) DeepCopy() *FluentdSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentdStatus) DeepCopyInto(out *FluentdStatus) { - *out = *in - if in.Active != nil { - in, out := &in.Active, &out.Active - *out = new(bool) - **out = **in - } - if in.Problems != nil { - in, out := &in.Problems, &out.Problems - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentdStatus. -func (in *FluentdStatus) DeepCopy() *FluentdStatus { - if in == nil { - return nil - } - out := new(FluentdStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluentdTLS) DeepCopyInto(out *FluentdTLS) { *out = *in From dbf3b283524b225d6542bd143afdad9e4da8fa6e Mon Sep 17 00:00:00 2001 From: Peter Wilcsinszky Date: Tue, 5 Dec 2023 11:44:49 +0100 Subject: [PATCH 28/28] add dev docs Signed-off-by: Peter Wilcsinszky --- docs/standalone-aggregator-config.md | 120 +++++++++++++++++++++++++++ pkg/resources/model/reconciler.go | 2 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 docs/standalone-aggregator-config.md diff --git a/docs/standalone-aggregator-config.md b/docs/standalone-aggregator-config.md new file mode 100644 index 000000000..2bdb7490e --- /dev/null +++ b/docs/standalone-aggregator-config.md @@ -0,0 +1,120 @@ +## Standalone Fluentd config + +The standalone `FluentdConfig` is a namespaced resource that allows the configuration of the Fluentd / SyslogNG +aggregator component in the control namespace separately from the Logging resource. + +The primary benefit of this behaviour is that it enables a multi-tenant model, where tenant owners are responsible +for operating their own aggregator, while the Logging resource is in control of the central operations team. +For more information about the multi-tenancy model where the collector is capable of routing logs based on namespaces +to individual aggregators and where aggregators are fully isolated, please see [Multi-tenancy](multi-tenancy.md) + +Traditional configuration of fluentd within the logging resource: +``` +apiVersion: logging.banzaicloud.io/v1beta1 +kind: Logging +metadata: + name: example +spec: + controlNamespace: logging + fluentd: + scaling: + replicas: 2 +``` + +The alternative configuration is as follows: +``` +apiVersion: logging.banzaicloud.io/v1beta1 +kind: Logging +metadata: + name: example +spec: + controlNamespace: logging +--- +apiVersion: logging.banzaicloud.io/v1beta1 +kind: FluentdConfig +metadata: + name: example + namespace: logging +spec: + scaling: + replicas: 2 +``` + +### Schema and migration + +The schema for `FluentdConfig.spec` is the same as it was withing `Logging.spec.fluentd`, so the migration should be a trivial lift and shift +exercise. + +### Restrictions and status + +There can only be one active `FluentdConfig` for a single `Logging` resource at a time. The controller will make +sure to register the active `FluentdConfig` resource into the `Logging` resource's status under `fluentdConfigName`, +while registering the `Logging` resource name under `logging` in the `FluentdConfig` resource's status. + +``` +kubectl get logging example -o jsonpath='{.status}' | jq . +{ + "configCheckResults": { + "ac2d4553": true + }, + "fluentdConfigName": "example" +} +``` + +``` +kubectl get fluentdconfig example -o jsonpath='{.status}' | jq . +{ + "active": true, + "logging": "example" +} +``` + +If there is a conflict, then the controller will add a problem to both resources so that both operations and tenant users can be aware of it. +For example add another `FluentdConfig` resource on top of the existing one: + +``` +apiVersion: logging.banzaicloud.io/v1beta1 +kind: FluentdConfig +metadata: + name: example2 + namespace: logging +spec: {} +``` + +The first `FluentdConfig` should be left intact, while the second one should have the following status: +``` +kubectl get fluentdconfig example2 -o jsonpath='{.status}' | jq . +{ + "active": false, + "problems": [ + "logging already has a detached fluentd configuration, remove excess configuration objects" + ], + "problemsCount": 1 +} +``` + +The `Logging` resource will also highlight the issue +``` +kubectl get logging example -o jsonpath='{.status}' | jq . +{ + "configCheckResults": { + "ac2d4553": true + }, + "fluentdConfigName": "example", + "problems": [ + "multiple fluentd configurations found, couldn't associate it with logging" + ], + "problemsCount": 1 +} +``` + +Once the extra `FluentdConfig` resource is removed the `Logging` resource status should return back to normal: +``` +kubectl get logging example -o jsonpath='{.status}' | jq . +{ + "configCheckResults": { + "ac2d4553": true + }, + "fluentdConfigName": "example" +} +``` diff --git a/pkg/resources/model/reconciler.go b/pkg/resources/model/reconciler.go index 98c0a718f..236d14f75 100644 --- a/pkg/resources/model/reconciler.go +++ b/pkg/resources/model/reconciler.go @@ -233,7 +233,7 @@ func NewValidationReconciler( resources.Logging.Status.Problems = append(resources.Logging.Status.Problems, fmt.Sprintf("Fluentd configuration reference set (name=%s), but inline fluentd configuration is set as well, clearing inline", resources.Fluentd.Configuration.Name)) resources.Logging.Spec.FluentdSpec = nil } - logger.Info("found detached fluentd aggregator, making association", "name=", resources.Fluentd.Configuration.Name) + logger.Info("found detached fluentd aggregator, making association", "name", resources.Fluentd.Configuration.Name) resources.Logging.Status.FluentdConfigName = resources.Fluentd.Configuration.Name resources.Fluentd.Configuration.Status.Active = utils.BoolPointer(true)