Skip to content
Open
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
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,26 @@ mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef

##@ Helm Chart

HELM ?= helm
HELM_CHART = charts/etcd-operator

.PHONY: helm-crds
helm-crds: ## Copy config/crd/bases into the chart's templates/crds, wrapped in a crds.enabled guard. Run after `make manifests`.
@mkdir -p $(HELM_CHART)/templates/crds
@rm -f $(HELM_CHART)/templates/crds/*.yaml
@for f in config/crd/bases/*.yaml; do \
out=$(HELM_CHART)/templates/crds/$$(basename $$f); \
echo "syncing $$f -> $$out"; \
{ \
echo '{{- if .Values.crds.enabled }}'; \
sed -e 's/{{/{{ "{{" }}/g' $$f; \
echo '{{- end }}'; \
} > $$out; \
done

.PHONY: helm-lint
helm-lint: ## Lint the Helm chart.
$(HELM) lint $(HELM_CHART)
23 changes: 23 additions & 0 deletions charts/etcd-operator/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
9 changes: 9 additions & 0 deletions charts/etcd-operator/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v2
name: etcd-operator
description: Operator managing etcd clusters on Kubernetes
type: application
version: 0.1.0
appVersion: "v0.2.0"
kubeVersion: ">=1.30.0-0"
sources:
- https://github.com/etcd-io/etcd-operator
95 changes: 95 additions & 0 deletions charts/etcd-operator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# etcd-operator Helm chart

Installs the etcd-operator: the EtcdCluster CRD, controller Deployment, RBAC,
metrics Service, and optionally the admission webhooks (server and
configurations). Covers the same surface as `kustomize build config/default`.

```sh
helm install etcd-operator ./charts/etcd-operator \
--namespace etcd-operator-system --create-namespace
```

## Values

| Key | Default | Description |
|-----|---------|-------------|
| `nameOverride` / `fullnameOverride` | `""` | Usual name overrides. |
| `crds.enabled` | `true` | Install the CRDs (`templates/crds/`, synced from `config/crd/bases` by `make helm-crds`). |
| `controller.enabled` | `true` | Render the runtime: Deployment, ServiceAccount, RBAC, Services. |
| `controller.replicas` | `1` | |
| `controller.image.repository` | `gcr.io/etcd-development/etcd-operator` | |
| `controller.image.tag` | `""` | Defaults to the chart `appVersion`. |
| `controller.image.digest` | `""` | Pins `repository@digest`; wins over `tag`. |
| `controller.image.pullPolicy` | `IfNotPresent` | |
| `controller.imagePullSecrets` | `[]` | |
| `controller.operatorImage` | `""` | `OPERATOR_IMAGE` env (image for operator-run utility containers). Defaults to the manager image ref, digest pin included. |
| `controller.leaderElection` | `true` | `--leader-elect`. |
| `controller.watchNamespace` | `""` | Scope the operator to one namespace: namespaced Role/RoleBinding there instead of ClusterRole/ClusterRoleBinding, plus `--watch-namespace` / `WATCH_NAMESPACE`. |
| `controller.restrictClusterIssuer` | `false` | `RESTRICT_CLUSTER_ISSUER=true`: webhook rejects `issuerKind: ClusterIssuer`. |
| `controller.resources` | see `values.yaml` | |
| `controller.serviceAccount.annotations` | `{}` | |
| `metrics.secure` | `true` | HTTPS metrics with authn/authz (installs the metrics-auth ClusterRoles). `false`: plain HTTP, no cluster-scoped metrics RBAC. |
| `metrics.port` | `8443` | Bind address, metrics Service, and NetworkPolicy port. Convention: `8080` when `secure=false`. |
| `metrics.serviceMonitor.enabled` | `false` | ServiceMonitor; scheme/auth follow `metrics.secure`. |
| `metrics.serviceMonitor.additionalLabels` | `{}` | e.g. your Prometheus `release:` selector. |
| `metrics.networkPolicy.enabled` | `false` | Allow metrics ingress only from namespaces labeled `metrics: enabled`. |
| `webhook.enabled` | `false` | Webhook server side: webhook Service, serving-cert mount and port 9443 on the Deployment. Off: `ENABLE_WEBHOOKS=false`. |
| `webhook.certManager.enabled` | `true` | SelfSigned Issuer + serving Certificate; CA-injection annotation on the WebhookConfigurations. |
| `admissionWebhooks.enabled` | `false` | The cluster-scoped Validating/Mutating WebhookConfigurations. |
| `admissionWebhooks.namespaceSelector` | `{}` | Constrain the fail-closed webhooks; empty = all namespaces. |

Webhook toggles default off because the `appVersion` operator does not serve
admission webhooks yet; enable them with an operator build that does
(etcd-io/etcd-operator#384).

## Split install (CRDs + webhook configurations vs runtime)

Cluster-scoped installs (CRDs, WebhookConfigurations) often deploy through a
privileged lane while the runtime deploys namespaced — e.g. two ArgoCD
Applications rendering this chart twice. Both releases must produce the same
resource names: set the same `fullnameOverride` and target namespace.

Application 1 — cluster-scoped only (CRDs + the two WebhookConfigurations):

```yaml
fullnameOverride: etcd-operator
controller:
enabled: false
admissionWebhooks:
enabled: true
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kv
```

Application 2 — runtime only, in namespace `kv`:

```yaml
fullnameOverride: etcd-operator
crds:
enabled: false
webhook:
enabled: true
```

## Namespace-scoped operator

```yaml
controller:
watchNamespace: kv
restrictClusterIssuer: true
metrics:
secure: false
port: 8080
```

Renders a Role/RoleBinding in `kv` instead of the manager
ClusterRole/ClusterRoleBinding and drops all other cluster-scoped RBAC.

## CRD sync

`templates/crds/` is generated — never edit it by hand:

```sh
make manifests helm-crds
```
57 changes: 57 additions & 0 deletions charts/etcd-operator/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "etcd-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name, truncated at 63 chars.
*/}}
{{- define "etcd-operator.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "etcd-operator.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{ include "etcd-operator.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "etcd-operator.selectorLabels" -}}
app.kubernetes.io/name: {{ include "etcd-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Manager image ref: digest pin wins over tag; tag defaults to appVersion.
*/}}
{{- define "etcd-operator.image" -}}
{{- if .Values.controller.image.digest -}}
{{ .Values.controller.image.repository }}@{{ .Values.controller.image.digest }}
{{- else -}}
{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }}
{{- end -}}
{{- end }}

{{- define "etcd-operator.serviceAccountName" -}}
{{ include "etcd-operator.fullname" . }}
{{- end }}
94 changes: 94 additions & 0 deletions charts/etcd-operator/templates/admission-webhooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{{- if .Values.admissionWebhooks.enabled }}
{{/*
From config/webhook/manifests.yaml. The objectSelector is the per-object
break-glass opt-out for the fail-closed webhooks: label an EtcdCluster
etcd.operator.etcd.io/skip-webhooks=true to bypass admission for that object.
*/}}
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ include "etcd-operator.fullname" . }}-mutating-webhook-configuration
labels:
{{- include "etcd-operator.labels" . | nindent 4 }}
{{- if .Values.webhook.certManager.enabled }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "etcd-operator.fullname" . }}-serving-cert
{{- end }}
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: {{ include "etcd-operator.fullname" . }}-webhook-service
namespace: {{ .Release.Namespace }}
path: /mutate-operator-etcd-io-v1alpha1-etcdcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: metcdcluster-v1alpha1.kb.io
{{- with .Values.admissionWebhooks.namespaceSelector }}
namespaceSelector:
{{- toYaml . | nindent 6 }}
{{- end }}
objectSelector:
matchExpressions:
- key: etcd.operator.etcd.io/skip-webhooks
operator: NotIn
values:
- "true"
rules:
- apiGroups:
- operator.etcd.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- etcdclusters
sideEffects: None
timeoutSeconds: 10
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: {{ include "etcd-operator.fullname" . }}-validating-webhook-configuration
labels:
{{- include "etcd-operator.labels" . | nindent 4 }}
{{- if .Values.webhook.certManager.enabled }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "etcd-operator.fullname" . }}-serving-cert
{{- end }}
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: {{ include "etcd-operator.fullname" . }}-webhook-service
namespace: {{ .Release.Namespace }}
path: /validate-operator-etcd-io-v1alpha1-etcdcluster
failurePolicy: Fail
matchPolicy: Equivalent
name: vetcdcluster-v1alpha1.kb.io
{{- with .Values.admissionWebhooks.namespaceSelector }}
namespaceSelector:
{{- toYaml . | nindent 6 }}
{{- end }}
objectSelector:
matchExpressions:
- key: etcd.operator.etcd.io/skip-webhooks
operator: NotIn
values:
- "true"
rules:
- apiGroups:
- operator.etcd.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- etcdclusters
sideEffects: None
timeoutSeconds: 10
{{- end }}
Loading