자체 빌드 이미지 3종(cloudnative-pg/cnpg-postgresql/etcd) + 대응 헬름 차트 도입

security-catalog 프로젝트에서 첫 실사용 자체 빌드 이미지 3종을 포팅한다 — 전부
상위 태그·베이스 OS 교체로 해소 안 되는 CVE(Go 모듈 정적 링크 또는 미수정 CRITICAL/
HIGH)를 자체 빌드(소스 컴파일 또는 SUSE BCI 재설치)로 대응한다:

- images/cloudnative-pg: CNPG operator, release-1.30 소스 컴파일 + bci-micro
- images/cnpg-postgresql: PostgreSQL 18.4, bci-base + zypper 재설치
- images/etcd: etcd v3.7.1, 소스 컴파일(x/text 강제 업그레이드) + bci-micro

함께 추가:
- manifests/helm/{cloudnative-pg,cnpg-cluster,etcd} — 위 이미지를 참조하는 카탈로그 차트
- scripts/deploy-test/*.sh, .claude/deploy-test-procedure.md — CVE 0건과 별개로
  "실제로 뜨는가"를 검증하는 배포 스모크 테스트
- .claude/pitfalls.md — 자체 빌드/배포 테스트 중 실측한 함정 모음

검토 중 발견해 반영한 수정:
- cloudnative-pg 차트의 image 블록을 etcd와 동일한 registry/repository/tag 3필드+
  따옴표 포맷으로 통일 — 기존 포맷(repository에 registry+repo 결합, 따옴표 없음)은
  patch-catalog-tag.py 의 split 패처가 tag만 갱신하고 repository는 그대로 남기는
  조용한 부분 치환을 일으켜, 향후 레지스트리 마이그레이션 시 깨진 참조를 만들 수 있었다
- cnpg-cluster 차트의 SLES 커버리지 코멘트를 최신 실측(trivy가 SLES 15.7을 정상
  커버함, 2026-07-29 재측정)에 맞게 정정 — 폐기된 "측정 불가/OVAL 우회 필요" 결론이
  남아있었다
- CLAUDE.md/MEMORY.md 의 "images/ 디렉토리 없음" 서술을 갱신하고, 레지스트리
  마이그레이션(docker.io/wbsong111 → docker.io/paasup)·decisions/analysis 문서 이관·
  리소스 프로파일 추가를 다음 작업으로 기록

이 3개 이미지는 아직 dip-catalog 자체 CI(build-image.yml)로 빌드·게이트·push 를
실행해본 적이 없다 — 현재 참조 태그는 security-catalog 쪽에서 이미 검증된 것이다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wbsong111
2026-08-03 12:03:37 +09:00
parent a168a3c7e6
commit 6878b61efa
89 changed files with 36608 additions and 11 deletions
+23
View File
@@ -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/
+109
View File
@@ -0,0 +1,109 @@
# etcd 버전 갱신 가이드
## 1. git 작업 환경 구성
```sh
git clone https://github.com/paasup/dip-catalog.git
cd dip-catalog
git checkout -b update-etcd/<신규버전>
```
## 2. helm chart 업데이트
### 1) 신규 버전 확인
```sh
helm repo add groundhog2k https://groundhog2k.github.io/helm-charts/
helm repo update groundhog2k
helm search repo groundhog2k/etcd --versions | head
```
차트 버전과 etcd 버전(appVersion)은 다르다. 대응 관계를 반드시 확인한다.
| 차트 버전 | etcd(appVersion) |
| --- | --- |
| 1.1.12 | v3.7.1 |
### 2) 이미지 레지스트리 재확인 (매 버전 갱신 시 필수)
`CUSTOM-README.md` 에 적어둔 대로 etcd 프로젝트는 `gcr.io/etcd-development`,
`quay.io/coreos` 를 **3.8부터 폐지**하고 `registry.k8s.io/etcd` 로 이전한다
([etcd-io/etcd#20928](https://github.com/etcd-io/etcd/issues/20928)). 버전을 올릴 때마다
아래를 확인해 어느 레지스트리로 고정할지 다시 판단한다.
```sh
NEW_VER=v3.8.0 # 예시
# registry.k8s.io 에 신규 버전이 이미 올라와 있는지 확인
curl -sL "https://registry.k8s.io/v2/etcd/tags/list" | grep "\"$NEW_VER\""
# 아직 없다면 과도기 레지스트리(quay.io/coreos, gcr.io/etcd-development)로 폴백
```
### 3) 신규 버전 디렉토리 생성
버전별 독립 디렉토리다. 기존 디렉토리를 수정하지 않고 새로 만든다.
```sh
NEW=1.2.0
OLD=1.1.12
cd manifests/helm/etcd
helm pull groundhog2k/etcd --version "$NEW" --untar --untardir /tmp/etcd-pull
mkdir -p "$NEW"
cp -R /tmp/etcd-pull/etcd/. "$NEW"/
# PaaSup 관리 파일을 이전 버전에서 승계한다
for f in custom-values.yaml dip-values.yaml dip-resources-quotas.yaml \
dip-volumes-quotas.yaml CUSTOM-README.md BUILD-README.md; do
cp "$OLD/$f" "$NEW/$f"
done
```
### 4) diff 확인
```sh
diff -u "$OLD/values.yaml" "$NEW/values.yaml" | less
helm template test "$NEW" -f "$NEW/custom-values.yaml" >/dev/null && echo "렌더링 OK"
```
`custom-values.yaml``image.tag`/`initImage.tag` 를 신규 appVersion·busybox 최신
고정 태그로 갱신한다(위 2번 결과 반영).
### 5) 렌더링 결과 비교
```sh
helm template etcd "$OLD" -f "$OLD/custom-values.yaml" -n etcd-system > /tmp/old.yaml
helm template etcd "$NEW" -f "$NEW/custom-values.yaml" -n etcd-system > /tmp/new.yaml
diff -u /tmp/old.yaml /tmp/new.yaml
```
## 3. 문서 갱신
| 파일 | 갱신 내용 |
| --- | --- |
| `CUSTOM-README.md` | 차트/etcd 버전 번호, 이미지 레지스트리 판단 결과 |
| `BUILD-README.md` | 위 버전 대응 표에 신규 행 추가 |
| `doc/charts/etcd/deploy-test.md` | 신규 버전으로 배포 테스트 재실행 후 결과 갱신 |
| `doc/image-selection.md` | 현재 카탈로그 상태 표의 etcd 행 갱신 |
## 4. 배포 검증
```sh
IMAGE_NAME=<registry>/<repository>:<tag> bash scripts/deploy-test/deploy-test-etcd.sh /tmp/etcd-deploy-test-out
```
최소한 다음을 통과해야 한다.
1. 3-replica StatefulSet 이 모두 `Running`
2. `etcdctl endpoint health --cluster` 전 멤버 healthy
3. `etcdctl put`/`get` 쓰기·읽기 왕복 확인
## 5. PR
```sh
git add manifests/helm/etcd/<신규버전> doc/
git commit -m "etcd <신규버전> 추가"
git push -u origin update-etcd/<신규버전>
```
PR 생성 시 `helm-catalog-sbom` 워크플로가 변경 차트에 대해 SBOM·취약점 스캔을 수행한다.
CRITICAL 취약점이 있으면 내용을 확인하고 PR 본문에 판단 근거를 남긴다.
+106
View File
@@ -0,0 +1,106 @@
# etcd 배포
차트 버전 `1.1.12` (`groundhog2k/etcd`) / etcd 버전 `v3.7.1`
etcd 는 분산 key-value 저장소다. 이 차트는 오퍼레이터 없이 StatefulSet 으로 직접
멀티노드 클러스터를 구성한다(cnpg 처럼 operator + CR 구조가 아니다).
## 1. 배포 방법
### 1) 배포 시 주의 사항
- **`replicas` 는 최초 배포 후 변경할 수 없다.** 업스트림 차트가 명시하는 제약이다
(`values.yaml` 주석 — "Automatic scaling or manually scaling the etcd cluster after
first deployment is not supported"). 클러스터 크기를 바꾸려면 재배포(새 클러스터 생성
+ 데이터 마이그레이션)가 필요하다. 배포 전에 티어(`dip-resources-quotas.yaml`)를 반드시
확정한다.
- **자동 백업이 없다.** cnpg 의 `barmanObjectStore`/`scheduledBackup` 같은 내장 기능이
없다. 스냅샷은 운영자가 수동으로 실행한다.
```sh
kubectl -n <ns> exec <pod-0> -- etcdctl snapshot save /tmp/snapshot.db
kubectl -n <ns> cp <pod-0>:/tmp/snapshot.db ./snapshot.db
```
정기 백업이 필요하면 별도 CronJob 을 구성해야 한다 — 이 차트 범위 밖이다.
- **TLS 는 기본 비활성이다.** `custom-values.yaml` 은 업스트림 기본값(평문 클라이언트/피어
통신)을 그대로 쓴다. 운영 배포는 `dip-values.yaml` 로 `settings.https.autoTls: true` 를
켠다(자체 서명 인증서 자동 생성). CA 발급 인증서로 교체하려면 `extraSecrets` 로 마운트하고
`settings.https.autoTls` 를 `false` 로 내린 뒤 인증서 경로를 직접 지정해야 한다
(차트 `values.yaml` 의 `settings.https` 주석 참고).
- init 컨테이너(`busybox`)가 데이터 디렉토리(`/data/etcd`)를 `chmod 700` 으로 생성한다.
`securityContext`(uid/gid 999, non-root, RO rootfs)와 함께 이 권한이 맞물려야 정상
기동한다 — 배포 테스트에서 이미지가 실제로 uid 999 로 뜨는지 확인 완료
(`doc/charts/etcd/deploy-test.md`).
### 2) 배포
```sh
git clone https://github.com/paasup/dip-catalog.git
cd dip-catalog/manifests/helm/etcd/1.1.12
helm upgrade etcd ./ -f custom-values.yaml --install -n etcd-system --create-namespace --wait
```
### 3) 확인
```sh
kubectl -n etcd-system get pods -l app.kubernetes.io/name=etcd
kubectl -n etcd-system exec etcd-0 -- etcdctl endpoint health --cluster
```
## 2. custom-values.yaml 설명
### 1) 이미지 설정
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `image.registry` / `image.repository` / `image.tag` | etcd 본체 이미지. **자체 빌드**(`docker.io/wbsong111/etcd:3.7.1-security-hardened-20260731`) — 업스트림 `quay.io/coreos/etcd:v3.7.1` 이 게이트 차단 HIGH 1건(`CVE-2026-56852`, `golang.org/x/text`)으로 막혀 대체했다. 근거·빌드 정의는 [images/etcd/README.md](../../../images/etcd/README.md), 채택 결정 배경은 security-catalog 프로젝트 decisions/0007(dip-catalog 미이관). 상위 태그가 나오거나 `release-3.7` 에 백포트되면 업스트림으로 되돌리는 것이 우선(대응 우선순위 a) | 업스트림 `quay.io/coreos/etcd` (태그 미지정) |
| `initImage.registry` / `initImage.repository` / `initImage.tag` | 데이터 디렉토리 초기화용 init 컨테이너. 업스트림 기본값(`busybox:stable`)은 롤링 태그라 `busybox:1.38.0-uclibc` 로 고정 | 업스트림 `busybox:stable` |
### 2) 클러스터 크기
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `replicas` | 최초 배포 후 변경 불가(위 주의사항). 이 카탈로그 항목은 단일 APISIX 인스턴스의 설정 저장소 용도라 쿼럼 HA 대신 단일 노드로 둔다(결정 배경: security-catalog 프로젝트 decisions/0006, dip-catalog 미이관) — 노드 장애 시 단일 장애점이 되는 트레이드오프를 받아들인 것. 쿼럼 HA가 필요하면 `dip-values.yaml`(3, 홀수 권장) 사용 | 1 |
### 3) 스토리지
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `storage.requestedSize` | PVC 크기. 티어별 값은 `dip-volumes-quotas.yaml` 참고 | `5Gi` |
| `storage.className` | `longhorn` | `longhorn` |
etcd 는 권장 데이터 크기 상한이 있다(기본 `--quota-backend-bytes` 2GB, 업스트림도 8GB 초과를
권장하지 않음). 볼륨을 과하게 키우는 것이 능사가 아니다.
### 4) TLS
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `settings.https.enabled` | 클라이언트/피어 통신 TLS 사용 여부 | `false`(custom-values) / `true`(dip-values) |
| `settings.https.autoTls` | etcd 자체 서명 인증서 자동 생성 | `false`(custom-values) / `true`(dip-values) |
### 5) 리소스
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `resources` | 티어별 값은 `dip-resources-quotas.yaml` 참고 | 업스트림은 `{}`(무제한) |
## 3. 업그레이드
버전 갱신 절차는 `BUILD-README.md` 참고. etcd 는 마이너 버전 간 데이터 포맷 호환성을
공식 문서에서 보장하는 범위 내에서만 순차 업그레이드해야 한다(예: 3.6→3.7). 여러 마이너
버전을 건너뛰지 않는다.
## 4. 제거
```sh
helm uninstall etcd -n etcd-system
kubectl -n etcd-system delete pvc -l app.kubernetes.io/name=etcd
```
PVC 는 helm uninstall 로 지워지지 않는다(StatefulSet 볼륨클레임 기본 동작). 데이터를
보존할 필요가 없다면 위처럼 명시적으로 삭제한다. `longhorn` 은 `reclaimPolicy: Retain` 이므로
PV 자체가 남을 수 있다 — `.claude/pitfalls.md` 참고.
## 5. 검증 이력
`doc/charts/etcd/deploy-test.md` 참고.
+13
View File
@@ -0,0 +1,13 @@
apiVersion: v2
appVersion: v3.7.1
description: A Helm chart for etcd on Kubernetes
icon: https://etcd.io/etcd-horizontal-white.png
keywords:
- database
- etcd
maintainers:
- name: groundhog2k
url: https://github.com/groundhog2k/helm-charts
name: etcd
type: application
version: 1.1.12
+176
View File
@@ -0,0 +1,176 @@
# Etcd
![Version: 1.1.12](https://img.shields.io/badge/Version-1.1.12-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v3.7.1](https://img.shields.io/badge/AppVersion-v3.7.1-informational?style=flat-square)
## Changelog
see [RELEASENOTES.md](RELEASENOTES.md)
A Helm chart for a Etcd HA-cluster on Kubernetes
## TL;DR
```bash
helm repo add groundhog2k https://groundhog2k.github.io/helm-charts/
helm install my-release groundhog2k/etcd
```
## Introduction
This chart uses the original [Etcd image from Quay.io](https://quay.io/repository/coreos/etcd) to deploy a stateful Etcd cluster in Kubernetes.
It fully supports deployment of the multi-architecture docker image.
## Prerequisites
- Kubernetes 1.12+
- Helm 3.x
- PV provisioner support in the underlying infrastructure
## Installing the Chart
To install the chart with the release name `my-release`:
```bash
helm install my-release groundhog2k/etcd
```
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```bash
helm uninstall my-release
```
## Common parameters
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| fullnameOverride | string | `""` | Fully override the deployment name |
| nameOverride | string | `""` | Partially override the deployment name |
## Deployment parameters
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
| image.registry | string | `"quay.io/coreos"` | Image registry |
| image.repository | string | `"etcd"` | Image name |
| image.tag | string | `""` | Image tag |
| initImage.pullPolicy | string | `"IfNotPresent"` | Init image pull policy |
| initImage.registry | string | `"docker.io"` | Image registry |
| initImage.repository | string | `"busybox"` | Init image name |
| initImage.tag | string | `"stable"` | Init image tag |
| imagePullSecrets | list | `[]` | Image pull secrets |
| extraInitContainers | list | `[]` | Extra init containers |
| extaContainers | list | `[]` | Extra containers for usage as sidecars |
| startupProbe | object | `see values.yaml` | Startup probe configuration |
| livenessProbe | object | `see values.yaml` | Liveness probe configuration |
| readinessProbe | object | `see values.yaml` | Readiness probe configuration |
| customStartupProbe | object | `{}` | Custom startup probe (overwrites default startup probe configuration) |
| customLivenessProbe | object | `{}` | Custom liveness probe (overwrites default liveness probe configuration) |
| customReadinessProbe | object | `{}` | Custom readiness probe (overwrites default readiness probe configuration) |
| resources | object | `{}` | Resource limits and requests |
| priorityClassName | string | `""` | Deployment priority class name |
| nodeSelector | object | `{}` | Deployment node selector |
| customLabels | object | `{}` | Additional labels for Deployment or StatefulSet |
| customAnnotations | object | `{}` | Additional annotations for Deployment or StatefulSet |
| podAnnotations | object | `{}` | Additional pod annotations |
| podLabels | object | `{}` | Additional pod labels |
| podSecurityContext | object | `see values.yaml` | Pod security context |
| securityContext | object | `see values.yaml` | Container security context |
| env | list | `[]` | Additional container environmment variables |
| args | list | `[]` | Additional container command arguments |
| rbac.create | bool | `true` | Enable creation of RBAC |
| serviceAccount.annotations | object | `{}` | Additional service account annotations |
| serviceAccount.create | bool | `true` | Enable service account creation |
| serviceAccount.name | string | `""` | Optional name of the service account |
| serviceAccount.automountServiceAccountToken | bool | `true` | Specifies whether a service account token should be automatically mounted |
| affinity | object | `{}` | Affinity for pod assignment |
| tolerations | list | `[]` | Tolerations for pod assignment |
| topologySpreadConstraints | object | `{}` | Topology spread constraints for pods |
| podManagementPolicy | string | `"Parallel"` | Pod management policy |
| updateStrategyType | string | `"RollingUpdate"` | Pod update strategy |
| replicas | int | `1` | Number of replicas (Due to the nature of etcd cluster initialization this value must be set before deploying the cluster) |
| revisionHistoryLimit | int | `nil` | Maximum number of revisions maintained in revision history |
| podDisruptionBudget | object | `{}` | Pod disruption budget |
| podDisruptionBudget.minAvailable | int | `nil` | Minimum number of pods that must be available after eviction |
| podDisruptionBudget.maxUnavailable | int | `nil` | Maximum number of pods that can be unavailable after eviction |
| clusterDomain | string | `"cluster.local"` | Kubernetes cluster domain (DNS) suffix |
## Service parameters
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| service.type | string | `"ClusterIP"` | Service type |
| service.clusterIP | string | `nil` | The cluster ip address (only relevant for type LoadBalancer or NodePort) |
| service.loadBalancerIP | string | `nil` | The load balancer ip address (only relevant for type LoadBalancer) |
| service.loadBalancerSourceRanges | list | `[]` | The list of IP CIDR ranges that are allowed to access the load balancer (only relevent for type LoadBalancer) |
| service.client.port | int | `2379` | Client service port |
| service.client.nodePort | int | `nil` | Service node port (only relevant for type LoadBalancer or NodePort) |
| service.peer.port | int | `2380` | Peer service port |
| service.peer.nodePort | int | `nil` | Service node port (only relevant for type LoadBalancer or NodePort) |
| service.annotations | object | `{}` | Additional service annotations |
| service.labels | object | `{}` | Additional service labels |
## Service monitor parameters
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| serviceMonitor.enabled | bool | `false` | Enable service monitor |
| serviceMonitor.additionalLabels | object | `{}` | Additional labels for the service monitor object |
| serviceMonitor.annotations | object | `{}` | Annotations for the service monitor object |
| serviceMonitor.interval | Duration | `nil` | Scrape interval for prometheus |
| serviceMonitor.scrapeTimeout | Duration | `nil` | Scrape timeout value |
| serviceMonitor.extraEndpointParameters | object | `nil` | Extra parameters rendered to the [service monitor endpoint](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#endpoint) |
| serviceMonitor.extraParameters | object | `nil` | Extra parameters rendered to the [service monitor object](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#servicemonitorspec) |
## Network policies
Allows to define optional network policies for [ingress and egress](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
The policyTypes will be automatically set
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| networkPolicy.ingress | object | `{}` | Ingress network policies |
| networkPolicy.egress | object | `{}` | Egress network policies |
## Storage parameters
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| storage.accessModes[0] | string | `"ReadWriteOnce"` | Storage access mode |
| storage.volumeName | string | `"etcd-data"` | Internal volume name and prefix of a created PVC |
| storage.persistentVolumeClaimName | string | `nil` | PVC name when existing storage volume should be used |
| storage.requestedSize | string | `nil` | Size for new PVC, when no existing PVC is used |
| storage.className | string | `nil` | Storage class name |
| storage.annotations | object | `{}` | Additional storage annotations |
| storage.labels | object | `{}` | Additional storage labels |
| extraStorage | list | `[]` | A list of additional existing PVC that will be mounted into the container |
| extraStorage[].name | string | `nil` | Internal name of the volume |
| extraStorage[].pvcName | string | `nil` | Name of the existing PVC |
| extraStorage[].mountPath | string | `nil` | Mount path where the PVC should be mounted into the container |
## Etcd settings
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| settings.clusterToken | bool | `"etcd-cluster-0"` | Unique cluser token |
| settings.https.enabled | bool | `false` | Enable HTTPS |
| settings.https.autoTls | bool | `false` | Automatic TLS mode of etcd (TLS certs. created automaically) |
| settings.shutdownDelay | int | `3` | Delay after termination request to give etcd process time for graceful shutdown |
## Etcd secrets and configuration
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| extraSecrets | list | `[]` | A list of additional existing secrets that will be mounted into the container |
| extraSecrets[].name | string | `nil` | Name of the existing K8s secret |
| extraSecrets[].defaultMode | int | `0440` | Mount default access mode |
| extraSecrets[].mountPath | string | `nil` | Mount path where the secret should be mounted into the container (f.e. /mysecretfolder) |
| extraConfigs | list | `[]` | A list of additional existing configMaps that will be mounted into the container |
| extraConfigs[].name | string | `nil` | Name of the existing K8s configMap |
| extraConfigs[].defaultMode | int | `0440` | Mount default access mode |
| extraConfigs[].mountPath | string | `nil` | Mount path where the configMap should be mounted into the container (f.e. /myconfigfolder) |
| extraEnvSecrets | list | `[]` | A list of existing secrets that will be mounted into the container as environment variables |
@@ -0,0 +1,38 @@
# Changelog
| Chart version | App version | Change description |
| :------------ | :---------- | :----------------- |
| 0.1.0 | v3.5.6 | Initial version |
| 0.1.1 | v3.5.7 | Upgraded etcd to v3.5.7 |
| 0.1.2 | v3.5.7 | Updated default security context |
| 0.1.3 | v3.5.7 | Fixed "nil" syntax error for health checks (thx @omegazeng) |
| 0.1.4 | v3.5.8 | Upgraded etcd to v3.5.8 |
| 0.1.5 | v3.5.9 | Upgraded etcd to v3.5.9 |
| 0.1.6 | v3.5.9 | Added support for network policies and additional labels and annotations |
| 0.1.7 | v3.5.10 | Upgraded etcd to v3.5.10 |
| 0.1.8 | v3.5.11 | Upgraded etcd to v3.5.11 |
| 0.1.9 | v3.5.12 | Upgraded etcd to v3.5.12 |
| 0.1.10 | v3.5.13 | Upgraded etcd to v3.5.13 |
| 0.1.11 | v3.5.13 | Fixed build pipeline issue |
| 1.0.0 | v3.5.13 | Final version with configuration secret, extra config and extra volume support |
| 1.0.1 | v3.5.15 | Upgraded etcd to v3.5.15 |
| 1.0.2 | v3.5.16 | Upgraded etcd to v3.5.16 |
| 1.0.3 | v3.5.17 | Upgraded etcd to v3.5.17 |
| 1.0.4 | v3.5.18 | Upgraded etcd to v3.5.18 |
| 1.0.6 | v3.5.20 | Upgraded etcd to v3.5.20 |
| 1.0.7 | v3.5.21 | Upgraded etcd to v3.5.21 |
| 1.0.8 | v3.5.21 | Added support for loadBalancerSourceRanges |
| 1.1.0 | v3.6.4 | Upgraded etcd to v3.6.4 |
| 1.1.1 | v3.6.4 | Changed to busybox:stable containter image |
| 1.1.2 | v3.6.4 | Added ability to set automountServiceAccountToken - thx @krizzpiBiGdirekt |
| 1.1.3 | v3.6.4 | Added priorityClassName - thx @JimCronqvist |
| 1.1.4 | v3.6.6 | Upgraded etcd to v3.6.6 |
| 1.1.5 | v3.6.7 | Upgraded etcd to v3.6.7 |
| 1.1.6 | v3.6.9 | Upgraded etcd to v3.6.9 |
| 1.1.7 | v3.6.9 | Fixed insecure parameters - thx @oleksiialeksieiev |
| 1.1.8 | v3.6.11 | Upgraded etcd to v3.6.11 |
| 1.1.9 | v3.6.13 | Upgraded etcd to v3.6.13, fixed PVC definition - thx @trandbert37 |
| 1.1.10 | v3.7.0 | Upgraded etcd to v3.7.0 |
| 1.1.11 | v3.7.0 | Fixed README.md markdown formatting |
| 1.1.12 | v3.7.1 | Upgraded etcd to v3.7.1 |
| | | |
@@ -0,0 +1,50 @@
# etcd — PaaSup 오버라이드
# 업스트림 기본값은 values.yaml 참고. 여기에는 변경이 필요한 항목만 둔다.
image:
# 자체 빌드(대응 우선순위 c) — 업스트림 quay.io/coreos/etcd:v3.7.1 이 게이트 차단
# HIGH 1건(golang.org/x/text, CVE-2026-56852, 바이너리 정적 링크라 베이스 OS 교체로
# 해소 불가)으로 막혀 v3.7.1 태그가 가리키는 commit 을 그대로 컴파일했다. x/text 만
# go.work 워크스페이스 전역 replace 로 0.39.0 이상으로 강제. 근거: doc/analysis/etcd-cve.md,
# 결정: doc/decisions/0007-etcd-image-self-build.md. 빌드 정의: images/etcd/.
# 상위 태그가 나오거나 release-3.7 에 백포트되면(대응 우선순위 a) 되돌리는 것이 우선.
#
# 이전 값: quay.io/coreos/etcd:v3.7.1 (업스트림). etcd 프로젝트는 3.8부터
# gcr.io/etcd-development·quay.io/coreos 를 폐지하고 registry.k8s.io/etcd 로 이전
# 예정이다(etcd-io/etcd#20928) — 상위 태그로 돌아갈 때 이것도 함께 재검토한다.
registry: "docker.io/wbsong111"
repository: "etcd"
tag: "3.7.1-security-hardened-20260731"
initImage:
# 업스트림 기본값 "stable" 은 롤링 태그다 (doc/image-selection.md 2번 규칙 위반).
# 이 init 컨테이너도 extract-helm-images.sh 에 잡혀 게이트 대상이 되므로 고정한다.
registry: "docker.io"
repository: "busybox"
tag: "1.38.0-uclibc"
# 클러스터 초기화 특성상 최초 배포 전에 정해야 하며, 이후 자동/수동 스케일링을
# 지원하지 않는다(업스트림 values.yaml 주석).
#
# 이 카탈로그 항목의 용도는 단일 APISIX 인스턴스의 설정 저장소다 — APISIX 자체가
# 단일 인스턴스라 etcd 쪽에서 쿼럼 HA를 가져갈 이유가 없고, 오퍼레이터 없이 가벼운
# 차트 하나로 충분하다는 것이 이 결정의 핵심이다(doc/decisions/0006-etcd-chart-selection.md).
# 노드 장애 시 단일 장애점이 된다는 것을 받아들인 트레이드오프다. 쿼럼 HA가 필요한
# 다른 소비자가 생기면 dip-values.yaml(replicas: 3)을 쓰거나 이 값을 재검토한다.
replicas: 1
storage:
requestedSize: 5Gi
className: "longhorn"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# TLS — 업스트림 기본값(평문 클라이언트/피어 통신)을 그대로 둔다. 운영 배포는
# dip-values.yaml 에서 autoTls: true 로 켠다. 여기서는 CVE 스캔 기준값 + 최소 동작
# 확인용이라 단순하게 유지한다.
@@ -0,0 +1,33 @@
# etcd 는 데이터셋이 작고(대개 수백 MB~수 GB) CPU/메모리 요구량도 낮다.
# 티어는 주로 replica 수(가용성)로 구분한다 — replica 수는 최초 배포 후 변경 불가
# (업스트림 values.yaml 주석)하므로 반드시 배포 전에 티어를 정해야 한다.
small:
replicas: 1
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
medium:
replicas: 3
resources:
requests:
cpu: "1"
memory: 1Gi
limits:
cpu: "2"
memory: 2Gi
large:
replicas: 5
resources:
requests:
cpu: "2"
memory: 2Gi
limits:
cpu: "4"
memory: 4Gi
@@ -0,0 +1,32 @@
# etcd — DIP 플랫폼 기본 배포값 (운영 기준)
replicas: 3
settings:
clusterToken: "etcd-cluster-0"
https:
# 평문 클라이언트/피어 통신은 운영 기본값으로 부적절하다.
# autoTls 는 etcd 가 자체 서명 인증서를 생성한다 — CA 발급 인증서로
# 교체하려면 extraSecrets 로 마운트하고 이 값을 다시 false 로 내려야 한다.
enabled: true
autoTls: true
serviceMonitor:
# rancher-monitoring(Prometheus Operator) 설치 환경에서만 true
enabled: true
storage:
requestedSize: 20Gi
className: "longhorn"
resources:
requests:
cpu: "1"
memory: 1Gi
limits:
cpu: "2"
memory: 2Gi
# 이 차트는 자동 백업이 없다. 스냅샷은 운영자가 수동으로 실행한다
# kubectl exec <pod> -- etcdctl snapshot save /tmp/snapshot.db
# 정기 백업이 필요하면 별도 CronJob 을 구성해야 한다(이번 범위 밖).
@@ -0,0 +1,17 @@
# etcd 는 권장 데이터 크기 상한이 있다(기본 quota-backend-bytes 2GB, 상향 시에도
# 8GB 를 넘기지 않는 것을 업스트림이 권장). 볼륨은 여유를 두되 과하게 키우지 않는다.
small:
storage:
requestedSize: 5Gi
className: "longhorn"
medium:
storage:
requestedSize: 20Gi
className: "longhorn"
large:
storage:
requestedSize: 50Gi
className: "longhorn"
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "etcd.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "etcd.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 }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "etcd.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "etcd.labels" -}}
helm.sh/chart: {{ include "etcd.chart" . }}
{{ include "etcd.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "etcd.selectorLabels" -}}
app.kubernetes.io/name: {{ include "etcd.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "etcd.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "etcd.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
@@ -0,0 +1,29 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ include "etcd.fullname" . }}
labels:
{{- include "etcd.labels" . | nindent 4 }}
data:
{{- $replicaCount := int .Values.replicas }}
{{- $initialCluster := list }}
{{- $etcdFullname := include "etcd.fullname" . }}
{{- $etcdInternalServiceName := printf "%s-internal" $etcdFullname }}
{{- $protocol := (or .Values.settings.https.enabled .Values.settings.https.autoTls) | ternary "https" "http" }}
{{- $servicefqdn := printf "%s.%s.svc.%s" $etcdInternalServiceName .Release.Namespace .Values.clusterDomain }}
ETCD_DATA_DIR: "/data/etcd"
ETCD_INITIAL_CLUSTER_TOKEN: "{{ .Values.settings.clusterToken }}"
ETCD_INITIAL_CLUSTER_STATE: "new"
ETCD_LISTEN_CLIENT_URLS: "{{ $protocol }}://0.0.0.0:2379"
ETCD_LISTEN_PEER_URLS: "{{ $protocol }}://0.0.0.0:2380"
{{- if .Values.serviceMonitor.enabled }}
ETCD_LISTEN_METRICS_URLS: "http://0.0.0.0:12379"
{{- end }}
{{- range $e, $i := until $replicaCount }}
{{- $initialCluster = append $initialCluster (printf "%s-%d=%s://%s-%d.%s:%d" $etcdFullname $i $protocol $etcdFullname $i $servicefqdn 2380) }}
{{- end }}
ETCD_INITIAL_CLUSTER: {{ join "," $initialCluster | quote }}
{{- if .Values.settings.https.autoTls }}
ETCD_AUTO_TLS: "true"
ETCD_PEER_AUTO_TLS: "true"
{{- end }}
@@ -0,0 +1,25 @@
{{- with .Values.networkPolicy }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "etcd.fullname" $ }}
spec:
podSelector:
matchLabels:
{{- include "etcd.selectorLabels" $ | nindent 6 }}
policyTypes:
{{- if .ingress }}
- Ingress
{{- end }}
{{- if .egress }}
- Egress
{{- end }}
{{- with .ingress }}
ingress:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .egress }}
egress:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "etcd.fullname" . }}-internal
labels:
{{- include "etcd.labels" . | nindent 4 }}
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- port: {{ .Values.service.client.port }}
targetPort: client
name: client
- port: {{ .Values.service.peer.port }}
targetPort: peer
name: peer
selector:
{{- include "etcd.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,47 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "etcd.fullname" . }}
labels:
{{- include "etcd.labels" . | nindent 4 }}
{{- with .Values.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.client.port }}
targetPort: client
name: client
{{- if and ( or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") ) (.Values.service.client.nodePort) }}
nodePort: {{ .Values.service.client.nodePort }}
{{- end }}
- port: {{ .Values.service.peer.port }}
targetPort: peer
name: peer
{{- if and ( or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") ) (.Values.service.peer.nodePort) }}
nodePort: {{ .Values.service.peer.nodePort }}
{{- end }}
{{- if .Values.serviceMonitor.enabled }}
- port: {{ .Values.service.prometheus.port }}
targetPort: prometheus
name: prometheus
{{- if and ( or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") ) (.Values.service.prometheus.nodePort) }}
nodePort: {{ .Values.service.prometheus.nodePort }}
{{- end }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (.Values.service.loadBalancerIP) }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (.Values.service.loadBalancerSourceRanges) }}
loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
{{- end }}
{{- if .Values.service.clusterIP }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
selector:
{{- include "etcd.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "etcd.serviceAccountName" . }}
labels:
{{- include "etcd.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
{{- end }}
@@ -0,0 +1,34 @@
{{- if .Values.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "etcd.fullname" . }}
labels:
{{- include "etcd.labels" . | nindent 4 }}
{{- with .Values.serviceMonitor.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.serviceMonitor.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- port: "prometheus"
path: "/metrics"
{{- if .Values.serviceMonitor.interval }}
interval: {{ .Values.serviceMonitor.interval }}
{{- end }}
{{- if .Values.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }}
{{- end }}
{{- with .Values.serviceMonitor.extraEndpointParameters }}
{{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.serviceMonitor.extraParameters }}
{{- toYaml . | nindent 2 }}
{{- end }}
selector:
matchLabels:
{{- include "etcd.selectorLabels" . | nindent 6 }}
{{- end }}
@@ -0,0 +1,280 @@
{{- $fullname := include "etcd.fullname" . }}
{{- $etcdInternalServiceName := printf "%s-internal" $fullname }}
{{- $protocol := (or .Values.settings.https.enabled .Values.settings.https.autoTls) | ternary "https" "http" }}
{{- $servicefqdn := printf "%s.%s.svc.%s" $etcdInternalServiceName .Release.Namespace .Values.clusterDomain }}
{{- $createPvc := and (empty .Values.storage.persistentVolumeClaimName) (.Values.storage.requestedSize) }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ $fullname }}
labels:
{{- include "etcd.labels" . | nindent 4 }}
{{- with .Values.customLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.customAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.replicas }}
{{- if .Values.revisionHistoryLimit }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
{{- end }}
serviceName: {{ $fullname }}-internal
podManagementPolicy: {{ .Values.podManagementPolicy }}
updateStrategy:
type: {{ .Values.updateStrategyType }}
selector:
matchLabels:
{{- include "etcd.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/etcdconfig: {{ include (print $.Template.BasePath "/etcdconfig.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "etcd.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- if .Values.priorityClassName }}
priorityClassName: {{ .Values.priorityClassName }}
{{- end }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "etcd.serviceAccountName" . }}
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: {{ .Chart.Name }}-init
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.initImage.registry }}/{{ .Values.initImage.repository }}:{{ .Values.initImage.tag }}"
imagePullPolicy: {{ .Values.initImage.pullPolicy }}
volumeMounts:
- name: {{ .Values.storage.volumeName }}
mountPath: /data
command: ["/bin/sh"]
args: ["-c", "mkdir -p /data/etcd && chmod 700 /data/etcd"]
{{- with .Values.extraInitContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: client
containerPort: 2379
- name: peer
containerPort: 2380
{{- if .Values.serviceMonitor.enabled }}
- name: prometheus
containerPort: 12379
{{- end }}
{{- if .Values.customStartupProbe }}
startupProbe:
{{- toYaml .Values.customStartupProbe | nindent 12 }}
{{- else }}
{{- if .Values.startupProbe.enabled }}
startupProbe:
exec:
command:
- /usr/local/bin/etcdctl
- endpoint
- health
{{- if (or .Values.settings.https.enabled .Values.settings.https.autoTls) }}
- --insecure-skip-tls-verify=true
- --insecure-transport=false
{{- end }}
{{- with .Values.startupProbe }}
initialDelaySeconds: {{ .initialDelaySeconds }}
timeoutSeconds: {{ .timeoutSeconds }}
failureThreshold: {{ .failureThreshold }}
successThreshold: {{ .successThreshold }}
periodSeconds: {{ .periodSeconds }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.customLivenessProbe }}
livenessProbe:
{{- toYaml .Values.customLivenessProbe | nindent 12 }}
{{- else }}
{{- if .Values.livenessProbe.enabled }}
livenessProbe:
exec:
command:
- /usr/local/bin/etcdctl
- endpoint
- health
{{- if (or .Values.settings.https.enabled .Values.settings.https.autoTls) }}
- --insecure-skip-tls-verify=true
- --insecure-transport=false
{{- end }}
{{- with .Values.livenessProbe }}
initialDelaySeconds: {{ .initialDelaySeconds }}
timeoutSeconds: {{ .timeoutSeconds }}
failureThreshold: {{ .failureThreshold }}
successThreshold: {{ .successThreshold }}
periodSeconds: {{ .periodSeconds }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.customReadinessProbe }}
readinessProbe:
{{- toYaml .Values.customReadinessProbe | nindent 12 }}
{{- else }}
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
exec:
command:
- /usr/local/bin/etcdctl
- endpoint
- health
{{- if (or .Values.settings.https.enabled .Values.settings.https.autoTls) }}
- --insecure-skip-tls-verify=true
- --insecure-transport=false
{{- end }}
{{- with .Values.readinessProbe }}
initialDelaySeconds: {{ .initialDelaySeconds }}
timeoutSeconds: {{ .timeoutSeconds }}
failureThreshold: {{ .failureThreshold }}
successThreshold: {{ .successThreshold }}
periodSeconds: {{ .periodSeconds }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.args }}
args:
{{- range .Values.args }}
- {{ . }}
{{- end }}
{{- end }}
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ETCD_NAME
value: $(NODE_NAME)
- name: ETCD_ADVERTISE_CLIENT_URLS
value: "{{ $protocol }}://$(NODE_NAME).{{ $servicefqdn }}:2379"
- name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: "{{ $protocol }}://$(NODE_NAME).{{ $servicefqdn }}:2380"
{{- with .Values.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
envFrom:
- configMapRef:
name: {{ $fullname }}
{{- range .Values.extraEnvSecrets }}
- secretRef:
name: {{ . }}
{{- end }}
volumeMounts:
- name: {{ .Values.storage.volumeName }}
mountPath: /data
- name: tmp
mountPath: /tmp
{{- range $secret := .Values.extraSecrets }}
- name: {{ $secret.name }}
mountPath: {{ $secret.mountPath }}
{{- end }}
{{- range $config := .Values.extraConfigs }}
- name: {{ $config.name }}
mountPath: {{ $config.mountPath }}
{{- end }}
{{- range $storage := .Values.extraStorage }}
- name: {{ $storage.name }}
mountPath: {{ $storage.mountPath }}
{{- end }}
{{- with .Values.extraContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: tmp
emptyDir: {}
{{- range $secret := .Values.extraSecrets }}
- name: {{ $secret.name }}
secret:
secretName: {{ $secret.name }}
defaultMode: {{ $secret.defaultMode | default 0440 }}
{{- end }}
{{- range $config := .Values.extraConfigs }}
- name: {{ $config.name }}
configMap:
name: {{ $config.name }}
defaultMode: {{ $config.defaultMode | default 0440 }}
{{- end }}
{{- range $storage := .Values.extraStorage }}
- name: {{ $storage.name }}
persistentVolumeClaim:
claimName: {{ $storage.pvcName }}
{{- end }}
{{- with .Values.storage }}
{{- if not $createPvc }}
- name: {{ .volumeName }}
{{- if .persistentVolumeClaimName }}
persistentVolumeClaim:
claimName: {{ .persistentVolumeClaimName }}
{{- else }}
emptyDir: {}
{{- end }}
{{- else }}
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .volumeName }}
{{- with .labels }}
labels:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
{{- with .accessModes }}
accessModes:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- if .className }}
storageClassName: {{ .className }}
{{- end }}
resources:
requests:
storage: {{ .requestedSize }}
{{- end }}
{{- end }}
+273
View File
@@ -0,0 +1,273 @@
# Default values for Etcd deployment
## Etcd container image
image:
registry: "quay.io/coreos"
repository: "etcd"
pullPolicy: IfNotPresent
tag: ""
# Default Init container image
initImage:
registry: "docker.io"
repository: "busybox"
pullPolicy: IfNotPresent
tag: "stable"
## Pull secrets and name override options
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
## Additional labels for Deployment or StatefulSet
customLabels: {}
## Additional annotations for Deployment or StatefulSet
customAnnotations: {}
## Number of etcd replicas in the cluster
## Due to the nature of etcd cluster initialization this value must be set before deploying the cluster
## Automatic scaling or manually scaling the etcd cluster after first deployment is not supported
replicas: 1
## Optional service account
serviceAccount:
# Specifies whether a service account should be created
create: false
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# Specifies whether a service account token should be automatically mounted
automountServiceAccountToken: true
## Additional pod annotations
podAnnotations: {}
## Additional pod labels
podLabels: {}
## Pod management policy
podManagementPolicy: Parallel
## Pod update strategy
updateStrategyType: RollingUpdate
## Pod security context uses file system group 999 (postgres)
podSecurityContext:
fsGroup: 999
supplementalGroups:
- 999
## Default security options to run PostgreSQL as non-root (postgres user), read only container without privilege escalation
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsGroup: 999
runAsUser: 999
capabilities:
drop:
- ALL
## Etcd service ports (default: Client port 2379, Peer port 2380)
service:
type: ClusterIP
## Client service port
client:
port: 2379
## The node port (only relevant for type LoadBalancer or NodePort)
nodePort:
## Peer service port
peer:
port: 2380
## The node port (only relevant for type LoadBalancer or NodePort)
nodePort:
## Prometheus service port
prometheus:
port: 12379
## The node port (only relevant for type LoadBalancer or NodePort)
nodePort:
## The cluster ip address (only relevant for type LoadBalancer or NodePort)
clusterIP:
## The loadbalancer ip address (only relevant for type LoadBalancer)
loadBalancerIP:
## The list of IP CIDR ranges that are allowed to access the load balancer (only relevent for type LoadBalancer)
loadBalancerSourceRanges: []
## Annotations to add to the service
annotations: {}
## Labels to add to the service
labels: {}
## Service monitor configuration for Prometheus metrics
serviceMonitor:
## Enable service monitor
enabled: false
## Additional labels for the service monitor object
additionalLabels: {}
## Annotations for the service monitor object
annotations: {}
## The scrape interval for prometheus
# interval:
## The scrape timeout value
# scrapeTimeout:
## Extra parameters rendered to the service monitor endpoint
extraEndpointParameters: {}
## Extra parameters rendered to the service monitor
extraParameters: {}
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
## Pod priority class name
priorityClassName: ""
## Additional node selector
nodeSelector: {}
## Tolerations for pod assignment
tolerations: []
## Affinity for pod assignment
affinity: {}
## Topology spread constraints for pods
topologySpreadConstraints: {}
## Maximum number of revisions maintained in revision history
revisionHistoryLimit:
## Custom startup probe (overwrites default startup probe)
customStartupProbe: {}
## Default startup check
startupProbe:
enabled: true
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 30
successThreshold: 1
periodSeconds: 10
## Custom liveness probe (overwrites default liveness probe)
customLivenessProbe: {}
## Default health check
livenessProbe:
enabled: true
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
periodSeconds: 10
## Custom readiness probe (overwrites default readiness probe)
customReadinessProbe: {}
## Default readiness probe
readinessProbe:
enabled: true
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
periodSeconds: 10
## Extra init containers
extraInitContainers: []
## Extra containers for usage as sidecars
extraContainers: []
## Additional environment variables
env: []
## Arguments for the container entrypoint process
args: []
## A list of existing secrets that will be mounted into the container as environment variables
extraEnvSecrets: []
## A list of additional existing secrets that will be mounted into the container
## The mounted files of the secrets can be used for advanced configuration (see settings.https.enabled)
extraSecrets: []
## Name of the existing K8s secret
# - name:
## Mount default mode (0440 if parameter is omitted)
# defaultMode: 0440
## Mount path where the secret should be mounted into the container (f.e. /mysecretfolder)
# mountPath:
## A list of additional existing configMaps that will be mounted into the container
extraConfigs: []
## Name of the existing K8s configMap
# - name:
## Mount default mode (0440 if parameter is omitted)
# defaultMode: 0440
## Mount path where the configMap should be mounted into the container (f.e. /mysecretfolder)
# mountPath:
## Default Kubernetes cluster domain
clusterDomain: cluster.local
## Etcd specific settings
settings:
## Unique cluser token
clusterToken: "etcd-cluster-0"
## Configure secure transport
## Certificates must be mounted into the container using `extraSecrets:` or generated automatically using autoTls: true
## Other tls options have to be added manually using environment variables or args: (see https://etcd.io/docs/v3.5/op-guide/clustering/#tls and https://etcd.io/docs/v3.5/op-guide/configuration/)
https:
## Enable HTTPS
enabled: false
## Automatic TLS mode of etcd (TLS certs. created automaically)
autoTls: false
## Delay after termination request to give etcd process time for graceful shutdown
shutdownDelay: 3
## Storage parameters
storage:
## Set persistentVolumenClaimName to reference an existing PVC
persistentVolumeClaimName:
## Internal volume name and prefix of a created PVC
volumeName: "etcd-data"
## Alternative set requestedSize to define a size for a dynmaically created PVC
requestedSize:
## the storage class name
className:
## Default access mode (ReadWriteOnce)
accessModes:
- ReadWriteOnce
## Additional storage annotations
annotations: {}
## Additional storage labels
labels: {}
## Mount existing extra PVC
extraStorage: {}
## Internal volume name
# - name:
## Container mount path
# mountPath:
## Name of existing PVC
# pvcName:
## Network policies
networkPolicy: {}
## Ingress and Egress policies
# ingress: {}
# egress: {}