From 51adcf8f1dcc2efb18effca1aeed3e35b245d1b3 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Fri, 10 Jan 2025 15:14:43 +0100 Subject: [PATCH 1/4] NETOBSERV-2010: manage cardinality for netevents nested labels --- pkg/helper/cardinality/cardinality.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/helper/cardinality/cardinality.json b/pkg/helper/cardinality/cardinality.json index 4df48dfd38..c145f3180f 100644 --- a/pkg/helper/cardinality/cardinality.json +++ b/pkg/helper/cardinality/cardinality.json @@ -50,7 +50,12 @@ "DnsErrno": "fine", "TimeFlowRttNs": "avoid", "NetworkEvents": "avoid", + "NetworkEvents>Type": "fine", + "NetworkEvents>Namespace": "fine", + "NetworkEvents>Name": "fine", + "NetworkEvents>Action": "fine", + "NetworkEvents>Direction": "fine", "K8S_ClusterName": "fine", "_RecordType": "fine", "_HashId": "avoid" -} \ No newline at end of file +} From 877c1fefd03aef1eb2b2b076172b9dac1db39975 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Fri, 10 Jan 2025 15:55:11 +0100 Subject: [PATCH 2/4] Distinguish type/docType; add missing cardinality --- .../config/static-frontend-config.yaml | 21 ++++++++++++++----- hack/asciidoc-flows-gen.sh | 14 ++++++++++--- pkg/helper/cardinality/cardinality.json | 8 +++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/controllers/consoleplugin/config/static-frontend-config.yaml b/controllers/consoleplugin/config/static-frontend-config.yaml index 714ca98c6d..dbb0091b4a 100644 --- a/controllers/consoleplugin/config/static-frontend-config.yaml +++ b/controllers/consoleplugin/config/static-frontend-config.yaml @@ -1255,20 +1255,23 @@ fields: - 2: Inner (with the same source and destination node) - name: IfDirections type: number + docType: number[] description: | Flow directions from the network interface observation point. Can be one of: + - 0: Ingress (interface incoming traffic) + - 1: Egress (interface outgoing traffic) - name: Interfaces type: string + docType: string[] description: Network interfaces - name: Flags type: string + docType: string[] description: | - Logical OR combination of unique TCP flags comprised in the flow, as per RFC-9293, with additional custom flags to represent the following per-packet combinations: + - - SYN+ACK (0x100) + - - FIN+ACK (0x200) + - - RST+ACK (0x400) + List of TCP flags comprised in the flow, as per RFC-9293, with additional custom flags to represent the following per-packet combinations: + + - SYN_ACK + + - FIN_ACK + + - RST_ACK - name: Bytes type: number description: Number of bytes @@ -1312,7 +1315,15 @@ fields: description: TCP Smoothed Round Trip Time (SRTT), in nanoseconds - name: NetworkEvents type: string - description: Network events flow monitoring + docType: object[] + description: | + Network events, such as network policy actions, composed of nested fields: + + - Feature (such as "acl" for network policies) + + - Type (such as an "AdminNetworkPolicy") + + - Namespace (namespace where the event applies, if any) + + - Name (name of the resource that triggered the event) + + - Action (such as "allow" or "drop") + + - Direction (Ingress or Egress) - name: ZoneId type: number description: packet translation zone id diff --git a/hack/asciidoc-flows-gen.sh b/hack/asciidoc-flows-gen.sh index b7cc85c464..95443f7020 100755 --- a/hack/asciidoc-flows-gen.sh +++ b/hack/asciidoc-flows-gen.sh @@ -19,11 +19,15 @@ nbfields=$(yq '.fields | length' $FE_SOURCE) lokiLabels=$(cat $LOKI_LABEL_SOURCE) cardinalityMap=$(cat $CARDINALITY_SOURCE) otelMap=$(cat $OTEL_SOURCE) +errors="" for i in $(seq 0 $(( $nbfields-1 )) ); do frontEntry=$(yq ".fields | sort_by(.name) | .[$i]" $FE_SOURCE) name=$(printf "$frontEntry" | yq ".name") - type=$(printf "$frontEntry" | yq ".type") + type=$(printf "$frontEntry" | yq ".docType") + if [[ "$type" == "null" ]]; then + type=$(printf "$frontEntry" | yq ".type") + fi desc=$(printf "$frontEntry" | yq ".description") filter=$(printf "$frontEntry" | yq ".filter") if [[ "$filter" == "null" ]]; then @@ -44,8 +48,7 @@ for i in $(seq 0 $(( $nbfields-1 )) ); do fi cardWarn=$(printf "$cardinalityMap" | jq -r ".$name") if [[ "$cardWarn" == "null" ]]; then - echo "missing cardinality for field $name" - exit 1 + errors="$errors\nmissing cardinality for field $name" fi otel=$(printf "$otelMap" | jq -r ".$name") if [[ "$otel" == "null" ]]; then @@ -60,4 +63,9 @@ for i in $(seq 0 $(( $nbfields-1 )) ); do echo -e "| $otel" >> $ADOC done +if [[ $errors != "" ]]; then + echo -e $errors + exit 1 +fi + echo -e '|===' >> $ADOC diff --git a/pkg/helper/cardinality/cardinality.json b/pkg/helper/cardinality/cardinality.json index c145f3180f..1f19d555e7 100644 --- a/pkg/helper/cardinality/cardinality.json +++ b/pkg/helper/cardinality/cardinality.json @@ -50,12 +50,20 @@ "DnsErrno": "fine", "TimeFlowRttNs": "avoid", "NetworkEvents": "avoid", + "NetworkEvents>Feature": "fine", "NetworkEvents>Type": "fine", "NetworkEvents>Namespace": "fine", "NetworkEvents>Name": "fine", "NetworkEvents>Action": "fine", "NetworkEvents>Direction": "fine", "K8S_ClusterName": "fine", + "Sampling": "fine", + "ZoneId": "avoid", + "XlatSrcPort": "careful", + "XlatSrcAddr": "avoid", + "XlatIcmpId": "avoid", + "XlatDstPort": "careful", + "XlatDstAddr": "avoid", "_RecordType": "fine", "_HashId": "avoid" } From f6304bdf1556d896465b2f7438a83bbe1fe08da6 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Mon, 20 Jan 2025 10:45:55 +0100 Subject: [PATCH 3/4] Align with NETOBSERV-2056 --- .../config/static-frontend-config.yaml | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/controllers/consoleplugin/config/static-frontend-config.yaml b/controllers/consoleplugin/config/static-frontend-config.yaml index dbb0091b4a..561ee60fca 100644 --- a/controllers/consoleplugin/config/static-frontend-config.yaml +++ b/controllers/consoleplugin/config/static-frontend-config.yaml @@ -1049,7 +1049,7 @@ scopes: name: Node shortName: Node description: Node on which the resources are running - labels: + labels: - SrcK8S_HostName - DstK8S_HostName groups: @@ -1064,7 +1064,7 @@ scopes: name: Namespace shortName: NS description: Resource namespace - labels: + labels: - SrcK8S_Namespace - DstK8S_Namespace groups: @@ -1082,7 +1082,7 @@ scopes: name: Owner shortName: Own description: Controller owner, such as a Deployment - labels: + labels: - SrcK8S_OwnerName - SrcK8S_OwnerType - DstK8S_OwnerName @@ -1108,7 +1108,7 @@ scopes: name: Resource shortName: Res description: Base resource, such as a Pod, a Service or a Node - labels: + labels: - SrcK8S_Name - SrcK8S_Type - SrcK8S_OwnerName @@ -1170,6 +1170,7 @@ fields: description: Source namespace - name: SrcAddr type: string + format: IP description: Source IP address (ipv4 or ipv6) - name: SrcPort type: number @@ -1179,6 +1180,7 @@ fields: description: Source MAC address - name: SrcK8S_HostIP type: string + format: IP description: Source node IP - name: SrcK8S_HostName type: string @@ -1206,6 +1208,7 @@ fields: description: Destination namespace - name: DstAddr type: string + format: IP description: Destination IP address (ipv4 or ipv6) - name: DstPort type: number @@ -1215,6 +1218,7 @@ fields: description: Destination MAC address - name: DstK8S_HostIP type: string + format: IP description: Destination node IP - name: DstK8S_HostName type: string @@ -1254,19 +1258,16 @@ fields: - 1: Egress (outgoing traffic, from the node observation point) + - 2: Inner (with the same source and destination node) - name: IfDirections - type: number - docType: number[] + type: number[] description: | Flow directions from the network interface observation point. Can be one of: + - 0: Ingress (interface incoming traffic) + - 1: Egress (interface outgoing traffic) - name: Interfaces - type: string - docType: string[] + type: string[] description: Network interfaces - name: Flags - type: string - docType: string[] + type: string[] description: | List of TCP flags comprised in the flow, as per RFC-9293, with additional custom flags to represent the following per-packet combinations: + - SYN_ACK + @@ -1314,7 +1315,7 @@ fields: type: number description: TCP Smoothed Round Trip Time (SRTT), in nanoseconds - name: NetworkEvents - type: string + type: string[] docType: object[] description: | Network events, such as network policy actions, composed of nested fields: + From c8f3f11b38101d0196dbae8b4cddc00d41a6e774 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Tue, 21 Jan 2025 08:59:44 +0100 Subject: [PATCH 4/4] Add integration test --- .../flp/flp_controller_flowmetrics_test.go | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/controllers/flp/flp_controller_flowmetrics_test.go b/controllers/flp/flp_controller_flowmetrics_test.go index bead119384..a4ebd573e9 100644 --- a/controllers/flp/flp_controller_flowmetrics_test.go +++ b/controllers/flp/flp_controller_flowmetrics_test.go @@ -60,13 +60,24 @@ func ControllerFlowMetricsSpecs() { Labels: []string{"DstAddr"}, }, } + metric3 := metricslatest.FlowMetric{ // With nested labels + ObjectMeta: metav1.ObjectMeta{ + Name: "metric-3", + Namespace: operatorNamespace, + }, + Spec: metricslatest.FlowMetricSpec{ + MetricName: "m_3", + Type: metricslatest.CounterMetric, + Labels: []string{"NetworkEvents>Type", "NetworkEvents>Name"}, + }, + } metricUnwatched := metricslatest.FlowMetric{ ObjectMeta: metav1.ObjectMeta{ Name: "metric-unwatched", Namespace: otherNamespace, }, Spec: metricslatest.FlowMetricSpec{ - MetricName: "m_3", + MetricName: "m_unwatched", Type: metricslatest.CounterMetric, }, } @@ -121,6 +132,7 @@ func ControllerFlowMetricsSpecs() { Expect(k8sClient.Create(ctx, &metric1)).Should(Succeed()) Expect(k8sClient.Create(ctx, &metricUnwatched)).Should(Succeed()) Expect(k8sClient.Create(ctx, &metric2)).Should(Succeed()) + Expect(k8sClient.Create(ctx, &metric3)).Should(Succeed()) }) It("Should update configmap with custom metrics", func() { @@ -139,6 +151,7 @@ func ControllerFlowMetricsSpecs() { names := getSortedMetricsNames(metrics) return slices.Contains(names, metric1.Spec.MetricName) && slices.Contains(names, metric2.Spec.MetricName) && + slices.Contains(names, metric3.Spec.MetricName) && !slices.Contains(names, metricUnwatched.Spec.MetricName) })) }) @@ -153,6 +166,7 @@ func ControllerFlowMetricsSpecs() { }, timeout, interval).Should(Satisfy(func(conds []metav1.Condition) bool { ready := meta.FindStatusCondition(conds, fmstatus.ConditionReady) card := meta.FindStatusCondition(conds, fmstatus.ConditionCardinalityOK) + // Metrics 1 has cardinality FINE (no label) return ready != nil && card != nil && ready.Status == metav1.ConditionTrue && card.Status == metav1.ConditionTrue && ready.Reason == "Ready" && card.Reason == string(cardinality.WarnFine) })) @@ -164,11 +178,26 @@ func ControllerFlowMetricsSpecs() { } return metric2.Status.Conditions }, timeout, interval).Should(Satisfy(func(conds []metav1.Condition) bool { + // Metrics 2 has cardinality AVOID (Addr label) ready := meta.FindStatusCondition(conds, fmstatus.ConditionReady) card := meta.FindStatusCondition(conds, fmstatus.ConditionCardinalityOK) return ready != nil && card != nil && ready.Status == metav1.ConditionTrue && card.Status == metav1.ConditionFalse && ready.Reason == "Ready" && card.Reason == string(cardinality.WarnAvoid) })) + + Eventually(func() interface{} { + err := k8sClient.Get(ctx, helper.NamespacedName(&metric3), &metric3) + if err != nil { + return err + } + return metric3.Status.Conditions + }, timeout, interval).Should(Satisfy(func(conds []metav1.Condition) bool { + // Metrics 3 has cardinality FINE (NetworkEvents nested labels) + ready := meta.FindStatusCondition(conds, fmstatus.ConditionReady) + card := meta.FindStatusCondition(conds, fmstatus.ConditionCardinalityOK) + return ready != nil && card != nil && ready.Status == metav1.ConditionTrue && card.Status == metav1.ConditionTrue && + ready.Reason == "Ready" && card.Reason == string(cardinality.WarnFine) + })) }) })