Kubernetes 环境下的 Etcd 部署指南

Kubernetes 环境下的 Etcd 部署指南

基于 bitnami/etcd 镜像的生产级部署实践

前言

在 Kubernetes 生态系统中,Etcd 作为核心的分布式键值存储,承担着至关重要的角色。它不仅是 Kubernetes API Server 的数据后端,还广泛用于服务发现、配置共享等场景。

今天,我将分享一套基于 Kubernetes 的 Etcd 部署方案,这套方案已经在生产环境中稳定运行,服务于 APISIX 网关等关键系统。


为什么选择这个方案?

在深入技术细节之前,先说说为什么选择这个部署方案:

特性 说明
bitnami 镜像 业界最可靠的 etcd 容器镜像,维护活跃,安全更新及时
StatefulSet 原生支持有状态应用,保证 Pod 启动顺序和数据持久性
双 Service 模式 Headless + NodePort,分别满足内部发现和外部访问需求
HostPath 存储 简化运维,节点级别的数据持久化

整体架构一览

先来看一张部署架构图,对整体结构有个直观认识:

Etcd 部署架构图

从图中可以看到,整个部署包含以下几个核心组件:

1. Namespace 隔离

所有资源都部署在 bjac-etcd 命名空间中,实现了与其他业务资源的逻辑隔离。

2. StatefulSet 控制器

采用 StatefulSet 而非 Deployment,是 etcd 作为有状态应用的必然选择:

  • 稳定的 Pod 标识:Pod 名称固定为 etcd-0etcd-1...
  • 有序的部署和扩缩容:新 Pod 必须等前一个就绪后才启动
  • 独立的持久存储:每个 Pod 绑定独立的 PV

3. 双 Service 模式

┌─────────────────────────────────────────────────────────┐
│                    etcd-hs (Headless)                    │
│                                                          │
│  • ClusterIP: None                                       │
│  • 用于 Pod 之间的 DNS 发现                               │
│  • 支持 publishNotReadyAddresses=true                   │
│                                                          │
│  DNS: etcd-0.etcd-hs.bjac-etcd.svc.cluster.local       │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                   etcd-cs (NodePort)                     │
│                                                          │
│  • Type: NodePort                                        │
│  • NodePort: 30379                                       │
│  • 用于集群外部客户端访问                                 │
│                                                          │
│  访问地址: <NodeIP>:30379                                │
└─────────────────────────────────────────────────────────┘

4. 存储设计

采用 HostPath 方式挂载宿主机目录:

volumes:
  - name: etcd-data
    hostPath:
      path: /home/etcd/data/

提示:在生产环境中,建议使用 Local PV 或云存储以获得更好的数据可靠性保障。


配置文件深度解析

完整的 YAML 编排

apiVersion: v1
kind: Namespace
metadata:
  name: bjac-etcd

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: etcd-cs
  name: etcd-cs
  namespace: bjac-etcd
spec:
  type: NodePort
  ports:
    - name: tcp-client
      port: 2379
      targetPort: 2379
      nodePort: 30379
  selector:
    app: etcd

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: etcd
  name: etcd
  namespace: bjac-etcd
spec:
  serviceName: etcd-hs
  replicas: 1
  selector:
    matchLabels:
      app: etcd
  template:
    metadata:
      labels:
        app: etcd
    spec:
      nodeSelector:
        etcd-server: master
      containers:
        - name: etcd
          image: bitnami/etcd:3.5.6
          imagePullPolicy: IfNotPresent
          ports:
            - name: client
              containerPort: 2379
          env:
            - name: ETCD_ENABLE_V2
              value: "true"
            - name: ALLOW_NONE_AUTHENTICATION
              value: "yes"
            - name: ETCD_ADVERTISE_CLIENT_URLS
              value: "http://0.0.0.0:2379"
            - name: ETCD_LISTEN_CLIENT_URLS
              value: "http://0.0.0.0:2379"
          volumeMounts:
            - name: etcd-data
              mountPath: /bitnami/etcd/
      volumes:
        - name: etcd-data
          hostPath:
            path: /home/etcd/data/

关键环境变量说明

环境变量 作用
ETCD_ENABLE_V2 true 启用 V2 API(APISIX 需要)
ALLOW_NONE_AUTHENTICATION yes 无认证模式(开发环境)
ETCD_ADVERTISE_CLIENT_URLS http://0.0.0.0:2379 通告给客户端的地址
ETCD_LISTEN_CLIENT_URLS http://0.0.0.0:2379 监听客户端连接的地址

部署实战

部署流程

下面通过一张流程图,展示完整的部署步骤:

部署流程图

详细部署步骤

步骤一:节点标签

# 查看当前节点及其标签
kubectl get node --show-labels=true

# 给指定节点添加标签
kubectl label nodes <YOUR_NODE_NAME> etcd-server=master

这一步很关键!StatefulSet 使用 nodeSelector 确保 Pod 调度到专用节点。

步骤二:创建存储目录

# 在目标节点上创建数据目录
mkdir -p /home/etcd/data
chmod -R 777 /home/etcd

注意chmod -R 777 确保容器内的 etcd 进程有权限读写数据目录。

步骤三:部署资源

# 一键部署所有资源
kubectl apply -f etcd.yaml

步骤四:验证部署

# 检查 Pod 状态
kubectl get pod -n bjac-etcd -o wide

# 查看 Pod 详细信息
kubectl -n bjac-etcd describe pod etcd-0

# 查看日志
kubectl -n bjac-etcd logs etcd-0 --all-containers=true

步骤五:DNS 解析验证

# 测试 Headless Service DNS
nslookup etcd-hs.bjac-etcd.svc.cluster.local <COREDNS_IP>

# 测试 Pod 专属 DNS
nslookup etcd-0.etcd-hs.bjac-etcd.svc.cluster.local 172.16.0.10

数据备份:保障数据安全

数据备份是运维工作中不可或缺的一环。以下是完整的备份方案:

备份策略架构

数据备份与恢复策略

备份实战

# 进入 Etcd Pod
kubectl exec -it pod/etcd-0 -n bjac-etcd -- bash

# 进入备份目录
cd /opt/
mkdir backup
cd backup

# 方式一:导出 APISIX 配置
etcdctl --endpoints=<ETCD_ENDPOINT> \
    get /apisix/ --prefix --print-value-only=false \
    > apisix_backup.txt -w=simple

# 方式二:创建完整快照
etcdctl --endpoints=<ETCD_ENDPOINT> \
    snapshot save snapshot.db

# 查看快照状态
etcdctl --endpoints=<ETCD_ENDPOINT> \
    snapshot status snapshot.db -w=table

# 退出 Pod
exit

# 将备份复制到宿主机
kubectl cp bjac-etcd/etcd-0:/opt/backup /home/tmp/etcd

备份数据分析

从备份文件中可以看到,APISIX 的关键配置数据结构如下:

路径 说明
/apisix/routes/ 路由规则配置
/apisix/services/ 服务(Upstream)定义
/apisix/consumers/ 消费者/认证配置
/apisix/ssl/ SSL 证书
/apisix/plugins/ 插件配置
/apisix/upstreams/ 上游服务器组

运维最佳实践

日常检查清单

# 1. Pod 状态检查
kubectl get pod -n bjac-etcd

# 2. Service 端点检查
kubectl get ep -n bjac-etcd

# 3. 存储使用情况
kubectl exec etcd-0 -n bjac-etcd -- df -h /bitnami/etcd/

# 4. 健康检查
etcdctl --endpoints=10.105.197.216:30379 endpoint health

故障排查指南

症状 可能原因 解决方案
Pod 处于 Pending 节点标签不存在 添加 kubectl label nodes <node> etcd-server=master
Pod 处于 CrashLoopBackOff 数据目录权限问题 检查 /home/etcd/data/ 权限
无法从外部访问 NodePort 未开放 检查防火墙规则
DNS 解析失败 CoreDNS 问题 检查 publishNotReadyAddresses 设置

总结

本文详细介绍了在 Kubernetes 环境中部署 Etcd 的完整方案,涵盖了:

  • 架构设计:Namespace + StatefulSet + 双 Service 模式
  • 配置详解:bitnami 镜像的环境变量配置
  • 部署流程:从节点准备到验证的完整步骤
  • 数据备份:快照备份与数据导出方案
  • 运维实践:日常检查与故障排查

阅读更多

Skills系统:可扩展AI能力设计

Skills系统:可扩展AI能力设计

概述 Skills系统是AI-Native架构中的重要组件,它允许通过声明式配置扩展AI的能力。本文将介绍Skills系统的设计与实现,让大模型能够像人类专家一样具备特定领域的能力。 什么是Skills系统 概念 Skills(技能)是一种声明式的AI能力扩展机制,类似于人类的"专业技能": 通用AI助手 专业AI助手(带Skills) ┌──────────────────────┐ ┌──────────────────────────────┐ │ │ │ │ │ 用户:请帮我写代码 │ │ 用户:请帮我审查这段代码 │ │ │ │ │ │ AI:我是一个AI助手 │ │ AI:[激活

By 菱角
插件化架构设计模式

插件化架构设计模式

概述 插件化架构是一种将核心功能与扩展功能分离的设计模式,允许系统在运行时动态加载和卸载功能模块。本文将介绍如何在微服务平台中设计和实现插件化架构。 为什么需要插件化 插件化优势 1. 模块化:功能独立,边界清晰 2. 可扩展:按需加载,动态增删 3. 隔离性:插件间互不干扰 4. 可维护:独立开发、测试、部署 5. 可定制:用户按需选择功能 核心设计 架构概览 核心组件实现 1. 插件接口定义 // core/plugin.interface.ts // 插件接口 export interface IPlugin { // 插件名称 readonly name: string // 插件版本 readonly version: string // 插件配置 getConfig(): PluginConfig // 插件清单

By 菱角
gRPC服务通信设计与实践

gRPC服务通信设计与实践

概述 在微服务架构中,服务间通信是关键环节。相比REST API,gRPC提供了更高的性能和更强的类型安全。本文将介绍如何在微服务平台中设计和实现gRPC服务通信。 为什么选择gRPC gRPC vs REST对比 特性 gRPC REST 协议 HTTP/2 HTTP/1.1 序列化 Protocol Buffers (二进制) JSON (文本) 性能 高(二进制+压缩) 中(文本开销) 类型安全 强(代码生成) 弱(运行时检查) 流式通信 原生支持(双向流) 需额外实现(SSE/WebSocket) 代码生成 自动生成 手动编写 浏览器支持 需gRPC-Web 原生支持 调试难度

By 菱角
多语言微服务架构:Node.js与Python协作

多语言微服务架构:Node.js与Python协作

概述 在微服务架构中,根据场景选择最适合的编程语言是最佳实践。本文将介绍如何在微服务平台中实现Node.js与Python的协作,发挥各自技术优势。 技术选型策略 为什么混合使用 服务划分 Node.js服务(7个) 服务 功能 选择Node.js的原因 llm.api 大模型服务 高并发SSE流式响应 ucenter.api 用户中心 RESTful API标准实践 doc.api 文件服务 流式上传下载处理 resource.api 资源管理 gRPC高性能通信 rag.api 知识库服务 MongoDB集成便利 statistic.api 统计分析 事件驱动架构 pptonline.api PPT服务 与前端技术栈统一 Python服务(1个) 服务 功能 选择Python的原因

By 菱角