diff --git a/build/charts/antrea/crds/traceflow.yaml b/build/charts/antrea/crds/traceflow.yaml index 814e7f5de32..45cf9f0f243 100644 --- a/build/charts/antrea/crds/traceflow.yaml +++ b/build/charts/antrea/crds/traceflow.yaml @@ -454,6 +454,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index d0f8737c613..dfd386b9928 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -5110,6 +5110,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea-crds.yml b/build/yamls/antrea-crds.yml index 06db6b42ff8..7439bdf964d 100644 --- a/build/yamls/antrea-crds.yml +++ b/build/yamls/antrea-crds.yml @@ -5083,6 +5083,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index 4e4cd7e8973..54fda94fe63 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -5110,6 +5110,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index 482b5c87676..7381280024b 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -5110,6 +5110,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index a431b60cdee..e83065eb1c0 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -5110,6 +5110,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index 66601292006..4a071a0cf04 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -5110,6 +5110,8 @@ spec: type: string egress: type: string + egressNode: + type: string capturedPacket: properties: srcIP: diff --git a/pkg/agent/controller/egress/egress_controller.go b/pkg/agent/controller/egress/egress_controller.go index 523584bec1d..382cf28fc4b 100644 --- a/pkg/agent/controller/egress/egress_controller.go +++ b/pkg/agent/controller/egress/egress_controller.go @@ -1360,13 +1360,13 @@ func (c *EgressController) GetEgressIPByMark(mark uint32) (string, error) { return "", fmt.Errorf("no EgressIP associated with mark %v", mark) } -// GetEgress returns effective Egress and Egress IP applied on a Pod. -func (c *EgressController) GetEgress(ns, podName string) (string, string, error) { +// GetEgress returns effective EgressName, EgressIP and EgressNode name of Egress applied on a Pod. +func (c *EgressController) GetEgress(ns, podName string) (string, string, string, error) { if c == nil { - return "", "", fmt.Errorf("Egress is not enabled") + return "", "", "", fmt.Errorf("Egress is not enabled") } pod := k8s.NamespacedName(ns, podName) - egress, exists := func() (string, bool) { + egressName, exists := func() (string, bool) { c.egressBindingsMutex.RLock() defer c.egressBindingsMutex.RUnlock() binding, exists := c.egressBindings[pod] @@ -1376,13 +1376,15 @@ func (c *EgressController) GetEgress(ns, podName string) (string, string, error) return binding.effectiveEgress, true }() if !exists { - return "", "", fmt.Errorf("no Egress applied to Pod %v", pod) + return "", "", "", fmt.Errorf("no Egress applied to Pod %v", pod) } - state, exists := c.getEgressState(egress) - if !exists { - return "", "", fmt.Errorf("no Egress State associated with name %s", egress) + egress, err := c.egressLister.Get(egressName) + if err != nil { + return "", "", "", err } - return egress, state.egressIP, nil + egressNode := egress.Status.EgressNode + egressIP := egress.Status.EgressIP + return egressName, egressIP, egressNode, nil } // An Egress is schedulable if its Egress IP is allocated from ExternalIPPool. diff --git a/pkg/agent/controller/egress/egress_controller_test.go b/pkg/agent/controller/egress/egress_controller_test.go index 101edfe3ae8..8c66a0f2a1b 100644 --- a/pkg/agent/controller/egress/egress_controller_test.go +++ b/pkg/agent/controller/egress/egress_controller_test.go @@ -1616,6 +1616,10 @@ func TestGetEgress(t *testing.T) { egress := &crdv1b1.Egress{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, Spec: crdv1b1.EgressSpec{EgressIP: fakeLocalEgressIP1}, + Status: crdv1b1.EgressStatus{ + EgressNode: fakeNode, + EgressIP: fakeLocalEgressIP1, + }, } egressGroup := &cpv1b2.EgressGroup{ ObjectMeta: metav1.ObjectMeta{Name: "egressA", UID: "uidA"}, @@ -1648,6 +1652,7 @@ func TestGetEgress(t *testing.T) { args args expectedEgressName string expectedEgressIP string + expectedEgressNode string expectedErr string }{ { @@ -1658,6 +1663,7 @@ func TestGetEgress(t *testing.T) { }, expectedEgressName: "egressA", expectedEgressIP: fakeLocalEgressIP1, + expectedEgressNode: fakeNode, }, { name: "no local egress applied on a pod", @@ -1670,7 +1676,7 @@ func TestGetEgress(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotEgressName, gotEgressIP, err := c.GetEgress(tt.args.ns, tt.args.podName) + gotEgressName, gotEgressIP, gotEgressNode, err := c.GetEgress(tt.args.ns, tt.args.podName) if tt.expectedErr == "" { require.NoError(t, err) } else { @@ -1678,6 +1684,7 @@ func TestGetEgress(t *testing.T) { } assert.Equal(t, tt.expectedEgressName, gotEgressName) assert.Equal(t, tt.expectedEgressIP, gotEgressIP) + assert.Equal(t, tt.expectedEgressNode, gotEgressNode) }) } } diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go index 8f331254d8b..c60ec7b639b 100644 --- a/pkg/agent/controller/traceflow/packetin.go +++ b/pkg/agent/controller/traceflow/packetin.go @@ -292,11 +292,11 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1beta1.Traceflo } } if isRemoteEgress == 1 { // an Egress packet, currently on source Node and forwarded to Egress Node. - egress, _, err := c.egressQuerier.GetEgress(ns, srcPod) + egressName, egressIP, egressNode, err := c.egressQuerier.GetEgress(ns, srcPod) if err != nil { return nil, nil, nil, err } - obEgress := getEgressObservation(false, tunnelDstIP, egress) + obEgress := getEgressObservation(false, egressIP, egressName, egressNode) obs = append(obs, *obEgress) } ob.TunnelDstIP = tunnelDstIP @@ -312,18 +312,19 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1beta1.Traceflo } } if pktMark != 0 { // Egress packet on Egress Node - egressIP, err := c.egressQuerier.GetEgressIPByMark(pktMark) - if err != nil { - return nil, nil, nil, err - } - egress := "" + egressName, egressIP, egressNode := "", "", "" if tunnelDstIP == "" { // Egress Node is Source Node of this Egress packet - egress, _, err = c.egressQuerier.GetEgress(ns, srcPod) + egressName, egressIP, egressNode, err = c.egressQuerier.GetEgress(ns, srcPod) + if err != nil { + return nil, nil, nil, err + } + } else { + egressIP, err = c.egressQuerier.GetEgressIPByMark(pktMark) if err != nil { return nil, nil, nil, err } } - obEgress := getEgressObservation(true, egressIP, egress) + obEgress := getEgressObservation(true, egressIP, egressName, egressNode) obs = append(obs, *obEgress) } ob.Action = crdv1beta1.ActionForwardedOutOfOverlay @@ -485,11 +486,12 @@ func parseCapturedPacket(pktIn *ofctrl.PacketIn) *crdv1beta1.Packet { return &capturedPacket } -func getEgressObservation(isEgressNode bool, egressIP, egressName string) *crdv1beta1.Observation { +func getEgressObservation(isEgressNode bool, egressIP, egressName, egressNode string) *crdv1beta1.Observation { ob := new(crdv1beta1.Observation) ob.Component = crdv1beta1.ComponentEgress ob.EgressIP = egressIP ob.Egress = egressName + ob.EgressNode = egressNode if isEgressNode { ob.Action = crdv1beta1.ActionMarkedForSNAT } else { diff --git a/pkg/agent/controller/traceflow/packetin_test.go b/pkg/agent/controller/traceflow/packetin_test.go index 66250e22a06..9cf6748da13 100644 --- a/pkg/agent/controller/traceflow/packetin_test.go +++ b/pkg/agent/controller/traceflow/packetin_test.go @@ -41,6 +41,7 @@ import ( var ( egressName = "dummyEgress" egressIP = "192.168.100.100" + egressNode = "fakeEgressNode" ) func prepareMockTables() { @@ -303,8 +304,7 @@ func TestParsePacketIn(t *testing.T) { }, }, expectedCalls: func(npQuerierq *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { - egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, nil) - egressQuerier.EXPECT().GetEgressIPByMark(uint32(1)).Return(egressIP, nil) + egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, egressNode, nil) }, expectedTf: &crdv1beta1.Traceflow{ ObjectMeta: metav1.ObjectMeta{ @@ -331,10 +331,11 @@ func TestParsePacketIn(t *testing.T) { Action: crdv1beta1.ActionForwarded, }, { - Component: crdv1beta1.ComponentEgress, - Action: crdv1beta1.ActionMarkedForSNAT, - Egress: egressName, - EgressIP: egressIP, + Component: crdv1beta1.ComponentEgress, + Action: crdv1beta1.ActionMarkedForSNAT, + Egress: egressName, + EgressIP: egressIP, + EgressNode: egressNode, }, { Component: crdv1beta1.ComponentForwarding, @@ -370,7 +371,7 @@ func TestParsePacketIn(t *testing.T) { }, }, expectedCalls: func(npQuerierq *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { - egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, nil) + egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, egressNode, nil) }, expectedTf: &crdv1beta1.Traceflow{ ObjectMeta: metav1.ObjectMeta{ @@ -397,10 +398,11 @@ func TestParsePacketIn(t *testing.T) { Action: crdv1beta1.ActionForwarded, }, { - Component: crdv1beta1.ComponentEgress, - Action: crdv1beta1.ActionForwardedToEgressNode, - Egress: egressName, - EgressIP: egressIP, + Component: crdv1beta1.ComponentEgress, + Action: crdv1beta1.ActionForwardedToEgressNode, + Egress: egressName, + EgressIP: egressIP, + EgressNode: egressNode, }, { Component: crdv1beta1.ComponentForwarding, diff --git a/pkg/agent/flowexporter/exporter/exporter.go b/pkg/agent/flowexporter/exporter/exporter.go index 0f85949d5e1..d559893a574 100644 --- a/pkg/agent/flowexporter/exporter/exporter.go +++ b/pkg/agent/flowexporter/exporter/exporter.go @@ -641,14 +641,15 @@ func (exp *FlowExporter) findFlowType(conn flowexporter.Connection) uint8 { } func (exp *FlowExporter) fillEgressInfo(conn *flowexporter.Connection) { - egressName, egressIP, err := exp.egressQuerier.GetEgress(conn.SourcePodNamespace, conn.SourcePodName) + egressName, egressIP, egressNode, err := exp.egressQuerier.GetEgress(conn.SourcePodNamespace, conn.SourcePodName) if err != nil { // Egress is not enabled or no Egress is applied to this Pod return } conn.EgressName = egressName conn.EgressIP = egressIP - klog.V(4).InfoS("Filling Egress Info for flow", "Egress", conn.EgressName, "EgressIP", conn.EgressIP, "SourcePodNamespace", conn.SourcePodNamespace, "SourcePodName", conn.SourcePodName) + conn.EgressNode = egressNode + klog.V(4).InfoS("Filling Egress Info for flow", "Egress", conn.EgressName, "EgressIP", conn.EgressIP, "EgressNode", conn.EgressNode, "SourcePodNamespace", conn.SourcePodNamespace, "SourcePodName", conn.SourcePodName) } func (exp *FlowExporter) exportConn(conn *flowexporter.Connection) error { diff --git a/pkg/agent/flowexporter/exporter/exporter_test.go b/pkg/agent/flowexporter/exporter/exporter_test.go index ea7fc42cd17..7cc4287a084 100644 --- a/pkg/agent/flowexporter/exporter/exporter_test.go +++ b/pkg/agent/flowexporter/exporter/exporter_test.go @@ -811,14 +811,16 @@ func TestFlowExporter_fillEgressInfo(t *testing.T) { sourcePodName string expectedEgressName string expectedEgressIP string + expectedEgressNode string expectedErr string }{ { - name: "Both EgressName and EgressIP filled", + name: "EgressName, EgressIP and EgressNode filled", sourcePodNamespace: "namespaceA", sourcePodName: "podA", expectedEgressName: "test-egress", expectedEgressIP: "172.18.0.1", + expectedEgressNode: "test-egress-node", }, { name: "No Egress Information filled", @@ -826,6 +828,7 @@ func TestFlowExporter_fillEgressInfo(t *testing.T) { sourcePodName: "podC", expectedEgressName: "", expectedEgressIP: "", + expectedEgressNode: "", }, } @@ -841,13 +844,14 @@ func TestFlowExporter_fillEgressInfo(t *testing.T) { SourcePodName: tc.sourcePodName, } if tc.expectedEgressName != "" { - egressQuerier.EXPECT().GetEgress(conn.SourcePodNamespace, conn.SourcePodName).Return(tc.expectedEgressName, tc.expectedEgressIP, nil) + egressQuerier.EXPECT().GetEgress(conn.SourcePodNamespace, conn.SourcePodName).Return(tc.expectedEgressName, tc.expectedEgressIP, tc.expectedEgressNode, nil) } else { - egressQuerier.EXPECT().GetEgress(conn.SourcePodNamespace, conn.SourcePodName).Return("", "", fmt.Errorf("no Egress applied to Pod %s", conn.SourcePodName)) + egressQuerier.EXPECT().GetEgress(conn.SourcePodNamespace, conn.SourcePodName).Return("", "", "", fmt.Errorf("no Egress applied to Pod %s", conn.SourcePodName)) } exp.fillEgressInfo(&conn) assert.Equal(t, tc.expectedEgressName, conn.EgressName) assert.Equal(t, tc.expectedEgressIP, conn.EgressIP) + assert.Equal(t, tc.expectedEgressNode, conn.EgressNode) }) } } diff --git a/pkg/agent/flowexporter/types.go b/pkg/agent/flowexporter/types.go index f091fe7f3f2..38c34ddb4c5 100644 --- a/pkg/agent/flowexporter/types.go +++ b/pkg/agent/flowexporter/types.go @@ -86,6 +86,7 @@ type Connection struct { EgressIP string AppProtocolName string HttpVals string + EgressNode string } type ItemToExpire struct { diff --git a/pkg/apis/crd/v1beta1/types.go b/pkg/apis/crd/v1beta1/types.go index f969a4e4ce3..034e9626577 100644 --- a/pkg/apis/crd/v1beta1/types.go +++ b/pkg/apis/crd/v1beta1/types.go @@ -1165,6 +1165,8 @@ type Observation struct { // TunnelDstIP is the tunnel destination IP. TunnelDstIP string `json:"tunnelDstIP,omitempty" yaml:"tunnelDstIP,omitempty"` EgressIP string `json:"egressIP,omitempty" yaml:"egressIP,omitempty"` + // EgressNode is the name of the Egress Node. + EgressNode string `json:"egressNode,omitempty" yaml:"egressNode,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apiserver/openapi/zz_generated.openapi.go b/pkg/apiserver/openapi/zz_generated.openapi.go index 626f6d18b8f..ea1fbd3968f 100644 --- a/pkg/apiserver/openapi/zz_generated.openapi.go +++ b/pkg/apiserver/openapi/zz_generated.openapi.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated // +build !ignore_autogenerated -// Copyright 2023 Antrea Authors +// Copyright 2024 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -4997,6 +4997,13 @@ func schema_pkg_apis_crd_v1beta1_Observation(ref common.ReferenceCallback) commo Format: "", }, }, + "egressNode": { + SchemaProps: spec.SchemaProps{ + Description: "EgressNode is the name of the Egress Node.", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 5fa821da9ea..6285dfe04a8 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -62,7 +62,7 @@ type ControllerNetworkPolicyInfoQuerier interface { type EgressQuerier interface { GetEgressIPByMark(mark uint32) (string, error) - GetEgress(podNamespace, podName string) (string, string, error) + GetEgress(podNamespace, podName string) (string, string, string, error) } // GetSelfPod gets current pod. diff --git a/pkg/querier/testing/mock_querier.go b/pkg/querier/testing/mock_querier.go index 7d8f165ecb6..03541e73b4a 100644 --- a/pkg/querier/testing/mock_querier.go +++ b/pkg/querier/testing/mock_querier.go @@ -1,4 +1,4 @@ -// Copyright 2023 Antrea Authors +// Copyright 2024 Antrea Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -302,13 +302,14 @@ func (m *MockEgressQuerier) EXPECT() *MockEgressQuerierMockRecorder { } // GetEgress mocks base method. -func (m *MockEgressQuerier) GetEgress(arg0, arg1 string) (string, string, error) { +func (m *MockEgressQuerier) GetEgress(arg0, arg1 string) (string, string, string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetEgress", arg0, arg1) ret0, _ := ret[0].(string) ret1, _ := ret[1].(string) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 + ret2, _ := ret[2].(string) + ret3, _ := ret[3].(error) + return ret0, ret1, ret2, ret3 } // GetEgress indicates an expected call of GetEgress. diff --git a/test/e2e/traceflow_test.go b/test/e2e/traceflow_test.go index 38aff071c54..98bc03e52f4 100644 --- a/test/e2e/traceflow_test.go +++ b/test/e2e/traceflow_test.go @@ -2118,10 +2118,11 @@ func testTraceflowEgress(t *testing.T, data *TestData) { Action: v1beta1.ActionForwarded, }, { - Component: v1beta1.ComponentEgress, - Action: v1beta1.ActionMarkedForSNAT, - Egress: egress.Name, - EgressIP: egressIP, + Component: v1beta1.ComponentEgress, + Action: v1beta1.ActionMarkedForSNAT, + Egress: egress.Name, + EgressIP: egressIP, + EgressNode: egressNode, }, { Component: v1beta1.ComponentForwarding, @@ -2189,10 +2190,11 @@ func testTraceflowEgress(t *testing.T, data *TestData) { Action: v1beta1.ActionForwarded, }, { - Component: v1beta1.ComponentEgress, - Action: v1beta1.ActionForwardedToEgressNode, - Egress: egress.Name, - EgressIP: egressIP, + Component: v1beta1.ComponentEgress, + Action: v1beta1.ActionForwardedToEgressNode, + Egress: egress.Name, + EgressIP: egressIP, + EgressNode: egressNode, }, { Component: v1beta1.ComponentForwarding, @@ -2345,6 +2347,7 @@ func compareObservations(expected v1beta1.NodeResult, actual v1beta1.NodeResult) exObs[i].TranslatedDstIP != acObs[i].TranslatedDstIP || exObs[i].EgressIP != acObs[i].EgressIP || exObs[i].Egress != acObs[i].Egress || + exObs[i].EgressNode != acObs[i].EgressNode || exObs[i].Action != acObs[i].Action || exObs[i].NetworkPolicy != acObs[i].NetworkPolicy || exObs[i].NetworkPolicyRule != acObs[i].NetworkPolicyRule {