Skip to content

Commit c6476c3

Browse files
[etcd]: Initial etcd implementation (CloudPirates-io#230)
* [etcd]: Initial etcd implementation * Update CHANGELOG.md Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Update CHANGELOG.md Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> --------- Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 6554cc9 commit c6476c3

17 files changed

+1965
-0
lines changed

charts/etcd/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Changelog
2+
3+
## 0.1.0 (2025-10-09)
4+
5+
* [etcd]: Initial etcd implementation ([#230](https://github.com/CloudPirates-io/helm-charts/pull/230))

charts/etcd/Chart.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dependencies:
2+
- name: common
3+
repository: oci://registry-1.docker.io/cloudpirates
4+
version: 1.1.1
5+
digest: sha256:8da3c04e2c4a1ebfff4f21936399938e0f3fcf9fbd2f7135e7e907ce725b8f00
6+
generated: "2025-10-08T12:49:37.237547+02:00"

charts/etcd/Chart.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apiVersion: v2
2+
name: etcd
3+
description: etcd is a distributed reliable key-value store for the most critical data of a distributed system
4+
type: application
5+
version: 0.1.0
6+
appVersion: "3.6.0"
7+
keywords:
8+
- etcd
9+
- distributed
10+
- key-value
11+
- consensus
12+
- raft
13+
home: https://etcd.io/
14+
sources:
15+
- https://github.com/etcd-io/etcd
16+
annotations:
17+
category: Database
18+
license: Apache-2.0
19+
maintainers:
20+
- name: CloudPirates GmbH & Co. KG
21+
url: https://www.cloudpirates.io
22+
dependencies:
23+
- name: common
24+
version: "1.x.x"
25+
repository: oci://registry-1.docker.io/cloudpirates
26+
icon: https://raw.githubusercontent.com/cncf/artwork/master/projects/etcd/icon/color/etcd-icon-color.svg

charts/etcd/README.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
<p align="center">
2+
<a href="https://artifacthub.io/packages/search?repo=cloudpirates-etcd"><img src="https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/cloudpirates-etcd" /></a>
3+
</p>
4+
5+
# etcd Helm Chart
6+
7+
etcd is a distributed reliable key-value store for the most critical data of a distributed system, with a focus on being simple, secure, fast, and reliable.
8+
9+
## Quick Start
10+
11+
### Prerequisites
12+
13+
- Kubernetes 1.24+
14+
- Helm 3.2.0+
15+
- PV provisioner support in the underlying infrastructure (if persistence is enabled)
16+
17+
### Installation
18+
19+
To install the chart with the release name `my-etcd`:
20+
21+
```bash
22+
helm install my-etcd oci://registry-1.docker.io/cloudpirates/etcd
23+
```
24+
25+
To install with custom values:
26+
27+
```bash
28+
helm install my-etcd oci://registry-1.docker.io/cloudpirates/etcd -f my-values.yaml
29+
```
30+
31+
Or install directly from the local chart:
32+
33+
```bash
34+
helm install my-etcd ./charts/etcd
35+
```
36+
37+
### Getting Started
38+
39+
1. Check the status of your etcd cluster:
40+
41+
```bash
42+
kubectl exec -it my-etcd-0 -- etcdctl \
43+
--endpoints=my-etcd:2379 \
44+
endpoint health
45+
```
46+
47+
2. Connect to etcd from inside the cluster:
48+
49+
```bash
50+
kubectl run etcd-client --rm --tty -i --restart='Never' \
51+
--image gcr.io/etcd-development/etcd:v3.6.0-alpha.0 -- bash
52+
53+
# Inside the pod:
54+
etcdctl --endpoints=my-etcd:2379 endpoint status --write-out=table
55+
```
56+
57+
## Configuration
58+
59+
### Image Configuration
60+
61+
| Parameter | Description | Default |
62+
| ------------------- | ------------------------------------- | ------------------------------------ |
63+
| `image.registry` | etcd image registry | `gcr.io` |
64+
| `image.repository` | etcd image repository | `etcd-development/etcd` |
65+
| `image.tag` | etcd image tag | `v3.6.0-alpha.0` |
66+
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
67+
| `global.imageRegistry` | Global Docker image registry override | `""` |
68+
| `global.imagePullSecrets` | Global Docker registry secret names | `[]` |
69+
70+
### Common Parameters
71+
72+
| Parameter | Description | Default |
73+
| ------------------- | --------------------------------------- | ------- |
74+
| `nameOverride` | String to partially override etcd.fullname | `""` |
75+
| `fullnameOverride` | String to fully override etcd.fullname | `""` |
76+
| `commonLabels` | Labels to add to all deployed objects | `{}` |
77+
| `commonAnnotations` | Annotations to add to all deployed objects | `{}` |
78+
| `replicaCount` | Number of etcd replicas to deploy (must be odd) | `3` |
79+
| `podLabels` | Additional labels for etcd pods | `{}` |
80+
| `podAnnotations` | Additional annotations for etcd pods | `{}` |
81+
82+
### Service Configuration
83+
84+
| Parameter | Description | Default |
85+
| ---------------------- | ----------------------- | ----------- |
86+
| `service.type` | Kubernetes service type | `ClusterIP` |
87+
| `service.annotations` | Service annotations | `{}` |
88+
| `service.clientPort` | etcd client port | `2379` |
89+
| `service.peerPort` | etcd peer port | `2380` |
90+
| `service.metricsPort` | etcd metrics port | `2381` |
91+
92+
### Authentication and Security
93+
94+
| Parameter | Description | Default |
95+
| --------------------------- | -------------------------------------------------- | ------- |
96+
| `auth.enabled` | Enable client-to-server TLS authentication | `false` |
97+
| `auth.existingSecret` | Name of existing secret containing client certificates | `""` |
98+
| `auth.peer.enabled` | Enable peer-to-peer TLS authentication | `false` |
99+
| `auth.peer.existingSecret` | Name of existing secret containing peer certificates | `""` |
100+
101+
### etcd Configuration
102+
103+
| Parameter | Description | Default |
104+
| -------------------------------- | -------------------------------------------- | --------------- |
105+
| `config.initialClusterState` | Initial cluster state (new or existing) | `new` |
106+
| `config.autoCompactionMode` | Auto compaction mode (periodic or revision) | `periodic` |
107+
| `config.autoCompactionRetention` | Auto compaction retention | `1` |
108+
| `config.snapshotCount` | Number of transactions to trigger a snapshot | `10000` |
109+
| `config.quotaBackendBytes` | Backend storage quota in bytes (2GB) | `2147483648` |
110+
| `config.maxRequestBytes` | Maximum client request size in bytes | `1572864` |
111+
| `config.logLevel` | Log level (debug, info, warn, error, panic, fatal) | `info` |
112+
| `config.initialClusterToken` | Initial cluster token | `etcd-cluster` |
113+
| `config.heartbeatInterval` | Heartbeat interval in milliseconds | `100` |
114+
| `config.electionTimeout` | Election timeout in milliseconds | `1000` |
115+
| `config.maxSnapshots` | Maximum number of snapshot files to retain | `5` |
116+
| `config.maxWals` | Maximum number of WAL files to retain | `5` |
117+
| `config.listenPeerIp` | IP address to bind for peer traffic | `0.0.0.0` |
118+
| `config.listenClientIp` | IP address to bind for client traffic | `0.0.0.0` |
119+
120+
### Persistence
121+
122+
| Parameter | Description | Default |
123+
| ----------------------------- | ---------------------------------------- | ---------------- |
124+
| `persistence.enabled` | Enable persistence using PVC | `true` |
125+
| `persistence.storageClass` | Storage class of backing PVC | `""` |
126+
| `persistence.annotations` | Annotations for the PVC | `{}` |
127+
| `persistence.size` | Size of data volume | `8Gi` |
128+
| `persistence.accessModes` | Persistent Volume Access Modes | `[ReadWriteOnce]`|
129+
| `persistence.mountPath` | Mount path for data volume | `/var/run/etcd` |
130+
131+
### Resources
132+
133+
| Parameter | Description | Default |
134+
| ----------- | ------------------------------------ | ------- |
135+
| `resources` | CPU/Memory resource requests/limits | `{}` |
136+
137+
### StatefulSet Configuration
138+
139+
| Parameter | Description | Default |
140+
| ------------------ | ------------------------------ | ----------------- |
141+
| `updateStrategy.type` | StatefulSet update strategy | `RollingUpdate` |
142+
143+
### Metrics Configuration
144+
145+
| Parameter | Description | Default |
146+
| -------------------------------------------- | ------------------------------------------------ | ------- |
147+
| `metrics.enabled` | Enable Prometheus metrics | `true` |
148+
| `metrics.serviceMonitor.enabled` | Create ServiceMonitor for Prometheus Operator | `false` |
149+
| `metrics.serviceMonitor.namespace` | Namespace for ServiceMonitor | `""` |
150+
| `metrics.serviceMonitor.interval` | Scrape interval | `30s` |
151+
| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout | `""` |
152+
| `metrics.serviceMonitor.relabelings` | Relabel configurations | `[]` |
153+
| `metrics.serviceMonitor.metricRelabelings` | Metric relabel configurations | `[]` |
154+
| `metrics.serviceMonitor.labels` | Additional labels for ServiceMonitor | `{}` |
155+
| `metrics.serviceMonitor.honorLabels` | Honor labels from metrics | `false` |
156+
157+
### High Availability
158+
159+
| Parameter | Description | Default |
160+
| ----------------------------------- | ------------------------------------- | ------- |
161+
| `podDisruptionBudget.enabled` | Enable PodDisruptionBudget | `false` |
162+
| `podDisruptionBudget.minAvailable` | Minimum number of available pods | `""` |
163+
| `podDisruptionBudget.maxUnavailable`| Maximum number of unavailable pods | `1` |
164+
165+
### Service Account
166+
167+
| Parameter | Description | Default |
168+
| -------------------------------------------- | ---------------------------------------- | ------- |
169+
| `serviceAccount.create` | Create service account | `true` |
170+
| `serviceAccount.name` | Service account name | `""` |
171+
| `serviceAccount.annotations` | Service account annotations | `{}` |
172+
| `serviceAccount.automountServiceAccountToken`| Automount service account token | `false` |
173+
174+
### Network Policy
175+
176+
| Parameter | Description | Default |
177+
| -------------------------------- | ------------------------------------ | ------- |
178+
| `networkPolicy.enabled` | Enable NetworkPolicy | `false` |
179+
| `networkPolicy.allowExternal` | Allow external traffic | `true` |
180+
| `networkPolicy.extraIngress` | Additional ingress rules | `[]` |
181+
| `networkPolicy.extraEgress` | Additional egress rules | `[]` |
182+
183+
### Security Context
184+
185+
| Parameter | Description | Default |
186+
| -------------------------------------------- | -------------------------------------------- | ------------------ |
187+
| `containerSecurityContext.runAsUser` | User ID to run the container | `1000` |
188+
| `containerSecurityContext.runAsGroup` | Group ID to run the container | `1000` |
189+
| `containerSecurityContext.runAsNonRoot` | Run as non-root user | `true` |
190+
| `containerSecurityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
191+
| `containerSecurityContext.readOnlyRootFilesystem` | Mount root filesystem as read-only | `true` |
192+
| `containerSecurityContext.capabilities.drop` | Linux capabilities to drop | `[ALL]` |
193+
| `podSecurityContext.fsGroup` | Group ID for the volumes | `1000` |
194+
195+
### Probes
196+
197+
| Parameter | Description | Default |
198+
| ----------------------------------- | ---------------------------------- | ------- |
199+
| `startupProbe.enabled` | Enable startup probe | `true` |
200+
| `startupProbe.initialDelaySeconds` | Initial delay for startup probe | `0` |
201+
| `startupProbe.periodSeconds` | Period for startup probe | `10` |
202+
| `startupProbe.timeoutSeconds` | Timeout for startup probe | `5` |
203+
| `startupProbe.failureThreshold` | Failure threshold for startup probe| `30` |
204+
| `livenessProbe.enabled` | Enable liveness probe | `true` |
205+
| `livenessProbe.initialDelaySeconds` | Initial delay for liveness probe | `10` |
206+
| `livenessProbe.periodSeconds` | Period for liveness probe | `10` |
207+
| `livenessProbe.timeoutSeconds` | Timeout for liveness probe | `5` |
208+
| `livenessProbe.failureThreshold` | Failure threshold for liveness probe | `3` |
209+
| `readinessProbe.enabled` | Enable readiness probe | `true` |
210+
| `readinessProbe.initialDelaySeconds`| Initial delay for readiness probe | `5` |
211+
| `readinessProbe.periodSeconds` | Period for readiness probe | `10` |
212+
| `readinessProbe.timeoutSeconds` | Timeout for readiness probe | `5` |
213+
| `readinessProbe.failureThreshold` | Failure threshold for readiness probe | `3` |
214+
215+
### Scheduling
216+
217+
| Parameter | Description | Default |
218+
| ------------------------------ | --------------------------------------- | ------- |
219+
| `nodeSelector` | Node labels for pod assignment | `{}` |
220+
| `tolerations` | Tolerations for pod assignment | `[]` |
221+
| `affinity` | Affinity rules for pod assignment | `{}` |
222+
| `topologySpreadConstraints` | Topology Spread Constraints | `[]` |
223+
| `priorityClassName` | Priority class name for pod eviction | `""` |
224+
225+
### Extra Configuration
226+
227+
| Parameter | Description | Default |
228+
| ------------------- | ------------------------------------------------- | ------- |
229+
| `extraArgs` | Additional etcd command line arguments | `[]` |
230+
| `extraEnv` | Additional environment variables | `[]` |
231+
| `extraVolumes` | Additional volumes to add to the pod | `[]` |
232+
| `extraVolumeMounts` | Additional volume mounts for etcd container | `[]` |
233+
| `extraObjects` | Array of extra objects to deploy with the release | `[]` |
234+
235+
## Upgrading
236+
237+
To upgrade your release:
238+
239+
```bash
240+
helm upgrade my-etcd oci://registry-1.docker.io/cloudpirates/etcd
241+
```
242+
243+
## Uninstalling
244+
245+
To uninstall/delete the `my-etcd` deployment:
246+
247+
```bash
248+
helm delete my-etcd
249+
```
250+
251+
## License
252+
253+
Copyright © 2024 CloudPirates GmbH & Co. KG
254+
255+
Licensed under the Apache License, Version 2.0 (the "License");
256+
you may not use this file except in compliance with the License.
257+
You may obtain a copy of the License at
258+
259+
http://www.apache.org/licenses/LICENSE-2.0
260+
261+
Unless required by applicable law or agreed to in writing, software
262+
distributed under the License is distributed on an "AS IS" BASIS,
263+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
264+
See the License for the specific language governing permissions and
265+
limitations under the License.

charts/etcd/templates/_helpers.tpl

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "etcd.name" -}}
5+
{{- include "common.name" . -}}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
*/}}
11+
{{- define "etcd.fullname" -}}
12+
{{- include "common.fullname" . -}}
13+
{{- end }}
14+
15+
{{/*
16+
Create chart name and version as used by the chart label.
17+
*/}}
18+
{{- define "etcd.chart" -}}
19+
{{- include "common.chart" . -}}
20+
{{- end }}
21+
22+
{{/*
23+
Common labels
24+
*/}}
25+
{{- define "etcd.labels" -}}
26+
{{- include "common.labels" . }}
27+
{{- end }}
28+
29+
{{/*
30+
Selector labels
31+
*/}}
32+
{{- define "etcd.selectorLabels" -}}
33+
{{- include "common.selectorLabels" . -}}
34+
{{- end }}
35+
36+
{{/*
37+
Common annotations
38+
*/}}
39+
{{- define "etcd.annotations" -}}
40+
{{- include "common.annotations" . -}}
41+
{{- end }}
42+
43+
{{/*
44+
Return the proper etcd image name
45+
*/}}
46+
{{- define "etcd.image" -}}
47+
{{- include "common.image" (dict "image" .Values.image "global" .Values.global) -}}
48+
{{- end }}
49+
50+
{{/*
51+
Return the proper Docker Image Registry Secret Names
52+
*/}}
53+
{{- define "etcd.imagePullSecrets" -}}
54+
{{ include "common.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }}
55+
{{- end -}}
56+
57+
{{/*
58+
Create the name of the service account to use
59+
*/}}
60+
{{- define "etcd.serviceAccountName" -}}
61+
{{- if .Values.serviceAccount.create }}
62+
{{- default (include "etcd.fullname" .) .Values.serviceAccount.name }}
63+
{{- else }}
64+
{{- default "default" .Values.serviceAccount.name }}
65+
{{- end }}
66+
{{- end }}
67+
68+
{{/*
69+
Validate etcd values
70+
*/}}
71+
{{- define "etcd.validateValues" -}}
72+
{{- $replicaCount := int .Values.replicaCount }}
73+
{{- if and (gt $replicaCount 1) (eq (mod $replicaCount 2) 0) }}
74+
{{- fail (printf "etcd: Invalid replica count. etcd requires an odd number of replicas for quorum (e.g., 1, 3, 5, 7). Current value: %d" $replicaCount) }}
75+
{{- end }}
76+
{{- end }}
77+
78+
{{/*
79+
Generate etcd initial cluster string
80+
*/}}
81+
{{- define "etcd.initialCluster" -}}
82+
{{- $namespace := .Release.Namespace }}
83+
{{- $name := include "etcd.fullname" . -}}
84+
{{- $peerPort := .Values.service.peerPort -}}
85+
{{- $replicaCount := int .Values.replicaCount }}
86+
{{- $protocol := "http" }}
87+
{{- if .Values.auth.peer.enabled }}
88+
{{- $protocol = "https" }}
89+
{{- end }}
90+
{{- range $i := until $replicaCount }}
91+
{{- if $i }},{{ end -}}{{ $name }}-{{ $i }}={{ $protocol }}://{{ $name }}-{{ $i }}.{{ $name }}-headless.{{ $namespace }}.svc.cluster.local:{{ $peerPort }}
92+
{{- end }}
93+
{{- end }}

0 commit comments

Comments
 (0)