Skip to content

Commit

Permalink
connectivity: add endpointslice clustermesh sync test
Browse files Browse the repository at this point in the history
This adds endpointslice synchronization testing inside a clustermesh.
It does that by checking that we can get a DNS answer with a global
headless service with endpointslice synchronization enabled across two clusters.

Testing it via DNS ensures that the created EndpointSlice are correctly
linked to the headless service.

Signed-off-by: Arthur Outhenin-Chalandre <[email protected]>
  • Loading branch information
MrFreezeex committed Jan 28, 2024
1 parent 6f49f30 commit 7d82a98
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 10 deletions.
6 changes: 6 additions & 0 deletions connectivity/check/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,12 @@ func (ct *ConnectivityTest) DigCommand(peer TestPeer, ipFam features.IPFamily) [
return cmd
}

func (ct *ConnectivityTest) DigCommandService(peer TestPeer) []string {
cmd := []string{"dig", "+time=2", peer.Name()}

return cmd
}

func (ct *ConnectivityTest) RandomClientPod() *Pod {
for _, p := range ct.clientPods {
return &p
Expand Down
40 changes: 31 additions & 9 deletions connectivity/check/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ const (

DNSTestServerContainerName = "dns-test-server"

echoSameNodeDeploymentName = "echo-same-node"
echoOtherNodeDeploymentName = "echo-other-node"
echoExternalNodeDeploymentName = "echo-external-node"
corednsConfigMapName = "coredns-configmap"
corednsConfigVolumeName = "coredns-config-volume"
kindEchoName = "echo"
kindEchoExternalNodeName = "echo-external-node"
kindClientName = "client"
kindPerfName = "perf"
echoSameNodeDeploymentName = "echo-same-node"
echoOtherNodeDeploymentName = "echo-other-node"
echoOtherNodeDeploymentHeadlessServiceName = "echo-other-node-headless"
echoExternalNodeDeploymentName = "echo-external-node"
corednsConfigMapName = "coredns-configmap"
corednsConfigVolumeName = "coredns-config-volume"
kindEchoName = "echo"
kindEchoExternalNodeName = "echo-external-node"
kindClientName = "client"
kindPerfName = "perf"

hostNetNSDeploymentName = "host-netns"
hostNetNSDeploymentNameNonCilium = "host-netns-non-cilium" // runs on non-Cilium test nodes
Expand Down Expand Up @@ -532,6 +533,16 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error {
if err != nil {
return err
}

svcHeadless := svc.DeepCopy()
svcHeadless.Name = echoOtherNodeDeploymentHeadlessServiceName
svcHeadless.Spec.ClusterIP = corev1.ClusterIPNone
svcHeadless.Spec.Type = corev1.ServiceTypeClusterIP
svcHeadless.ObjectMeta.Annotations["service.cilium.io/global-sync-endpoint-slices"] = "true"
_, err = ct.clients.src.CreateService(ctx, ct.params.TestNamespace, svcHeadless, metav1.CreateOptions{})
if err != nil {
return err
}
}
}

Expand Down Expand Up @@ -745,6 +756,16 @@ func (ct *ConnectivityTest) deploy(ctx context.Context) error {
svc.ObjectMeta.Annotations = map[string]string{}
svc.ObjectMeta.Annotations["service.cilium.io/global"] = "true"
svc.ObjectMeta.Annotations["io.cilium/global-service"] = "true"

svcHeadless := svc.DeepCopy()
svcHeadless.Name = echoOtherNodeDeploymentHeadlessServiceName
svcHeadless.Spec.ClusterIP = corev1.ClusterIPNone
svcHeadless.Spec.Type = corev1.ServiceTypeClusterIP
svcHeadless.ObjectMeta.Annotations["service.cilium.io/global-sync-endpoint-slices"] = "true"
_, err = ct.clients.dst.CreateService(ctx, ct.params.TestNamespace, svcHeadless, metav1.CreateOptions{})
if err != nil {
return err
}
}

_, err = ct.clients.dst.CreateService(ctx, ct.params.TestNamespace, svc, metav1.CreateOptions{})
Expand Down Expand Up @@ -1075,6 +1096,7 @@ func (ct *ConnectivityTest) deleteDeployments(ctx context.Context, client *k8s.C
_ = client.DeleteServiceAccount(ctx, ct.params.TestNamespace, client3DeploymentName, metav1.DeleteOptions{})
_ = client.DeleteService(ctx, ct.params.TestNamespace, echoSameNodeDeploymentName, metav1.DeleteOptions{})
_ = client.DeleteService(ctx, ct.params.TestNamespace, echoOtherNodeDeploymentName, metav1.DeleteOptions{})
_ = client.DeleteService(ctx, ct.params.TestNamespace, echoOtherNodeDeploymentHeadlessServiceName, metav1.DeleteOptions{})
_ = client.DeleteConfigMap(ctx, ct.params.TestNamespace, corednsConfigMapName, metav1.DeleteOptions{})
_ = client.DeleteNamespace(ctx, ct.params.TestNamespace, metav1.DeleteOptions{})

Expand Down
6 changes: 5 additions & 1 deletion connectivity/check/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/cilium/cilium/api/v1/models"
"golang.org/x/exp/slices"
corev1 "k8s.io/api/core/v1"

"github.com/cilium/cilium-cli/defaults"
"github.com/cilium/cilium-cli/k8s"
Expand Down Expand Up @@ -149,7 +150,7 @@ func WaitForService(ctx context.Context, log Logger, client Pod, service Service
// Lookup successful.
if err == nil {
svcIP := service.Service.Spec.ClusterIP
if svcIP == "" {
if svcIP == "" || svcIP == corev1.ClusterIPNone {
return nil
}

Expand Down Expand Up @@ -224,6 +225,9 @@ func checkServiceEndpoints(ctx context.Context, agent Pod, service Service, back
}

for _, ip := range service.Service.Spec.ClusterIPs {
if ip == corev1.ClusterIPNone {
continue
}
addr, err := netip.ParseAddr(ip)
if err != nil {
return fmt.Errorf("failed to parse ClusterIP %q: %w", ip, err)
Expand Down
7 changes: 7 additions & 0 deletions connectivity/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,13 @@ func Run(ctx context.Context, ct *check.ConnectivityTest, addExtraTests func(*ch
ct.NewTest("check-log-errors").WithScenarios(tests.NoErrorsInLogs(ct.CiliumVersion))
}

if versioncheck.MustCompile(">=1.16.0")(ct.CiliumVersion) && ct.Params().MultiCluster != "" {
ct.NewTest("endpointslice-mesh").
WithScenarios(
tests.EndpointSliceMesh(),
)
}

return ct.Run(ctx)
}

Expand Down
46 changes: 46 additions & 0 deletions connectivity/tests/endpointslicemesh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package tests

import (
"context"
"fmt"

"github.com/cilium/cilium-cli/connectivity/check"
"github.com/cilium/cilium-cli/utils/features"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func EndpointSliceMesh() check.Scenario {
return &endpointSliceMesh{}
}

type endpointSliceMesh struct{}

func (s *endpointSliceMesh) Name() string {
return "endpointslice-mesh"
}

func (s *endpointSliceMesh) Run(ctx context.Context, t *check.Test) {
ct := t.Context()

// Ping hosts (pod to host connectivity). Should not get masqueraded with egress IP
i := 0
for _, client := range ct.ClientPods() {
client := client // copy to avoid memory aliasing when using reference

kubeService, err := ct.K8sClient().GetService(ctx, ct.Params().TestNamespace, "echo-other-node-headless", metav1.GetOptions{})
if err != nil {
t.Fatal("Cannot get echo-other-node-headless service")
}
service := check.Service{Service: kubeService}
fmt.Println("todo", kubeService)

t.NewAction(s, fmt.Sprintf("dig-%d", i), &client, service, features.IPFamilyV4).Run(func(a *check.Action) {
a.ExecInPod(ctx, ct.DigCommandService(service))
})
i++
}
}

0 comments on commit 7d82a98

Please sign in to comment.