자체 빌드 이미지 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:
@@ -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/
|
||||
@@ -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 본문에 판단 근거를 남긴다.
|
||||
@@ -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` 참고.
|
||||
@@ -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
|
||||
@@ -0,0 +1,176 @@
|
||||
# Etcd
|
||||
|
||||
  
|
||||
|
||||
## 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 }}
|
||||
@@ -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: {}
|
||||
Reference in New Issue
Block a user