Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions api/v1alpha1/etcdcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,76 @@ type EtcdClusterSpec struct {
EtcdOptions []string `json:"etcdOptions,omitempty"`
// PodTemplate is the pod template to use for the etcd cluster.
PodTemplate *PodTemplate `json:"podTemplate,omitempty"`
// Metrics configures Prometheus observability for this cluster. When unset,
// the operator still exports its own per-cluster domain metrics on its
// /metrics endpoint, but does not create a PodMonitor for the etcd member
// pods. See MetricsSpec for the available knobs.
// +optional
Metrics *MetricsSpec `json:"metrics,omitempty"`
}

// MetricsSpec configures Prometheus observability for an EtcdCluster.
type MetricsSpec struct {
// Enabled toggles emission of the operator's per-cluster domain metrics
// (member counts, quorum, leader changes, reconcile timings, etc.) for this
// cluster. When nil it defaults to true: metrics are exported unless
// explicitly disabled. Disabling drops the cluster's series from the
// operator's /metrics endpoint.
// +optional
Enabled *bool `json:"enabled,omitempty"`

// PodMonitor, when set and enabled, instructs the operator to create and
// maintain a prometheus-operator PodMonitor selecting this cluster's etcd
// member pods so that Prometheus scrapes etcd's own /metrics endpoint.
// This requires the prometheus-operator PodMonitor CRD to be installed in
// the cluster; if it is absent the operator logs and skips PodMonitor
// reconciliation without failing the rest of the reconcile.
// +optional
PodMonitor *PodMonitorSpec `json:"podMonitor,omitempty"`
}

// PodMonitorSpec controls creation of a PodMonitor for the etcd member pods.
type PodMonitorSpec struct {
// Enabled toggles creation of the PodMonitor. Defaults to false.
// +optional
Enabled bool `json:"enabled,omitempty"`

// Interval at which Prometheus scrapes the etcd member pods, e.g. "30s".
// When empty the prometheus-operator default is used.
// +optional
Interval string `json:"interval,omitempty"`

// Port is the name of the pod port exposing etcd's /metrics endpoint.
// Defaults to "client" when empty.
// +optional
Port string `json:"port,omitempty"`

// Labels are additional metadata labels to set on the generated
// PodMonitor. They are merged on top of the operator-managed labels
// (app.kubernetes.io/name, /managed-by, /instance): user-provided keys
// take precedence on conflict. This is typically used to satisfy a
// namespaced Prometheus's podMonitorSelector, e.g. setting
// "release: kvs-prometheus" so a release-scoped Prometheus discovers and
// scrapes this PodMonitor. When empty, only the operator-managed labels
// are applied (today's behavior).
// +optional
Labels map[string]string `json:"labels,omitempty"`
}

// MetricsEnabled reports whether per-cluster domain metrics should be exported
// for this cluster. Metrics are on by default and only disabled when
// spec.metrics.enabled is explicitly set to false.
func (s *EtcdClusterSpec) MetricsEnabled() bool {
if s.Metrics == nil || s.Metrics.Enabled == nil {
return true
}
return *s.Metrics.Enabled
}

// PodMonitorEnabled reports whether a PodMonitor should be reconciled for this
// cluster's etcd member pods.
func (s *EtcdClusterSpec) PodMonitorEnabled() bool {
return s.MetricsEnabled() && s.Metrics != nil && s.Metrics.PodMonitor != nil && s.Metrics.PodMonitor.Enabled
}

type PodTemplate struct {
Expand Down
54 changes: 53 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

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

5 changes: 5 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

operatorv1alpha1 "go.etcd.io/etcd-operator/api/v1alpha1"
"go.etcd.io/etcd-operator/internal/controller"
"go.etcd.io/etcd-operator/internal/metrics"
// nolint:gci
// +kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -85,6 +86,10 @@ func main() {

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

// Register the operator's custom per-cluster domain metrics with the
// controller-runtime global registry so they are served on /metrics.
metrics.MustRegister()

// if the enable-http2 flag is false (the default), http/2 should be disabled
// due to its vulnerabilities. More specifically, disabling http/2 will
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
Expand Down
55 changes: 54 additions & 1 deletion config/crd/bases/operator.etcd.io_etcdclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.20.1
controller-gen.kubebuilder.io/version: v0.21.0
name: etcdclusters.operator.etcd.io
spec:
group: operator.etcd.io
Expand Down Expand Up @@ -52,6 +52,59 @@ spec:
If unset, it defaults to the value provided via the controller's
--image-registry flag, which itself defaults to "gcr.io/etcd-development/etcd".
type: string
metrics:
description: |-
Metrics configures Prometheus observability for this cluster. When unset,
the operator still exports its own per-cluster domain metrics on its
/metrics endpoint, but does not create a PodMonitor for the etcd member
pods. See MetricsSpec for the available knobs.
properties:
enabled:
description: |-
Enabled toggles emission of the operator's per-cluster domain metrics
(member counts, quorum, leader changes, reconcile timings, etc.) for this
cluster. When nil it defaults to true: metrics are exported unless
explicitly disabled. Disabling drops the cluster's series from the
operator's /metrics endpoint.
type: boolean
podMonitor:
description: |-
PodMonitor, when set and enabled, instructs the operator to create and
maintain a prometheus-operator PodMonitor selecting this cluster's etcd
member pods so that Prometheus scrapes etcd's own /metrics endpoint.
This requires the prometheus-operator PodMonitor CRD to be installed in
the cluster; if it is absent the operator logs and skips PodMonitor
reconciliation without failing the rest of the reconcile.
properties:
enabled:
description: Enabled toggles creation of the PodMonitor. Defaults
to false.
type: boolean
interval:
description: |-
Interval at which Prometheus scrapes the etcd member pods, e.g. "30s".
When empty the prometheus-operator default is used.
type: string
labels:
additionalProperties:
type: string
description: |-
Labels are additional metadata labels to set on the generated
PodMonitor. They are merged on top of the operator-managed labels
(app.kubernetes.io/name, /managed-by, /instance): user-provided keys
take precedence on conflict. This is typically used to satisfy a
namespaced Prometheus's podMonitorSelector, e.g. setting
"release: kvs-prometheus" so a release-scoped Prometheus discovers and
scrapes this PodMonitor. When empty, only the operator-managed labels
are applied (today's behavior).
type: object
port:
description: |-
Port is the name of the pod port exposing etcd's /metrics endpoint.
Defaults to "client" when empty.
type: string
type: object
type: object
podTemplate:
description: PodTemplate is the pod template to use for the etcd cluster.
properties:
Expand Down
4 changes: 4 additions & 0 deletions config/e2e/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ patches:
target:
kind: Deployment
name: controller-manager
- path: patch-metrics.yaml
target:
kind: Deployment
name: controller-manager
20 changes: 20 additions & 0 deletions config/e2e/patch-metrics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Serve metrics over plain HTTP on :8080 for the e2e suite, which scrapes the
# operator pod via the API server pod-proxy (see test/e2e/metrics_test.go). The
# default overlay serves secure HTTPS metrics on :8443 behind authn/authz, which
# the pod-proxy scrape cannot reach. This replaces the manager's args so the
# metrics endpoint is reachable; it intentionally does not touch the env patched
# in patch-env.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
name: etcd-operator
spec:
template:
spec:
containers:
- name: manager
args:
- --metrics-bind-address=:8080
- --metrics-secure=false
- --leader-elect
- --health-probe-bind-address=:8081
Loading