如何使用 Helm 在 Kubernetes 上部署高可用 ETCD 集群?
摘要:# ETCD 集群部署指南 (v3.6.4) > 基于 Kubernetes + Helm 部署高可用 ETCD 集群 ## 目录 - [一、常规部署步骤](#一常规部署步骤) - [二、检查集群状态
# ETCD 集群部署指南 (v3.6.4)
> 基于 Kubernetes + Helm 部署高可用 ETCD 集群
---
## 目录
- [一、常规部署步骤](#一常规部署步骤)
- [二、检查集群状态](#二检查集群状态)
- [三、集群数据验证](#三集群数据验证)
- [四、values.yaml 配置详解](#四valuesyaml-配置详解)
- [五、LoadBalancer 创建](#五loadbalancer-创建)
- [六、监控配置](#六监控配置)
- [七、ArgoCD 管理](#七argocd-管理)
---
## 一、常规部署步骤
### 1.1 添加 Helm 仓库
```bash
# 添加 Bitnami 仓库(维护最完善的 etcd Helm Chart)
helm repo add bitnami https://charts.bitnami.com/bitnami
# 更新仓库索引
helm repo update
```
### 1.2 创建命名空间和 Secret
```bash
# 创建命名空间
kubectl create ns etcd-dev
# 创建密码 Secret(替代 values.yaml 中的明文密码)
kubectl create secret generic etcd-rbac-secret -n etcd-dev \
--from-literal=password=运维配置
```
### 1.3 拉取 Chart 并部署
```bash
# 拉取 charts 至本地
helm pull bitnami/etcd --untar
# 备份默认 values.yaml 文件,创建自定义 etcd-values.yaml
# 建议在执行部署升级命令之前添加 --dry-run --debug 参数验证 values.yaml 文件正确性
# 部署命令
helm install etcd ./etcd -f ./etcd/values.yaml -n etcd-dev
# 升级命令
helm upgrade etcd ./etcd -f ./etcd/values.yaml -n etcd-dev
```
---
## 二、检查集群状态
### 2.1 查看 Pod 和 Service 状态
```bash
# 查看 pod, svc 状态
kubectl get pods -n etcd-dev
kubectl get svc -n etcd-dev
```
### 2.2 进入 Pod 检查集群
```bash
# 进入 pod,使用 etcdctl 命令查看
kubectl exec -it etcd-0 -n etcd-dev -- /bin/sh
# 查看集群成员
etcdctl member list
# 检查集群健康状态(高可用核心验证)
etcdctl --user=root:认证密码 endpoint health \
--endpoints=http://etcd-0.etcd-headless.etcd-dev.svc.cluster.local:2379,http://etcd-1.etcd-headless.etcd-dev.svc.cluster.local:2379,http://etcd-2.etcd-headless.etcd-dev.svc.cluster.local:2379
```
---
## 三、集群数据验证
### 3.1 写入测试数据
```bash
# 在 etcd-0 POD 节点创建数据
etcdctl --user root:认证密码 put a 1
```
### 3.2 在所有节点验证
```bash
# 在所有 POD 节点查询,都能查询到说明集群正常
etcdctl --user root:认证密码 get a
# 预期输出
# a
# 1
```
---
## 四、values.yaml 配置详解
### 4.1 镜像配置
```yaml
# 1. 镜像仓库修改,原 docker.io 镜像地址不可用
image:
registry: public.ecr.aws
repository: bitnami/etcd
tag: 3.6.4-debian-12-r3
```
### 4.2 RBAC 认证配置
```yaml
# 2. rbac 认证账号密钥配置
auth:
rbac:
create: true
allowNoneAuthentication: false
rootPassword: ""
existingSecret: "etcd-rbac-secret"
existingSecretPasswordKey: "password"
```
### 4.3 资源配置
```yaml
# 3. etcd 容器资源配置
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 4Gi
```
### 4.4 持久化存储配置
```yaml
# 4. PVC 持久卷配置
persistence:
storageClass: "gp3"
annotations: {}
labels: {}
accessModes:
- ReadWriteOnce
size: 20Gi
```
### 4.5 监控指标配置
```yaml
# 5. 开启 metrics 监控指标推送
metrics:
enabled: true
useSeparateEndpoint: true
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.metrics.useSeparateEndpoint | ternary .Values.containerPorts.metrics .Values.containerPorts.client }}"
```
### 4.6 安全配置
```yaml
# 6. 开启容器镜像安全限制,解决第1步修改导致报错
global:
security:
allowInsecureImages: true
```
---
## 五、LoadBalancer 创建
### 5.1 创建外部访问 Service
```yaml
# etcd 通过 grpc 协议通讯,创建 LoadBalancer 类型 SVC 允许外部访问
apiVersion: v1
kind: Service
metadata:
name: etcd-lb-service
namespace: etcd-dev
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
spec:
type: LoadBalancer
ports:
- name: etcd-client
port: 2379 # Service 端口(外部访问端口)
targetPort: 2379 # etcd Pod 端口
protocol: TCP # etcd 基于 TCP 通信
appProtocol: grpc # 标识为 gRPC 协议(AWS NLB 可优化转发)
selector:
app.kubernetes.io/component: etcd
app.kubernetes.io/name: etcd
app.kubernetes.io/instance: etcd-cluster-dev # 不同环境需区分
```
---
## 六、监控配置
### 6.1 Prometheus 采集配置
```yaml
# 生产修改 job_name, env 即可,看板 setting 中修改 cluster 变量即可
- job_name: 'ltp_dev_etcd_cluster'
metrics_path: /metrics
scrape_interval: 15s
scrape_timeout: 15s
static_configs:
- targets: ['etcd-0.etcd-headless.etcd-dev.svc.cluster.local:9090']
labels:
instance: etcd-0
env: dev
- targets: ['etcd-1.etcd-headless.etcd-dev.svc.cluster.local:9090']
labels:
instance: etcd-1
env: dev
- targets: ['etcd-2.etcd-headless.etcd-dev.svc.cluster.local:9090']
labels:
instance: etcd-2
env: dev
```
### 6.2 Grafana 看板
看板 URL:
```
https://grafana.ltpin.com/d/655de576-0806-4a29-b04f-84bf4984a2d9/etcd-cluster-nonprod?orgId=1&from=now-3h&to=now&timezone=browser&var-cluster=ltp_nonprod_etcd_cluster
```
### 6.3 关键监控指标
| 指标 | 说明 |
|------|------|
| **Etcd has a leader?** | 集群是否有 Leader(YES/NO) |
| **Leader changes seen** | Leader 切换次数 |
| **Failed proposals** | 失败提案数 |
| **RPC Rate** | RPC 请求速率 |
| **Active Streams** | 活跃连接数 |
| **DB Size** | 数据库大小 |
| **Disk Sync Duration** | 磁盘同步耗时 |
| **Memory** | 内存使用 |
---
## 七、ArgoCD 管理
### 7.1 Helm Chart 仓库地址
```
https://github.com/LiquidityTech/devops-infra-deploy-manifests/tree/main/etcd
```
### 7.2 不同环境配置
| 环境 | values 文件 |
|------|-------------|
| dev | `values-dev.yaml` |
| qa | `values-qa.yaml` |
### 7.3 ArgoCD 应用配置
```yaml
fullnameOverride: "etcd"
namespaceOverride: "etcd-dev"
podMonitor:
enabled: true
namespace: etcd-dev # podmonitor 指定创建命名空间,需随环境修改
```
### 7.4 部署流程
1. 同步前需手动按步骤1创建 Secret
2. 同步完成后按步骤5创建外部访问 LB
---
## 八、架构图
```
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ etcd-0 │ │ etcd-1 │ │ etcd-2 │ │
│ │ (Leader) │◄──►│ (Follower) │◄──►│ (Follower) │ │
│ │ :2379 │ │ :2379 │ │ :2379 │ │
│ │ :9090 │ │ :9090 │ │ :9090 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┬┴─────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ etcd-headless │ │
│ │ (Service) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ etcd-lb-svc │ │
│ │ (LoadBalancer) │ │
│ │ :2379 │ │
│ └────────┬────────┘ │
│ │ │
└───────────────────────────┼──────────────────────────────────────┘
│
┌────────▼────────┐
│ AWS NLB │
│ (Internal) │
└────────┬────────┘
│
┌────────▼────────┐
│ External Apps │
└─────────────────┘
```
---
## 九、最佳实践
| 场景 | 建议 |
|------|------|
| **生产环境** | 使用 3 节点集群,配置 gp3 存储 |
| **密码管理** | 使用 Secret 而非明文配置 |
| **监控告警** | 配置 Leader 切换、RPC 延迟告警 |
| **备份** | 定期执行 etcdctl snapshot save |
| **升级** | 使用滚动升级,先升级 Follower |
---
