From: Adrian Villin Date: Fri, 25 Jul 2025 14:11:20 +0000 (+0200) Subject: hs-test: add nginx mirroring KinD test, cleanup X-Git-Tag: v26.02-rc0~142 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F87%2F43387%2F4;p=vpp.git hs-test: add nginx mirroring KinD test, cleanup Type: test Change-Id: I15e145023226ea0d442f69e42da4cdc586366873 Signed-off-by: Adrian Villin --- diff --git a/extras/hs-test/infra/kind/deployment.go b/extras/hs-test/infra/kind/deployment.go index 64040565009..20fc6c80c3e 100644 --- a/extras/hs-test/infra/kind/deployment.go +++ b/extras/hs-test/infra/kind/deployment.go @@ -49,6 +49,7 @@ func (s *KindSuite) deleteNamespace(namespace string) error { } func (s *KindSuite) DeployPod(pod *Pod) { + pod.suite = s s.CurrentlyRunning = append(s.CurrentlyRunning, pod.Name) pod.CreatedPod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -100,5 +101,5 @@ func (s *KindSuite) DeployPod(pod *Pod) { } } - s.Log("IP: %s", pod.IpAddress) + s.Log("IP: %s\n", pod.IpAddress) } diff --git a/extras/hs-test/infra/kind/pod.go b/extras/hs-test/infra/kind/pod.go index 1b37047149b..f323130af21 100644 --- a/extras/hs-test/infra/kind/pod.go +++ b/extras/hs-test/infra/kind/pod.go @@ -1,8 +1,20 @@ package hst_kind -import corev1 "k8s.io/api/core/v1" +import ( + "bytes" + "context" + "os" + "os/exec" + "text/template" + "time" + + . "fd.io/hs-test/infra/common" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/remotecommand" +) type Pod struct { + suite *KindSuite Name string Image string ContainerName string @@ -21,6 +33,7 @@ func (s *KindSuite) initPods() { clientCont := "client" serverCont := "server" + // TODO: load from file s.images = append(s.images, vppImg, nginxLdpImg, abImg) s.Namespace = "namespace" + s.Ppid @@ -47,4 +60,74 @@ func (s *KindSuite) initPods() { s.Pods.Nginx.Image = nginxLdpImg s.Pods.Nginx.ContainerName = serverCont s.Pods.Nginx.Worker = wrk2 + + s.Pods.NginxProxy = new(Pod) + s.Pods.NginxProxy.Name = "nginx-proxy" + s.Ppid + s.Pods.NginxProxy.Image = nginxLdpImg + s.Pods.NginxProxy.ContainerName = serverCont + s.Pods.NginxProxy.Worker = wrk2 +} + +func (pod *Pod) CopyToPod(namespace string, src string, dst string) { + cmd := exec.Command("kubectl", "--kubeconfig="+pod.suite.KubeconfigPath, "cp", src, namespace+"/"+pod.Name+":"+dst) + out, err := cmd.CombinedOutput() + pod.suite.AssertNil(err, string(out)) +} + +func (pod *Pod) Exec(command []string) (string, error) { + var stdout, stderr bytes.Buffer + + // Prepare the request + req := pod.suite.ClientSet.CoreV1().RESTClient().Post(). + Resource("pods"). + Name(pod.Name). + Namespace(pod.suite.Namespace). + SubResource("exec"). + Param("container", pod.ContainerName). + Param("stdout", "true"). + Param("stderr", "true"). + Param("tty", "true") + + for _, cmd := range command { + req = req.Param("command", cmd) + } + pod.suite.Log("%s: %s\n", pod.Name, command) + + executor, err := remotecommand.NewSPDYExecutor(pod.suite.Config, "POST", req.URL()) + if err != nil { + pod.suite.Log("Error creating executor: %s", err.Error()) + } + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Second) + defer cancel() + + err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{ + Stdout: &stdout, + Stderr: &stderr, + Tty: true, + }) + + output := stdout.String() + stderr.String() + + if err != nil { + return output, err + } + + return output, nil +} + +func (pod *Pod) CreateConfigFromTemplate(targetConfigName string, templateName string, values any) { + template := template.Must(template.ParseFiles(templateName)) + + f, err := os.CreateTemp(LogDir, "hst-config") + pod.suite.AssertNil(err, err) + defer os.Remove(f.Name()) + + err = template.Execute(f, values) + pod.suite.AssertNil(err, err) + + err = f.Close() + pod.suite.AssertNil(err, err) + + pod.CopyToPod(pod.suite.Namespace, f.Name(), targetConfigName) } diff --git a/extras/hs-test/infra/kind/suite_kind.go b/extras/hs-test/infra/kind/suite_kind.go index 45b24fc3cfb..1754853f789 100644 --- a/extras/hs-test/infra/kind/suite_kind.go +++ b/extras/hs-test/infra/kind/suite_kind.go @@ -2,12 +2,10 @@ package hst_kind import ( "fmt" - "os" "reflect" "regexp" "runtime" "strings" - "text/template" . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" @@ -30,12 +28,32 @@ type KindSuite struct { ServerGeneric *Pod ClientGeneric *Pod Nginx *Pod + NginxProxy *Pod Ab *Pod } } var kindTests = map[string][]func(s *KindSuite){} +const VclConfIperf = "echo \"vcl {\n" + + "rx-fifo-size 4000000\n" + + "tx-fifo-size 4000000\n" + + "app-scope-local\n" + + "app-scope-global\n" + + "app-socket-api abstract:vpp/session\n" + + "}\" > /vcl.conf" + +const VclConfNginx = "echo \"vcl {\n" + + "heapsize 64M\n" + + "rx-fifo-size 4000000\n" + + "tx-fifo-size 4000000\n" + + "segment-size 4000000000\n" + + "add-segment-size 4000000000\n" + + "event-queue-size 100000\n" + + "use-mq-eventfd\n" + + "app-socket-api abstract:vpp/session\n" + + "}\" > /vcl.conf" + func RegisterKindTests(tests ...func(s *KindSuite)) { kindTests[GetTestFilename()] = tests } @@ -74,6 +92,7 @@ func (s *KindSuite) SetupSuite() { func (s *KindSuite) TeardownTest() { s.HstCommon.TeardownTest() if len(s.CurrentlyRunning) != 0 { + s.Log("Removing:") for _, pod := range s.CurrentlyRunning { s.Log(" %s", pod) s.deletePod(s.Namespace, pod) @@ -83,7 +102,7 @@ func (s *KindSuite) TeardownTest() { func (s *KindSuite) TeardownSuite() { s.HstCommon.TeardownSuite() - s.Log(" %s", s.Namespace) + s.Log("Removing:\n %s", s.Namespace) s.AssertNil(s.deleteNamespace(s.Namespace)) } @@ -91,7 +110,7 @@ func (s *KindSuite) TeardownSuite() { // and searches for the first version string, then creates symlinks. func (s *KindSuite) FixVersionNumber(pods ...*Pod) { regex := regexp.MustCompile(`lib.*\.so\.([0-9]+\.[0-9]+)`) - o, _ := s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c", + o, _ := s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c", "ldd /usr/lib/libvcl_ldpreload.so"}) match := regex.FindStringSubmatch(o) @@ -106,7 +125,7 @@ func (s *KindSuite) FixVersionNumber(pods ...*Pod) { "fi\n"+ "done", version) for _, pod := range pods { - s.Exec(pod, []string{"/bin/bash", "-c", cmd}) + pod.Exec([]string{"/bin/bash", "-c", cmd}) } } else { @@ -114,23 +133,7 @@ func (s *KindSuite) FixVersionNumber(pods ...*Pod) { } } -func (s *KindSuite) CreateConfigFromTemplate(targetConfigName string, templateName string, values any) { - template := template.Must(template.ParseFiles(templateName)) - - f, err := os.CreateTemp(LogDir, "hst-config") - s.AssertNil(err, err) - defer os.Remove(f.Name()) - - err = template.Execute(f, values) - s.AssertNil(err, err) - - err = f.Close() - s.AssertNil(err, err) - - s.CopyToPod(s.Pods.Nginx.Name, s.Namespace, f.Name(), targetConfigName) -} - -func (s *KindSuite) CreateNginxConfig() { +func (s *KindSuite) CreateNginxConfig(pod *Pod) { values := struct { Workers uint8 Port uint16 @@ -138,13 +141,41 @@ func (s *KindSuite) CreateNginxConfig() { Workers: 1, Port: 8081, } - s.CreateConfigFromTemplate( + pod.CreateConfigFromTemplate( "/nginx.conf", "./resources/nginx/nginx.conf", values, ) } +func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) { + pod.Exec([]string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"}) + values := struct { + Workers uint8 + LogPrefix string + Proxy string + Server string + Port uint16 + Upstream1 string + Upstream2 string + Upstream3 string + }{ + Workers: 1, + LogPrefix: s.Pods.NginxProxy.Name, + Proxy: s.Pods.NginxProxy.IpAddress, + Server: s.Pods.Nginx.IpAddress, + Port: 8080, + Upstream1: "8081", + Upstream2: "8081", + Upstream3: "8081", + } + pod.CreateConfigFromTemplate( + "/nginx.conf", + "./resources/nginx/nginx_proxy_mirroring.conf", + values, + ) +} + var _ = Describe("KindSuite", Ordered, ContinueOnFailure, Label("Perf"), func() { var s KindSuite BeforeAll(func() { diff --git a/extras/hs-test/infra/kind/utils.go b/extras/hs-test/infra/kind/utils.go index d6f37194b8a..ea82085f324 100644 --- a/extras/hs-test/infra/kind/utils.go +++ b/extras/hs-test/infra/kind/utils.go @@ -1,62 +1,5 @@ package hst_kind -import ( - "bytes" - "context" - "os/exec" - "time" - - "k8s.io/client-go/tools/remotecommand" -) - -func (s *KindSuite) CopyToPod(podName string, namespace string, src string, dst string) { - cmd := exec.Command("kubectl", "--kubeconfig="+s.KubeconfigPath, "cp", src, namespace+"/"+podName+":"+dst) - out, err := cmd.CombinedOutput() - s.AssertNil(err, string(out)) -} - -func (s *KindSuite) Exec(pod *Pod, command []string) (string, error) { - var stdout, stderr bytes.Buffer - - // Prepare the request - req := s.ClientSet.CoreV1().RESTClient().Post(). - Resource("pods"). - Name(pod.Name). - Namespace(s.Namespace). - SubResource("exec"). - Param("container", pod.ContainerName). - Param("stdout", "true"). - Param("stderr", "true"). - Param("tty", "true") - - for _, cmd := range command { - req = req.Param("command", cmd) - } - s.Log("%s: %s", pod.Name, command) - - executor, err := remotecommand.NewSPDYExecutor(s.Config, "POST", req.URL()) - if err != nil { - s.Log("Error creating executor: %s", err.Error()) - } - - ctx, cancel := context.WithTimeout(context.Background(), 500*time.Second) - defer cancel() - - err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{ - Stdout: &stdout, - Stderr: &stderr, - Tty: true, - }) - - output := stdout.String() + stderr.String() - - if err != nil { - return output, err - } - - return output, nil -} - func boolPtr(b bool) *bool { return &b } diff --git a/extras/hs-test/kind_test.go b/extras/hs-test/kind_test.go index 0e0431d0c27..bc09fb7c3e4 100644 --- a/extras/hs-test/kind_test.go +++ b/extras/hs-test/kind_test.go @@ -8,7 +8,7 @@ import ( ) func init() { - RegisterKindTests(KindIperfVclTest, NginxRpsTest) + RegisterKindTests(KindIperfVclTest, NginxRpsTest, NginxProxyMirroringTest) } const vcl string = "VCL_CONFIG=/vcl.conf" @@ -18,58 +18,70 @@ func KindIperfVclTest(s *KindSuite) { s.DeployPod(s.Pods.ClientGeneric) s.DeployPod(s.Pods.ServerGeneric) - vclConf := "echo \"vcl {\n" + - "rx-fifo-size 4000000\n" + - "tx-fifo-size 4000000\n" + - "app-scope-local\n" + - "app-scope-global\n" + - "app-socket-api abstract:vpp/session\n" + - "}\" > /vcl.conf" - - _, err := s.Exec(s.Pods.ClientGeneric, []string{"/bin/bash", "-c", vclConf}) + _, err := s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf}) s.AssertNil(err) - _, err = s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c", vclConf}) + _, err = s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c", VclConfIperf}) s.AssertNil(err) s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric) - o, err := s.Exec(s.Pods.ServerGeneric, []string{"/bin/bash", "-c", + o, err := s.Pods.ServerGeneric.Exec([]string{"/bin/bash", "-c", vcl + " " + ldp + " iperf3 -s -D -4"}) s.AssertNil(err, o) - output, err := s.Exec(s.Pods.ClientGeneric, []string{"/bin/bash", "-c", + o, err = s.Pods.ClientGeneric.Exec([]string{"/bin/bash", "-c", vcl + " " + ldp + " iperf3 -l 1460 -b 10g -c " + s.Pods.ServerGeneric.IpAddress}) - s.Log(output) + s.Log(o) s.AssertNil(err) } func NginxRpsTest(s *KindSuite) { s.DeployPod(s.Pods.Nginx) s.DeployPod(s.Pods.Ab) - s.CreateNginxConfig() - - vclConf := "echo \"vcl {\n" + - "heapsize 64M\n" + - "rx-fifo-size 4000000\n" + - "tx-fifo-size 4000000\n" + - "segment-size 4000000000\n" + - "add-segment-size 4000000000\n" + - "event-queue-size 100000\n" + - "use-mq-eventfd\n" + - "app-socket-api abstract:vpp/session\n" + - "}\" > /vcl.conf" - - out, err := s.Exec(s.Pods.Nginx, []string{"/bin/bash", "-c", vclConf}) + s.CreateNginxConfig(s.Pods.Nginx) + + out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", VclConfNginx}) + s.AssertNil(err, out) + + go func() { + defer GinkgoRecover() + out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"}) + s.AssertNil(err, out) + }() + + // wait for nginx to start up + time.Sleep(time.Second * 2) + out, err = s.Pods.Ab.Exec([]string{"ab", "-k", "-r", "-n", "1000000", "-c", "1000", "http://" + s.Pods.Nginx.IpAddress + ":8081/64B.json"}) + s.Log(out) + s.AssertNil(err) +} + +func NginxProxyMirroringTest(s *KindSuite) { + s.DeployPod(s.Pods.Nginx) + s.DeployPod(s.Pods.NginxProxy) + s.DeployPod(s.Pods.ClientGeneric) + s.CreateNginxConfig(s.Pods.Nginx) + s.CreateNginxProxyConfig(s.Pods.NginxProxy) + + out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", VclConfNginx}) s.AssertNil(err, out) + out, err = s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", VclConfNginx}) + s.AssertNil(err, out) + + go func() { + defer GinkgoRecover() + out, err := s.Pods.Nginx.Exec([]string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"}) + s.AssertNil(err, out) + }() go func() { defer GinkgoRecover() - out, err := s.Exec(s.Pods.Nginx, []string{"/bin/bash", "-c", ldp + " " + vcl + " nginx -c /nginx.conf"}) + out, err := s.Pods.NginxProxy.Exec([]string{"/bin/bash", "-c", "nginx -c /nginx.conf"}) s.AssertNil(err, out) }() // wait for nginx to start up time.Sleep(time.Second * 2) - out, err = s.Exec(s.Pods.Ab, []string{"ab", "-k", "-r", "-n", "1000000", "-c", "1000", "http://" + s.Pods.Nginx.IpAddress + ":8081/64B.json"}) + out, err = s.Pods.ClientGeneric.Exec([]string{"curl", "-v", "--noproxy", "'*'", "--insecure", "http://" + s.Pods.NginxProxy.IpAddress + ":8080/64B.json"}) s.Log(out) s.AssertNil(err) } diff --git a/extras/hs-test/kubernetes/setupCluster.sh b/extras/hs-test/kubernetes/setupCluster.sh index 3c176f6e98b..4eba189fba1 100755 --- a/extras/hs-test/kubernetes/setupCluster.sh +++ b/extras/hs-test/kubernetes/setupCluster.sh @@ -67,7 +67,7 @@ setup_master() { make -C $CALICOVPP_DIR kind-new-cluster N_KIND_WORKERS=2 kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.3/manifests/tigera-operator.yaml make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=origin/master VPP_DIR=$VPP_DIR - make build-vpp-release + make -C $VPP_DIR/extras/hs-test build-vpp-release make -C $CALICOVPP_DIR dev-kind make -C $CALICOVPP_DIR load-kind $CALICOVPP_DIR/yaml/overlays/dev/kustomize.sh up