diff --git a/.circleci/config.yml b/.circleci/config.yml index 882d7d245d..6c169d7da3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -100,6 +100,7 @@ commands: << parameters.additional-flags >> \ ${ENABLE_ENTERPRISE:+-enable-enterprise} \ -debug-directory="$TEST_RESULTS/debug" \ + -consul-image=hashicorppreview/consul-enterprise:1.14-dev \ -consul-k8s-image=<< parameters.consul-k8s-image >> then echo "Tests in ${pkg} failed, aborting early" diff --git a/acceptance/tests/connect/connect_helper.go b/acceptance/tests/connect/connect_helper.go index 473c2ab562..26d5b5a95e 100644 --- a/acceptance/tests/connect/connect_helper.go +++ b/acceptance/tests/connect/connect_helper.go @@ -4,6 +4,7 @@ import ( "context" "strconv" "testing" + "time" "github.com/hashicorp/consul-k8s/acceptance/framework/config" "github.com/hashicorp/consul-k8s/acceptance/framework/consul" @@ -93,7 +94,8 @@ func (c *ConnectHelper) DeployClientAndServer(t *testing.T) { // deployments because golang will execute them in reverse order // (i.e. the last registered cleanup function will be executed first). t.Cleanup(func() { - retry.Run(t, func(r *retry.R) { + retrier := &retry.Timer{Timeout: 30 * time.Second, Wait: 100 * time.Millisecond} + retry.RunWith(retrier, t, func(r *retry.R) { tokens, _, err := c.consulClient.ACL().TokenList(nil) require.NoError(r, err) for _, token := range tokens { diff --git a/acceptance/tests/connect/connect_inject_test.go b/acceptance/tests/connect/connect_inject_test.go index 5240dd6f05..a0078d6f6e 100644 --- a/acceptance/tests/connect/connect_inject_test.go +++ b/acceptance/tests/connect/connect_inject_test.go @@ -94,7 +94,7 @@ func TestConnectInject(t *testing.T) { logger.Log(t, output) // Both proxies must see their own local agent and app as clusters. - require.Regexp(r, "local_agent.*STATIC", output) + require.Regexp(r, "consul-dataplane.*STATIC", output) require.Regexp(r, "local_app.*STATIC", output) // Static Client must have Static Server as a cluster and endpoint. @@ -102,7 +102,6 @@ func TestConnectInject(t *testing.T) { require.Regexp(r, "static-server.*static-server\\.default\\.dc1\\.internal.*EDS", output) require.Regexp(r, ipv4RegEx+".*static-server.default.dc1.internal", output) } - } }) @@ -175,26 +174,16 @@ func TestConnectInjectOnUpgrade(t *testing.T) { // Test the endpoints controller cleans up force-killed pods. func TestConnectInject_CleanupKilledPods(t *testing.T) { - cases := []struct { - secure bool - autoEncrypt bool - }{ - {false, false}, - {true, false}, - {true, true}, - } - - for _, c := range cases { - name := fmt.Sprintf("secure: %t; auto-encrypt: %t", c.secure, c.autoEncrypt) + for _, secure := range []bool{false, true} { + name := fmt.Sprintf("secure: %t", secure) t.Run(name, func(t *testing.T) { cfg := suite.Config() ctx := suite.Environment().DefaultContext(t) helmValues := map[string]string{ "connectInject.enabled": "true", - "global.tls.enabled": strconv.FormatBool(c.secure), - "global.tls.enableAutoEncrypt": strconv.FormatBool(c.autoEncrypt), - "global.acls.manageSystemACLs": strconv.FormatBool(c.secure), + "global.tls.enabled": strconv.FormatBool(secure), + "global.acls.manageSystemACLs": strconv.FormatBool(secure), } releaseName := helpers.RandomName() @@ -206,7 +195,7 @@ func TestConnectInject_CleanupKilledPods(t *testing.T) { k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-inject") logger.Log(t, "waiting for static-client to be registered with Consul") - consulClient, _ := consulCluster.SetupConsulClient(t, c.secure) + consulClient, _ := consulCluster.SetupConsulClient(t, secure) retry.Run(t, func(r *retry.R) { for _, name := range []string{"static-client", "static-client-sidecar-proxy"} { instances, _, err := consulClient.Catalog().Service(name, "", nil) @@ -253,17 +242,9 @@ const multiportAdmin = "multiport-admin" // two ports. This tests inbound connections to each port of the multiport app, and outbound connections from the // multiport app to static-server. func TestConnectInject_MultiportServices(t *testing.T) { - cases := []struct { - secure bool - autoEncrypt bool - }{ - {false, false}, - {true, false}, - {true, true}, - } - - for _, c := range cases { - name := fmt.Sprintf("secure: %t; auto-encrypt: %t", c.secure, c.autoEncrypt) + t.Skipf("skipping until multi-port workaround is supported") + for _, secure := range []bool{false, true} { + name := fmt.Sprintf("secure: %t", secure) t.Run(name, func(t *testing.T) { cfg := suite.Config() ctx := suite.Environment().DefaultContext(t) @@ -276,9 +257,8 @@ func TestConnectInject_MultiportServices(t *testing.T) { helmValues := map[string]string{ "connectInject.enabled": "true", - "global.tls.enabled": strconv.FormatBool(c.secure), - "global.tls.enableAutoEncrypt": strconv.FormatBool(c.autoEncrypt), - "global.acls.manageSystemACLs": strconv.FormatBool(c.secure), + "global.tls.enabled": strconv.FormatBool(secure), + "global.acls.manageSystemACLs": strconv.FormatBool(secure), } releaseName := helpers.RandomName() @@ -286,10 +266,10 @@ func TestConnectInject_MultiportServices(t *testing.T) { consulCluster.Create(t) - consulClient, _ := consulCluster.SetupConsulClient(t, c.secure) + consulClient, _ := consulCluster.SetupConsulClient(t, secure) // Check that the ACL token is deleted. - if c.secure { + if secure { // We need to register the cleanup function before we create the deployments // because golang will execute them in reverse order i.e. the last registered // cleanup function will be executed first. @@ -328,7 +308,7 @@ func TestConnectInject_MultiportServices(t *testing.T) { require.Len(t, podList.Items, 1) require.Len(t, podList.Items[0].Spec.Containers, 4) - if c.secure { + if secure { logger.Log(t, "checking that the connection is not successful because there's no intention") k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), StaticClientName, "http://localhost:1234") k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), StaticClientName, "http://localhost:2234") @@ -373,7 +353,7 @@ func TestConnectInject_MultiportServices(t *testing.T) { // For outbound connections from the multi port pod, only intentions from the first service in the multiport // pod need to be created, since all upstream connections are made through the first service's envoy proxy. - if c.secure { + if secure { logger.Log(t, "checking that the connection is not successful because there's no intention") k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), multiport, "http://localhost:3234") diff --git a/acceptance/tests/metrics/metrics_test.go b/acceptance/tests/metrics/metrics_test.go index 3c26c2081d..b923658736 100644 --- a/acceptance/tests/metrics/metrics_test.go +++ b/acceptance/tests/metrics/metrics_test.go @@ -90,6 +90,7 @@ func TestComponentMetrics(t *testing.T) { // Test that merged service and envoy metrics are accessible from the // endpoints that have been exposed on the service. func TestAppMetrics(t *testing.T) { + t.Skipf("Skipping this test because it's not yet supported with agentless") env := suite.Environment() cfg := suite.Config() ctx := env.DefaultContext(t) diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 3a7891eb3b..08e18385c1 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -128,12 +128,13 @@ spec: -log-json={{ .Values.global.logJSON }} \ -default-inject={{ .Values.connectInject.default }} \ -consul-image="{{ default .Values.global.image .Values.connectInject.imageConsul }}" \ - -envoy-image="{{ .Values.global.imageEnvoy }}" \ + -consul-dataplane-image="{{ .Values.global.imageConsulDataplane }}" \ -consul-k8s-image="{{ default .Values.global.imageK8S .Values.connectInject.image }}" \ -release-name="{{ .Release.Name }}" \ -release-namespace="{{ .Release.Namespace }}" \ -resource-prefix={{ template "consul.fullname" . }} \ -listen=:8080 \ + -tls-server-name="server.{{ .Values.global.datacenter }}.{{ .Values.global.domain }}" \ {{- if and .Values.externalServers.enabled (not .Values.externalServers.hosts) }}{{ fail "externalServers.hosts must be set if externalServers.enabled is true" }}{{ end -}} {{- if .Values.externalServers.enabled }} {{- if .Values.global.tls.enabled }} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index af529bba8d..e68d475175 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -317,14 +317,14 @@ EOF [ "${actual}" = "true" ] } -@test "connectInject/Deployment: envoy-image can be set via global" { +@test "connectInject/Deployment: consul-dataplane-image can be set via global" { cd `chart_dir` local actual=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ - --set 'global.imageEnvoy=foo' \ + --set 'global.imageConsulDataplane=foo' \ . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].command | any(contains("-envoy-image=\"foo\""))' | tee /dev/stderr) + yq '.spec.template.spec.containers[0].command | any(contains("-consul-dataplane-image=\"foo\""))' | tee /dev/stderr) [ "${actual}" = "true" ] } diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 0ef341ebde..ef559bb380 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -631,6 +631,11 @@ global: # @default: envoyproxy/envoy-alpine: imageEnvoy: "envoyproxy/envoy:v1.22.4" + # The name (and tag) of the consul-dataplane Docker image used for the + # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. + # @default: hashicorp/consul-dataplane: + imageConsulDataplane: "ishustava/consul-dataplane:latest@sha256:5ac25d6a159e360b9cbe9b12ea6be70cde8f4677cbf00ae4885e5f5fd9b1ad36" + # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. openshift: diff --git a/control-plane/connect-inject/envoy_sidecar.go b/control-plane/connect-inject/consul_dataplane_sidecar.go similarity index 52% rename from control-plane/connect-inject/envoy_sidecar.go rename to control-plane/connect-inject/consul_dataplane_sidecar.go index 37195114c9..982d0ac6fb 100644 --- a/control-plane/connect-inject/envoy_sidecar.go +++ b/control-plane/connect-inject/consul_dataplane_sidecar.go @@ -6,28 +6,27 @@ import ( "strconv" "strings" - "github.com/google/shlex" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/pointer" ) -func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, mpi multiPortInfo) (corev1.Container, error) { - resources, err := w.envoySidecarResources(pod) +func (w *MeshWebhook) consulDataplaneSidecar(namespace corev1.Namespace, pod corev1.Pod, mpi multiPortInfo) (corev1.Container, error) { + resources, err := w.sidecarResources(pod) if err != nil { return corev1.Container{}, err } multiPort := mpi.serviceName != "" - cmd, err := w.getContainerSidecarCommand(pod, mpi.serviceName, mpi.serviceIndex) + cmd, err := w.getContainerSidecarCommand(namespace, pod, mpi.serviceName) if err != nil { return corev1.Container{}, err } - containerName := envoySidecarContainer + containerName := sidecarContainer if multiPort { - containerName = fmt.Sprintf("%s-%s", envoySidecarContainer, mpi.serviceName) + containerName = fmt.Sprintf("%s-%s", sidecarContainer, mpi.serviceName) } probe := &corev1.Probe{ @@ -40,8 +39,17 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m } container := corev1.Container{ Name: containerName, - Image: w.ImageEnvoy, + Image: w.ImageConsulDataplane, Resources: resources, + // We need to set tmp dir to an ephemeral volume that we're mounting so that + // consul-dataplane can write files to it. Otherwise, it wouldn't be able to + // because we set file system to be read-only. + Env: []corev1.EnvVar{ + { + Name: "TMPDIR", + Value: "/consul/connect-inject", + }, + }, VolumeMounts: []corev1.VolumeMount{ { Name: volumeName, @@ -53,7 +61,7 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m LivenessProbe: probe, } - // Add any extra Envoy VolumeMounts. + // Add any extra VolumeMounts. if _, ok := pod.Annotations[annotationConsulSidecarUserVolumeMount]; ok { var volumeMount []corev1.VolumeMount err := json.Unmarshal([]byte(pod.Annotations[annotationConsulSidecarUserVolumeMount]), &volumeMount) @@ -70,26 +78,26 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m // If not running in transparent proxy mode and in an OpenShift environment, // skip setting the security context and let OpenShift set it for us. - // When transparent proxy is enabled, then Envoy needs to run as our specific user + // When transparent proxy is enabled, then consul-dataplane needs to run as our specific user // so that traffic redirection will work. if tproxyEnabled || !w.EnableOpenShift { if pod.Spec.SecurityContext != nil { - // User container and Envoy container cannot have the same UID. - if pod.Spec.SecurityContext.RunAsUser != nil && *pod.Spec.SecurityContext.RunAsUser == envoyUserAndGroupID { - return corev1.Container{}, fmt.Errorf("pod security context cannot have the same uid as envoy: %v", envoyUserAndGroupID) + // User container and consul-dataplane container cannot have the same UID. + if pod.Spec.SecurityContext.RunAsUser != nil && *pod.Spec.SecurityContext.RunAsUser == sidecarUserAndGroupID { + return corev1.Container{}, fmt.Errorf("pod's security context cannot have the same UID as consul-dataplane: %v", sidecarUserAndGroupID) } } - // Ensure that none of the user's containers have the same UID as Envoy. At this point in injection the meshWebhook + // Ensure that none of the user's containers have the same UID as consul-dataplane. At this point in injection the meshWebhook // has only injected init containers so all containers defined in pod.Spec.Containers are from the user. for _, c := range pod.Spec.Containers { - // User container and Envoy container cannot have the same UID. - if c.SecurityContext != nil && c.SecurityContext.RunAsUser != nil && *c.SecurityContext.RunAsUser == envoyUserAndGroupID && c.Image != w.ImageEnvoy { - return corev1.Container{}, fmt.Errorf("container %q has runAsUser set to the same uid %q as envoy which is not allowed", c.Name, envoyUserAndGroupID) + // User container and consul-dataplane container cannot have the same UID. + if c.SecurityContext != nil && c.SecurityContext.RunAsUser != nil && *c.SecurityContext.RunAsUser == sidecarUserAndGroupID && c.Image != w.ImageConsulDataplane { + return corev1.Container{}, fmt.Errorf("container %q has runAsUser set to the same UID \"%d\" as consul-dataplane which is not allowed", c.Name, sidecarUserAndGroupID) } } container.SecurityContext = &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), - RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), + RunAsGroup: pointer.Int64(sidecarUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), } @@ -97,63 +105,90 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m return container, nil } -func (w *MeshWebhook) getContainerSidecarCommand(pod corev1.Pod, multiPortSvcName string, multiPortSvcIdx int) ([]string, error) { - bootstrapFile := "/consul/connect-inject/envoy-bootstrap.yaml" + +func (w *MeshWebhook) getContainerSidecarCommand(namespace corev1.Namespace, pod corev1.Pod, multiPortSvcName string) ([]string, error) { + proxyIDFileName := "/consul/connect-inject/proxyid" if multiPortSvcName != "" { - bootstrapFile = fmt.Sprintf("/consul/connect-inject/envoy-bootstrap-%s.yaml", multiPortSvcName) - } - cmd := []string{ - "envoy", - "--config-path", bootstrapFile, + proxyIDFileName = fmt.Sprintf("/consul/connect-inject/proxyid-%s", multiPortSvcName) } + aclTokenFile := "/consul/connect-inject/acl-token" if multiPortSvcName != "" { - // --base-id is needed so multiple Envoy proxies can run on the same host. - cmd = append(cmd, "--base-id", fmt.Sprintf("%d", multiPortSvcIdx)) + aclTokenFile = fmt.Sprintf("/consul/connect-inject/acl-token-%s", multiPortSvcName) } - - // Check to see if the user has overriden concurrency via an annotation. - if pod.Annotations[annotationEnvoyProxyConcurrency] != "" { - val, err := strconv.ParseInt(pod.Annotations[annotationEnvoyProxyConcurrency], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse annotation: %s", annotationEnvoyProxyConcurrency) - } - if val < 0 { - return nil, fmt.Errorf("invalid envoy concurrency, must be >= 0: %s", pod.Annotations[annotationEnvoyProxyConcurrency]) - } else { - cmd = append(cmd, "--concurrency", pod.Annotations[annotationEnvoyProxyConcurrency]) + cmd := []string{ + "consul-dataplane", + "-addresses=" + w.ConsulAddress, + "-grpc-port=" + w.ConsulGRPCPort, + "-proxy-service-id=" + fmt.Sprintf("$(cat %s)", proxyIDFileName), + "-service-node-name=" + ConsulNodeName, + "-log-level=" + w.LogLevel, + "-log-json=" + strconv.FormatBool(w.LogJSON), + } + if w.AuthMethod != "" { + cmd = append(cmd, "-static-token="+fmt.Sprintf("$(cat %s)", aclTokenFile)) + } + if w.EnableNamespaces { + cmd = append(cmd, "-service-namespace="+w.consulNamespace(namespace.Name)) + } + if w.ConsulPartition != "" { + cmd = append(cmd, "-service-partition="+w.ConsulPartition) + } + if w.TLSEnabled { + cmd = append(cmd, "-tls-enabled", "-tls-server-name="+w.ConsulTLSServerName) + if w.ConsulCACert != "" { + cmd = append(cmd, "-tls-ca-certs-path=/consul/connect-inject/consul-ca.pem") } - } else { - // Use the default concurrency. - cmd = append(cmd, "--concurrency", fmt.Sprintf("%d", w.DefaultEnvoyProxyConcurrency)) } - extraArgs, annotationSet := pod.Annotations[annotationEnvoyExtraArgs] - - if annotationSet || w.EnvoyExtraArgs != "" { - extraArgsToUse := w.EnvoyExtraArgs - - // Prefer args set by pod annotation over the flag to the consul-k8s binary (h.EnvoyExtraArgs). - if annotationSet { - extraArgsToUse = extraArgs - } - - // Split string into tokens. - // e.g. "--foo bar --boo baz" --> ["--foo", "bar", "--boo", "baz"] - tokens, err := shlex.Split(extraArgsToUse) - if err != nil { - return []string{}, err - } - for _, t := range tokens { - if strings.Contains(t, " ") { - t = strconv.Quote(t) - } - cmd = append(cmd, t) - } - } + // todo (agentless): we need to enable this once we support passing extra flags to envoy through consul-dataplane + //if multiPortSvcName != "" { + // // --base-id is needed so multiple Envoy proxies can run on the same host. + // cmd = append(cmd, "--base-id", fmt.Sprintf("%d", multiPortSvcIdx)) + //} + // Check to see if the user has overriden concurrency via an annotation. + //if pod.Annotations[annotationEnvoyProxyConcurrency] != "" { + // val, err := strconv.ParseInt(pod.Annotations[annotationEnvoyProxyConcurrency], 10, 64) + // if err != nil { + // return nil, fmt.Errorf("unable to parse annotation: %s", annotationEnvoyProxyConcurrency) + // } + // if val < 0 { + // return nil, fmt.Errorf("invalid envoy concurrency, must be >= 0: %s", pod.Annotations[annotationEnvoyProxyConcurrency]) + // } else { + // cmd = append(cmd, "--concurrency", pod.Annotations[annotationEnvoyProxyConcurrency]) + // } + //} else { + // // Use the default concurrency. + // cmd = append(cmd, "--concurrency", fmt.Sprintf("%d", w.DefaultEnvoyProxyConcurrency)) + //} + // + //extraArgs, annotationSet := pod.Annotations[annotationEnvoyExtraArgs] + // + //if annotationSet || w.EnvoyExtraArgs != "" { + // extraArgsToUse := w.EnvoyExtraArgs + // + // // Prefer args set by pod annotation over the flag to the consul-k8s binary (h.EnvoyExtraArgs). + // if annotationSet { + // extraArgsToUse = extraArgs + // } + // + // // Split string into tokens. + // // e.g. "--foo bar --boo baz" --> ["--foo", "bar", "--boo", "baz"] + // tokens, err := shlex.Split(extraArgsToUse) + // if err != nil { + // return []string{}, err + // } + // for _, t := range tokens { + // if strings.Contains(t, " ") { + // t = strconv.Quote(t) + // } + // cmd = append(cmd, t) + // } + //} + cmd = append([]string{"/bin/sh", "-ec"}, strings.Join(cmd, " ")) return cmd, nil } -func (w *MeshWebhook) envoySidecarResources(pod corev1.Pod) (corev1.ResourceRequirements, error) { +func (w *MeshWebhook) sidecarResources(pod corev1.Pod) (corev1.ResourceRequirements, error) { resources := corev1.ResourceRequirements{ Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, @@ -166,7 +201,7 @@ func (w *MeshWebhook) envoySidecarResources(pod corev1.Pod) (corev1.ResourceRequ // was explicitly set. If it's not explicitly set, it will be the zero value // which would show up in the pod spec as being explicitly set to zero if we // set that key, e.g. "cpu" to zero. - // We want it to not show up in the pod spec at all if if it's not explicitly + // We want it to not show up in the pod spec at all if it's not explicitly // set so that users aren't wondering why it's set to 0 when they didn't specify // a request/limit. If they have explicitly set it to 0 then it will be set // to 0 in the pod spec because we're doing a comparison to the zero-valued diff --git a/control-plane/connect-inject/envoy_sidecar_test.go b/control-plane/connect-inject/consul_dataplane_sidecar_test.go similarity index 60% rename from control-plane/connect-inject/envoy_sidecar_test.go rename to control-plane/connect-inject/consul_dataplane_sidecar_test.go index 69ca0fd6b7..c72dc98e5e 100644 --- a/control-plane/connect-inject/envoy_sidecar_test.go +++ b/control-plane/connect-inject/consul_dataplane_sidecar_test.go @@ -2,6 +2,7 @@ package connectinject import ( "fmt" + "strconv" "testing" "github.com/stretchr/testify/require" @@ -12,52 +13,146 @@ import ( "k8s.io/utils/pointer" ) -func TestHandlerEnvoySidecar(t *testing.T) { - h := MeshWebhook{} - pod := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - annotationService: "foo", +func TestHandlerConsulDataplaneSidecar(t *testing.T) { + cases := map[string]struct { + webhookSetupFunc func(w *MeshWebhook) + additionalExpCmdArgs string + }{ + "default": { + webhookSetupFunc: nil, + }, + "with custom gRPC port": { + webhookSetupFunc: func(w *MeshWebhook) { + w.ConsulGRPCPort = "8602" }, }, - - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "web", - }, + "with ACLs": { + webhookSetupFunc: func(w *MeshWebhook) { + w.AuthMethod = "test-auth-method" }, + additionalExpCmdArgs: " -static-token=$(cat /consul/connect-inject/acl-token)", }, - } - - container, err := h.envoySidecar(testNS, pod, multiPortInfo{}) - require.NoError(t, err) - require.Equal(t, container.Command, []string{ - "envoy", - "--config-path", "/consul/connect-inject/envoy-bootstrap.yaml", - "--concurrency", "0", - }) - - require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ - { - Name: volumeName, - MountPath: "/consul/connect-inject", + "with TLS and CA cert provided": { + webhookSetupFunc: func(w *MeshWebhook) { + w.TLSEnabled = true + w.ConsulTLSServerName = "server.dc1.consul" + w.ConsulCACert = "consul-ca-cert" + }, + additionalExpCmdArgs: " -tls-enabled -tls-server-name=server.dc1.consul -tls-ca-certs-path=/consul/connect-inject/consul-ca.pem", + }, + "with TLS and no CA cert provided": { + webhookSetupFunc: func(w *MeshWebhook) { + w.TLSEnabled = true + w.ConsulTLSServerName = "server.dc1.consul" + }, + additionalExpCmdArgs: " -tls-enabled -tls-server-name=server.dc1.consul", }, - }) - expectedProbe := &corev1.Probe{ - Handler: corev1.Handler{ - TCPSocket: &corev1.TCPSocketAction{ - Port: intstr.FromInt(EnvoyInboundListenerPort), + "with single destination namespace": { + webhookSetupFunc: func(w *MeshWebhook) { + w.EnableNamespaces = true + w.ConsulDestinationNamespace = "consul-namespace" + }, + additionalExpCmdArgs: " -service-namespace=consul-namespace", + }, + "with namespace mirroring": { + webhookSetupFunc: func(w *MeshWebhook) { + w.EnableNamespaces = true + w.EnableK8SNSMirroring = true + }, + additionalExpCmdArgs: " -service-namespace=k8snamespace", + }, + "with namespace mirroring prefix": { + webhookSetupFunc: func(w *MeshWebhook) { + w.EnableNamespaces = true + w.EnableK8SNSMirroring = true + w.K8SNSMirroringPrefix = "foo-" + }, + additionalExpCmdArgs: " -service-namespace=foo-k8snamespace", + }, + "with partitions": { + webhookSetupFunc: func(w *MeshWebhook) { + w.ConsulPartition = "partition-1" + }, + additionalExpCmdArgs: " -service-partition=partition-1", + }, + "with different log level": { + webhookSetupFunc: func(w *MeshWebhook) { + w.LogLevel = "debug" + }, + }, + "with different log level and log json": { + webhookSetupFunc: func(w *MeshWebhook) { + w.LogLevel = "debug" + w.LogJSON = true }, }, - InitialDelaySeconds: 1, } - require.Equal(t, expectedProbe, container.ReadinessProbe) - require.Equal(t, expectedProbe, container.LivenessProbe) - require.Nil(t, container.StartupProbe) + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + w := &MeshWebhook{ + ConsulAddress: "1.1.1.1", + ConsulGRPCPort: "8502", + LogLevel: "info", + LogJSON: false, + } + if c.webhookSetupFunc != nil { + c.webhookSetupFunc(w) + } + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Annotations: map[string]string{ + annotationService: "foo", + }, + }, + + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "web", + }, + }, + }, + } + + container, err := w.consulDataplaneSidecar(testNS, pod, multiPortInfo{}) + require.NoError(t, err) + // todo(agentless): test default concurrency + expCmd := []string{ + "/bin/sh", "-ec", + "consul-dataplane -addresses=1.1.1.1 -grpc-port=" + w.ConsulGRPCPort + + " -proxy-service-id=$(cat /consul/connect-inject/proxyid) " + + "-service-node-name=k8s-service-mesh -log-level=" + w.LogLevel + " -log-json=" + strconv.FormatBool(w.LogJSON) + c.additionalExpCmdArgs} + require.Equal(t, container.Command, expCmd) + + require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ + { + Name: volumeName, + MountPath: "/consul/connect-inject", + }, + }) + expectedProbe := &corev1.Probe{ + Handler: corev1.Handler{ + TCPSocket: &corev1.TCPSocketAction{ + Port: intstr.FromInt(EnvoyInboundListenerPort), + }, + }, + InitialDelaySeconds: 1, + } + require.Equal(t, expectedProbe, container.ReadinessProbe) + require.Equal(t, expectedProbe, container.LivenessProbe) + require.Nil(t, container.StartupProbe) + require.Len(t, container.Env, 1) + require.Equal(t, container.Env[0].Name, "TMPDIR") + require.Equal(t, container.Env[0].Value, "/consul/connect-inject") + }) + } } -func TestHandlerEnvoySidecar_Concurrency(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_Concurrency(t *testing.T) { + // todo(agentless): re-enable once we support passing extra flags to Envoy. + t.Skipf("skip until we support extra flag to Envoy") cases := map[string]struct { annotations map[string]string expCommand []string @@ -108,7 +203,7 @@ func TestHandlerEnvoySidecar_Concurrency(t *testing.T) { }, }, } - container, err := h.envoySidecar(testNS, pod, multiPortInfo{}) + container, err := h.consulDataplaneSidecar(testNS, pod, multiPortInfo{}) if c.expErr != "" { require.EqualError(t, err, c.expErr) } else { @@ -119,68 +214,87 @@ func TestHandlerEnvoySidecar_Concurrency(t *testing.T) { } } -func TestHandlerEnvoySidecar_Multiport(t *testing.T) { - h := MeshWebhook{} - pod := corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - annotationService: "web,web-admin", - }, - }, +func TestHandlerConsulDataplaneSidecar_Multiport(t *testing.T) { + for _, aclsEnabled := range []bool{false, true} { + name := fmt.Sprintf("acls enabled: %t", aclsEnabled) + t.Run(name, func(t *testing.T) { + w := MeshWebhook{ + ConsulAddress: "1.1.1.1", + ConsulGRPCPort: "8502", + LogLevel: "info", + } + if aclsEnabled { + w.AuthMethod = "test-auth-method" + } + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationService: "web,web-admin", + }, + }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "web", + }, + { + Name: "web-admin", + }, + }, + }, + } + multiPortInfos := []multiPortInfo{ { - Name: "web", + serviceIndex: 0, + serviceName: "web", }, { - Name: "web-admin", + serviceIndex: 1, + serviceName: "web-admin", }, - }, - }, - } - multiPortInfos := []multiPortInfo{ - { - serviceIndex: 0, - serviceName: "web", - }, - { - serviceIndex: 1, - serviceName: "web-admin", - }, - } - expCommand := map[int][]string{ - 0: {"envoy", "--config-path", "/consul/connect-inject/envoy-bootstrap-web.yaml", "--base-id", "0", "--concurrency", "0"}, - 1: {"envoy", "--config-path", "/consul/connect-inject/envoy-bootstrap-web-admin.yaml", "--base-id", "1", "--concurrency", "0"}, - } - for i := 0; i < 2; i++ { - container, err := h.envoySidecar(testNS, pod, multiPortInfos[i]) - require.NoError(t, err) - require.Equal(t, expCommand[i], container.Command) + } + expCommand := [][]string{ + {"/bin/sh", "-ec", "consul-dataplane -addresses=1.1.1.1 -grpc-port=8502 -proxy-service-id=$(cat /consul/connect-inject/proxyid-web) -service-node-name=k8s-service-mesh -log-level=info -log-json=false"}, + {"/bin/sh", "-ec", "consul-dataplane -addresses=1.1.1.1 -grpc-port=8502 -proxy-service-id=$(cat /consul/connect-inject/proxyid-web-admin) -service-node-name=k8s-service-mesh -log-level=info -log-json=false"}, + } + if aclsEnabled { + expCommand = [][]string{ + {"/bin/sh", "-ec", "consul-dataplane -addresses=1.1.1.1 -grpc-port=8502 -proxy-service-id=$(cat /consul/connect-inject/proxyid-web) -service-node-name=k8s-service-mesh -log-level=info -log-json=false -static-token=$(cat /consul/connect-inject/acl-token-web)"}, + {"/bin/sh", "-ec", "consul-dataplane -addresses=1.1.1.1 -grpc-port=8502 -proxy-service-id=$(cat /consul/connect-inject/proxyid-web-admin) -service-node-name=k8s-service-mesh -log-level=info -log-json=false -static-token=$(cat /consul/connect-inject/acl-token-web-admin)"}, + } + } - require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ - { - Name: volumeName, - MountPath: "/consul/connect-inject", - }, - }) + for i, expCmd := range expCommand { + container, err := w.consulDataplaneSidecar(testNS, pod, multiPortInfos[i]) + require.NoError(t, err) + require.Equal(t, expCmd, container.Command) - port := EnvoyInboundListenerPort + i - expectedProbe := &corev1.Probe{ - Handler: corev1.Handler{ - TCPSocket: &corev1.TCPSocketAction{ - Port: intstr.FromInt(port), - }, - }, - InitialDelaySeconds: 1, - } - require.Equal(t, expectedProbe, container.ReadinessProbe) - require.Equal(t, expectedProbe, container.LivenessProbe) - require.Nil(t, container.StartupProbe) + require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ + { + Name: volumeName, + MountPath: "/consul/connect-inject", + }, + }) + + port := EnvoyInboundListenerPort + i + expectedProbe := &corev1.Probe{ + Handler: corev1.Handler{ + TCPSocket: &corev1.TCPSocketAction{ + Port: intstr.FromInt(port), + }, + }, + InitialDelaySeconds: 1, + } + require.Equal(t, expectedProbe, container.ReadinessProbe) + require.Equal(t, expectedProbe, container.LivenessProbe) + require.Nil(t, container.StartupProbe) + } + }) } } -func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_withSecurityContext(t *testing.T) { cases := map[string]struct { tproxyEnabled bool openShiftEnabled bool @@ -190,8 +304,8 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { tproxyEnabled: false, openShiftEnabled: false, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), - RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), + RunAsGroup: pointer.Int64(sidecarUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), }, @@ -200,8 +314,8 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { tproxyEnabled: true, openShiftEnabled: false, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), - RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), + RunAsGroup: pointer.Int64(sidecarUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), }, @@ -215,8 +329,8 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { tproxyEnabled: true, openShiftEnabled: true, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), - RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), + RunAsGroup: pointer.Int64(sidecarUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), }, @@ -243,16 +357,16 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { }, }, } - ec, err := w.envoySidecar(testNS, pod, multiPortInfo{}) + ec, err := w.consulDataplaneSidecar(testNS, pod, multiPortInfo{}) require.NoError(t, err) require.Equal(t, c.expSecurityContext, ec.SecurityContext) }) } } -// Test that if the user specifies a pod security context with the same uid as `envoyUserAndGroupID` that we return +// Test that if the user specifies a pod security context with the same uid as `sidecarUserAndGroupID` that we return // an error to the meshWebhook. -func TestHandlerEnvoySidecar_FailsWithDuplicatePodSecurityContextUID(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_FailsWithDuplicatePodSecurityContextUID(t *testing.T) { require := require.New(t) w := MeshWebhook{} pod := corev1.Pod{ @@ -263,27 +377,27 @@ func TestHandlerEnvoySidecar_FailsWithDuplicatePodSecurityContextUID(t *testing. }, }, SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), }, }, } - _, err := w.envoySidecar(testNS, pod, multiPortInfo{}) - require.Error(err, fmt.Sprintf("pod security context cannot have the same uid as envoy: %v", envoyUserAndGroupID)) + _, err := w.consulDataplaneSidecar(testNS, pod, multiPortInfo{}) + require.EqualError(err, fmt.Sprintf("pod's security context cannot have the same UID as consul-dataplane: %v", sidecarUserAndGroupID)) } -// Test that if the user specifies a container with security context with the same uid as `envoyUserAndGroupID` that we -// return an error to the meshWebhook. If a container using the envoy image has the same uid, we don't return an error -// because in multiport pod there can be multiple envoy sidecars. -func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *testing.T) { +// Test that if the user specifies a container with security context with the same uid as `sidecarUserAndGroupID` that we +// return an error to the meshWebhook. If a container using the consul-dataplane image has the same uid, we don't return an error +// because in multiport pod there can be multiple consul-dataplane sidecars. +func TestHandlerConsulDataplaneSidecar_FailsWithDuplicateContainerSecurityContextUID(t *testing.T) { cases := []struct { name string pod corev1.Pod webhook MeshWebhook expErr bool - expErrMessage error + expErrMessage string }{ { - name: "fails with non envoy image", + name: "fails with non consul-dataplane image", pod: corev1.Pod{ Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -298,16 +412,16 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te Name: "app", // Setting RunAsUser: 5995 should fail. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), }, - Image: "not-envoy", + Image: "not-consul-dataplane", }, }, }, }, webhook: MeshWebhook{}, expErr: true, - expErrMessage: fmt.Errorf("container app has runAsUser set to the same uid %q as envoy which is not allowed", envoyUserAndGroupID), + expErrMessage: fmt.Sprintf("container \"app\" has runAsUser set to the same UID \"%d\" as consul-dataplane which is not allowed", sidecarUserAndGroupID), }, { name: "doesn't fail with envoy image", @@ -323,9 +437,9 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te }, { Name: "sidecar", - // Setting RunAsUser: 5995 should succeed if the image matches h.ImageEnvoy. + // Setting RunAsUser: 5995 should succeed if the image matches h.ImageConsulDataplane. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(sidecarUserAndGroupID), }, Image: "envoy", }, @@ -333,7 +447,7 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te }, }, webhook: MeshWebhook{ - ImageEnvoy: "envoy", + ImageConsulDataplane: "envoy", }, expErr: false, }, @@ -341,9 +455,9 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - _, err := tc.webhook.envoySidecar(testNS, tc.pod, multiPortInfo{}) + _, err := tc.webhook.consulDataplaneSidecar(testNS, tc.pod, multiPortInfo{}) if tc.expErr { - require.Error(t, err, tc.expErrMessage) + require.EqualError(t, err, tc.expErrMessage) } else { require.NoError(t, err) } @@ -354,7 +468,9 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te // Test that we can pass extra args to envoy via the extraEnvoyArgs flag // or via pod annotations. When arguments are passed in both ways, the // arguments set via pod annotations are used. -func TestHandlerEnvoySidecar_EnvoyExtraArgs(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_EnvoyExtraArgs(t *testing.T) { + // todo(agentless): enable when we support passing extra args to Envoy. + t.Skipf("skip until we support passing extra args to Envoy") cases := []struct { name string envoyExtraArgs string @@ -435,19 +551,19 @@ func TestHandlerEnvoySidecar_EnvoyExtraArgs(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { h := MeshWebhook{ - ImageConsul: "hashicorp/consul:latest", - ImageEnvoy: "hashicorp/consul-k8s:latest", - EnvoyExtraArgs: tc.envoyExtraArgs, + ImageConsul: "hashicorp/consul:latest", + ImageConsulDataplane: "hashicorp/consul-k8s:latest", + EnvoyExtraArgs: tc.envoyExtraArgs, } - c, err := h.envoySidecar(testNS, *tc.pod, multiPortInfo{}) + c, err := h.consulDataplaneSidecar(testNS, *tc.pod, multiPortInfo{}) require.NoError(t, err) require.Equal(t, tc.expectedContainerCommand, c.Command) }) } } -func TestHandlerEnvoySidecar_UserVolumeMounts(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_UserVolumeMounts(t *testing.T) { cases := []struct { name string pod corev1.Pod @@ -495,10 +611,10 @@ func TestHandlerEnvoySidecar_UserVolumeMounts(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { h := MeshWebhook{ - ImageConsul: "hashicorp/consul:latest", - ImageEnvoy: "hashicorp/consul-k8s:latest", + ImageConsul: "hashicorp/consul:latest", + ImageConsulDataplane: "hashicorp/consul-k8s:latest", } - c, err := h.envoySidecar(testNS, tc.pod, multiPortInfo{}) + c, err := h.consulDataplaneSidecar(testNS, tc.pod, multiPortInfo{}) if tc.expErr == "" { require.NoError(t, err) require.Equal(t, tc.expectedContainerVolumeMounts, c.VolumeMounts) @@ -510,7 +626,7 @@ func TestHandlerEnvoySidecar_UserVolumeMounts(t *testing.T) { } } -func TestHandlerEnvoySidecar_Resources(t *testing.T) { +func TestHandlerConsulDataplaneSidecar_Resources(t *testing.T) { mem1 := resource.MustParse("100Mi") mem2 := resource.MustParse("200Mi") cpu1 := resource.MustParse("100m") @@ -677,7 +793,7 @@ func TestHandlerEnvoySidecar_Resources(t *testing.T) { }, }, } - container, err := c.webhook.envoySidecar(testNS, pod, multiPortInfo{}) + container, err := c.webhook.consulDataplaneSidecar(testNS, pod, multiPortInfo{}) if c.expErr != "" { require.NotNil(err) require.Contains(err.Error(), c.expErr) diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index 8dcffe76f6..8ca76e27fd 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -17,12 +17,13 @@ const ( InjectInitCopyContainerName = "copy-consul-bin" InjectInitContainerName = "consul-connect-inject-init" rootUserAndGroupID = 0 - envoyUserAndGroupID = 5995 + sidecarUserAndGroupID = 5995 copyContainerUserAndGroupID = 5996 netAdminCapability = "NET_ADMIN" dnsServiceHostEnvSuffix = "DNS_SERVICE_HOST" ) +// todo: remove any unused params type initContainerCommandData struct { ServiceName string ServiceAccountName string @@ -188,7 +189,7 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, TProxyExcludeOutboundCIDRs: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundCIDRs, pod), TProxyExcludeUIDs: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeUIDs, pod), ConsulDNSClusterIP: consulDNSClusterIP, - EnvoyUID: envoyUserAndGroupID, + EnvoyUID: sidecarUserAndGroupID, MultiPort: multiPort, EnvoyAdminPort: 19000 + mpi.serviceIndex, ConsulAPITimeout: w.ConsulAPITimeout, @@ -259,13 +260,13 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, // Validate required Prometheus TLS config is present if set. if data.PrometheusCertFile != "" || data.PrometheusKeyFile != "" || data.PrometheusCAFile != "" || data.PrometheusCAPath != "" { if data.PrometheusCAFile == "" && data.PrometheusCAPath == "" { - return corev1.Container{}, fmt.Errorf("Must set one of %q or %q when providing prometheus TLS config", annotationPrometheusCAFile, annotationPrometheusCAPath) + return corev1.Container{}, fmt.Errorf("must set one of %q or %q when providing prometheus TLS config", annotationPrometheusCAFile, annotationPrometheusCAPath) } if data.PrometheusCertFile == "" { - return corev1.Container{}, fmt.Errorf("Must set %q when providing prometheus TLS config", annotationPrometheusCertFile) + return corev1.Container{}, fmt.Errorf("must set %q when providing prometheus TLS config", annotationPrometheusCertFile) } if data.PrometheusKeyFile == "" { - return corev1.Container{}, fmt.Errorf("Must set %q when providing prometheus TLS config", annotationPrometheusKeyFile) + return corev1.Container{}, fmt.Errorf("must set %q when providing prometheus TLS config", annotationPrometheusKeyFile) } } @@ -286,18 +287,6 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, Name: initContainerName, Image: w.ImageConsulK8S, Env: []corev1.EnvVar{ - { - Name: "HOST_IP", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "status.hostIP"}, - }, - }, - { - Name: "POD_IP", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "status.podIP"}, - }, - }, { Name: "POD_NAME", ValueFrom: &corev1.EnvVarSource{ @@ -310,12 +299,33 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, }, }, + { + Name: "CONSUL_HTTP_ADDR", + Value: fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulHTTPPort), + }, + { + Name: "CONSUL_GRPC_ADDR", + Value: fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulGRPCPort), + }, }, Resources: w.InitContainerResources, VolumeMounts: volMounts, Command: []string{"/bin/sh", "-ec", buf.String()}, } + if w.TLSEnabled { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "CONSUL_HTTP_SSL", + Value: "true", + }) + if w.ConsulCACert != "" { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "CONSUL_CACERT", + Value: "/consul/connect-inject/consul-ca.pem", + }) + } + } + if tproxyEnabled { // Running consul connect redirect-traffic with iptables // requires both being a root user and having NET_ADMIN capability. @@ -389,19 +399,11 @@ func splitCommaSeparatedItemsFromAnnotation(annotation string, pod corev1.Pod) [ // initContainerCommandTpl is the template for the command executed by // the init container. const initContainerCommandTpl = ` -{{- if .TLSEnabled }} -export CONSUL_HTTP_ADDR="https://{{ .ConsulAddress }}:{{ .ConsulHTTPPort }}" -export CONSUL_GRPC_ADDR="https://{{ .ConsulAddress }}:{{ .ConsulGRPCPort }}" {{- if .ConsulCACert }} -export CONSUL_CACERT=/consul/connect-inject/consul-ca.pem cat </consul/connect-inject/consul-ca.pem {{ .ConsulCACert }} EOF {{- end }} -{{- else}} -export CONSUL_HTTP_ADDR="{{ .ConsulAddress }}:{{ .ConsulHTTPPort }}" -export CONSUL_GRPC_ADDR="{{ .ConsulAddress }}:{{ .ConsulGRPCPort }}" -{{- end}} consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout={{ .ConsulAPITimeout }} \ -consul-node-name={{ .ConsulNodeName }} \ @@ -437,51 +439,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -consul-service-namespace="{{ .ConsulNamespace }}" \ {{- end }} -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name={{ .ConsulNodeName }} \ - {{- if .MultiPort }} - -proxy-id="$(cat /consul/connect-inject/proxyid-{{.ServiceName}})" \ - {{- else }} - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - {{- end }} - {{- if .PrometheusScrapePath }} - -prometheus-scrape-path="{{ .PrometheusScrapePath }}" \ - {{- end }} - {{- if .PrometheusBackendPort }} - -prometheus-backend-port="{{ .PrometheusBackendPort }}" \ - {{- end }} - {{- if .PrometheusCAFile }} - -prometheus-ca-file="{{ .PrometheusCAFile }}" \ - {{- end }} - {{- if .PrometheusCAPath }} - -prometheus-ca-path="{{ .PrometheusCAPath }}" \ - {{- end }} - {{- if .PrometheusCertFile }} - -prometheus-cert-file="{{ .PrometheusCertFile }}" \ - {{- end }} - {{- if .PrometheusKeyFile }} - -prometheus-key-file="{{ .PrometheusKeyFile }}" \ - {{- end }} - {{- if .AuthMethod }} - {{- if .MultiPort }} - -token-file="/consul/connect-inject/acl-token-{{ .ServiceName }}" \ - {{- else }} - -token-file="/consul/connect-inject/acl-token" \ - {{- end }} - {{- end }} - {{- if .ConsulPartition }} - -partition="{{ .ConsulPartition }}" \ - {{- end }} - {{- if .ConsulNamespace }} - -namespace="{{ .ConsulNamespace }}" \ - {{- end }} - {{- if .MultiPort }} - -admin-bind=127.0.0.1:{{ .EnvoyAdminPort }} \ - {{- end }} - -bootstrap > {{ if .MultiPort }}/consul/connect-inject/envoy-bootstrap-{{.ServiceName}}.yaml{{ else }}/consul/connect-inject/envoy-bootstrap.yaml{{ end }} - - {{- if .EnableTransparentProxy }} {{- /* The newline below is intentional to allow extra space in the rendered template between this and the previous commands. */}} diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index cc98acefb7..cf004c4334 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -66,17 +66,9 @@ func TestHandlerContainerInit(t *testing.T) { ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=0s \ - -consul-node-name=k8s-service-mesh \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-node-name=k8s-service-mesh \`, "", "", }, @@ -102,8 +94,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -114,45 +104,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD "", "", }, - { - "When running the merged metrics server, configures consul connect envoy command", - func(pod *corev1.Pod) *corev1.Pod { - // The annotations to enable metrics, enable merging, and - // service metrics port make the condition to run the merged - // metrics server true. When that is the case, - // prometheusScrapePath and mergedMetricsPort should get - // rendered as -prometheus-scrape-path and - // -prometheus-backend-port to the consul connect envoy command. - pod.Annotations[annotationService] = "web" - pod.Annotations[annotationEnableMetrics] = "true" - pod.Annotations[annotationEnableMetricsMerging] = "true" - pod.Annotations[annotationMergedMetricsPort] = "20100" - pod.Annotations[annotationServiceMetricsPort] = "1234" - pod.Annotations[annotationPrometheusScrapePort] = "22222" - pod.Annotations[annotationPrometheusScrapePath] = "/scrape-path" - pod.Annotations[annotationPrometheusCAFile] = "/certs/ca.crt" - pod.Annotations[annotationPrometheusCAPath] = "/certs/ca/" - pod.Annotations[annotationPrometheusCertFile] = "/certs/server.crt" - pod.Annotations[annotationPrometheusKeyFile] = "/certs/key.pem" - return pod - }, - MeshWebhook{ - ConsulAPITimeout: 5 * time.Second, - }, - `# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -prometheus-scrape-path="/scrape-path" \ - -prometheus-backend-port="20100" \ - -prometheus-ca-file="/certs/ca.crt" \ - -prometheus-ca-path="/certs/ca/" \ - -prometheus-cert-file="/certs/server.crt" \ - -prometheus-key-file="/certs/key.pem" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, - "", - "", - }, { "When providing Prometheus TLS config, missing CA gives an error", func(pod *corev1.Pod) *corev1.Pod { @@ -171,7 +122,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD }, "", "", - fmt.Sprintf("Must set one of %q or %q", annotationPrometheusCAFile, annotationPrometheusCAPath), + fmt.Sprintf("must set one of %q or %q", annotationPrometheusCAFile, annotationPrometheusCAPath), }, { "When providing Prometheus TLS config, missing cert gives an error", @@ -191,7 +142,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD }, "", "", - fmt.Sprintf("Must set %q", annotationPrometheusCertFile), + fmt.Sprintf("must set %q", annotationPrometheusCertFile), }, { "When providing Prometheus TLS config, missing key gives an error", @@ -211,25 +162,29 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD }, "", "", - fmt.Sprintf("Must set %q", annotationPrometheusKeyFile), + fmt.Sprintf("must set %q", annotationPrometheusKeyFile), }, } for _, tt := range cases { t.Run(tt.Name, func(t *testing.T) { - h := tt.Webhook + w := tt.Webhook pod := *tt.Pod(minimal()) - container, err := h.containerInit(testNS, pod, multiPortInfo{}) + container, err := w.containerInit(testNS, pod, multiPortInfo{}) if tt.ErrStr == "" { require.NoError(t, err) + require.Equal(t, "CONSUL_HTTP_ADDR", container.Env[2].Name) + require.Equal(t, fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulHTTPPort), container.Env[2].Value) + require.Equal(t, "CONSUL_GRPC_ADDR", container.Env[3].Name) + require.Equal(t, fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulGRPCPort), container.Env[3].Value) + actual := strings.Join(container.Command, " ") + require.Contains(t, actual, tt.Cmd) + if tt.CmdNot != "" { + require.NotContains(t, actual, tt.CmdNot) + } } else { require.Contains(t, err.Error(), tt.ErrStr) } - actual := strings.Join(container.Command, " ") - require.Contains(t, actual, tt.Cmd) - if tt.CmdNot != "" { - require.NotContains(t, actual, tt.CmdNot) - } }) } } @@ -574,19 +529,10 @@ func TestHandlerContainerInit_namespacesAndPartitionsEnabled(t *testing.T) { ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ - -consul-service-namespace="default" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -namespace="default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="default" \`, }, { "whole template, default namespace, default partition", @@ -604,21 +550,11 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -partition="default" \ - -consul-service-namespace="default" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -partition="default" \ - -namespace="default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="default" \`, }, { "whole template, non-default namespace, no partition", @@ -636,19 +572,10 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ - -consul-service-namespace="non-default" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -namespace="non-default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="non-default" \`, }, { "whole template, non-default namespace, non-default partition", @@ -666,21 +593,11 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -partition="non-default-part" \ - -consul-service-namespace="non-default" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -partition="non-default-part" \ - -namespace="non-default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="non-default" \`, }, { "Whole template, auth method, non-default namespace, mirroring disabled, default partition", @@ -699,8 +616,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -710,16 +625,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -bearer-token-file=/var/run/secrets/kubernetes.io/serviceaccount/token \ -auth-method-namespace="non-default" \ -partition="default" \ - -consul-service-namespace="non-default" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -token-file="/consul/connect-inject/acl-token" \ - -partition="default" \ - -namespace="non-default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="non-default" \`, }, { "Whole template, auth method, non-default namespace, mirroring enabled, non-default partition", @@ -739,8 +645,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -750,16 +654,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -bearer-token-file=/var/run/secrets/kubernetes.io/serviceaccount/token \ -auth-method-namespace="default" \ -partition="non-default" \ - -consul-service-namespace="k8snamespace" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -token-file="/consul/connect-inject/acl-token" \ - -partition="non-default" \ - -namespace="k8snamespace" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + -consul-service-namespace="k8snamespace" \`, }, { "whole template, default namespace, tproxy enabled, no partition", @@ -778,20 +673,11 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -consul-service-namespace="default" \ -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -namespace="default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml - # Apply traffic redirection rules. /consul/connect-inject/consul connect redirect-traffic \ -namespace="default" \ @@ -815,22 +701,12 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -partition="default" \ -consul-service-namespace="non-default" \ -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -partition="default" \ - -namespace="non-default" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml - # Apply traffic redirection rules. /consul/connect-inject/consul connect redirect-traffic \ -partition="default" \ @@ -858,8 +734,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD ConsulGRPCPort: "8502", }, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -871,15 +745,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -partition="non-default" \ -consul-service-namespace="k8snamespace" \ -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -token-file="/consul/connect-inject/acl-token" \ - -partition="non-default" \ - -namespace="k8snamespace" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml - # Apply traffic redirection rules. /consul/connect-inject/consul connect redirect-traffic \ -token-file="/consul/connect-inject/acl-token" \ @@ -975,38 +840,20 @@ func TestHandlerContainerInit_Multiport(t *testing.T) { }, }, []string{`/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -multiport=true \ -proxy-id-file=/consul/connect-inject/proxyid-web \ - -service-name="web" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid-web)" \ - -admin-bind=127.0.0.1:19000 \ - -bootstrap > /consul/connect-inject/envoy-bootstrap-web.yaml`, + -service-name="web" \`, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -multiport=true \ -proxy-id-file=/consul/connect-inject/proxyid-web-admin \ - -service-name="web-admin" \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid-web-admin)" \ - -admin-bind=127.0.0.1:19001 \ - -bootstrap > /consul/connect-inject/envoy-bootstrap-web-admin.yaml`, + -service-name="web-admin" \`, }, }, { @@ -1033,8 +880,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD }, }, []string{`/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -1044,19 +889,9 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -bearer-token-file=/var/run/secrets/kubernetes.io/serviceaccount/token \ -acl-token-sink=/consul/connect-inject/acl-token-web \ -multiport=true \ - -proxy-id-file=/consul/connect-inject/proxyid-web \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid-web)" \ - -token-file="/consul/connect-inject/acl-token-web" \ - -admin-bind=127.0.0.1:19000 \ - -bootstrap > /consul/connect-inject/envoy-bootstrap-web.yaml`, + -proxy-id-file=/consul/connect-inject/proxyid-web \`, `/bin/sh -ec -export CONSUL_HTTP_ADDR="10.0.0.0:8500" -export CONSUL_GRPC_ADDR="10.0.0.0:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ @@ -1066,15 +901,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -bearer-token-file=/consul/serviceaccount-web-admin/token \ -acl-token-sink=/consul/connect-inject/acl-token-web-admin \ -multiport=true \ - -proxy-id-file=/consul/connect-inject/proxyid-web-admin \ - -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid-web-admin)" \ - -token-file="/consul/connect-inject/acl-token-web-admin" \ - -admin-bind=127.0.0.1:19001 \ - -bootstrap > /consul/connect-inject/envoy-bootstrap-web-admin.yaml`, + -proxy-id-file=/consul/connect-inject/proxyid-web-admin \`, }, }, } @@ -1129,13 +956,6 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -consul-api-timeout=5s \ -consul-node-name=k8s-service-mesh \ -acl-auth-method="release-name-consul-k8s-auth-method"`) - require.Contains(t, actual, ` -# Generate the envoy bootstrap code -/consul/connect-inject/consul connect envoy \ - -node-name=k8s-service-mesh \ - -proxy-id="$(cat /consul/connect-inject/proxyid)" \ - -token-file="/consul/connect-inject/acl-token" \ - -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`) } // If TLSEnabled is set, @@ -1174,20 +994,26 @@ func TestHandlerContainerInit_WithTLSAndCustomPorts(t *testing.T) { } container, err := w.containerInit(testNS, *pod, multiPortInfo{}) require.NoError(t, err) - actual := strings.Join(container.Command, " ") - if caProvided { - require.Contains(t, actual, ` -export CONSUL_HTTP_ADDR="https://10.0.0.0:443" -export CONSUL_GRPC_ADDR="https://10.0.0.0:8503" -export CONSUL_CACERT=/consul/connect-inject/consul-ca.pem -cat </consul/connect-inject/consul-ca.pem -consul-ca-cert -EOF`) - } else { - require.Contains(t, actual, ` -export CONSUL_HTTP_ADDR="https://10.0.0.0:443" -export CONSUL_GRPC_ADDR="https://10.0.0.0:8503" -`) + require.Equal(t, "CONSUL_HTTP_ADDR", container.Env[2].Name) + require.Equal(t, fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulHTTPPort), container.Env[2].Value) + require.Equal(t, "CONSUL_GRPC_ADDR", container.Env[3].Name) + require.Equal(t, fmt.Sprintf("%s:%s", w.ConsulAddress, w.ConsulGRPCPort), container.Env[3].Value) + if w.TLSEnabled { + require.Equal(t, "CONSUL_HTTP_SSL", container.Env[4].Name) + require.Equal(t, "true", container.Env[4].Value) + if caProvided { + require.Equal(t, "CONSUL_CACERT", container.Env[5].Name) + require.Equal(t, "/consul/connect-inject/consul-ca.pem", container.Env[5].Value) + } else { + caCertEnvVarSet := false + + for _, ev := range container.Env { + if ev.Name == "CONSUL_CACERT" { + caCertEnvVarSet = true + } + } + require.False(t, caCertEnvVarSet) + } } }) diff --git a/control-plane/connect-inject/container_volume.go b/control-plane/connect-inject/container_volume.go index 53ba985f3e..2cb086c29a 100644 --- a/control-plane/connect-inject/container_volume.go +++ b/control-plane/connect-inject/container_volume.go @@ -14,7 +14,7 @@ func (w *MeshWebhook) containerVolume() corev1.Volume { return corev1.Volume{ Name: volumeName, VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + EmptyDir: &corev1.EmptyDirVolumeSource{Medium: corev1.StorageMediumMemory}, }, } } diff --git a/control-plane/connect-inject/endpoints_controller.go b/control-plane/connect-inject/endpoints_controller.go index b746b19d9c..61cbd9dce0 100644 --- a/control-plane/connect-inject/endpoints_controller.go +++ b/control-plane/connect-inject/endpoints_controller.go @@ -33,7 +33,7 @@ const ( TokenMetaPodNameKey = "pod" kubernetesSuccessReasonMsg = "Kubernetes health checks passing" envoyPrometheusBindAddr = "envoy_prometheus_bind_addr" - envoySidecarContainer = "envoy-sidecar" + sidecarContainer = "consul-dataplane" // clusterIPTaggedAddressName is the key for the tagged address to store the service's cluster IP and service port // in Consul. Note: This value should not be changed without a corresponding change in Consul. diff --git a/control-plane/connect-inject/endpoints_controller_test.go b/control-plane/connect-inject/endpoints_controller_test.go index 0269d23055..67df084a2a 100644 --- a/control-plane/connect-inject/endpoints_controller_test.go +++ b/control-plane/connect-inject/endpoints_controller_test.go @@ -4684,7 +4684,7 @@ func TestCreateServiceRegistrations_withTransparentProxy(t *testing.T) { }, }, { - Name: envoySidecarContainer, + Name: sidecarContainer, Ports: []corev1.ContainerPort{ { Name: "http", diff --git a/control-plane/connect-inject/mesh_webhook.go b/control-plane/connect-inject/mesh_webhook.go index b2af10646b..3f448d7d06 100644 --- a/control-plane/connect-inject/mesh_webhook.go +++ b/control-plane/connect-inject/mesh_webhook.go @@ -37,11 +37,11 @@ type MeshWebhook struct { Clientset kubernetes.Interface // ImageConsul is the container image for Consul to use. - // ImageEnvoy is the container image for Envoy to use. + // ImageConsulDataplane is the container image for Envoy to use. // // Both of these MUST be set. - ImageConsul string - ImageEnvoy string + ImageConsul string + ImageConsulDataplane string // ImageConsulK8S is the container image for consul-k8s to use. // This image is used for the consul-sidecar container. @@ -77,6 +77,10 @@ type MeshWebhook struct { // host (i.e. not including port or protocol). ConsulAddress string + // ConsulTLSServerName is the SNI header to use to connect to the Consul servers + // over TLS. + ConsulTLSServerName string + // ConsulPartition is the name of the Admin Partition that the controller // is deployed in. It is an enterprise feature requiring Consul Enterprise 1.11+. // Its value is an empty string if partitions aren't enabled. @@ -172,7 +176,7 @@ type MeshWebhook struct { // Log Log logr.Logger - // Log settings for consul-sidecar + // Log settings for consul-dataplane LogLevel string LogJSON bool @@ -281,7 +285,7 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi pod.Spec.InitContainers = append(pod.Spec.InitContainers, initContainer) // Add the Envoy sidecar. - envoySidecar, err := w.envoySidecar(*ns, pod, multiPortInfo{}) + envoySidecar, err := w.consulDataplaneSidecar(*ns, pod, multiPortInfo{}) if err != nil { w.Log.Error(err, "error configuring injection sidecar container", "request name", req.Name) return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error configuring injection sidecar container: %s", err)) @@ -342,7 +346,7 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi pod.Spec.InitContainers = append(pod.Spec.InitContainers, initContainer) // Add the Envoy sidecar. - envoySidecar, err := w.envoySidecar(*ns, pod, mpi) + envoySidecar, err := w.consulDataplaneSidecar(*ns, pod, mpi) if err != nil { w.Log.Error(err, "error configuring injection sidecar container", "request name", req.Name) return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error configuring injection sidecar container: %s", err)) @@ -458,7 +462,7 @@ func (w *MeshWebhook) overwriteProbes(ns corev1.Namespace, pod *corev1.Pod) erro if tproxyEnabled && overwriteProbes { for i, container := range pod.Spec.Containers { // skip the "envoy-sidecar" container from having it's probes overridden - if container.Name == envoySidecarContainer { + if container.Name == sidecarContainer { continue } if container.LivenessProbe != nil && container.LivenessProbe.HTTPGet != nil { diff --git a/control-plane/connect-inject/mesh_webhook_test.go b/control-plane/connect-inject/mesh_webhook_test.go index 8b37462506..0505797acd 100644 --- a/control-plane/connect-inject/mesh_webhook_test.go +++ b/control-plane/connect-inject/mesh_webhook_test.go @@ -1710,7 +1710,7 @@ func TestOverwriteProbes(t *testing.T) { overwriteProbes: true, podContainers: []corev1.Container{ { - Name: envoySidecarContainer, + Name: sidecarContainer, }, }, }, diff --git a/control-plane/subcommand/flags/http.go b/control-plane/subcommand/flags/http.go index db06345cd5..06bbcc6b7d 100644 --- a/control-plane/subcommand/flags/http.go +++ b/control-plane/subcommand/flags/http.go @@ -90,6 +90,10 @@ func (f *HTTPFlags) SetTokenFile(v string) error { return f.tokenFile.Set(v) } +func (f *HTTPFlags) TLSServerName() string { + return f.tlsServerName.String() +} + func (f *HTTPFlags) ReadTokenFile() (string, error) { tokenFile := f.tokenFile.String() if tokenFile == "" { diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 01c92673b9..ed0dec77f6 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -42,7 +42,7 @@ type Command struct { flagCertDir string // Directory with TLS certs for listening (PEM) flagDefaultInject bool // True to inject by default flagConsulImage string // Docker image for Consul - flagEnvoyImage string // Docker image for Envoy + flagConsulDataplaneImage string // Docker image for Envoy flagConsulK8sImage string // Docker image for consul-k8s flagACLAuthMethod string // Auth Method to use for ACLs, if enabled flagWriteServiceDefaults bool // True to enable central config injection @@ -148,8 +148,8 @@ func (c *Command) init() { "Directory with PEM-encoded TLS certificate and key to serve.") c.flagSet.StringVar(&c.flagConsulImage, "consul-image", "", "Docker image for Consul.") - c.flagSet.StringVar(&c.flagEnvoyImage, "envoy-image", "", - "Docker image for Envoy.") + c.flagSet.StringVar(&c.flagConsulDataplaneImage, "consul-dataplane-image", "", + "Docker image for Consul Dataplane.") c.flagSet.StringVar(&c.flagConsulK8sImage, "consul-k8s-image", "", "Docker image for consul-k8s. Used for the connect sidecar.") c.flagSet.BoolVar(&c.flagEnablePeering, "enable-peering", false, "Enable cluster peering controllers.") @@ -269,6 +269,7 @@ func (c *Command) Run(args []string) int { return 1 } } + if c.flagDefaultSidecarProxyCPULimit != "" { sidecarProxyCPULimit, err = resource.ParseQuantity(c.flagDefaultSidecarProxyCPULimit) if err != nil { @@ -526,7 +527,7 @@ func (c *Command) Run(args []string) int { Clientset: c.clientset, ConsulClient: c.consulClient, ImageConsul: c.flagConsulImage, - ImageEnvoy: c.flagEnvoyImage, + ImageConsulDataplane: c.flagConsulDataplaneImage, EnvoyExtraArgs: c.flagEnvoyExtraArgs, ImageConsulK8S: c.flagConsulK8sImage, RequireAnnotation: !c.flagDefaultInject, @@ -536,6 +537,7 @@ func (c *Command) Run(args []string) int { ConsulHTTPPort: consulURL.Port(), ConsulGRPCPort: "8502", // todo(ishustava): should be passed via flag ConsulAddress: consulURL.Hostname(), + ConsulTLSServerName: c.http.TLSServerName(), DefaultProxyCPURequest: sidecarProxyCPURequest, DefaultProxyCPULimit: sidecarProxyCPULimit, DefaultProxyMemoryRequest: sidecarProxyMemoryRequest, @@ -600,8 +602,8 @@ func (c *Command) validateFlags() error { if c.flagConsulImage == "" { return errors.New("-consul-image must be set") } - if c.flagEnvoyImage == "" { - return errors.New("-envoy-image must be set") + if c.flagConsulDataplaneImage == "" { + return errors.New("-consul-dataplane-image must be set") } if c.flagWriteServiceDefaults { return errors.New("-enable-central-config is no longer supported") diff --git a/control-plane/subcommand/inject-connect/command_test.go b/control-plane/subcommand/inject-connect/command_test.go index 93fff95a94..e54cf9da8b 100644 --- a/control-plane/subcommand/inject-connect/command_test.go +++ b/control-plane/subcommand/inject-connect/command_test.go @@ -25,64 +25,64 @@ func TestRun_FlagValidation(t *testing.T) { }, { flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo"}, - expErr: "-envoy-image must be set", + expErr: "-consul-dataplane-image must be set", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0"}, + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0"}, expErr: "-consul-api-timeout must be set to a value greater than 0", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-log-level", "invalid"}, expErr: "unknown log level \"invalid\": unrecognized level: \"invalid\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-enable-central-config", "true"}, expErr: "-enable-central-config is no longer supported", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-protocol", "http"}, expErr: "-default-protocol is no longer supported", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-ca-file", "bar"}, expErr: "error reading Consul's CA cert file \"bar\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-enable-partitions", "true"}, expErr: "-partition-name must set if -enable-partitions is set to 'true'", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-partition", "default"}, expErr: "-enable-partitions must be set to 'true' if -partition-name is set", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-cpu-limit=unparseable"}, expErr: "-default-sidecar-proxy-cpu-limit is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-cpu-request=unparseable"}, expErr: "-default-sidecar-proxy-cpu-request is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-memory-limit=unparseable"}, expErr: "-default-sidecar-proxy-memory-limit is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-memory-request=unparseable"}, expErr: "-default-sidecar-proxy-memory-request is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-memory-request=50Mi", "-default-sidecar-proxy-memory-limit=25Mi", @@ -90,7 +90,7 @@ func TestRun_FlagValidation(t *testing.T) { expErr: "request must be <= limit: -default-sidecar-proxy-memory-request value of \"50Mi\" is greater than the -default-sidecar-proxy-memory-limit value of \"25Mi\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-sidecar-proxy-cpu-request=50m", "-default-sidecar-proxy-cpu-limit=25m", @@ -98,87 +98,87 @@ func TestRun_FlagValidation(t *testing.T) { expErr: "request must be <= limit: -default-sidecar-proxy-cpu-request value of \"50m\" is greater than the -default-sidecar-proxy-cpu-limit value of \"25m\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-cpu-limit=unparseable"}, expErr: "-init-container-cpu-limit 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-cpu-request=unparseable"}, expErr: "-init-container-cpu-request 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-memory-limit=unparseable"}, expErr: "-init-container-memory-limit 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-memory-request=unparseable"}, expErr: "-init-container-memory-request 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-memory-request=50Mi", "-init-container-memory-limit=25Mi", }, expErr: "request must be <= limit: -init-container-memory-request value of \"50Mi\" is greater than the -init-container-memory-limit value of \"25Mi\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-init-container-cpu-request=50m", "-init-container-cpu-limit=25m", }, expErr: "request must be <= limit: -init-container-cpu-request value of \"50m\" is greater than the -init-container-cpu-limit value of \"25m\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-cpu-limit=unparseable"}, expErr: "-default-consul-sidecar-cpu-limit 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-cpu-request=unparseable"}, expErr: "-default-consul-sidecar-cpu-request 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-memory-limit=unparseable"}, expErr: "-default-consul-sidecar-memory-limit 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-memory-request=unparseable"}, expErr: "-default-consul-sidecar-memory-request 'unparseable' is invalid", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-memory-request=50Mi", "-default-consul-sidecar-memory-limit=25Mi", }, expErr: "request must be <= limit: -default-consul-sidecar-memory-request value of \"50Mi\" is greater than the -default-consul-sidecar-memory-limit value of \"25Mi\"", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-consul-sidecar-cpu-request=50m", "-default-consul-sidecar-cpu-limit=25m", }, expErr: "request must be <= limit: -default-consul-sidecar-cpu-request value of \"50m\" is greater than the -default-consul-sidecar-cpu-limit value of \"25m\"", }, { - flags: []string{"-consul-k8s-image", "hashicorp/consul-k8s", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "hashicorp/consul-k8s", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-http-addr=http://0.0.0.0:9999", "-listen", "999999"}, expErr: "missing port in address: 999999", }, { - flags: []string{"-consul-k8s-image", "hashicorp/consul-k8s", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "hashicorp/consul-k8s", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-http-addr=http://0.0.0.0:9999", "-listen", ":foobar"}, expErr: "unable to parse port string: strconv.Atoi: parsing \"foobar\": invalid syntax", }, { - flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-envoy-image", "envoy:1.16.0", + flags: []string{"-consul-k8s-image", "foo", "-consul-image", "foo", "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", "-default-envoy-proxy-concurrency=-42", }, expErr: "-default-envoy-proxy-concurrency must be >= 0 if set", @@ -227,7 +227,7 @@ func TestRun_ValidationConsulHTTPAddr(t *testing.T) { flags := []string{ "-consul-k8s-image", "hashicorp/consul-k8s", "-consul-image", "foo", - "-envoy-image", "envoy:1.16.0", + "-consul-dataplane-image", "consul-dataplane:1.14.0", "-consul-api-timeout", "5s", }