diff --git a/apis/flowcollector/v1beta1/flowcollector_types.go b/apis/flowcollector/v1beta1/flowcollector_types.go index df61c5ac2..e413ccbd0 100644 --- a/apis/flowcollector/v1beta1/flowcollector_types.go +++ b/apis/flowcollector/v1beta1/flowcollector_types.go @@ -505,6 +505,10 @@ type FlowCollectorFLP struct { // This feature requires the "topology.kubernetes.io/zone" label to be set on nodes. AddZone *bool `json:"addZone,omitempty"` + //+optional + // `subnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. + SubnetLabels SubnetLabels `json:"subnetLabels,omitempty"` + // `debug` allows setting some aspects of the internal configuration of the flow processor. // This section is aimed exclusively for debugging and fine-grained performance optimizations, // such as `GOGC` and `GOMAXPROCS` env vars. Set these values at your own risk. @@ -844,6 +848,29 @@ type DebugConfig struct { Env map[string]string `json:"env,omitempty"` } +// `SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. +type SubnetLabels struct { + // `openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the + // OpenShift install configuration and the Cluster Network Operator configuration. + //+optional + OpenShiftAutoDetect *bool `json:"openShiftAutoDetect,omitempty"` + + // `customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. + // If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap. + //+optional + CustomLabels []SubnetLabel `json:"customLabels,omitempty"` +} + +// SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. +type SubnetLabel struct { + // List of CIDRs, such as `["1.2.3.4/32"]`. + //+required + CIDRs []string `json:"cidrs,omitempty"` // Note, starting with k8s 1.31 / ocp 4.16 there's a new way to validate CIDR such as `+kubebuilder:validation:XValidation:rule="isCIDR(self)",message="field should be in CIDR notation format"`. But older versions would reject the CRD so we cannot implement it now to maintain compatibility. + // Label name, used to flag matching flows. + //+required + Name string `json:"name,omitempty"` +} + // Add more exporter types below type ExporterType string diff --git a/apis/flowcollector/v1beta1/zz_generated.conversion.go b/apis/flowcollector/v1beta1/zz_generated.conversion.go index 3033edea0..ea755fbda 100644 --- a/apis/flowcollector/v1beta1/zz_generated.conversion.go +++ b/apis/flowcollector/v1beta1/zz_generated.conversion.go @@ -178,6 +178,26 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*SubnetLabel)(nil), (*v1beta2.SubnetLabel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetLabel_To_v1beta2_SubnetLabel(a.(*SubnetLabel), b.(*v1beta2.SubnetLabel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.SubnetLabel)(nil), (*SubnetLabel)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_SubnetLabel_To_v1beta1_SubnetLabel(a.(*v1beta2.SubnetLabel), b.(*SubnetLabel), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SubnetLabels)(nil), (*v1beta2.SubnetLabels)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels(a.(*SubnetLabels), b.(*v1beta2.SubnetLabels), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.SubnetLabels)(nil), (*SubnetLabels)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels(a.(*v1beta2.SubnetLabels), b.(*SubnetLabels), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*DebugConfig)(nil), (*v1beta2.AdvancedAgentConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_DebugConfig_To_v1beta2_AdvancedAgentConfig(a.(*DebugConfig), b.(*v1beta2.AdvancedAgentConfig), scope) }); err != nil { @@ -660,6 +680,9 @@ func autoConvert_v1beta1_FlowCollectorFLP_To_v1beta2_FlowCollectorFLP(in *FlowCo out.ClusterName = in.ClusterName out.MultiClusterDeployment = (*bool)(unsafe.Pointer(in.MultiClusterDeployment)) out.AddZone = (*bool)(unsafe.Pointer(in.AddZone)) + if err := Convert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels(&in.SubnetLabels, &out.SubnetLabels, s); err != nil { + return err + } // WARNING: in.Debug requires manual conversion: does not exist in peer-type return nil } @@ -681,6 +704,9 @@ func autoConvert_v1beta2_FlowCollectorFLP_To_v1beta1_FlowCollectorFLP(in *v1beta out.ClusterName = in.ClusterName out.MultiClusterDeployment = (*bool)(unsafe.Pointer(in.MultiClusterDeployment)) out.AddZone = (*bool)(unsafe.Pointer(in.AddZone)) + if err := Convert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels(&in.SubnetLabels, &out.SubnetLabels, s); err != nil { + return err + } // WARNING: in.Advanced requires manual conversion: does not exist in peer-type return nil } @@ -1051,3 +1077,47 @@ func autoConvert_v1beta2_ServerTLS_To_v1beta1_ServerTLS(in *v1beta2.ServerTLS, o out.ProvidedCaFile = (*FileReference)(unsafe.Pointer(in.ProvidedCaFile)) return nil } + +func autoConvert_v1beta1_SubnetLabel_To_v1beta2_SubnetLabel(in *SubnetLabel, out *v1beta2.SubnetLabel, s conversion.Scope) error { + out.CIDRs = *(*[]string)(unsafe.Pointer(&in.CIDRs)) + out.Name = in.Name + return nil +} + +// Convert_v1beta1_SubnetLabel_To_v1beta2_SubnetLabel is an autogenerated conversion function. +func Convert_v1beta1_SubnetLabel_To_v1beta2_SubnetLabel(in *SubnetLabel, out *v1beta2.SubnetLabel, s conversion.Scope) error { + return autoConvert_v1beta1_SubnetLabel_To_v1beta2_SubnetLabel(in, out, s) +} + +func autoConvert_v1beta2_SubnetLabel_To_v1beta1_SubnetLabel(in *v1beta2.SubnetLabel, out *SubnetLabel, s conversion.Scope) error { + out.CIDRs = *(*[]string)(unsafe.Pointer(&in.CIDRs)) + out.Name = in.Name + return nil +} + +// Convert_v1beta2_SubnetLabel_To_v1beta1_SubnetLabel is an autogenerated conversion function. +func Convert_v1beta2_SubnetLabel_To_v1beta1_SubnetLabel(in *v1beta2.SubnetLabel, out *SubnetLabel, s conversion.Scope) error { + return autoConvert_v1beta2_SubnetLabel_To_v1beta1_SubnetLabel(in, out, s) +} + +func autoConvert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels(in *SubnetLabels, out *v1beta2.SubnetLabels, s conversion.Scope) error { + out.OpenShiftAutoDetect = (*bool)(unsafe.Pointer(in.OpenShiftAutoDetect)) + out.CustomLabels = *(*[]v1beta2.SubnetLabel)(unsafe.Pointer(&in.CustomLabels)) + return nil +} + +// Convert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels is an autogenerated conversion function. +func Convert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels(in *SubnetLabels, out *v1beta2.SubnetLabels, s conversion.Scope) error { + return autoConvert_v1beta1_SubnetLabels_To_v1beta2_SubnetLabels(in, out, s) +} + +func autoConvert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels(in *v1beta2.SubnetLabels, out *SubnetLabels, s conversion.Scope) error { + out.OpenShiftAutoDetect = (*bool)(unsafe.Pointer(in.OpenShiftAutoDetect)) + out.CustomLabels = *(*[]SubnetLabel)(unsafe.Pointer(&in.CustomLabels)) + return nil +} + +// Convert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels is an autogenerated conversion function. +func Convert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels(in *v1beta2.SubnetLabels, out *SubnetLabels, s conversion.Scope) error { + return autoConvert_v1beta2_SubnetLabels_To_v1beta1_SubnetLabels(in, out, s) +} diff --git a/apis/flowcollector/v1beta1/zz_generated.deepcopy.go b/apis/flowcollector/v1beta1/zz_generated.deepcopy.go index 6df931c4b..4471d21f4 100644 --- a/apis/flowcollector/v1beta1/zz_generated.deepcopy.go +++ b/apis/flowcollector/v1beta1/zz_generated.deepcopy.go @@ -384,6 +384,7 @@ func (in *FlowCollectorFLP) DeepCopyInto(out *FlowCollectorFLP) { *out = new(bool) **out = **in } + in.SubnetLabels.DeepCopyInto(&out.SubnetLabels) in.Debug.DeepCopyInto(&out.Debug) } @@ -711,3 +712,50 @@ func (in *ServerTLS) DeepCopy() *ServerTLS { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetLabel) DeepCopyInto(out *SubnetLabel) { + *out = *in + if in.CIDRs != nil { + in, out := &in.CIDRs, &out.CIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetLabel. +func (in *SubnetLabel) DeepCopy() *SubnetLabel { + if in == nil { + return nil + } + out := new(SubnetLabel) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetLabels) DeepCopyInto(out *SubnetLabels) { + *out = *in + if in.OpenShiftAutoDetect != nil { + in, out := &in.OpenShiftAutoDetect, &out.OpenShiftAutoDetect + *out = new(bool) + **out = **in + } + if in.CustomLabels != nil { + in, out := &in.CustomLabels, &out.CustomLabels + *out = make([]SubnetLabel, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetLabels. +func (in *SubnetLabels) DeepCopy() *SubnetLabels { + if in == nil { + return nil + } + out := new(SubnetLabels) + in.DeepCopyInto(out) + return out +} diff --git a/apis/flowcollector/v1beta2/flowcollector_types.go b/apis/flowcollector/v1beta2/flowcollector_types.go index a5a160415..c467bd32d 100644 --- a/apis/flowcollector/v1beta2/flowcollector_types.go +++ b/apis/flowcollector/v1beta2/flowcollector_types.go @@ -462,6 +462,10 @@ type FlowCollectorFLP struct { // This feature requires the "topology.kubernetes.io/zone" label to be set on nodes. AddZone *bool `json:"addZone,omitempty"` + //+optional + // `SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. + SubnetLabels SubnetLabels `json:"subnetLabels,omitempty"` + // `advanced` allows setting some aspects of the internal configuration of the flow processor. // This section is aimed mostly for debugging and fine-grained performance optimizations, // such as `GOGC` and `GOMAXPROCS` env vars. Set these values at your own risk. @@ -1055,6 +1059,29 @@ type AdvancedPluginConfig struct { PriorityClassName string `json:"priorityClassName,omitempty"` } +// `SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. +type SubnetLabels struct { + // `openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the + // OpenShift install configuration and the Cluster Network Operator configuration. + //+optional + OpenShiftAutoDetect *bool `json:"openShiftAutoDetect,omitempty"` + + // `customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. + // If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap. + //+optional + CustomLabels []SubnetLabel `json:"customLabels,omitempty"` +} + +// SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. +type SubnetLabel struct { + // List of CIDRs, such as `["1.2.3.4/32"]`. + //+required + CIDRs []string `json:"cidrs,omitempty"` // Note, starting with k8s 1.31 / ocp 4.16 there's a new way to validate CIDR such as `+kubebuilder:validation:XValidation:rule="isCIDR(self)",message="field should be in CIDR notation format"`. But older versions would reject the CRD so we cannot implement it now to maintain compatibility. + // Label name, used to flag matching flows. + //+required + Name string `json:"name,omitempty"` +} + // Add more exporter types below type ExporterType string diff --git a/apis/flowcollector/v1beta2/zz_generated.deepcopy.go b/apis/flowcollector/v1beta2/zz_generated.deepcopy.go index 3c0d8ce73..4316f1a11 100644 --- a/apis/flowcollector/v1beta2/zz_generated.deepcopy.go +++ b/apis/flowcollector/v1beta2/zz_generated.deepcopy.go @@ -531,6 +531,7 @@ func (in *FlowCollectorFLP) DeepCopyInto(out *FlowCollectorFLP) { *out = new(bool) **out = **in } + in.SubnetLabels.DeepCopyInto(&out.SubnetLabels) if in.Advanced != nil { in, out := &in.Advanced, &out.Advanced *out = new(AdvancedProcessorConfig) @@ -911,3 +912,50 @@ func (in *ServerTLS) DeepCopy() *ServerTLS { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetLabel) DeepCopyInto(out *SubnetLabel) { + *out = *in + if in.CIDRs != nil { + in, out := &in.CIDRs, &out.CIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetLabel. +func (in *SubnetLabel) DeepCopy() *SubnetLabel { + if in == nil { + return nil + } + out := new(SubnetLabel) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubnetLabels) DeepCopyInto(out *SubnetLabels) { + *out = *in + if in.OpenShiftAutoDetect != nil { + in, out := &in.OpenShiftAutoDetect, &out.OpenShiftAutoDetect + *out = new(bool) + **out = **in + } + if in.CustomLabels != nil { + in, out := &in.CustomLabels, &out.CustomLabels + *out = make([]SubnetLabel, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubnetLabels. +func (in *SubnetLabels) DeepCopy() *SubnetLabels { + if in == nil { + return nil + } + out := new(SubnetLabels) + in.DeepCopyInto(out) + return out +} diff --git a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml index 4c7714e26..a707cd898 100644 --- a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml +++ b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml @@ -2272,6 +2272,38 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + subnetLabels: + description: '`subnetLabels` allows to define custom labels on + subnets and IPs or to enable automatic labelling of recognized + subnets in OpenShift.' + properties: + customLabels: + description: '`customLabels` allows to customize subnets and + IPs labelling, such as to identify cluster-external workloads + or web services. If you enable `openShiftAutoDetect`, `customLabels` + can override the detected subnets in case they overlap.' + items: + description: SubnetLabel allows to label subnets and IPs, + such as to identify cluster-external workloads or web + services. + properties: + cidrs: + description: List of CIDRs, such as `["1.2.3.4/32"]`. + items: + type: string + type: array + name: + description: Label name, used to flag matching flows. + type: string + type: object + type: array + openShiftAutoDetect: + description: '`openShiftAutoDetect` allows, when set to `true`, + to detect automatically the machines, pods and services + subnets based on the OpenShift install configuration and + the Cluster Network Operator configuration.' + type: boolean + type: object type: object type: object status: @@ -6104,6 +6136,38 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + subnetLabels: + description: '`SubnetLabels` allows to define custom labels on + subnets and IPs or to enable automatic labelling of recognized + subnets in OpenShift.' + properties: + customLabels: + description: '`customLabels` allows to customize subnets and + IPs labelling, such as to identify cluster-external workloads + or web services. If you enable `openShiftAutoDetect`, `customLabels` + can override the detected subnets in case they overlap.' + items: + description: SubnetLabel allows to label subnets and IPs, + such as to identify cluster-external workloads or web + services. + properties: + cidrs: + description: List of CIDRs, such as `["1.2.3.4/32"]`. + items: + type: string + type: array + name: + description: Label name, used to flag matching flows. + type: string + type: object + type: array + openShiftAutoDetect: + description: '`openShiftAutoDetect` allows, when set to `true`, + to detect automatically the machines, pods and services + subnets based on the OpenShift install configuration and + the Cluster Network Operator configuration.' + type: boolean + type: object type: object type: object status: diff --git a/bundle/manifests/netobserv-operator.clusterserviceversion.yaml b/bundle/manifests/netobserv-operator.clusterserviceversion.yaml index 8d7a1130f..44d285a55 100644 --- a/bundle/manifests/netobserv-operator.clusterserviceversion.yaml +++ b/bundle/manifests/netobserv-operator.clusterserviceversion.yaml @@ -752,6 +752,12 @@ spec: path: processor.metrics.includeList - displayName: Port path: processor.metrics.server.port + - displayName: Subnet labels + path: processor.subnetLabels + - displayName: Custom labels + path: processor.subnetLabels.customLabels + - displayName: Open shift auto detect + path: processor.subnetLabels.openShiftAutoDetect statusDescriptors: - description: Namespace where console plugin and flowlogs-pipeline have been deployed. @@ -904,6 +910,7 @@ spec: - config.openshift.io resources: - clusterversions + - networks verbs: - get - list diff --git a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml index c888ccee3..d9edda55c 100644 --- a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml +++ b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml @@ -1764,6 +1764,28 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + subnetLabels: + description: '`subnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift.' + properties: + customLabels: + description: '`customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap.' + items: + description: SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. + properties: + cidrs: + description: List of CIDRs, such as `["1.2.3.4/32"]`. + items: + type: string + type: array + name: + description: Label name, used to flag matching flows. + type: string + type: object + type: array + openShiftAutoDetect: + description: '`openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the OpenShift install configuration and the Cluster Network Operator configuration.' + type: boolean + type: object type: object type: object status: @@ -4959,6 +4981,28 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + subnetLabels: + description: '`SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift.' + properties: + customLabels: + description: '`customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap.' + items: + description: SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. + properties: + cidrs: + description: List of CIDRs, such as `["1.2.3.4/32"]`. + items: + type: string + type: array + name: + description: Label name, used to flag matching flows. + type: string + type: object + type: array + openShiftAutoDetect: + description: '`openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the OpenShift install configuration and the Cluster Network Operator configuration.' + type: boolean + type: object type: object type: object status: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 707342f2f..f4972b7ef 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -61,6 +61,7 @@ rules: - config.openshift.io resources: - clusterversions + - networks verbs: - get - list diff --git a/config/samples/flows_v1beta2_flowcollector.yaml b/config/samples/flows_v1beta2_flowcollector.yaml index 5b1a4b396..abe9f7bb3 100644 --- a/config/samples/flows_v1beta2_flowcollector.yaml +++ b/config/samples/flows_v1beta2_flowcollector.yaml @@ -55,6 +55,11 @@ spec: # Append a unique cluster name to each record # clusterName: # addZone: true + # subnetLabels: + # openShiftAutoDetect: true + # customLabels: + # - cidrs: [] + # name: "" metrics: server: port: 9102 diff --git a/controllers/consoleplugin/config/static-frontend-config.yaml b/controllers/consoleplugin/config/static-frontend-config.yaml index bfc0615b7..07c6ebd8a 100644 --- a/controllers/consoleplugin/config/static-frontend-config.yaml +++ b/controllers/consoleplugin/config/static-frontend-config.yaml @@ -157,6 +157,14 @@ columns: default: false width: 15 feature: zones + - id: SrcSubnetLabel + group: Source + name: Subnet Label + field: SrcSubnetLabel + filter: src_subnet_label + default: false + width: 10 + feature: subnetLabels - id: DstK8S_Name group: Destination name: Name @@ -277,6 +285,14 @@ columns: default: false width: 15 feature: zones + - id: DstSubnetLabel + group: Destination + name: Subnet Label + field: DstSubnetLabel + filter: dst_subnet_label + default: false + width: 10 + feature: subnetLabels - id: K8S_Name name: Names calculated: getSrcOrDstValue(SrcK8S_Name,DstK8S_Name) @@ -606,6 +622,16 @@ filters: component: autocomplete category: destination hint: Specify a single zone. + - id: src_subnet_label + name: Subnet Label + component: autocomplete + category: source + hint: Specify a subnet label, or an empty string to get unmatched sources. + - id: dst_subnet_label + name: Subnet Label + component: autocomplete + category: destination + hint: Specify a subnet label, or an empty string to get unmatched destinations. - id: src_resource name: Resource component: autocomplete @@ -883,6 +909,9 @@ fields: type: string description: Source availability zone lokiLabel: true + - name: SrcSubnetLabel + type: string + description: Source subnet label - name: DstK8S_Name type: string description: Name of the destination Kubernetes object, such as Pod name, Service name or Node name. @@ -920,6 +949,9 @@ fields: type: string description: Destination availability zone lokiLabel: true + - name: DstSubnetLabel + type: string + description: Destination subnet label - name: K8S_FlowLayer type: string description: "Flow layer: 'app' or 'infra'" diff --git a/controllers/consoleplugin/consoleplugin_objects.go b/controllers/consoleplugin/consoleplugin_objects.go index 82549ddb5..df032dc19 100644 --- a/controllers/consoleplugin/consoleplugin_objects.go +++ b/controllers/consoleplugin/consoleplugin_objects.go @@ -404,6 +404,9 @@ func (b *builder) setFrontendConfig(fconf *config.FrontendConfig) error { if helper.IsZoneEnabled(&b.desired.Processor) { fconf.Features = append(fconf.Features, "zones") } + if helper.IsSubnetLabelsEnabled(&b.desired.Processor) { + fconf.Features = append(fconf.Features, "subnetLabels") + } return nil } diff --git a/controllers/flp/flp_common_objects.go b/controllers/flp/flp_common_objects.go index d201a7343..3b86a05f4 100644 --- a/controllers/flp/flp_common_objects.go +++ b/controllers/flp/flp_common_objects.go @@ -50,22 +50,23 @@ var FlpConfSuffix = map[ConfKind]string{ } type Builder struct { - info *reconcilers.Instance - labels map[string]string - selector map[string]string - desired *flowslatest.FlowCollectorSpec - flowMetrics *metricslatest.FlowMetricList - promTLS *flowslatest.CertificateReference - confKind ConfKind - volumes volumes.Builder - loki *helper.LokiConfig - pipeline *PipelineBuilder - isDownstream bool + info *reconcilers.Instance + labels map[string]string + selector map[string]string + desired *flowslatest.FlowCollectorSpec + flowMetrics *metricslatest.FlowMetricList + detectedSubnets []flowslatest.SubnetLabel + promTLS *flowslatest.CertificateReference + confKind ConfKind + volumes volumes.Builder + loki *helper.LokiConfig + pipeline *PipelineBuilder + isDownstream bool } type builder = Builder -func NewBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList, ck ConfKind) (Builder, error) { +func NewBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList, detectedSubnets []flowslatest.SubnetLabel, ck ConfKind) (Builder, error) { version := helper.ExtractVersion(info.Image) name := name(ck) var promTLS *flowslatest.CertificateReference @@ -94,12 +95,13 @@ func NewBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSp selector: map[string]string{ "app": name, }, - desired: desired, - flowMetrics: flowMetrics, - confKind: ck, - promTLS: promTLS, - loki: info.Loki, - isDownstream: info.IsDownstream, + desired: desired, + flowMetrics: flowMetrics, + detectedSubnets: detectedSubnets, + confKind: ck, + promTLS: promTLS, + loki: info.Loki, + isDownstream: info.IsDownstream, }, nil } @@ -138,7 +140,7 @@ func (b *builder) NewKafkaPipeline() PipelineBuilder { } func (b *builder) initPipeline(ingest config.PipelineBuilderStage) PipelineBuilder { - pipeline := newPipelineBuilder(b.desired, b.flowMetrics, b.info.Loki, b.info.ClusterID, &b.volumes, &ingest) + pipeline := newPipelineBuilder(b.desired, b.flowMetrics, b.detectedSubnets, b.info.Loki, b.info.ClusterID, &b.volumes, &ingest) b.pipeline = &pipeline return pipeline } diff --git a/controllers/flp/flp_controller.go b/controllers/flp/flp_controller.go index 04a521cfe..bc1e1ed71 100644 --- a/controllers/flp/flp_controller.go +++ b/controllers/flp/flp_controller.go @@ -14,9 +14,11 @@ import ( "github.com/netobserv/network-observability-operator/pkg/manager/status" "github.com/netobserv/network-observability-operator/pkg/watchers" configv1 "github.com/openshift/api/config/v1" + "gopkg.in/yaml.v2" appsv1 "k8s.io/api/apps/v1" ascv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -74,7 +76,7 @@ func Start(ctx context.Context, mgr *manager.Manager) error { type subReconciler interface { context(context.Context) context.Context cleanupNamespace(context.Context) - reconcile(context.Context, *flowslatest.FlowCollector, *metricslatest.FlowMetricList) error + reconcile(context.Context, *flowslatest.FlowCollector, *metricslatest.FlowMetricList, []flowslatest.SubnetLabel) error getStatus() *status.Instance } @@ -132,6 +134,16 @@ func (r *Reconciler) reconcile(ctx context.Context, clh *helper.Client, fc *flow } } + // Auto-detect subnets + var subnetLabels []flowslatest.SubnetLabel + if r.mgr.IsOpenShift() && helper.AutoDetectOpenShiftNetworks(&fc.Spec.Processor) { + var err error + subnetLabels, err = r.getOpenShiftSubnets(ctx) + if err != nil { + log.Error(err, "error while reading subnet definitions") + } + } + // List custom metrics fm := metricslatest.FlowMetricList{} if err := r.Client.List(ctx, &fm, &client.ListOptions{Namespace: ns}); err != nil { @@ -161,7 +173,7 @@ func (r *Reconciler) reconcile(ctx context.Context, clh *helper.Client, fc *flow } for _, sr := range reconcilers { - if err := sr.reconcile(sr.context(ctx), fc, &fm); err != nil { + if err := sr.reconcile(sr.context(ctx), fc, &fm, subnetLabels); err != nil { return sr.getStatus().Error("FLPReconcileError", err) } } @@ -253,3 +265,89 @@ func reconcileLokiRoles(ctx context.Context, r *reconcilers.Common, b *builder) } return nil } + +func (r *Reconciler) getOpenShiftSubnets(ctx context.Context) ([]flowslatest.SubnetLabel, error) { + var subnets []flowslatest.SubnetLabel + + // Pods and Services subnets are found in CNO config + if r.mgr.HasCNO() { + network := &configv1.Network{} + err := r.Get(ctx, types.NamespacedName{Name: "cluster"}, network) + if err != nil { + return nil, fmt.Errorf("can't get Network information: %w", err) + } + var podCIDRs []string + for _, podsNet := range network.Spec.ClusterNetwork { + podCIDRs = append(podCIDRs, podsNet.CIDR) + } + if len(podCIDRs) > 0 { + subnets = append(subnets, flowslatest.SubnetLabel{ + Name: "Pods", + CIDRs: podCIDRs, + }) + } + if len(network.Spec.ServiceNetwork) > 0 { + subnets = append(subnets, flowslatest.SubnetLabel{ + Name: "Services", + CIDRs: network.Spec.ServiceNetwork, + }) + } + if network.Spec.ExternalIP != nil && len(network.Spec.ExternalIP.AutoAssignCIDRs) > 0 { + subnets = append(subnets, flowslatest.SubnetLabel{ + Name: "ExternalIP", + CIDRs: network.Spec.ExternalIP.AutoAssignCIDRs, + }) + } + } + + // Nodes subnet found in CM cluster-config-v1 (kube-system) + cm := &corev1.ConfigMap{} + if err := r.Get(ctx, types.NamespacedName{Name: "cluster-config-v1", Namespace: "kube-system"}, cm); err != nil { + return nil, fmt.Errorf(`can't read "cluster-config-v1" ConfigMap: %w`, err) + } + machines, err := readMachineNetworks(cm) + if err != nil { + return nil, err + } + + if len(machines) > 0 { + subnets = append(subnets, machines...) + } + + return subnets, nil +} + +func readMachineNetworks(cm *corev1.ConfigMap) ([]flowslatest.SubnetLabel, error) { + var subnets []flowslatest.SubnetLabel + + type ClusterConfig struct { + Networking struct { + MachineNetwork []struct { + CIDR string `yaml:"cidr"` + } `yaml:"machineNetwork"` + } `yaml:"networking"` + } + + var rawConfig string + var ok bool + if rawConfig, ok = cm.Data["install-config"]; !ok { + return nil, fmt.Errorf(`can't find key "install-config" in "cluster-config-v1" ConfigMap`) + } + var config ClusterConfig + if err := yaml.Unmarshal([]byte(rawConfig), &config); err != nil { + return nil, fmt.Errorf(`can't deserialize content of "cluster-config-v1" ConfigMap: %w`, err) + } + + var cidrs []string + for _, cidr := range config.Networking.MachineNetwork { + cidrs = append(cidrs, cidr.CIDR) + } + if len(cidrs) > 0 { + subnets = append(subnets, flowslatest.SubnetLabel{ + Name: "Machines", + CIDRs: cidrs, + }) + } + + return subnets, nil +} diff --git a/controllers/flp/flp_monolith_objects.go b/controllers/flp/flp_monolith_objects.go index 6c6311e8e..cc1aa060d 100644 --- a/controllers/flp/flp_monolith_objects.go +++ b/controllers/flp/flp_monolith_objects.go @@ -15,8 +15,8 @@ type monolithBuilder struct { generic builder } -func newMonolithBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList) (monolithBuilder, error) { - gen, err := NewBuilder(info, desired, flowMetrics, ConfMonolith) +func newMonolithBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList, detectedSubnets []flowslatest.SubnetLabel) (monolithBuilder, error) { + gen, err := NewBuilder(info, desired, flowMetrics, detectedSubnets, ConfMonolith) return monolithBuilder{ generic: gen, }, err diff --git a/controllers/flp/flp_monolith_reconciler.go b/controllers/flp/flp_monolith_reconciler.go index 1afe914de..7a36e768a 100644 --- a/controllers/flp/flp_monolith_reconciler.go +++ b/controllers/flp/flp_monolith_reconciler.go @@ -64,7 +64,7 @@ func (r *monolithReconciler) getStatus() *status.Instance { return &r.Status } -func (r *monolithReconciler) reconcile(ctx context.Context, desired *flowslatest.FlowCollector, flowMetrics *metricslatest.FlowMetricList) error { +func (r *monolithReconciler) reconcile(ctx context.Context, desired *flowslatest.FlowCollector, flowMetrics *metricslatest.FlowMetricList, detectedSubnets []flowslatest.SubnetLabel) error { // Retrieve current owned objects err := r.Managed.FetchAll(ctx) if err != nil { @@ -79,7 +79,7 @@ func (r *monolithReconciler) reconcile(ctx context.Context, desired *flowslatest r.Status.SetReady() // will be overidden if necessary, as error or pending - builder, err := newMonolithBuilder(r.Instance, &desired.Spec, flowMetrics) + builder, err := newMonolithBuilder(r.Instance, &desired.Spec, flowMetrics, detectedSubnets) if err != nil { return err } diff --git a/controllers/flp/flp_pipeline_builder.go b/controllers/flp/flp_pipeline_builder.go index c2c405e61..193ba0d0d 100644 --- a/controllers/flp/flp_pipeline_builder.go +++ b/controllers/flp/flp_pipeline_builder.go @@ -22,16 +22,18 @@ import ( type PipelineBuilder struct { *config.PipelineBuilderStage - desired *flowslatest.FlowCollectorSpec - flowMetrics metricslatest.FlowMetricList - volumes *volumes.Builder - loki *helper.LokiConfig - clusterID string + desired *flowslatest.FlowCollectorSpec + flowMetrics metricslatest.FlowMetricList + detectedSubnets []flowslatest.SubnetLabel + volumes *volumes.Builder + loki *helper.LokiConfig + clusterID string } func newPipelineBuilder( desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList, + detectedSubnets []flowslatest.SubnetLabel, loki *helper.LokiConfig, clusterID string, volumes *volumes.Builder, @@ -41,6 +43,7 @@ func newPipelineBuilder( PipelineBuilderStage: pipeline, desired: desired, flowMetrics: *flowMetrics, + detectedSubnets: detectedSubnets, loki: loki, clusterID: clusterID, volumes: volumes, @@ -56,25 +59,31 @@ func (b *PipelineBuilder) AddProcessorStages() error { addZone := helper.IsZoneEnabled(&b.desired.Processor) - // enrich stage (transform) configuration - enrichedStage := lastStage.TransformNetwork("enrich", api.TransformNetwork{ - Rules: api.NetworkTransformRules{{ + // Get all subnet labels + allLabels := append(b.detectedSubnets, b.desired.Processor.SubnetLabels.CustomLabels...) + flpLabels := subnetLabelsToFLP(allLabels) + + rules := api.NetworkTransformRules{ + { Type: api.NetworkAddKubernetes, Kubernetes: &api.K8sRule{ Input: "SrcAddr", Output: "SrcK8S", AddZone: addZone, }, - }, { + }, + { Type: api.NetworkAddKubernetes, Kubernetes: &api.K8sRule{ Input: "DstAddr", Output: "DstK8S", AddZone: addZone, }, - }, { + }, + { Type: api.NetworkReinterpretDirection, - }, { + }, + { Type: api.NetworkAddKubernetesInfra, KubernetesInfra: &api.K8sInfraRule{ Inputs: []string{ @@ -94,13 +103,38 @@ func (b *PipelineBuilder) AddProcessorStages() error { }, }, }, - }}, + }, + } + + if len(flpLabels) > 0 { + rules = append(rules, []api.NetworkTransformRule{ + { + Type: api.NetworkAddSubnetLabel, + AddSubnetLabel: &api.NetworkAddSubnetLabelRule{ + Input: "SrcAddr", + Output: "SrcSubnetLabel", + }, + }, + { + Type: api.NetworkAddSubnetLabel, + AddSubnetLabel: &api.NetworkAddSubnetLabelRule{ + Input: "DstAddr", + Output: "DstSubnetLabel", + }, + }, + }...) + } + + // enrich stage (transform) configuration + enrichedStage := lastStage.TransformNetwork("enrich", api.TransformNetwork{ + Rules: rules, DirectionInfo: api.NetworkTransformDirectionInfo{ ReporterIPField: "AgentIP", SrcHostField: "SrcK8S_HostIP", DstHostField: "DstK8S_HostIP", FlowDirectionField: "FlowDirection", }, + SubnetLabels: flpLabels, }) // loki stage (write) configuration @@ -466,3 +500,14 @@ func getKafkaSASL(sasl *flowslatest.SASLConfig, volumePrefix string, volumes *vo ClientSecretPath: secretPath, } } + +func subnetLabelsToFLP(labels []flowslatest.SubnetLabel) []api.NetworkTransformSubnetLabel { + var cats []api.NetworkTransformSubnetLabel + for _, subnetLabel := range labels { + cats = append(cats, api.NetworkTransformSubnetLabel{ + Name: subnetLabel.Name, + CIDRs: subnetLabel.CIDRs, + }) + } + return cats +} diff --git a/controllers/flp/flp_test.go b/controllers/flp/flp_test.go index f7278e309..0fdebd218 100644 --- a/controllers/flp/flp_test.go +++ b/controllers/flp/flp_test.go @@ -171,14 +171,14 @@ func getAutoScalerSpecs() (ascv2.HorizontalPodAutoscaler, flowslatest.FlowCollec func monoBuilder(ns string, cfg *flowslatest.FlowCollectorSpec) monolithBuilder { loki := helper.NewLokiConfig(&cfg.Loki, "any") info := reconcilers.Common{Namespace: ns, Loki: &loki} - b, _ := newMonolithBuilder(info.NewInstance(image, status.Instance{}), cfg, &metricslatest.FlowMetricList{}) + b, _ := newMonolithBuilder(info.NewInstance(image, status.Instance{}), cfg, &metricslatest.FlowMetricList{}, nil) return b } func transfBuilder(ns string, cfg *flowslatest.FlowCollectorSpec) transfoBuilder { loki := helper.NewLokiConfig(&cfg.Loki, "any") info := reconcilers.Common{Namespace: ns, Loki: &loki} - b, _ := newTransfoBuilder(info.NewInstance(image, status.Instance{}), cfg, &metricslatest.FlowMetricList{}) + b, _ := newTransfoBuilder(info.NewInstance(image, status.Instance{}), cfg, &metricslatest.FlowMetricList{}, nil) return b } @@ -553,7 +553,7 @@ func TestServiceMonitorChanged(t *testing.T) { // Check labels change info := reconcilers.Common{Namespace: "namespace2"} - b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics) + b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics, nil) third := b.generic.serviceMonitor() report = helper.NewChangeReport("") @@ -561,7 +561,7 @@ func TestServiceMonitorChanged(t *testing.T) { assert.Contains(report.String(), "ServiceMonitor labels changed") // Check scheme changed - b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics) + b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics, nil) fourth := b.generic.serviceMonitor() fourth.Spec.Endpoints[0].Scheme = "https" @@ -606,7 +606,7 @@ func TestPrometheusRuleChanged(t *testing.T) { // Check labels change info := reconcilers.Common{Namespace: "namespace2"} - b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics) + b, _ = newMonolithBuilder(info.NewInstance(image2, status.Instance{}), &cfg, b.generic.flowMetrics, nil) third := b.generic.prometheusRule() report = helper.NewChangeReport("") @@ -755,8 +755,8 @@ func TestLabels(t *testing.T) { cfg := getConfig() info := reconcilers.Common{Namespace: "ns"} - builder, _ := newMonolithBuilder(info.NewInstance(image, status.Instance{}), &cfg, &metricslatest.FlowMetricList{}) - tBuilder, _ := newTransfoBuilder(info.NewInstance(image, status.Instance{}), &cfg, &metricslatest.FlowMetricList{}) + builder, _ := newMonolithBuilder(info.NewInstance(image, status.Instance{}), &cfg, &metricslatest.FlowMetricList{}, nil) + tBuilder, _ := newTransfoBuilder(info.NewInstance(image, status.Instance{}), &cfg, &metricslatest.FlowMetricList{}, nil) // Deployment depl := tBuilder.deployment(annotate("digest")) @@ -983,3 +983,53 @@ func TestPipelineWithoutLoki(t *testing.T) { pipeline, ) } + +func TestReadMachineNetworks(t *testing.T) { + cm := corev1.ConfigMap{ + Data: map[string]string{ + "install-config": ` +additionalTrustBundlePolicy: Proxyonly +apiVersion: v1 +baseDomain: my.openshift.com +compute: +- architecture: amd64 + hyperthreading: Enabled + name: worker + platform: {} + replicas: 3 +controlPlane: + architecture: amd64 + hyperthreading: Enabled + name: master + platform: {} + replicas: 3 +metadata: + creationTimestamp: null + name: my-cluster +networking: + clusterNetwork: + - cidr: 10.128.0.0/14 + hostPrefix: 23 + machineNetwork: + - cidr: 10.0.0.0/16 + networkType: OVNKubernetes + serviceNetwork: + - 172.30.0.0/16 +platform: + aws: + region: eu-west-3 +publish: External`, + }, + } + + machines, err := readMachineNetworks(&cm) + assert.NoError(t, err) + + assert.Equal(t, + []flowslatest.SubnetLabel{ + { + Name: "Machines", + CIDRs: []string{"10.0.0.0/16"}, + }, + }, machines) +} diff --git a/controllers/flp/flp_transfo_objects.go b/controllers/flp/flp_transfo_objects.go index 70138afe8..787106186 100644 --- a/controllers/flp/flp_transfo_objects.go +++ b/controllers/flp/flp_transfo_objects.go @@ -16,8 +16,8 @@ type transfoBuilder struct { generic builder } -func newTransfoBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList) (transfoBuilder, error) { - gen, err := NewBuilder(info, desired, flowMetrics, ConfKafkaTransformer) +func newTransfoBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, flowMetrics *metricslatest.FlowMetricList, detectedSubnets []flowslatest.SubnetLabel) (transfoBuilder, error) { + gen, err := NewBuilder(info, desired, flowMetrics, detectedSubnets, ConfKafkaTransformer) return transfoBuilder{ generic: gen, }, err diff --git a/controllers/flp/flp_transfo_reconciler.go b/controllers/flp/flp_transfo_reconciler.go index 009d46b9c..a265584fa 100644 --- a/controllers/flp/flp_transfo_reconciler.go +++ b/controllers/flp/flp_transfo_reconciler.go @@ -65,7 +65,7 @@ func (r *transformerReconciler) getStatus() *status.Instance { return &r.Status } -func (r *transformerReconciler) reconcile(ctx context.Context, desired *flowslatest.FlowCollector, flowMetrics *metricslatest.FlowMetricList) error { +func (r *transformerReconciler) reconcile(ctx context.Context, desired *flowslatest.FlowCollector, flowMetrics *metricslatest.FlowMetricList, detectedSubnets []flowslatest.SubnetLabel) error { // Retrieve current owned objects err := r.Managed.FetchAll(ctx) if err != nil { @@ -80,7 +80,7 @@ func (r *transformerReconciler) reconcile(ctx context.Context, desired *flowslat r.Status.SetReady() // will be overidden if necessary, as error or pending - builder, err := newTransfoBuilder(r.Instance, &desired.Spec, flowMetrics) + builder, err := newTransfoBuilder(r.Instance, &desired.Spec, flowMetrics, detectedSubnets) if err != nil { return err } diff --git a/controllers/flp/metrics_api_test.go b/controllers/flp/metrics_api_test.go index 463d22ee1..011bc749a 100644 --- a/controllers/flp/metrics_api_test.go +++ b/controllers/flp/metrics_api_test.go @@ -34,7 +34,7 @@ func defaultBuilderWithMetrics(metrics *metricslatest.FlowMetricList) (monolithB cfg := getConfig() loki := helper.NewLokiConfig(&cfg.Loki, "any") info := reconcilers.Common{Namespace: "namespace", Loki: &loki} - return newMonolithBuilder(info.NewInstance(image, status.Instance{}), &cfg, metrics) + return newMonolithBuilder(info.NewInstance(image, status.Instance{}), &cfg, metrics, nil) } func metric(metrics api.MetricsItems, name string) *api.MetricsItem { diff --git a/docs/FlowCollector.md b/docs/FlowCollector.md index e1f4e267b..18eb853f1 100644 --- a/docs/FlowCollector.md +++ b/docs/FlowCollector.md @@ -3531,6 +3531,13 @@ TLS client configuration for Loki URL. Default: map[limits:map[memory:800Mi] requests:map[cpu:100m memory:100Mi]]
false + + subnetLabels + object + + `subnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift.
+ + false @@ -4805,6 +4812,74 @@ ResourceClaim references one entry in PodSpec.ResourceClaims. +### FlowCollector.spec.processor.subnetLabels +[↩ Parent](#flowcollectorspecprocessor) + + + +`subnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
customLabels[]object + `customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap.
+
false
openShiftAutoDetectboolean + `openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the OpenShift install configuration and the Cluster Network Operator configuration.
+
false
+ + +### FlowCollector.spec.processor.subnetLabels.customLabels[index] +[↩ Parent](#flowcollectorspecprocessorsubnetlabels) + + + +SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
cidrs[]string + List of CIDRs, such as `["1.2.3.4/32"]`.
+
false
namestring + Label name, used to flag matching flows.
+
false
+ + ### FlowCollector.status [↩ Parent](#flowcollector) @@ -11716,6 +11791,13 @@ TLS client configuration for Loki URL. Default: map[limits:map[memory:800Mi] requests:map[cpu:100m memory:100Mi]]
false + + subnetLabels + object + + `SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift.
+ + false @@ -14441,6 +14523,74 @@ ResourceClaim references one entry in PodSpec.ResourceClaims. +### FlowCollector.spec.processor.subnetLabels +[↩ Parent](#flowcollectorspecprocessor-1) + + + +`SubnetLabels` allows to define custom labels on subnets and IPs or to enable automatic labelling of recognized subnets in OpenShift. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
customLabels[]object + `customLabels` allows to customize subnets and IPs labelling, such as to identify cluster-external workloads or web services. If you enable `openShiftAutoDetect`, `customLabels` can override the detected subnets in case they overlap.
+
false
openShiftAutoDetectboolean + `openShiftAutoDetect` allows, when set to `true`, to detect automatically the machines, pods and services subnets based on the OpenShift install configuration and the Cluster Network Operator configuration.
+
false
+ + +### FlowCollector.spec.processor.subnetLabels.customLabels[index] +[↩ Parent](#flowcollectorspecprocessorsubnetlabels-1) + + + +SubnetLabel allows to label subnets and IPs, such as to identify cluster-external workloads or web services. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
cidrs[]string + List of CIDRs, such as `["1.2.3.4/32"]`.
+
false
namestring + Label name, used to flag matching flows.
+
false
+ + ### FlowCollector.status [↩ Parent](#flowcollector-1) diff --git a/go.mod b/go.mod index 55e21d154..f472f62c5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.21.7 require ( github.com/go-logr/logr v1.4.1 - github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240322124726-d2b2352bfe0f + github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240325101510-5feb3c603334 github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.31.1 github.com/openshift/api v0.0.0-20220112145620-704957ce4980 diff --git a/go.sum b/go.sum index 12e03ba96..56e155059 100644 --- a/go.sum +++ b/go.sum @@ -155,8 +155,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240322124726-d2b2352bfe0f h1:JwOGw6FxAjknAaK9LciiDBEXmz5e6/KbU742bshpyW8= -github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240322124726-d2b2352bfe0f/go.mod h1:4RRivFK1Yvbrw76TB65PGAkDlleQE3O/h+0yNqofuFk= +github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240325101510-5feb3c603334 h1:46pTt4NT7s5buSwTe9YS+Vn+62kqFU1+vZ5I1QqcypQ= +github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240325101510-5feb3c603334/go.mod h1:aiCIZopeZfHuI1/jt/Gg2Cns2y4DOanIVJrOFRergYU= github.com/netobserv/prometheus-common v0.48.0-netobserv h1:yNde6dteyK69t7l3k8CcR2uM6q+S10xgCap7mofvvV8= github.com/netobserv/prometheus-common v0.48.0-netobserv/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= diff --git a/pkg/helper/flowcollector.go b/pkg/helper/flowcollector.go index a83b0fecb..7eaa8d67d 100644 --- a/pkg/helper/flowcollector.go +++ b/pkg/helper/flowcollector.go @@ -114,6 +114,10 @@ func IsEBPFMetricsEnabled(spec *flowslatest.FlowCollectorEBPF) bool { return spec.Metrics.Enable != nil && *spec.Metrics.Enable } +func IsSubnetLabelsEnabled(spec *flowslatest.FlowCollectorFLP) bool { + return AutoDetectOpenShiftNetworks(spec) || len(spec.SubnetLabels.CustomLabels) > 0 +} + func PtrBool(b *bool) bool { if b == nil { return false @@ -287,3 +291,7 @@ func GetAdvancedPluginConfig(specConfig *flowslatest.AdvancedPluginConfig) flows return cfg } + +func AutoDetectOpenShiftNetworks(spec *flowslatest.FlowCollectorFLP) bool { + return spec.SubnetLabels.OpenShiftAutoDetect != nil && *spec.SubnetLabels.OpenShiftAutoDetect +} diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go index 6c90cea59..322e1fa3a 100644 --- a/pkg/manager/manager.go +++ b/pkg/manager/manager.go @@ -20,7 +20,7 @@ import ( //+kubebuilder:rbac:groups=core,resources=endpoints,verbs=get;list;watch //+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterrolebindings;clusterroles;rolebindings;roles,verbs=get;list;create;delete;update;watch //+kubebuilder:rbac:groups=console.openshift.io,resources=consoleplugins,verbs=get;create;delete;update;patch;list;watch -//+kubebuilder:rbac:groups=operator.openshift.io,resources=consoles,verbs=get;update;list;update;watch +//+kubebuilder:rbac:groups=operator.openshift.io,resources=consoles,verbs=get;list;update;watch //+kubebuilder:rbac:groups=flows.netobserv.io,resources=flowcollectors,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=flows.netobserv.io,resources=flowcollectors/status,verbs=get;update;patch //+kubebuilder:rbac:groups=flows.netobserv.io,resources=flowcollectors/finalizers,verbs=update @@ -29,7 +29,7 @@ import ( //+kubebuilder:rbac:groups=security.openshift.io,resources=securitycontextconstraints,verbs=list;create;update;watch //+kubebuilder:rbac:groups=apiregistration.k8s.io,resources=apiservices,verbs=list;get;watch //+kubebuilder:rbac:groups=monitoring.coreos.com,resources=servicemonitors;prometheusrules,verbs=get;create;delete;update;patch;list;watch -//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions,verbs=get;list;watch +//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions;networks,verbs=get;list;watch //+kubebuilder:rbac:groups=loki.grafana.com,resources=network,resourceNames=logs,verbs=get;create //+kubebuilder:rbac:urls="/metrics",verbs=get diff --git a/vendor/github.com/netobserv/flowlogs-pipeline/pkg/api/transform_network.go b/vendor/github.com/netobserv/flowlogs-pipeline/pkg/api/transform_network.go index 012a6cbd5..b78b6665c 100644 --- a/vendor/github.com/netobserv/flowlogs-pipeline/pkg/api/transform_network.go +++ b/vendor/github.com/netobserv/flowlogs-pipeline/pkg/api/transform_network.go @@ -22,7 +22,7 @@ type TransformNetwork struct { KubeConfigPath string `yaml:"kubeConfigPath,omitempty" json:"kubeConfigPath,omitempty" doc:"path to kubeconfig file (optional)"` ServicesFile string `yaml:"servicesFile,omitempty" json:"servicesFile,omitempty" doc:"path to services file (optional, default: /etc/services)"` ProtocolsFile string `yaml:"protocolsFile,omitempty" json:"protocolsFile,omitempty" doc:"path to protocols file (optional, default: /etc/protocols)"` - IPCategories []NetworkTransformIPCategory `yaml:"ipCategories,omitempty" json:"ipCategories,omitempty" doc:"configure IP categories"` + SubnetLabels []NetworkTransformSubnetLabel `yaml:"subnetLabels,omitempty" json:"subnetLabels,omitempty" doc:"configure subnet and IPs custom labels"` DirectionInfo NetworkTransformDirectionInfo `yaml:"directionInfo,omitempty" json:"directionInfo,omitempty" doc:"information to reinterpret flow direction (optional, to use with reinterpret_direction rule)"` } @@ -48,7 +48,7 @@ const ( NetworkAddKubernetes TransformNetworkOperationEnum = "add_kubernetes" // add output kubernetes fields from input NetworkAddKubernetesInfra TransformNetworkOperationEnum = "add_kubernetes_infra" // add output kubernetes isInfra field from input NetworkReinterpretDirection TransformNetworkOperationEnum = "reinterpret_direction" // reinterpret flow direction at the node level (instead of net interface), to ease the deduplication process - NetworkAddIPCategory TransformNetworkOperationEnum = "add_ip_category" // categorize IPs based on known subnets configuration + NetworkAddSubnetLabel TransformNetworkOperationEnum = "add_subnet_label" // categorize IPs based on known subnets configuration ) type NetworkTransformRule struct { @@ -57,7 +57,7 @@ type NetworkTransformRule struct { Kubernetes *K8sRule `yaml:"kubernetes,omitempty" json:"kubernetes,omitempty" doc:"Kubernetes rule configuration"` AddSubnet *NetworkAddSubnetRule `yaml:"add_subnet,omitempty" json:"add_subnet,omitempty" doc:"Add subnet rule configuration"` AddLocation *NetworkGenericRule `yaml:"add_location,omitempty" json:"add_location,omitempty" doc:"Add location rule configuration"` - AddIPCategory *NetworkGenericRule `yaml:"add_ip_category,omitempty" json:"add_ip_category,omitempty" doc:"Add ip category rule configuration"` + AddSubnetLabel *NetworkAddSubnetLabelRule `yaml:"add_subnet_label,omitempty" json:"add_subnet_label,omitempty" doc:"Add subnet label rule configuration"` AddService *NetworkAddServiceRule `yaml:"add_service,omitempty" json:"add_service,omitempty" doc:"Add service rule configuration"` } @@ -92,6 +92,11 @@ type NetworkAddSubnetRule struct { SubnetMask string `yaml:"subnet_mask,omitempty" json:"subnet_mask,omitempty" doc:"subnet mask field"` } +type NetworkAddSubnetLabelRule struct { + Input string `yaml:"input,omitempty" json:"input,omitempty" doc:"entry input field"` + Output string `yaml:"output,omitempty" json:"output,omitempty" doc:"entry output field"` +} + type NetworkAddServiceRule struct { Input string `yaml:"input,omitempty" json:"input,omitempty" doc:"entry input field"` Output string `yaml:"output,omitempty" json:"output,omitempty" doc:"entry output field"` @@ -108,7 +113,7 @@ type NetworkTransformDirectionInfo struct { type NetworkTransformRules []NetworkTransformRule -type NetworkTransformIPCategory struct { - CIDRs []string `yaml:"cidrs,omitempty" json:"cidrs,omitempty" doc:"list of CIDRs to match a category"` - Name string `yaml:"name,omitempty" json:"name,omitempty" doc:"name of the category"` +type NetworkTransformSubnetLabel struct { + CIDRs []string `yaml:"cidrs,omitempty" json:"cidrs,omitempty" doc:"list of CIDRs to match a label"` + Name string `yaml:"name,omitempty" json:"name,omitempty" doc:"name of the label"` } diff --git a/vendor/modules.txt b/vendor/modules.txt index 1d190202b..94e947b0e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -109,7 +109,7 @@ github.com/munnerz/goautoneg # github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f ## explicit github.com/mwitkow/go-conntrack -# github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240322124726-d2b2352bfe0f +# github.com/netobserv/flowlogs-pipeline v0.1.12-0.20240325101510-5feb3c603334 ## explicit; go 1.21 github.com/netobserv/flowlogs-pipeline/pkg/api github.com/netobserv/flowlogs-pipeline/pkg/config