首页
/ Kubernetes The Hard Way:从零引导单节点 etcd 集群(kthw Lab 07 实战解析)

Kubernetes The Hard Way:从零引导单节点 etcd 集群(kthw Lab 07 实战解析)

2026-09-05 21:10:01作者:翟萌耘Ralph

Kubernetes The Hard Way 教程中,Kubernetes 各控制面组件本身都是无状态的——它们的所有集群状态(Node、Service、Deployment、Secret 等对象的真实数据)都存储在一个名为 etcd 的分布式键值数据库中。本篇对应 Bootstrapping the etcd Cluster 实验,带你以“无脚本、纯手工”的方式在 server 机器上安装并引导一个单节点 etcd 集群,逐一剖析 units/etcd.service 中的每个启动参数的含义。读完本篇,你将掌握:etcd 二进制与 systemd 服务的部署流程、etcd 各监听端口的职责(2379/2380)、集群成员与数据目录的权限配置,以及后续 kube-apiserver 如何以 --etcd-servers 参数接入这个数据后端。

为什么 Kubernetes 需要 etcd

README.md 的组件清单可以看到,本教程使用的组件版本为:

  • kubernetes v1.32.x(具体为 v1.32.3,见 downloads-amd64.txt
  • containerd v2.1.x
  • cni v1.6.x
  • etcd v3.6.x(本仓库下载列表锁定为 v3.6.0-rc.3)

Kubernetes API Server 是唯一与 etcd 直接通信的控制面组件。kube-schedulerkube-controller-manager 等组件通过 API Server 间接读写集群状态。因此,引导 etcd 是引导整个控制平面之前最关键的一步:一旦 etcd 不可用,集群将失去其持久化状态。本教程选择在 server 单机上引导一个单节点 etcd 集群,足以支撑学习目的;生产环境则通常需要 3 个(或 5 个)成员构成 Raft 集群。

前置条件:拷贝 etcd 二进制与 systemd 单元文件

整个教程在四台 Debian 12 (bookworm) 机器上运行(jumpboxservernode-0node-1,硬件要求见 Prerequisites)。etcd 的二进制文件已在 Set Up The Jumpbox 阶段从 downloads-amd64.txt(或 downloads-arm64.txt)统一下载并解压到 jumpboxdownloads/ 目录下,其中:

  • downloads/controller/etcd:etcd 服务端二进制
  • downloads/client/etcdctl:etcd 的命令行客户端工具

本 Lab 的第一步,是在 jumpbox 上把 etcd 二进制与 systemd 单元文件拷贝到 server 机器:

scp \
  downloads/controller/etcd \
  downloads/client/etcdctl \
  units/etcd.service \
  root@server:~/

之后登录 server 机器执行后续所有命令:

ssh root@server

注意:本 Lab 的后续命令都必须在 server 机器上执行,而不是 jumpbox

安装 etcd 二进制

server 机器上,把 etcd(服务端)与 etcdctl(命令行工具)移动到 PATH 中的 /usr/local/bin/

{
  mv etcd etcdctl /usr/local/bin/
}

这一步完成后,两个二进制都可以直接通过命令名调用。

配置 etcd 服务目录与数据目录

接下来创建 etcd 的配置目录与数据目录,并把 TLS 证书放进配置目录:

{
  mkdir -p /etc/etcd /var/lib/etcd
  chmod 700 /var/lib/etcd
  cp ca.crt kube-api-server.key kube-api-server.crt \
    /etc/etcd/
}

逐条拆解这个操作的用意:

  1. /etc/etcd/:存放 etcd 服务运行所需的证书等配置材料。这里复制了 Provisioning the CA and Generating TLS Certificates 实验在 jumpbox 生成并分发到 server 的三个文件:ca.crt(CA 根证书)、kube-api-server.keykube-api-server.crt(kube-apiserver 的客户端证书/密钥对)。这些证书在后续控制面组件中会被用作身份凭证。
  2. /var/lib/etcd:etcd 的数据目录(BBolt 数据库与 WAL 日志所在处),对应 systemd 单元中的 --data-dir=/var/lib/etcd
  3. chmod 700 /var/lib/etcd:把数据目录权限收紧为仅 root 可读写执行。etcd 中存储着集群的全部状态,其中可能包含 Secret 等敏感数据(即便本教程后续用 生成数据加密配置 的 encryption-config 对其做静态加密),收紧目录权限是基本的纵深防御措施。

原文档还特别强调了一点:etcd 集群中的每个成员必须拥有唯一的 --name,教程将该成员名设置为与当前计算实例的 hostname 一致(本教程中为 controller)。这一点直接体现在下文的 systemd 单元里。

深入解析 units/etcd.service 的每个启动参数

把单元文件放入 systemd 目录:

mv etcd.service /etc/systemd/system/

本仓库提供的 units/etcd.service 内容如下,这也是理解 etcd 启动行为的核心:

[Unit]
Description=etcd
Documentation=https://github.com/etcd-io/etcd

[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \
  --name controller \
  --initial-advertise-peer-urls http://127.0.0.1:2380 \
  --listen-peer-urls http://127.0.0.1:2380 \
  --listen-client-urls http://127.0.0.1:2379 \
  --advertise-client-urls http://127.0.0.1:2379 \
  --initial-cluster-token etcd-cluster-0 \
  --initial-cluster controller=http://127.0.0.1:2380 \
  --initial-cluster-state new \
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

参数逐一解析:

参数 取值 作用
--name controller 本成员在集群内的唯一标识,教程要求其等于实例 hostname
--initial-advertise-peer-urls http://127.0.0.1:2380 告知集群中其他成员用哪个地址与本节点通信(peer 流量)
--listen-peer-urls http://127.0.0.1:2380 etcd 实际监听 peer/Raft 通信的端口(2380)
--listen-client-urls http://127.0.0.1:2379 etcd 实际监听客户端 API 请求的端口(2379)
--advertise-client-urls http://127.0.0.1:2379 对外通告的客户端接入地址,供 kube-apiserver 等客户端使用
--initial-cluster-token etcd-cluster-0 集群令牌,用于防止把两个不同集群的成员混在同一 Raft 集群里
--initial-cluster controller=http://127.0.0.1:2380 初始成员列表;只有 controller 一个成员,即单节点集群
--initial-cluster-state new 声明这是一个全新集群(而非向已有集群加入)
--data-dir /var/lib/etcd 持久化数据目录

此外,单元文件还体现了几个 systemd 层面的设计:

  • Type=notify:etcd 会主动通过 systemd 的 sd_notify 协议汇报就绪状态,systemd 能准确判断服务真正完成启动,而不是只看进程是否拉起。
  • Restart=on-failureRestartSec=5:进程异常退出时 5 秒后自动重启,提供基本的自愈能力。
  • 全部地址绑定在 127.0.0.1:由于本教程把控制面组件全部部署在同一台 server 机器上,etcd 只需对本地回环接口可达即可,这也避免了数据端口暴露到网络。

值得对照的一点是:从 units/kube-apiserver.service--etcd-servers=http://127.0.0.1:2379 参数可以看出,API Server 正是通过 2379 客户端端口访问本集群的——两个服务文件在端口约定上是互相咬合的。同时可以看到,这个用于教学的单节点集群在 peer 与 client 连接上都使用 http://(未启用 TLS 与客户端证书认证);教程目标是学习引导流程本身,生产环境通常还会加上 --cert-file--key-file--client-cert-auth 等参数来启用 TLS 与身份认证。

启动 etcd 服务

把单元文件就位后,重载 systemd 配置并启用、启动服务:

{
  systemctl daemon-reload
  systemctl enable etcd
  systemctl start etcd
}

daemon-reload 让 systemd 重新读取 /etc/systemd/system/ 下新增的单元文件;enable 使 etcd 在机器重启后随 multi-user.target 自动拉起;start 立即启动服务。

验证:列出 etcd 集群成员

使用此前一并拷贝安装的 etcdctl 列出集群成员:

etcdctl member list

预期输出形如:

6702b0a34e2cfd39, started, controller, http://127.0.0.1:2380, http://127.0.0.1:2379, false

输出各字段的含义:

  • 6702b0a34e2cfd39:成员 ID(十六进制),由 etcd 在成员加入时分配;
  • started:成员状态正常、已参与 Raft 集群;
  • controller:与 --name controller 对应的成员名;
  • http://127.0.0.1:2380:该成员的 peer 地址;
  • http://127.0.0.1:2379:该成员的客户端地址;
  • false:非learner成员。

若输出中出现 unstarted 或地址对不上,通常意味着 --initial-cluster 与实际网络配置不一致,可回到单元文件逐项核对。你也可以用 systemctl status etcd 确认进程状态,配合单元文件中的 RestartSec=5 观察异常重启行为。

小结与下一步

本 Lab 以四个动作完成了单节点 etcd 集群的引导:拷贝二进制与单元文件 → 安装二进制并配置证书/数据目录 → 通过 systemd 单元启动服务 → 用 etcdctl member list 验证成员状态。etcd 就绪后,Kubernetes 集群状态的持久化后端就位了。

按照教程顺序,下一步是 Bootstrapping the Kubernetes Control Plane:在 server 上部署 kube-apiserver、kube-scheduler 与 kube-controller-manager,其中 kube-apiserver 会通过 --etcd-servers=http://127.0.0.1:2379(见 units/kube-apiserver.service)直接对接本实验建立的 etcd 实例。

适用前提与限制:本篇操作基于本仓库锁定的组件版本(Kubernetes v1.32.3 / etcd v3.6.0-rc.3,见 downloads-amd64.txt),操作系统为 Debian 12 (bookworm),全部命令以 root 用户执行,且控制面组件与 etcd 同机部署于 server。教程结果不应视为生产就绪方案,生产集群在成员数、TLS 与备份策略上均需另行设计。

登录后查看全文
热门项目推荐
相关项目推荐