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.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ capabilities |
+ object |
+
+ Capabilities defines the observability capabilities.
+Each capability has to be enabled explicitly.
+ |
+ false |
+
+ storage |
+ object |
+
+ 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.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ opentelemetry |
+ object |
+
+ OpenTelemetry defines the OpenTelemetry capabilities.
+ |
+ false |
+
+ tracing |
+ object |
+
+ Tracing defines the tracing capabilities.
+ |
+ false |
+
+
+
+
+### ClusterObservability.spec.capabilities.opentelemetry
+[↩ Parent](#clusterobservabilityspeccapabilities)
+
+
+
+OpenTelemetry defines the OpenTelemetry capabilities.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ enabled |
+ boolean |
+
+ Enabled indicates whether the capability is enabled and it operator should deploy an instance.
+By default, it is set to false.
+
+ Default: false
+ |
+ false |
+
+ exporter |
+ object |
+
+ Exporter defines the OpenTelemetry exporter configuration.
+When defined the collector will export telemetry data to the specified endpoint.
+ |
+ false |
+
+ operators |
+ object |
+
+ 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.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ endpoint |
+ string |
+
+ Endpoint is the OTLP endpoint.
+ |
+ false |
+
+
+
+
+### ClusterObservability.spec.capabilities.opentelemetry.operators
+[↩ Parent](#clusterobservabilityspeccapabilitiesopentelemetry)
+
+
+
+Operators defines the operators installation for the capability.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ install |
+ boolean |
+
+ 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.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ enabled |
+ boolean |
+
+ Enabled indicates whether the capability is enabled and it operator should deploy an instance.
+By default, it is set to false.
+
+ Default: false
+ |
+ false |
+
+ operators |
+ object |
+
+ Operators defines the operators installation for the capability.
+ |
+ false |
+
+
+
+
+### ClusterObservability.spec.capabilities.tracing.operators
+[↩ Parent](#clusterobservabilityspeccapabilitiestracing)
+
+
+
+Operators defines the operators installation for the capability.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ install |
+ boolean |
+
+ 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.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ secret |
+ object |
+
+ SecretSpec defines the secret for the storage.
+ |
+ false |
+
+
+
+
+### ClusterObservability.spec.storage.secret
+[↩ Parent](#clusterobservabilityspecstorage)
+
+
+
+SecretSpec defines the secret for the storage.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ name |
+ string |
+
+ 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
+}