From cb7fbfed837a52dea0d8351a6279effcb65ab3dc Mon Sep 17 00:00:00 2001 From: ajanikow <12255597+ajanikow@users.noreply.github.com> Date: Thu, 30 Jul 2020 07:15:10 +0000 Subject: [PATCH] Allow to disable HTTP in exporter --- CHANGELOG.md | 1 + pkg/apis/deployment/v1/metrics_spec.go | 9 ++ .../deployment/v1/zz_generated.deepcopy.go | 5 + pkg/deployment/deployment_metrics_test.go | 146 ++++++++++++++++++ pkg/deployment/deployment_suite_test.go | 22 +-- pkg/deployment/resources/exporter.go | 2 +- .../resources/pod_creator_arangod.go | 2 +- 7 files changed, 176 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a91ba965..b19a89cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A) - Add Labels and Annotations to ServiceMonitor +- Allow to expose Exporter in HTTP with secured Deployments ## [1.0.4](https://github.com/arangodb/kube-arangodb/tree/1.0.4) (2020-07-28) - Add Encryption Key rotation feature for ArangoDB EE 3.7+ diff --git a/pkg/apis/deployment/v1/metrics_spec.go b/pkg/apis/deployment/v1/metrics_spec.go index d252cd5ff..9a7cd7c72 100644 --- a/pkg/apis/deployment/v1/metrics_spec.go +++ b/pkg/apis/deployment/v1/metrics_spec.go @@ -72,10 +72,19 @@ type MetricsSpec struct { Authentication MetricsAuthenticationSpec `json:"authentication,omitempty"` Resources v1.ResourceRequirements `json:"resources,omitempty"` Mode *MetricsMode `json:"mode,omitempty"` + TLS *bool `json:"tls,omitempty"` Port *uint16 `json:"port,omitempty"` } +func (s *MetricsSpec) IsTLS() bool { + if s == nil || s.TLS == nil { + return true + } + + return *s.TLS +} + func (s *MetricsSpec) GetPort() uint16 { if s == nil || s.Port == nil { return k8sutil.ArangoExporterPort diff --git a/pkg/apis/deployment/v1/zz_generated.deepcopy.go b/pkg/apis/deployment/v1/zz_generated.deepcopy.go index ea5616af6..b896d58d6 100644 --- a/pkg/apis/deployment/v1/zz_generated.deepcopy.go +++ b/pkg/apis/deployment/v1/zz_generated.deepcopy.go @@ -818,6 +818,11 @@ func (in *MetricsSpec) DeepCopyInto(out *MetricsSpec) { *out = new(MetricsMode) **out = **in } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(bool) + **out = **in + } if in.Port != nil { in, out := &in.Port, &out.Port *out = new(uint16) diff --git a/pkg/deployment/deployment_metrics_test.go b/pkg/deployment/deployment_metrics_test.go index 2adf94eeb..d1bbc7ce7 100644 --- a/pkg/deployment/deployment_metrics_test.go +++ b/pkg/deployment/deployment_metrics_test.go @@ -429,6 +429,152 @@ func TestEnsurePod_Metrics(t *testing.T) { }, }, }, + { + Name: "Agency Pod with sidecar metrics exporter and port override, with enabled deployment tls", + ArangoDeployment: &api.ArangoDeployment{ + Spec: api.DeploymentSpec{ + Image: util.NewString(testImage), + Authentication: noAuthentication, + TLS: tlsSpec, + Metrics: func() api.MetricsSpec { + m := metricsSpec.DeepCopy() + + m.Port = util.NewUInt16(9999) + + m.Mode = api.MetricsModeSidecar.New() + + return *m + }(), + }, + }, + Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) { + deployment.status.last = api.DeploymentStatus{ + Members: api.DeploymentStatusMembers{ + Agents: api.MemberStatusList{ + firstAgentStatus, + }, + }, + Images: createTestImages(false), + } + + testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus) + testCase.ExpectedPod.ObjectMeta.Labels[k8sutil.LabelKeyArangoExporter] = testYes + }, + ExpectedEvent: "member agent is created", + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ + k8sutil.CreateVolumeEmptyDir(k8sutil.ArangodVolumeName), + createTestTLSVolume(api.ServerGroupAgentsString, firstAgentStatus.ID), + k8sutil.CreateVolumeWithSecret(k8sutil.ExporterJWTVolumeName, testExporterToken), + }, + Containers: []core.Container{ + { + Name: k8sutil.ServerContainerName, + Image: testImage, + Command: createTestCommandForAgent(firstAgentStatus.ID, true, false, false), + Ports: createTestPorts(), + VolumeMounts: []core.VolumeMount{ + k8sutil.ArangodVolumeMount(), + k8sutil.TlsKeyfileVolumeMount(), + }, + Resources: emptyResources, + LivenessProbe: createTestLivenessProbe(httpProbe, true, "", k8sutil.ArangoPort), + ImagePullPolicy: core.PullIfNotPresent, + SecurityContext: securityContext.NewSecurityContext(), + }, + func() core.Container { + z := testCreateExporterContainerWithPortAndSecureEndpoint(true, true, emptyResources, 9999) + + z.VolumeMounts = append(z.VolumeMounts, k8sutil.TlsKeyfileVolumeMount()) + + z.Command = append(z.Command, "--mode=passthru") + return z + }(), + }, + RestartPolicy: core.RestartPolicyNever, + TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout, + Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID, + Subdomain: testDeploymentName + "-int", + Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString, + false, ""), + }, + }, + }, + { + Name: "Agency Pod with sidecar metrics exporter and port override, with enabled deployment tls but disabled metrics tls", + ArangoDeployment: &api.ArangoDeployment{ + Spec: api.DeploymentSpec{ + Image: util.NewString(testImage), + Authentication: noAuthentication, + TLS: tlsSpec, + Metrics: func() api.MetricsSpec { + m := metricsSpec.DeepCopy() + + m.Port = util.NewUInt16(9999) + + m.Mode = api.MetricsModeSidecar.New() + + m.TLS = util.NewBool(false) + + return *m + }(), + }, + }, + Helper: func(t *testing.T, deployment *Deployment, testCase *testCaseStruct) { + deployment.status.last = api.DeploymentStatus{ + Members: api.DeploymentStatusMembers{ + Agents: api.MemberStatusList{ + firstAgentStatus, + }, + }, + Images: createTestImages(false), + } + + testCase.createTestPodData(deployment, api.ServerGroupAgents, firstAgentStatus) + testCase.ExpectedPod.ObjectMeta.Labels[k8sutil.LabelKeyArangoExporter] = testYes + }, + ExpectedEvent: "member agent is created", + ExpectedPod: core.Pod{ + Spec: core.PodSpec{ + Volumes: []core.Volume{ + k8sutil.CreateVolumeEmptyDir(k8sutil.ArangodVolumeName), + createTestTLSVolume(api.ServerGroupAgentsString, firstAgentStatus.ID), + k8sutil.CreateVolumeWithSecret(k8sutil.ExporterJWTVolumeName, testExporterToken), + }, + Containers: []core.Container{ + { + Name: k8sutil.ServerContainerName, + Image: testImage, + Command: createTestCommandForAgent(firstAgentStatus.ID, true, false, false), + Ports: createTestPorts(), + VolumeMounts: []core.VolumeMount{ + k8sutil.ArangodVolumeMount(), + k8sutil.TlsKeyfileVolumeMount(), + }, + Resources: emptyResources, + LivenessProbe: createTestLivenessProbe(httpProbe, true, "", k8sutil.ArangoPort), + ImagePullPolicy: core.PullIfNotPresent, + SecurityContext: securityContext.NewSecurityContext(), + }, + func() core.Container { + z := testCreateExporterContainerWithPortAndSecureEndpoint(true, false, emptyResources, 9999) + + z.VolumeMounts = append(z.VolumeMounts, k8sutil.TlsKeyfileVolumeMount()) + + z.Command = append(z.Command, "--mode=passthru") + return z + }(), + }, + RestartPolicy: core.RestartPolicyNever, + TerminationGracePeriodSeconds: &defaultAgentTerminationTimeout, + Hostname: testDeploymentName + "-" + api.ServerGroupAgentsString + "-" + firstAgentStatus.ID, + Subdomain: testDeploymentName + "-int", + Affinity: k8sutil.CreateAffinity(testDeploymentName, api.ServerGroupAgentsString, + false, ""), + }, + }, + }, } runTestCases(t, testCases...) diff --git a/pkg/deployment/deployment_suite_test.go b/pkg/deployment/deployment_suite_test.go index 24a600498..bff6e82a1 100644 --- a/pkg/deployment/deployment_suite_test.go +++ b/pkg/deployment/deployment_suite_test.go @@ -486,7 +486,7 @@ func createTestExporterPorts(port uint16) []core.ContainerPort { } } -func createTestExporterCommand(secure bool, port uint16) []string { +func createTestExporterCommand(secure, exporterSecure bool, port uint16) []string { command := []string{ "/app/arangodb-exporter", } @@ -499,14 +499,14 @@ func createTestExporterCommand(secure bool, port uint16) []string { command = append(command, "--arangodb.jwt-file=/secrets/exporter/jwt/token") - if secure { - command = append(command, "--ssl.keyfile=/secrets/tls/tls.keyfile") - } - if port != k8sutil.ArangoExporterPort { command = append(command, fmt.Sprintf("--server.address=:%d", port)) } + if exporterSecure { + command = append(command, "--ssl.keyfile=/secrets/tls/tls.keyfile") + } + return command } @@ -561,24 +561,28 @@ func (testCase *testCaseStruct) createTestPodData(deployment *Deployment, group testCase.ExpectedPod.Spec.Tolerations = deployment.resources.CreatePodTolerations(group, groupSpec) } -func testCreateExporterContainerWithPort(secure bool, resources core.ResourceRequirements, port uint16) core.Container { +func testCreateExporterContainerWithPortAndSecureEndpoint(secure, exporterSecure bool, resources core.ResourceRequirements, port uint16) core.Container { var securityContext api.ServerGroupSpecSecurityContext return core.Container{ Name: k8sutil.ExporterContainerName, Image: testExporterImage, - Command: createTestExporterCommand(secure, port), + Command: createTestExporterCommand(secure, exporterSecure, port), Ports: createTestExporterPorts(port), VolumeMounts: []core.VolumeMount{ k8sutil.ExporterJWTVolumeMount(), }, Resources: k8sutil.ExtractPodResourceRequirement(resources), - LivenessProbe: createTestExporterLivenessProbe(secure), + LivenessProbe: createTestExporterLivenessProbe(exporterSecure), ImagePullPolicy: core.PullIfNotPresent, SecurityContext: securityContext.NewSecurityContext(), } } +func testCreateExporterContainerWithPort(secure bool, resources core.ResourceRequirements, port uint16) core.Container { + return testCreateExporterContainerWithPortAndSecureEndpoint(secure, secure, resources, port) +} + func testCreateExporterContainer(secure bool, resources core.ResourceRequirements) core.Container { - return testCreateExporterContainerWithPort(secure, resources, k8sutil.ArangoExporterPort) + return testCreateExporterContainerWithPortAndSecureEndpoint(secure, secure, resources, k8sutil.ArangoExporterPort) } diff --git a/pkg/deployment/resources/exporter.go b/pkg/deployment/resources/exporter.go index bb2b21b4f..409141b64 100644 --- a/pkg/deployment/resources/exporter.go +++ b/pkg/deployment/resources/exporter.go @@ -75,7 +75,7 @@ func createExporterArgs(spec api.DeploymentSpec) []string { k8sutil.OptionPair{Key: "--arangodb.endpoint", Value: scheme + "://localhost:" + strconv.Itoa(k8sutil.ArangoPort)}, ) keyPath := filepath.Join(k8sutil.TLSKeyfileVolumeMountDir, constants.SecretTLSKeyfile) - if spec.IsSecure() { + if spec.IsSecure() && spec.Metrics.IsTLS() { options = append(options, k8sutil.OptionPair{Key: "--ssl.keyfile", Value: keyPath}, ) diff --git a/pkg/deployment/resources/pod_creator_arangod.go b/pkg/deployment/resources/pod_creator_arangod.go index 4694e20be..7b78dbb81 100644 --- a/pkg/deployment/resources/pod_creator_arangod.go +++ b/pkg/deployment/resources/pod_creator_arangod.go @@ -446,7 +446,7 @@ func (m *MemberArangoDPod) createMetricsExporterSidecar() *core.Container { } c := ArangodbExporterContainer(image, args, - createExporterLivenessProbe(m.spec.IsSecure()), m.spec.Metrics.Resources, + createExporterLivenessProbe(m.spec.IsSecure() && m.spec.Metrics.IsTLS()), m.spec.Metrics.Resources, m.groupSpec.SecurityContext.NewSecurityContext(), m.spec)