Skip to content

Commit

Permalink
Merge branch 'main' into update-chainsaw
Browse files Browse the repository at this point in the history
  • Loading branch information
jaronoff97 authored Oct 15, 2024
2 parents 29d46c5 + 8de23cc commit a2ce78b
Show file tree
Hide file tree
Showing 35 changed files with 1,303 additions and 141 deletions.
18 changes: 18 additions & 0 deletions .chloggen/fix_validation-stabilizationWindowSeconds.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
component: collector-webhook

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "Fixed validation of `stabilizationWindowSeconds` in autoscaler behaviour"

# One or more tracking issues related to the change
issues: [3345]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
The validation of `stabilizationWindowSeconds` in the `autoscaler.behaviour.scale[Up|Down]` incorrectly rejected 0 as an invalid value.
This has been fixed to ensure that the value is validated correctly (should be >=0 and <=3600) and the error messsage has been updated to reflect this.
34 changes: 34 additions & 0 deletions .chloggen/inst-tls.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
component: auto-instrumentation

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add support for specifying exporter TLS certificates in auto-instrumentation.

# One or more tracking issues related to the change
issues: [3338]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
Now Instrumentation CR supports specifying TLS certificates for exporter:
```yaml
spec:
exporter:
endpoint: https://otel-collector:4317
tls:
secretName: otel-tls-certs
configMapName: otel-ca-bundle
# otel-ca-bundle
ca: ca.crt
# present in otel-tls-certs
cert: tls.crt
# present in otel-tls-certs
key: tls.key
```
* Propagating secrets across namespaces can be done with https://github.com/EmberStack/kubernetes-reflector or https://github.com/zakkg3/ClusterSecret
* Restarting workloads on certificate renewal can be done with https://github.com/stakater/Reloader or https://github.com/wave-k8s/wave
29 changes: 29 additions & 0 deletions apis/v1alpha1/instrumentation_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,37 @@ type Resource struct {
// Exporter defines OTLP exporter configuration.
type Exporter struct {
// Endpoint is address of the collector with OTLP endpoint.
// If the endpoint defines https:// scheme TLS has to be specified.
// +optional
Endpoint string `json:"endpoint,omitempty"`

// TLS defines certificates for TLS.
// TLS needs to be enabled by specifying https:// scheme in the Endpoint.
TLS *TLS `json:"tls,omitempty"`
}

// TLS defines TLS configuration for exporter.
type TLS struct {
// SecretName defines secret name that will be used to configure TLS on the exporter.
// It is user responsibility to create the secret in the namespace of the workload.
// The secret must contain client certificate (Cert) and private key (Key).
// The CA certificate might be defined in the secret or in the config map.
SecretName string `json:"secretName,omitempty"`

// ConfigMapName defines configmap name with CA certificate. If it is not defined CA certificate will be
// used from the secret defined in SecretName.
ConfigMapName string `json:"configMapName,omitempty"`

// CA defines the key of certificate (e.g. ca.crt) in the configmap map, secret or absolute path to a certificate.
// The absolute path can be used when certificate is already present on the workload filesystem e.g.
// /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt
CA string `json:"ca,omitempty"`
// Cert defines the key (e.g. tls.crt) of the client certificate in the secret or absolute path to a certificate.
// The absolute path can be used when certificate is already present on the workload filesystem.
Cert string `json:"cert,omitempty"`
// Key defines a key (e.g. tls.key) of the private key in the secret or absolute path to a certificate.
// The absolute path can be used when certificate is already present on the workload filesystem.
Key string `json:"key,omitempty"`
}

// Sampler defines sampling configuration.
Expand Down
22 changes: 22 additions & 0 deletions apis/v1alpha1/instrumentation_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,31 @@ func (w InstrumentationWebhook) validate(r *Instrumentation) (admission.Warnings
default:
return warnings, fmt.Errorf("spec.sampler.type is not valid: %s", r.Spec.Sampler.Type)
}

warnings = append(warnings, validateExporter(r.Spec.Exporter)...)

return warnings, nil
}

func validateExporter(exporter Exporter) []string {
var warnings []string
if exporter.TLS != nil {
tls := exporter.TLS
if tls.Key != "" && tls.Cert == "" || tls.Cert != "" && tls.Key == "" {
warnings = append(warnings, "both exporter.tls.key and exporter.tls.cert mut be set")
}

if !strings.HasPrefix(exporter.Endpoint, "https://") {
warnings = append(warnings, "exporter.tls is configured but exporter.endpoint is not enabling TLS with https://")
}
}
if strings.HasPrefix(exporter.Endpoint, "https://") && exporter.TLS == nil {
warnings = append(warnings, "exporter is using https:// but exporter.tls is unset")
}

return warnings
}

func validateJaegerRemoteSamplerArgument(argument string) error {
parts := strings.Split(argument, ",")

Expand Down
88 changes: 88 additions & 0 deletions apis/v1alpha1/instrumentation_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,94 @@ func TestInstrumentationValidatingWebhook(t *testing.T) {
},
},
},
{
name: "exporter: tls cert set but missing key",
inst: Instrumentation{
Spec: InstrumentationSpec{
Sampler: Sampler{
Type: ParentBasedTraceIDRatio,
Argument: "0.99",
},
Exporter: Exporter{
Endpoint: "https://collector:4317",
TLS: &TLS{
Cert: "cert",
},
},
},
},
warnings: []string{"both exporter.tls.key and exporter.tls.cert mut be set"},
},
{
name: "exporter: tls key set but missing cert",
inst: Instrumentation{
Spec: InstrumentationSpec{
Sampler: Sampler{
Type: ParentBasedTraceIDRatio,
Argument: "0.99",
},
Exporter: Exporter{
Endpoint: "https://collector:4317",
TLS: &TLS{
Key: "key",
},
},
},
},
warnings: []string{"both exporter.tls.key and exporter.tls.cert mut be set"},
},
{
name: "exporter: tls set but using http://",
inst: Instrumentation{
Spec: InstrumentationSpec{
Sampler: Sampler{
Type: ParentBasedTraceIDRatio,
Argument: "0.99",
},
Exporter: Exporter{
Endpoint: "http://collector:4317",
TLS: &TLS{
Key: "key",
Cert: "cert",
},
},
},
},
warnings: []string{"exporter.tls is configured but exporter.endpoint is not enabling TLS with https://"},
},
{
name: "exporter: exporter using http://, but the tls is nil",
inst: Instrumentation{
Spec: InstrumentationSpec{
Sampler: Sampler{
Type: ParentBasedTraceIDRatio,
Argument: "0.99",
},
Exporter: Exporter{
Endpoint: "https://collector:4317",
},
},
},
warnings: []string{"exporter is using https:// but exporter.tls is unset"},
},
{
name: "exporter no warning set",
inst: Instrumentation{
Spec: InstrumentationSpec{
Sampler: Sampler{
Type: ParentBasedTraceIDRatio,
Argument: "0.99",
},
Exporter: Exporter{
Endpoint: "https://collector:4317",
TLS: &TLS{
Key: "key",
Cert: "cert",
},
},
},
},
},
}

for _, test := range tests {
Expand Down
22 changes: 21 additions & 1 deletion apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions apis/v1beta1/collector_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,13 +385,13 @@ func ValidatePorts(ports []PortsSpec) error {
func checkAutoscalerSpec(autoscaler *AutoscalerSpec) error {
if autoscaler.Behavior != nil {
if autoscaler.Behavior.ScaleDown != nil && autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds != nil &&
*autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds < int32(1) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleDown should be one or more")
(*autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds < int32(0) || *autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds > 3600) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleDown.stabilizationWindowSeconds should be >=0 and <=3600")
}

if autoscaler.Behavior.ScaleUp != nil && autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds != nil &&
*autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds < int32(1) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleUp should be one or more")
(*autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds < int32(0) || *autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds > 3600) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleUp.stabilizationWindowSeconds should be >=0 and <=3600")
}
}
if autoscaler.TargetCPUUtilization != nil && *autoscaler.TargetCPUUtilization < int32(1) {
Expand Down
46 changes: 40 additions & 6 deletions apis/v1beta1/collector_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package v1beta1_test
import (
"context"
"fmt"
"math"
"os"
"testing"

Expand Down Expand Up @@ -582,6 +583,7 @@ func TestOTELColValidatingWebhook(t *testing.T) {
one := int32(1)
three := int32(3)
five := int32(5)
maxInt := int32(math.MaxInt32)

cfg := v1beta1.Config{}
err := yaml.Unmarshal([]byte(cfgYaml), &cfg)
Expand Down Expand Up @@ -913,36 +915,68 @@ func TestOTELColValidatingWebhook(t *testing.T) {
expectedErr: "minReplicas should be one or more",
},
{
name: "invalid autoscaler scale down",
name: "invalid autoscaler scale down stablization window - <0",
otelcol: v1beta1.OpenTelemetryCollector{
Spec: v1beta1.OpenTelemetryCollectorSpec{
Autoscaler: &v1beta1.AutoscalerSpec{
MaxReplicas: &three,
Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{
ScaleDown: &autoscalingv2.HPAScalingRules{
StabilizationWindowSeconds: &zero,
StabilizationWindowSeconds: &minusOne,
},
},
},
},
},
expectedErr: "scaleDown should be one or more",
expectedErr: "scaleDown.stabilizationWindowSeconds should be >=0 and <=3600",
},
{
name: "invalid autoscaler scale up",
name: "invalid autoscaler scale down stablization window - >3600",
otelcol: v1beta1.OpenTelemetryCollector{
Spec: v1beta1.OpenTelemetryCollectorSpec{
Autoscaler: &v1beta1.AutoscalerSpec{
MaxReplicas: &three,
Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{
ScaleDown: &autoscalingv2.HPAScalingRules{
StabilizationWindowSeconds: &maxInt,
},
},
},
},
},
expectedErr: "scaleDown.stabilizationWindowSeconds should be >=0 and <=3600",
},
{
name: "invalid autoscaler scale up stablization window - <0",
otelcol: v1beta1.OpenTelemetryCollector{
Spec: v1beta1.OpenTelemetryCollectorSpec{
Autoscaler: &v1beta1.AutoscalerSpec{
MaxReplicas: &three,
Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{
ScaleUp: &autoscalingv2.HPAScalingRules{
StabilizationWindowSeconds: &minusOne,
},
},
},
},
},
expectedErr: "scaleUp.stabilizationWindowSeconds should be >=0 and <=3600",
},
{
name: "invalid autoscaler scale up stablization window - >3600",
otelcol: v1beta1.OpenTelemetryCollector{
Spec: v1beta1.OpenTelemetryCollectorSpec{
Autoscaler: &v1beta1.AutoscalerSpec{
MaxReplicas: &three,
Behavior: &autoscalingv2.HorizontalPodAutoscalerBehavior{
ScaleUp: &autoscalingv2.HPAScalingRules{
StabilizationWindowSeconds: &zero,
StabilizationWindowSeconds: &maxInt,
},
},
},
},
},
expectedErr: "scaleUp should be one or more",
expectedErr: "scaleUp.stabilizationWindowSeconds should be >=0 and <=3600",
},
{
name: "invalid autoscaler target cpu utilization",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ metadata:
categories: Logging & Tracing,Monitoring
certified: "false"
containerImage: ghcr.io/open-telemetry/opentelemetry-operator/opentelemetry-operator
createdAt: "2024-10-08T09:52:53Z"
createdAt: "2024-10-10T15:31:51Z"
description: Provides the OpenTelemetry components, including the Collector
operators.operatorframework.io/builder: operator-sdk-v1.29.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
Expand Down Expand Up @@ -284,7 +284,9 @@ spec:
- ""
resources:
- namespaces
- secrets
verbs:
- get
- list
- watch
- apiGroups:
Expand Down
Loading

0 comments on commit a2ce78b

Please sign in to comment.