Skip to content

Commit 7a91a24

Browse files
committed
Add TLS support to auto-instrumentation
Signed-off-by: Pavol Loffay <[email protected]>
1 parent 20a320c commit 7a91a24

10 files changed

+221
-9
lines changed

apis/v1alpha1/instrumentation_types.go

+23
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,31 @@ type Resource struct {
9797
// Exporter defines OTLP exporter configuration.
9898
type Exporter struct {
9999
// Endpoint is address of the collector with OTLP endpoint.
100+
// The TLS is enabled
100101
// +optional
101102
Endpoint string `json:"endpoint,omitempty"`
103+
104+
// TLS defines certificates for TLS.
105+
// TLS needs to be enabled by specifying https:// scheme in the Endpoint.
106+
TLS *TLS `json:"tls,omitempty"`
107+
}
108+
109+
// TLS defines TLS configuration for exporter.
110+
type TLS struct {
111+
// SecretName defines a secret name that will be used to configure TLS on the exporter.
112+
// It is user responsibility to create the secret in the namespace of the workload.
113+
// The secret should contain keys ca.crt, tls.key, tls.crt
114+
SecretName string `json:"secretName,omitempty"`
115+
// CA defines the key of certificate in the secret or absolute path to a certificate.
116+
// The absolute path can be used when certificate is already present on the workload filesystem e.g.
117+
// /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt
118+
CA string `json:"ca,omitempty"`
119+
// Cert defines the key of the client certificate in the secret or absolute path to a certificate.
120+
// The absolute path can be used when certificate is already present on the workload filesystem.
121+
Cert string `json:"cert,omitempty"`
122+
// Key defines a key of the private key in the secret or absolute path to a certificate.
123+
// The absolute path can be used when certificate is already present on the workload filesystem.
124+
Key string `json:"key,omitempty"`
102125
}
103126

104127
// Sampler defines sampling configuration.

apis/v1alpha1/zz_generated.deepcopy.go

+21-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/community/manifests/opentelemetry-operator.clusterserviceversion.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ metadata:
9999
categories: Logging & Tracing,Monitoring
100100
certified: "false"
101101
containerImage: ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator
102-
createdAt: "2024-09-19T17:15:52Z"
102+
createdAt: "2024-10-08T16:24:01Z"
103103
description: Provides the OpenTelemetry components, including the Collector
104104
operators.operatorframework.io/builder: operator-sdk-v1.29.0
105105
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3

bundle/community/manifests/opentelemetry.io_instrumentations.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,17 @@ spec:
409409
properties:
410410
endpoint:
411411
type: string
412+
tls:
413+
properties:
414+
ca:
415+
type: string
416+
cert:
417+
type: string
418+
key:
419+
type: string
420+
secretName:
421+
type: string
422+
type: object
412423
type: object
413424
go:
414425
properties:

bundle/openshift/manifests/opentelemetry-operator.clusterserviceversion.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ metadata:
9999
categories: Logging & Tracing,Monitoring
100100
certified: "false"
101101
containerImage: ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator
102-
createdAt: "2024-09-19T17:16:12Z"
102+
createdAt: "2024-10-08T16:24:02Z"
103103
description: Provides the OpenTelemetry components, including the Collector
104104
operators.operatorframework.io/builder: operator-sdk-v1.29.0
105105
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3

bundle/openshift/manifests/opentelemetry.io_instrumentations.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,17 @@ spec:
409409
properties:
410410
endpoint:
411411
type: string
412+
tls:
413+
properties:
414+
ca:
415+
type: string
416+
cert:
417+
type: string
418+
key:
419+
type: string
420+
secretName:
421+
type: string
422+
type: object
412423
type: object
413424
go:
414425
properties:

config/crd/bases/opentelemetry.io_instrumentations.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,17 @@ spec:
407407
properties:
408408
endpoint:
409409
type: string
410+
tls:
411+
properties:
412+
ca:
413+
type: string
414+
cert:
415+
type: string
416+
key:
417+
type: string
418+
secretName:
419+
type: string
420+
type: object
410421
type: object
411422
go:
412423
properties:

pkg/constants/env.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
package constants
1616

1717
const (
18-
EnvOTELServiceName = "OTEL_SERVICE_NAME"
19-
EnvOTELExporterOTLPEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT"
20-
EnvOTELResourceAttrs = "OTEL_RESOURCE_ATTRIBUTES"
21-
EnvOTELPropagators = "OTEL_PROPAGATORS"
22-
EnvOTELTracesSampler = "OTEL_TRACES_SAMPLER"
23-
EnvOTELTracesSamplerArg = "OTEL_TRACES_SAMPLER_ARG"
18+
EnvOTELServiceName = "OTEL_SERVICE_NAME"
19+
EnvOTELResourceAttrs = "OTEL_RESOURCE_ATTRIBUTES"
20+
EnvOTELPropagators = "OTEL_PROPAGATORS"
21+
EnvOTELTracesSampler = "OTEL_TRACES_SAMPLER"
22+
EnvOTELTracesSamplerArg = "OTEL_TRACES_SAMPLER_ARG"
23+
24+
EnvOTELExporterOTLPEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT"
25+
EnvOTELExporterCertificate = "OTEL_EXPORTER_OTLP_CERTIFICATE"
26+
EnvOTELExporterClientCertificate = "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE"
27+
EnvOTELExporterClientKey = "OTEL_EXPORTER_OTLP_CLIENT_KEY"
2428

2529
InstrumentationPrefix = "instrumentation.opentelemetry.io/"
2630
AnnotationDefaultAutoInstrumentationJava = InstrumentationPrefix + "default-auto-instrumentation-java-image"

pkg/instrumentation/sdk.go

+84
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package instrumentation
1717
import (
1818
"context"
1919
"fmt"
20+
"path/filepath"
2021
"sort"
2122
"strings"
2223
"time"
@@ -44,6 +45,9 @@ const (
4445
volumeName = "opentelemetry-auto-instrumentation"
4546
initContainerName = "opentelemetry-auto-instrumentation"
4647
sideCarName = "opentelemetry-auto-instrumentation"
48+
49+
exporterCertsVolumeName = volumeName + "-exporter-certs"
50+
exporterCertsMountPath = "/otel-auto-instrumentation-exporter-certs"
4751
)
4852

4953
// inject a new sidecar container to the given pod, based on the given OpenTelemetryCollector.
@@ -304,6 +308,7 @@ func (i *sdkInjector) injectCommonSDKConfig(ctx context.Context, otelinst v1alph
304308
Value: chooseServiceName(pod, useLabelsForResourceAttributes, resourceMap, appIndex),
305309
})
306310
}
311+
configureExporter(otelinst.Spec.Exporter, &pod, container)
307312
if otelinst.Spec.Exporter.Endpoint != "" {
308313
idx = getIndexOfEnv(container.Env, constants.EnvOTELExporterOTLPEndpoint)
309314
if idx == -1 {
@@ -413,6 +418,85 @@ func (i *sdkInjector) injectCommonSDKConfig(ctx context.Context, otelinst v1alph
413418
return pod
414419
}
415420

421+
func configureExporter(exporter v1alpha1.Exporter, pod *corev1.Pod, container *corev1.Container) {
422+
if exporter.Endpoint != "" {
423+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterOTLPEndpoint) == -1 {
424+
container.Env = append(container.Env, corev1.EnvVar{
425+
Name: constants.EnvOTELExporterOTLPEndpoint,
426+
Value: exporter.Endpoint,
427+
})
428+
}
429+
}
430+
if exporter.TLS == nil {
431+
return
432+
}
433+
434+
if exporter.TLS.CA != "" {
435+
val := fmt.Sprintf("%s/%s", exporterCertsMountPath, exporter.TLS.CA)
436+
if filepath.IsAbs(exporter.TLS.CA) {
437+
val = exporter.TLS.CA
438+
}
439+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterCertificate) == -1 {
440+
container.Env = append(container.Env, corev1.EnvVar{
441+
Name: constants.EnvOTELExporterCertificate,
442+
Value: val,
443+
})
444+
}
445+
}
446+
if exporter.TLS.Cert != "" {
447+
val := fmt.Sprintf("%s/%s", exporterCertsMountPath, exporter.TLS.Cert)
448+
if filepath.IsAbs(exporter.TLS.Cert) {
449+
val = exporter.TLS.Cert
450+
}
451+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterClientCertificate) == -1 {
452+
container.Env = append(container.Env, corev1.EnvVar{
453+
Name: constants.EnvOTELExporterClientCertificate,
454+
Value: val,
455+
})
456+
}
457+
}
458+
if exporter.TLS.Key != "" {
459+
val := fmt.Sprintf("%s/%s", exporterCertsMountPath, exporter.TLS.Key)
460+
if filepath.IsAbs(exporter.TLS.Key) {
461+
val = exporter.TLS.Key
462+
}
463+
if getIndexOfEnv(container.Env, constants.EnvOTELExporterClientKey) == -1 {
464+
container.Env = append(container.Env, corev1.EnvVar{
465+
Name: constants.EnvOTELExporterClientKey,
466+
Value: val,
467+
})
468+
}
469+
}
470+
471+
if exporter.TLS.SecretName != "" {
472+
addVolume := true
473+
for _, vol := range pod.Spec.Volumes {
474+
if vol.Name == exporterCertsVolumeName {
475+
addVolume = false
476+
}
477+
}
478+
if addVolume {
479+
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
480+
Name: exporterCertsVolumeName,
481+
VolumeSource: corev1.VolumeSource{
482+
Secret: &corev1.SecretVolumeSource{SecretName: exporter.TLS.SecretName},
483+
}})
484+
}
485+
addVolumeMount := true
486+
for _, vol := range container.VolumeMounts {
487+
if vol.Name == exporterCertsVolumeName {
488+
addVolumeMount = false
489+
}
490+
}
491+
if addVolumeMount {
492+
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
493+
Name: exporterCertsVolumeName,
494+
MountPath: exporterCertsMountPath,
495+
})
496+
}
497+
}
498+
}
499+
416500
// chooseServiceName returns the service name to be used in the instrumentation.
417501
// The precedence is as follows:
418502
// 1. label or annotation with key "service.name" or "app.kubernetes.io/name".

pkg/instrumentation/sdk_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -2565,3 +2565,51 @@ func TestChooseServiceName(t *testing.T) {
25652565
})
25662566
}
25672567
}
2568+
2569+
func TestExporter(t *testing.T) {
2570+
exp := v1alpha1.Exporter{
2571+
Endpoint: "http://collector:4318",
2572+
TLS: &v1alpha1.TLS{
2573+
SecretName: "my-certs",
2574+
CA: "ca.crt",
2575+
Cert: "cert.crt",
2576+
Key: "key.key",
2577+
},
2578+
}
2579+
pod := corev1.Pod{
2580+
Spec: corev1.PodSpec{
2581+
Containers: []corev1.Container{
2582+
{},
2583+
},
2584+
},
2585+
}
2586+
configureExporter(exp, &pod, &pod.Spec.Containers[0])
2587+
assert.Equal(t, []corev1.EnvVar{
2588+
{
2589+
Name: "OTEL_EXPORTER_OTLP_ENDPOINT",
2590+
Value: "http://collector:4318",
2591+
},
2592+
{
2593+
Name: "OTEL_EXPORTER_OTLP_CERTIFICATE",
2594+
Value: "/otel-auto-instrumentation-exporter-certs/ca.crt",
2595+
},
2596+
{
2597+
Name: "OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE",
2598+
Value: "/otel-auto-instrumentation-exporter-certs/cert.crt",
2599+
},
2600+
{
2601+
Name: "OTEL_EXPORTER_OTLP_CLIENT_KEY",
2602+
Value: "/otel-auto-instrumentation-exporter-certs/key.key",
2603+
},
2604+
}, pod.Spec.Containers[0].Env)
2605+
assert.Equal(t, []corev1.Volume{
2606+
{
2607+
Name: "opentelemetry-auto-instrumentation-exporter-certs",
2608+
VolumeSource: corev1.VolumeSource{
2609+
Secret: &corev1.SecretVolumeSource{
2610+
SecretName: "my-certs",
2611+
},
2612+
},
2613+
},
2614+
}, pod.Spec.Volumes)
2615+
}

0 commit comments

Comments
 (0)