From 4cf3c9c6d34f6d7c62c2f4c490add190638bd32b Mon Sep 17 00:00:00 2001 From: RamiBerm <54766858+RamiBerm@users.noreply.github.com> Date: Mon, 8 Nov 2021 11:23:03 +0200 Subject: [PATCH] TRA-3913 support mizu via expose service (#440) * Update README.md, tapRunner.go, and 4 more files... * Update testsUtils.go * Update proxy.go * Update README.md, testsUtils.go, and 3 more files... * Update testsUtils.go and provider.go --- README.md | 48 +++++++++++++++++++++++++++++++++-- acceptanceTests/testsUtils.go | 2 +- shared/kubernetes/provider.go | 39 ++++++++++++++-------------- shared/kubernetes/proxy.go | 15 +++++++---- ui/src/helpers/api.js | 6 ++--- 5 files changed, 78 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 3c31c489e..8d3c38a4a 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ To tap all pods in current namespace - ``` -To tap specific pod - +###To tap specific pod ```bash $ kubectl get pods NAME READY STATUS RESTARTS AGE @@ -96,7 +96,7 @@ To tap specific pod - ^C ``` -To tap multiple pods using regex - +###To tap multiple pods using regex ```bash $ kubectl get pods NAME READY STATUS RESTARTS AGE @@ -111,6 +111,50 @@ To tap multiple pods using regex - Web interface is now available at http://localhost:8899 ^C ``` +###To run mizu mizu daemon mode (detached from cli) +```bash +$ mizu tap "^ca.*" --daemon + Mizu will store up to 200MB of traffic, old traffic will be cleared once the limit is reached. + Tapping pods in namespaces "sock-shop" + Waiting for mizu to be ready... (may take a few minutes) + +carts-66c77f5fbb-fq65r + +catalogue-5f4cb7cf5-7zrmn + .. + +$ mizu view + Establishing connection to k8s cluster... + Mizu is available at http://localhost:8899 + ^C + .. + +$ mizu clean # mizu will continue running in cluster until clean is executed + Removing mizu resources +``` + + + +###To run mizu daemon mode with LoadBalancer kubernetes service +```bash +$ mizu tap "^ca.*" --daemon + Mizu will store up to 200MB of traffic, old traffic will be cleared once the limit is reached. + Tapping pods in namespaces "sock-shop" + Waiting for mizu to be ready... (may take a few minutes) + .. + +$ kubectl expose deployment -n mizu --port 80 --target-port 8899 mizu-api-server --type=LoadBalancer --name=mizu-lb + service/mizu-lb exposed + .. + +$ kubectl get services -n mizu + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + mizu-api-server ClusterIP 10.107.200.100 80/TCP 5m5s + mizu-lb LoadBalancer 10.107.200.101 34.77.120.116 80:30141/TCP 76s +``` +Note that `LoadBalancer` services only work on supported clusters (usually cloud providers) and might incur extra costs + +If you changed the `mizu-resources-namespace` value, make sure the `-n mizu` flag of the `kubectl expose` command is changed to the value of `mizu-resources-namespace` + +mizu will now be available both by running `mizu view` or by accessing the `EXTERNAL-IP` of the `mizu-lb` service through your browser. ## Configuration diff --git a/acceptanceTests/testsUtils.go b/acceptanceTests/testsUtils.go index 3569eb375..6b6681603 100644 --- a/acceptanceTests/testsUtils.go +++ b/acceptanceTests/testsUtils.go @@ -79,7 +79,7 @@ func getProxyUrl(namespace string, service string) string { } func getApiServerUrl(port uint16) string { - return fmt.Sprintf("http://localhost:%v/mizu", port) + return fmt.Sprintf("http://localhost:%v", port) } func getDefaultCommandArgs() []string { diff --git a/shared/kubernetes/provider.go b/shared/kubernetes/provider.go index 2df6385c6..06538f4c2 100644 --- a/shared/kubernetes/provider.go +++ b/shared/kubernetes/provider.go @@ -241,8 +241,8 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun }, }) volumeMounts = append(volumeMounts, core.VolumeMount{ - Name: volumeClaimName, - MountPath: shared.DataDirPath, + Name: volumeClaimName, + MountPath: shared.DataDirPath, }) } @@ -255,8 +255,8 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun pod := &core.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: opts.PodName, - Labels: map[string]string{"app": opts.PodName}, + Name: opts.PodName, + Labels: map[string]string{"app": opts.PodName}, }, Spec: core.PodSpec{ Containers: []core.Container{ @@ -264,8 +264,8 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun Name: opts.PodName, Image: opts.PodImage, ImagePullPolicy: opts.ImagePullPolicy, - VolumeMounts: volumeMounts, - Command: command, + VolumeMounts: volumeMounts, + Command: command, Env: []core.EnvVar{ { Name: shared.SyncEntriesConfigEnvVar, @@ -307,7 +307,7 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun }, }, }, - Volumes: volumes, + Volumes: volumes, DNSPolicy: core.DNSClusterFirstWithHostNet, TerminationGracePeriodSeconds: new(int64), }, @@ -320,7 +320,6 @@ func (provider *Provider) GetMizuApiServerPodObject(opts *ApiServerOptions, moun return pod, nil } - func (provider *Provider) CreatePod(ctx context.Context, namespace string, podSpec *core.Pod) (*core.Pod, error) { return provider.clientSet.CoreV1().Pods(namespace).Create(ctx, podSpec, metav1.CreateOptions{}) } @@ -335,14 +334,14 @@ func (provider *Provider) CreateDeployment(ctx context.Context, namespace string } deployment := &v1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: deploymentName, + Name: deploymentName, }, Spec: v1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"app": podSpec.ObjectMeta.Labels["app"]}, }, - Template: *podTemplate, - Strategy: v1.DeploymentStrategy{}, + Template: *podTemplate, + Strategy: v1.DeploymentStrategy{}, }, } return provider.clientSet.AppsV1().Deployments(namespace).Create(ctx, deployment, metav1.CreateOptions{}) @@ -351,7 +350,7 @@ func (provider *Provider) CreateDeployment(ctx context.Context, namespace string func (provider *Provider) CreateService(ctx context.Context, namespace string, serviceName string, appLabelValue string) (*core.Service, error) { service := core.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, + Name: serviceName, }, Spec: core.ServiceSpec{ Ports: []core.ServicePort{{TargetPort: intstr.FromInt(shared.DefaultApiServerPort), Port: 80}}, @@ -383,8 +382,8 @@ func (provider *Provider) doesResourceExist(resource interface{}, err error) (bo func (provider *Provider) CreateMizuRBAC(ctx context.Context, namespace string, serviceAccountName string, clusterRoleName string, clusterRoleBindingName string, version string) error { serviceAccount := &core.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Name: serviceAccountName, - Labels: map[string]string{"mizu-cli-version": version}, + Name: serviceAccountName, + Labels: map[string]string{"mizu-cli-version": version}, }, } clusterRole := &rbac.ClusterRole{ @@ -436,8 +435,8 @@ func (provider *Provider) CreateMizuRBAC(ctx context.Context, namespace string, func (provider *Provider) CreateMizuRBACNamespaceRestricted(ctx context.Context, namespace string, serviceAccountName string, roleName string, roleBindingName string, version string) error { serviceAccount := &core.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Name: serviceAccountName, - Labels: map[string]string{"mizu-cli-version": version}, + Name: serviceAccountName, + Labels: map[string]string{"mizu-cli-version": version}, }, } role := &rbac.Role{ @@ -610,7 +609,7 @@ func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, + Name: configMapName, }, Data: configMapData, } @@ -853,9 +852,9 @@ func (provider *Provider) CreatePersistentVolumeClaim(ctx context.Context, names ObjectMeta: metav1.ObjectMeta{ Name: volumeClaimName, }, - Spec: core.PersistentVolumeClaimSpec{ - AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce}, - Resources: core.ResourceRequirements{ + Spec: core.PersistentVolumeClaimSpec{ + AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce}, + Resources: core.ResourceRequirements{ Limits: core.ResourceList{ core.ResourceStorage: *sizeLimitQuantity, }, diff --git a/shared/kubernetes/proxy.go b/shared/kubernetes/proxy.go index cfb69e4db..138bce331 100644 --- a/shared/kubernetes/proxy.go +++ b/shared/kubernetes/proxy.go @@ -28,9 +28,9 @@ func StartProxy(kubernetesProvider *Provider, proxyHost string, mizuPort uint16, return err } mux := http.NewServeMux() - mux.Handle(k8sProxyApiPrefix, proxyHandler) + mux.Handle(k8sProxyApiPrefix, getRerouteHttpHandlerMizuAPI(proxyHandler, mizuNamespace, mizuServiceName)) mux.Handle("/static/", getRerouteHttpHandlerMizuStatic(proxyHandler, mizuNamespace, mizuServiceName)) - mux.Handle("/mizu/", getRerouteHttpHandlerMizuAPI(proxyHandler, mizuNamespace, mizuServiceName)) + l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", proxyHost, int(mizuPort))) if err != nil { @@ -45,16 +45,21 @@ func StartProxy(kubernetesProvider *Provider, proxyHost string, mizuPort uint16, } func getMizuApiServerProxiedHostAndPath(mizuNamespace string, mizuServiceName string) string { - return fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%d/proxy/", mizuNamespace, mizuServiceName, mizuServicePort) + return fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%d/proxy", mizuNamespace, mizuServiceName, mizuServicePort) } func GetMizuApiServerProxiedHostAndPath(mizuPort uint16) string { - return fmt.Sprintf("localhost:%d/mizu", mizuPort) + return fmt.Sprintf("localhost:%d", mizuPort) } func getRerouteHttpHandlerMizuAPI(proxyHandler http.Handler, mizuNamespace string, mizuServiceName string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - r.URL.Path = strings.Replace(r.URL.Path, "/mizu/", getMizuApiServerProxiedHostAndPath(mizuNamespace, mizuServiceName), 1) + proxiedPath := getMizuApiServerProxiedHostAndPath(mizuNamespace, mizuServiceName) + + //avoid redirecting several times + if !strings.Contains(r.URL.Path, proxiedPath) { + r.URL.Path = fmt.Sprintf("%s%s", getMizuApiServerProxiedHostAndPath(mizuNamespace, mizuServiceName), r.URL.Path) + } proxyHandler.ServeHTTP(w, r) }) } diff --git a/ui/src/helpers/api.js b/ui/src/helpers/api.js index 216b5b0c4..3e6d1de65 100644 --- a/ui/src/helpers/api.js +++ b/ui/src/helpers/api.js @@ -1,16 +1,14 @@ import * as axios from "axios"; -const mizuAPIPathPrefix = "/mizu"; - // When working locally cp `cp .env.example .env` -export const MizuWebsocketURL = process.env.REACT_APP_OVERRIDE_WS_URL ? process.env.REACT_APP_OVERRIDE_WS_URL : `ws://${window.location.host}${mizuAPIPathPrefix}/ws`; +export const MizuWebsocketURL = process.env.REACT_APP_OVERRIDE_WS_URL ? process.env.REACT_APP_OVERRIDE_WS_URL : `ws://${window.location.host}/ws`; export default class Api { constructor() { // When working locally cp `cp .env.example .env` - const apiURL = process.env.REACT_APP_OVERRIDE_API_URL ? process.env.REACT_APP_OVERRIDE_API_URL : `${window.location.origin}${mizuAPIPathPrefix}/`; + const apiURL = process.env.REACT_APP_OVERRIDE_API_URL ? process.env.REACT_APP_OVERRIDE_API_URL : `${window.location.origin}/`; this.client = axios.create({ baseURL: apiURL,