diff --git a/deploy/crds/common/observability.openshift.io_clusterobservabilities.yaml b/deploy/crds/common/observability.openshift.io_clusterobservabilities.yaml index 26c3542eb..a36c246a5 100644 --- a/deploy/crds/common/observability.openshift.io_clusterobservabilities.yaml +++ b/deploy/crds/common/observability.openshift.io_clusterobservabilities.yaml @@ -39,6 +39,74 @@ spec: type: object spec: description: Spec defines the desired state of the cluster observability. + properties: + capabilities: + description: |- + Capabilities defines the observability capabilities. + Each capability has to be enabled explicitly. + properties: + opentelemetry: + description: OpenTelemetry defines the OpenTelemetry capabilities. + properties: + enabled: + default: false + description: |- + Enabled indicates whether the capability is enabled and it operator should deploy an instance. + By default, it is set to false. + type: boolean + exporter: + description: |- + Exporter defines the OpenTelemetry exporter configuration. + When defined the collector will export telemetry data to the specified endpoint. + properties: + endpoint: + description: Endpoint is the OTLP endpoint. + type: string + type: object + operators: + description: Operators defines the operators installation + for the capability. + properties: + install: + description: |- + Install indicates whether the operator(s) used by the capability should be installed via OLM. + When the capability is enabled, the install is set to true, otherwise it is set to false. + type: boolean + type: object + type: object + tracing: + description: Tracing defines the tracing capabilities. + properties: + enabled: + default: false + description: |- + Enabled indicates whether the capability is enabled and it operator should deploy an instance. + By default, it is set to false. + type: boolean + operators: + description: Operators defines the operators installation + for the capability. + properties: + install: + description: |- + Install indicates whether the operator(s) used by the capability should be installed via OLM. + When the capability is enabled, the install is set to true, otherwise it is set to false. + type: boolean + type: object + type: object + type: object + storage: + description: Storage defines the storage for the capabilities that + require a storage. + properties: + secret: + description: SecretSpec defines the secret for the storage. + properties: + name: + description: Name is the name of the secret for the storage. + type: string + type: object + type: object type: object status: description: Status of the signal manager. diff --git a/docs/api.md b/docs/api.md index 3997c7e10..c3f30e018 100644 --- a/docs/api.md +++ b/docs/api.md @@ -4028,7 +4028,7 @@ ClusterObservability defines the desired state of the observability stack. Refer to the Kubernetes API documentation for the fields of the `metadata` field. true - spec + spec object Spec defines the desired state of the cluster observability.
@@ -4044,6 +4044,296 @@ ClusterObservability defines the desired state of the observability stack. + +### ClusterObservability.spec +[↩ Parent](#clusterobservability) + + + +Spec defines the desired state of the cluster observability. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
capabilitiesobject + Capabilities defines the observability capabilities. +Each capability has to be enabled explicitly.
+
false
storageobject + Storage defines the storage for the capabilities that require a storage.
+
false
+ + +### ClusterObservability.spec.capabilities +[↩ Parent](#clusterobservabilityspec) + + + +Capabilities defines the observability capabilities. +Each capability has to be enabled explicitly. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
opentelemetryobject + OpenTelemetry defines the OpenTelemetry capabilities.
+
false
tracingobject + Tracing defines the tracing capabilities.
+
false
+ + +### ClusterObservability.spec.capabilities.opentelemetry +[↩ Parent](#clusterobservabilityspeccapabilities) + + + +OpenTelemetry defines the OpenTelemetry capabilities. + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
enabledboolean + Enabled indicates whether the capability is enabled and it operator should deploy an instance. +By default, it is set to false.
+
+ Default: false
+
false
exporterobject + Exporter defines the OpenTelemetry exporter configuration. +When defined the collector will export telemetry data to the specified endpoint.
+
false
operatorsobject + Operators defines the operators installation for the capability.
+
false
+ + +### ClusterObservability.spec.capabilities.opentelemetry.exporter +[↩ Parent](#clusterobservabilityspeccapabilitiesopentelemetry) + + + +Exporter defines the OpenTelemetry exporter configuration. +When defined the collector will export telemetry data to the specified endpoint. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
endpointstring + Endpoint is the OTLP endpoint.
+
false
+ + +### ClusterObservability.spec.capabilities.opentelemetry.operators +[↩ Parent](#clusterobservabilityspeccapabilitiesopentelemetry) + + + +Operators defines the operators installation for the capability. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
installboolean + Install indicates whether the operator(s) used by the capability should be installed via OLM. +When the capability is enabled, the install is set to true, otherwise it is set to false.
+
false
+ + +### ClusterObservability.spec.capabilities.tracing +[↩ Parent](#clusterobservabilityspeccapabilities) + + + +Tracing defines the tracing capabilities. + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
enabledboolean + Enabled indicates whether the capability is enabled and it operator should deploy an instance. +By default, it is set to false.
+
+ Default: false
+
false
operatorsobject + Operators defines the operators installation for the capability.
+
false
+ + +### ClusterObservability.spec.capabilities.tracing.operators +[↩ Parent](#clusterobservabilityspeccapabilitiestracing) + + + +Operators defines the operators installation for the capability. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
installboolean + Install indicates whether the operator(s) used by the capability should be installed via OLM. +When the capability is enabled, the install is set to true, otherwise it is set to false.
+
false
+ + +### ClusterObservability.spec.storage +[↩ Parent](#clusterobservabilityspec) + + + +Storage defines the storage for the capabilities that require a storage. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
secretobject + SecretSpec defines the secret for the storage.
+
false
+ + +### ClusterObservability.spec.storage.secret +[↩ Parent](#clusterobservabilityspecstorage) + + + +SecretSpec defines the secret for the storage. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
namestring + Name is the name of the secret for the storage.
+
false
+ ## UIPlugin [↩ Parent](#observabilityopenshiftiov1alpha1 ) diff --git a/docs/clusterobservability.md b/docs/clusterobservability.md new file mode 100644 index 000000000..e18f43120 --- /dev/null +++ b/docs/clusterobservability.md @@ -0,0 +1,112 @@ +# ClusterObservability CRD + +This document describes the `ClusterObservability` Custom Resource Definition (CRD). +The goal of this CRD is to provide end-to-end observability capabilities with minimal configuration. +Power users should be able to customize the underlying components via server-side apply. + +## Examples + +### Logging and tracing + +```yaml +apiVersion: observability.openshift.io/v1alpha1 +kind: ClusterObservability +metadata: + name: logging-tracing +spec: + storage: + secret: + name: minio + type: s3 + capabilities: + logging: + enabled: true + tracing: + enabled: true +``` + +Notes: +* installs the Loki, ClusterLogForwarder, Tempo and opentelemetry operators +* creates storage secret for `LokiStack` and `TempoStack` from the secret `minio` which is reconciled by the `ClusterObservability` +* deploys logging stack with `ClusterLogForwarder` and `LokiStack` in the `openshift-logging` namespace +* deploys tracing stack with `OpenTelemetryCollector` and `TempoStack` in the `openshift-distributed-tracing` namespace +* Installs the UI plugins for Loki and Tempo +* The appropriate operators are installed only when given capability is enabled + +### OpenTelemetry with tracing and Dynatrace + +```yaml +apiVersion: observability.openshift.io/v1alpha1 +kind: ClusterObservability +metadata: + name: logging-tracing +spec: + storage: + secret: + name: minio + type: s3 + capabilities: + tracing: + enabled: true + opentelemetry: + enabled: true + tracesincluster: true + exporter: + endpoint: http://dynatrace:4317 + headers: + x-dynatrace: "token..." +``` + +Notes: +* installs the opentelemetry and tempo operators +* deploys tracing stack with `OpenTelemetryCollector` and `TempoStack` in the `openshift-distributed-tracing` namespace +* deploys `OpenTelemetryCollector` in the `openshift-opentelemetry` +* configures OTLP exporter on the collector to send traces to Dynatrace +* configures collector to export trace data to Tempo deployed by the `ClusterObservability` CR + +### Install only operators for a given capability + +```yaml +apiVersion: observability.openshift.io/v1alpha1 +kind: ClusterObservability +metadata: + name: logging-tracing +spec: + storage: + secret: + name: minio + type: s3 + capabilities: + tracing: + enabled: false + operators: + install: true +``` + +Notes: +* The tracing instance is not deployed, but the operators are installed + +### Deploy capability but don't deploy the operators. + +```yaml +apiVersion: observability.openshift.io/v1alpha1 +kind: ClusterObservability +metadata: + name: logging-tracing +spec: + storage: + secret: + name: minio + type: s3 + capabilities: + tracing: + enabled: true + operators: + install: false +``` + +Notes: +* The tracing instance is deployed, but the operators are not installed via COO. +* In this case, the user is responsible for installing the operators + +In this case the COO cannot guarantee that installed operator versions are compatible therefore we could forbit this configuration or show a warning/unmanaged state. diff --git a/pkg/apis/observability/v1alpha1/opentelemetry.go b/pkg/apis/observability/v1alpha1/opentelemetry.go new file mode 100644 index 000000000..9d795e7c8 --- /dev/null +++ b/pkg/apis/observability/v1alpha1/opentelemetry.go @@ -0,0 +1,16 @@ +package v1alpha1 + +// OpenTelemetrySpec defines the desired state of OpenTelemetry capability. +type OpenTelemetrySpec struct { + CommonCapabilitiesSpec CommonCapabilitiesSpec `json:",inline"` + + // Exporter defines the OpenTelemetry exporter configuration. + // When defined the collector will export telemetry data to the specified endpoint. + Exporter *OTLPExporter `json:"exporter,omitempty"` +} + +// OTLPExporter defines the OpenTelemetry Protocol (OTLP) exporter configuration. +type OTLPExporter struct { + // Endpoint is the OTLP endpoint. + Endpoint string `json:"endpoint,omitempty"` +} diff --git a/pkg/apis/observability/v1alpha1/tracing.go b/pkg/apis/observability/v1alpha1/tracing.go new file mode 100644 index 000000000..57fe54729 --- /dev/null +++ b/pkg/apis/observability/v1alpha1/tracing.go @@ -0,0 +1,6 @@ +package v1alpha1 + +// TracingSpec defines the desired state of the tracing capability. +type TracingSpec struct { + CommonCapabilitiesSpec CommonCapabilitiesSpec `json:",inline"` +} diff --git a/pkg/apis/observability/v1alpha1/types.go b/pkg/apis/observability/v1alpha1/types.go index d641c3110..e7a7ab7b6 100644 --- a/pkg/apis/observability/v1alpha1/types.go +++ b/pkg/apis/observability/v1alpha1/types.go @@ -37,7 +37,62 @@ type ClusterObservabilityList struct { } type ClusterObservabilitySpec struct { + // Storage defines the storage for the capabilities that require a storage. + Storage StorageSpec `json:"storage,omitempty"` + + // Capabilities defines the observability capabilities. + // Each capability has to be enabled explicitly. + Capabilities *CapabilitiesSpec `json:"capabilities,omitempty"` } // ClusterObservabilityStatus defines the observed state of ClusterObservability. type ClusterObservabilityStatus struct{} + +// StorageSpec defines the storage. +type StorageSpec struct { + Secret SecretSpec `json:"secret,omitempty"` +} + +// SecretSpec defines the secret for the storage. +type SecretSpec struct { + // Name is the name of the secret for the storage. + Name string `json:"name,omitempty"` +} + +// CapabilitiesSpec defines the observability capabilities. +type CapabilitiesSpec struct { + + // Tracing defines the tracing capabilities. + // +optional + // +kubebuilder:validation:Optional + Tracing TracingSpec `json:"tracing,omitempty"` + + // OpenTelemetry defines the OpenTelemetry capabilities. + // +optional + // +kubebuilder:validation:Optional + OpenTelemetry OpenTelemetrySpec `json:"opentelemetry,omitempty"` +} + +// CommonCapabilitiesSpec defines the common capabilities. +type CommonCapabilitiesSpec struct { + // Enabled indicates whether the capability is enabled and it operator should deploy an instance. + // By default, it is set to false. + // +optional + // +kubebuilder:validation:Optional + // +kubebuilder:default=false + Enabled bool `json:"enabled,omitempty"` + + // Operators defines the operators installation for the capability. + // +optional + // +kubebuilder:validation:Optional + Operators OperatorsSpec `json:"operators,omitempty"` +} + +// OperatorsSpec defines the operators installation. +type OperatorsSpec struct { + // Install indicates whether the operator(s) used by the capability should be installed via OLM. + // When the capability is enabled, the install is set to true, otherwise it is set to false. + // +optional + // +kubebuilder:validation:Optional + Install bool `json:"install,omitempty"` +} diff --git a/pkg/apis/observability/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/observability/v1alpha1/zz_generated.deepcopy.go index 18a20869a..b0f233950 100644 --- a/pkg/apis/observability/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/observability/v1alpha1/zz_generated.deepcopy.go @@ -24,12 +24,29 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CapabilitiesSpec) DeepCopyInto(out *CapabilitiesSpec) { + *out = *in + out.Tracing = in.Tracing + in.OpenTelemetry.DeepCopyInto(&out.OpenTelemetry) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CapabilitiesSpec. +func (in *CapabilitiesSpec) DeepCopy() *CapabilitiesSpec { + if in == nil { + return nil + } + out := new(CapabilitiesSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterObservability) DeepCopyInto(out *ClusterObservability) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -86,6 +103,12 @@ func (in *ClusterObservabilityList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterObservabilitySpec) DeepCopyInto(out *ClusterObservabilitySpec) { *out = *in + out.Storage = in.Storage + if in.Capabilities != nil { + in, out := &in.Capabilities, &out.Capabilities + *out = new(CapabilitiesSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterObservabilitySpec. @@ -112,3 +135,117 @@ func (in *ClusterObservabilityStatus) DeepCopy() *ClusterObservabilityStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonCapabilitiesSpec) DeepCopyInto(out *CommonCapabilitiesSpec) { + *out = *in + out.Operators = in.Operators +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonCapabilitiesSpec. +func (in *CommonCapabilitiesSpec) DeepCopy() *CommonCapabilitiesSpec { + if in == nil { + return nil + } + out := new(CommonCapabilitiesSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OTLPExporter) DeepCopyInto(out *OTLPExporter) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OTLPExporter. +func (in *OTLPExporter) DeepCopy() *OTLPExporter { + if in == nil { + return nil + } + out := new(OTLPExporter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenTelemetrySpec) DeepCopyInto(out *OpenTelemetrySpec) { + *out = *in + out.CommonCapabilitiesSpec = in.CommonCapabilitiesSpec + if in.Exporter != nil { + in, out := &in.Exporter, &out.Exporter + *out = new(OTLPExporter) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetrySpec. +func (in *OpenTelemetrySpec) DeepCopy() *OpenTelemetrySpec { + if in == nil { + return nil + } + out := new(OpenTelemetrySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperatorsSpec) DeepCopyInto(out *OperatorsSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorsSpec. +func (in *OperatorsSpec) DeepCopy() *OperatorsSpec { + if in == nil { + return nil + } + out := new(OperatorsSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretSpec) DeepCopyInto(out *SecretSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretSpec. +func (in *SecretSpec) DeepCopy() *SecretSpec { + if in == nil { + return nil + } + out := new(SecretSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageSpec) DeepCopyInto(out *StorageSpec) { + *out = *in + out.Secret = in.Secret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageSpec. +func (in *StorageSpec) DeepCopy() *StorageSpec { + if in == nil { + return nil + } + out := new(StorageSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TracingSpec) DeepCopyInto(out *TracingSpec) { + *out = *in + out.CommonCapabilitiesSpec = in.CommonCapabilitiesSpec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingSpec. +func (in *TracingSpec) DeepCopy() *TracingSpec { + if in == nil { + return nil + } + out := new(TracingSpec) + in.DeepCopyInto(out) + return out +}