Skip to content

Commit

Permalink
connectivity: add pod to external with DNS case in EGW scenario
Browse files Browse the repository at this point in the history
This test case checks if the traffic selected by an egress
gateway policy is masqueraded with an Egress IP when the clients
send a request using DNS.

The case is mainly to check the compatibility of Egress Gateway
and L7 policy.

Signed-off-by: Yusuke Suzuki <[email protected]>
  • Loading branch information
ysksuzuki committed Jun 6, 2024
1 parent d1d236e commit 9286aaa
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 13 deletions.
30 changes: 18 additions & 12 deletions connectivity/check/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,19 @@ type ConnectivityTest struct {
// Clients for source and destination clusters.
clients *deploymentClients

ciliumPods map[string]Pod
echoPods map[string]Pod
echoExternalPods map[string]Pod
clientPods map[string]Pod
clientCPPods map[string]Pod
perfClientPods []Pod
perfServerPod []Pod
PerfResults []common.PerfSummary
echoServices map[string]Service
ingressService map[string]Service
k8sService Service
externalWorkloads map[string]ExternalWorkload
ciliumPods map[string]Pod
echoPods map[string]Pod
echoExternalPods map[string]Pod
clientPods map[string]Pod
clientCPPods map[string]Pod
perfClientPods []Pod
perfServerPod []Pod
PerfResults []common.PerfSummary
echoServices map[string]Service
echoExternalServices map[string]Service
ingressService map[string]Service
k8sService Service
externalWorkloads map[string]ExternalWorkload

hostNetNSPodsByNode map[string]Pod
secondaryNetworkNodeIPv4 map[string]string // node name => secondary ip
Expand Down Expand Up @@ -207,6 +208,7 @@ func NewConnectivityTest(client *k8s.Client, p Parameters, version string, logge
perfServerPod: []Pod{},
PerfResults: []common.PerfSummary{},
echoServices: make(map[string]Service),
echoExternalServices: make(map[string]Service),
ingressService: make(map[string]Service),
externalWorkloads: make(map[string]ExternalWorkload),
hostNetNSPodsByNode: make(map[string]Pod),
Expand Down Expand Up @@ -1131,6 +1133,10 @@ func (ct *ConnectivityTest) EchoServicesAll() map[string]Service {
return ct.echoServices
}

func (ct *ConnectivityTest) EchoExternalServices() map[string]Service {
return ct.echoExternalServices
}

func (ct *ConnectivityTest) ExternalEchoPods() map[string]Pod {
return ct.echoExternalPods
}
Expand Down
21 changes: 21 additions & 0 deletions connectivity/check/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,16 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error {
if err != nil {
return fmt.Errorf("unable to create deployment %s: %s", echoExternalNodeDeploymentName, err)
}

svc := newService(echoExternalNodeDeploymentName,
map[string]string{"name": echoExternalNodeDeploymentName, "kind": kindEchoExternalNodeName},
map[string]string{"kind": kindEchoExternalNodeName}, "http", 8080)
svc.Spec.ClusterIP = corev1.ClusterIPNone
svc.Spec.Type = corev1.ServiceTypeClusterIP
_, err := ct.clients.src.CreateService(ctx, ct.params.TestNamespace, svc, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("unable to create service %s: %w", echoExternalNodeDeploymentName, err)
}
}
} else {
ct.Infof("Skipping tests that require a node Without Cilium")
Expand Down Expand Up @@ -1243,6 +1253,17 @@ func (ct *ConnectivityTest) validateDeployment(ctx context.Context) error {
port: uint32(ct.Params().ExternalDeploymentPort), // listen port of the echo server inside the container
}
}

echoExternalServices, err := ct.clients.dst.ListServices(ctx, ct.params.TestNamespace, metav1.ListOptions{LabelSelector: "kind=" + kindEchoExternalNodeName})
if err != nil {
return fmt.Errorf("unable to list echo external services: %w", err)
}

for _, echoExternalService := range echoExternalServices.Items {
ct.echoExternalServices[echoExternalService.Name] = Service{
Service: echoExternalService.DeepCopy(),
}
}
}

for _, cp := range ct.clientPods {
Expand Down
16 changes: 15 additions & 1 deletion connectivity/check/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (s Service) Path() string {
// Address returns the network address of the Service.
func (s Service) Address(family features.IPFamily) string {
// If the cluster IP is empty (headless service case) or the IP family is set to any, return the service name
if s.Service.Spec.ClusterIP == "" || family == features.IPFamilyAny {
if s.Service.Spec.ClusterIP == "" || s.Service.Spec.ClusterIP == corev1.ClusterIPNone || family == features.IPFamilyAny {
return fmt.Sprintf("%s.%s", s.Service.Name, s.Service.Namespace)
}

Expand Down Expand Up @@ -256,6 +256,12 @@ func (s Service) ToNodeportService(node *corev1.Node) NodeportService {
}
}

func (s Service) ToEchoIPService() EchoIPService {
return EchoIPService{
Service: s,
}
}

// NodeportService wraps a Service and exposes it through its nodeport, acting as a peer in a connectivity test.
// It implements interface TestPeer.
type NodeportService struct {
Expand Down Expand Up @@ -499,3 +505,11 @@ type EchoIPPod struct {
func (p EchoIPPod) Path() string {
return p.path + "/client-ip"
}

type EchoIPService struct {
Service
}

func (s EchoIPService) Path() string {
return s.URLPath + "/client-ip"
}
20 changes: 20 additions & 0 deletions connectivity/tests/egressgateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,26 @@ func (s *egressGateway) Run(ctx context.Context, t *check.Test) {
i++
}

// Traffic matching an egress gateway policy should leave the cluster masqueraded with the egress IP (pod to external service using DNS)
i = 0
for _, client := range ct.ClientPods() {
client := client

for _, externalEchoSvc := range ct.EchoExternalServices() {
externalEcho := externalEchoSvc.ToEchoIPService()

t.NewAction(s, fmt.Sprintf("curl-external-echo-service-%d", i), &client, externalEcho, features.IPFamilyV4).Run(func(a *check.Action) {
a.ExecInPod(ctx, ct.CurlCommandWithOutput(externalEcho, features.IPFamilyV4, "-4"))
clientIP := extractClientIPFromResponse(a.CmdOutput())

if !clientIP.Equal(egressGatewayNodeInternalIP) {
t.Fatal("Request reached external echo service with wrong source IP")
}
})
i++
}
}

// Traffic matching an egress gateway policy should leave the cluster masqueraded with the egress IP (pod to external service)
i = 0
for _, client := range ct.ClientPods() {
Expand Down

0 comments on commit 9286aaa

Please sign in to comment.