☰
Kubernetes高可用二进制部署:PKI证书签发与etcd集群搭建实战
2026/10/17 12:59:14 网站建设 项目流程

做了好几次 Kubernetes 高可用集群的二进制部署,我最大的感受是:证书(PKI)和 etcd 这两关撑过去,后面的 kubelet、apiserver、controller-manager 配置反而都是顺水推舟的事。kubeadm 一条命令能拉起集群,但它替你签的证书、替你编排的 etcd 集群,到了要自己掌控有效期、要跨机房扩展控制面的时候,全部得手动重来。

这篇文章是 kubernetes-ha-binary-deployment 系列的第 03 篇,聚焦在 PKI 证书签发和 etcd 三节点集群搭建。适合两类人看:一是准备在生产环境做 HA 二进制部署、不想被 kubeadm 黑盒约束的运维和架构师;二是已经用 kubeadm 搭过集群、想搞清楚证书体系到底是怎么转的人。看完你至少能自己签出 etcd 全套证书,并且知道三个节点怎么用 systemd 拉起、怎么判断集群真的健康,而不是只看进程活着就以为没事。

1. 二进制部署高可用集群,为什么第一道关卡是证书体系

1.1 kubeadm替你藏起来的证书,现在必须自己管

用 kubeadm 初始化集群时,它会自动生成一整套证书,大概十来个文件,分布在 /etc/kubernetes/pki 下。CA 根证书、apiserver 证书、etcd 证书、kubelet 证书,它全帮你安排好了。好处是省事,坏处是你不知道里面签了什么、多长有效期、SAN 里放了多少地址。

我见过有人线上用 kubeadm 搭的集群跑了一年多,突然证书过期导致 apiserver 连不上 etcd,查了半天才发现问题是 kubeadm 默认签发的证书有效期并不长,而 CA 又埋得太深,平时根本没人去看。二进制部署虽然步骤多,但每个证书从 CSR 到签发你都亲眼过一遍,后续维护、轮换、排查都踏实。说白了,kubeadm 适合让你快速拥有一个集群,而二进制部署适合让你真正拥有一个可控的集群。

1.2 etcd为什么要先于其他组件动工

在 HA 架构里,etcd 是状态中枢,apiserver、controller-manager、scheduler 全都依赖它。apiserver 要和 etcd 说话,kubelet 要和 apiserver 说话,这些通信在二进制方案里全部走 TLS。也就是说,证书不是"后面再补"的东西,而是第一步就得把根 CA 建好,否则 etcd 集群连成员间的 peer 通信都跑不通。

etcd 和常见的 Web 服务还不一样,它同时存在三套 TLS 关系:对外提供 2379 服务时是服务端身份,作为客户端连接其他节点时是客户端身份,节点之间通过 2380 端口互相复制数据时又是双向认证。一套证书同时要覆盖服务端和客户端的验证场景,所以签发前必须想清楚每个文件的用途。这也是为什么我在标题里把 PKI 和 etcd 放在一起——pki-etcd,这两件事本来就是绑定的。

1.3 设计一套够用的证书规划表

动手之前,先把证书清单拍在桌子上。我习惯用一张表把每份证书的角色、使用方、扩展用途列清楚,宁可多写几行也别漏。下面这张表是我每次部署都在用的规划,你可以直接抄:

证书文件签发类型扩展用途谁在使用
ca.pem / ca-key.pem根 CACA只负责签其他证书,不参与组件通信
etcd-server.pem / etcd-server-key.pem服务端证书server authetcd 进程对外提供 2379 服务
etcd-peer.pem / etcd-peer-key.pem对等证书server auth + client authetcd 节点之间 2380 通信
etcd-client.pem / etcd-client-key.pem客户端证书client authkube-apiserver、etcdctl 访问 2379

另外部署前要在所有节点上把 /etc/hosts 写好,三台机器的 hostname 和 IP 一一对应。比如我用 192.168.20.11、192.168.20.12、192.168.20.13 三台机器,hostname 分别是 etcd-1、etcd-2、etcd-3。这些名字和 IP 后面会同时出现在证书 SAN 和 etcd 的 initial-cluster 参数里,任何一处写错,集群都起不来。

2. 用CFSSL签发etcd全套证书

2.1 CA根证书:先给自己发一本"户口本"

CFSSL 是社区用得比较多的证书工具,包含 cfssl 和 cfssljson 两个二进制,下载后丢到 PATH 里就能用。它的逻辑很直接:先写一个 CSR(证书签名请求)文件,描述你想要的证书长什么样,然后用 cfssl 去签名。CFSSL 的优势是可以用 JSON 描述配置文件,批量签发时不容易写错,比 openssl 一条条堆参数要清晰。

第一步是建 CA。根 CA 是整个体系的信任原点,所有组件校验证书时都拿它当依据,所以 CA 的私钥要单独放好,权限尽量收紧。ca-csr.json 的内容很简单:

{ "CN": "etcd-ca", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "O": "etcd", "OU": "ops" } ] }

CN 是证书的通用名称,这里叫 etcd-ca,方便区分。签发命令:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

执行完会生成 ca.pem、ca-key.pem、ca.csr 三个文件。ca.pem 是公钥证书,ca-key.pem 是私钥,私钥必须留好,后续所有 etcd 证书都靠它签。

2.2 三类证书的用途区别和CSR写法

接下来是定义签发策略。ca-config.json 里可以配置不同的 profile,对应不同用途的证书,有效期直接写进 profile 里,这样每次签的时候不用重复指定:

{ "signing": { "default": { "expiry": "87600h" }, "profiles": { "etcd-server": { "usages": ["signing", "key encipherment", "server auth"], "expiry": "87600h" }, "etcd-peer": { "usages": ["signing", "key encipherment", "server auth", "client auth"], "expiry": "87600h" }, "etcd-client": { "usages": ["signing", "key encipherment", "client auth"], "expiry": "87600h" } } } }

这里的 usages 部分是关键。etcd-server 只需要 server auth,表示它只作为服务端对外提供 TLS 服务。etcd-client 只需要 client auth,表示它只作为客户端去访问别人。而 etcd-peer 必须同时包含 server auth 和 client auth,因为 etcd 节点之间是双向认证:A 节点连接 B 节点 2380 端口时,A 是客户端,B 是服务端;B 反过来连 A 时角色互换。证书如果漏了其中一个用途,集群成员之间握手就会失败。

2.3 签发命令和校验方法

以 etcd-peer 证书为例,CSR 文件里最需要注意的是 hosts 字段,它决定证书能用在哪些 IP 和主机名上。三个节点的 IP 和 hostname 全部写进去,另外建议把 127.0.0.1 也带上,方便本机调试:

{ "CN": "etcd-peer", "hosts": [ "192.168.20.11", "192.168.20.12", "192.168.20.13", "127.0.0.1" ], "key": { "algo": "rsa", "size": 2048 } }

签发命令:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \ -config=ca-config.json -profile=etcd-peer \ etcd-peer-csr.json | cfssljson -bare etcd-peer

同样的方式,用对应的 profile 和 CSR 文件签出 etcd-server、etcd-client。签发完别急着部署,先用命令验证一遍。看 SAN 和扩展用途,确认无误再分发:

openssl x509 -in etcd-peer.pem -noout -text | grep -A1 "Subject Alternative Name" openssl x509 -in etcd-peer.pem -noout -text | grep -A1 "Extended Key Usage" openssl verify -CAfile ca.pem etcd-peer.pem

3. 解压二进制,把三节点etcd跑起来

3.1 版本选择和目录规划

etcd 的版本选择要和你规划的 Kubernetes 版本匹配,这里以 etcd v3.5.x 为示例。从官方 release 页面下载 linux-amd64 的压缩包,解压后里面有 etcd 和 etcdctl 两个二进制。etcd 是服务进程,etcdctl 是命令行客户端,后面做健康检查全靠它。

目录规划我习惯固定成这样子:

  • 二进制放到 /opt/etcd/
  • 数据目录用 /var/lib/etcd/
  • 证书统一放 /etc/etcd/pki/
  • systemd 服务文件放 /etc/systemd/system/etcd.service

好处是结构清晰,排查问题时知道什么东西该去哪里找。证书分发就是把刚才签好的 ca.pem、etcd-server.pem、etcd-server-key.pem、etcd-peer.pem、etcd-peer-key.pem、etcd-client.pem、etcd-client-key.pem 复制到三台机器的 /etc/etcd/pki/ 下。注意私钥文件的权限,建议 600,属主是运行 etcd 的用户。

3.2 systemd unit里每个参数的含义

etcd 可以用命令行参数启动,也可以把参数写进 systemd 服务文件。我用 systemd 管理,因为重启、开机自启、看日志都方便。下面以 etcd-1(192.168.20.11)为例:

[Unit] Description=etcd After=network.target [Service] Type=notify ExecStart=/opt/etcd/etcd \ --name=etcd-1 \ --data-dir=/var/lib/etcd \ --listen-peer-urls=https://192.168.20.11:2380 \ --listen-client-urls=https://192.168.20.11:2379,https://127.0.0.1:2379 \ --advertise-client-urls=https://192.168.20.11:2379 \ --initial-advertise-peer-urls=https://192.168.20.11:2380 \ --initial-cluster=etcd-1=https://192.168.20.11:2380,etcd-2=https://192.168.20.12:2380,etcd-3=https://192.168.20.13:2380 \ --initial-cluster-state=new \ --initial-cluster-token=etcd-cluster-demo \ --cert-file=/etc/etcd/pki/etcd-server.pem \ --key-file=/etc/etcd/pki/etcd-server-key.pem \ --client-cert-auth=true \ --trusted-ca-file=/etc/etcd/pki/ca.pem \ --peer-cert-file=/etc/etcd/pki/etcd-peer.pem \ --peer-key-file=/etc/etcd/pki/etcd-peer-key.pem \ --peer-client-cert-auth=true \ --peer-trusted-ca-file=/etc/etcd/pki/ca.pem [Install] WantedBy=multi-user.target

有四个概念必须先分清,否则参数容易配错:

  • listen 是"监听",表示 etcd 进程在哪个地址上等别人来连接。
  • advertise 是"宣告",表示告诉集群里的其他节点,我对外公布的联系地址是哪个。
  • client 是"客户端入口",对应 2379 端口,apiserver 和 etcdctl 都走这里。
  • peer 是"节点间通信入口",对应 2380 端口,只有 etcd 成员之间互相连接才走这里。

3.3 三节点启动顺序和健康检查

三台机器的服务文件内容基本一样,只有 --name、listen 地址、advertise 地址对应各自的 IP。准备好之后,在三台机器上依次执行 systemctl daemon-reload、systemctl enable etcd、systemctl start etcd。注意要在一个较短的时间窗口内把三台都启动,因为它们都在等彼此的出现。

启动后用 etcdctl 做全面体检。先看成员列表,再看节点健康状态:

export ETCDCTL_API=3 export ETCDCTL_ENDPOINTS=https://192.168.20.11:2379,https://192.168.20.12:2379,https://192.168.20.13:2379 export ETCDCTL_CACERT=/etc/etcd/pki/ca.pem export ETCDCTL_CERT=/etc/etcd/pki/etcd-client.pem export ETCDCTL_KEY=/etc/etcd/pki/etcd-client-key.pem etcdctl endpoint health --cluster -w table etcdctl member list -w table etcdctl endpoint status --cluster -w table

健康的输出里,三台节点的 health 都应该是 true,status 里 leader 只有一台,其他两台是 follower。如果看到某台节点连不上,第一反应不是重启,而是去看它的日志:

journalctl -u etcd -f

4. 翻车点复盘:证书和etcd最常见的四个坑

4.1 SAN漏了IP,连接时报certificate is valid for

这是我在实际部署中遇到最多的问题,九成都是 CSR 文件的 hosts 字段写漏了。比如你只在 hosts 里写了 192.168.20.11,其他两台节点启动后连接这台的 2380 端口时,证书校验会发现证书里根本没有 192.168.20.12 或 192.168.20.13 对应的地址,直接报错:

certificate is valid for 192.168.20.11, not 192.168.20.12

处理办法只有一个:把三台节点的 IP 和 hostname 全部写进 hosts 字段,重新签发证书,然后分发到所有节点并重启 etcd。这里强调一下,分发后每台机器上的证书文件要相同,因为它们都需要互相验证,只更新其中一两台没用,必须全部同步。

4.2 client-cert-auth没开,TLS形同虚设

有人在配置里只写了 --cert-file 和 --key-file,却漏了 --client-cert-auth=true 和 --trusted-ca-file。这样做的结果是:etcd 自己展示证书,但不会要求客户端出示证书。也就是说,任何人不带证书也能访问 2379 端口,TLS 退化成单向加密,连身份验证都没有。

更隐蔽的是,单向加密不会立刻报错,因为 apiserver 那边只要配了证书就能正常连,表面看起来一切正常。直到某一天有内部工具或者误操作直接连上了 etcd,才发现数据在裸奔。所以 peer-client-cert-auth=true 和 client-cert-auth=true 这两个参数必须同时打开,trusted-ca-file 指向 ca.pem,保证所有连接都经过双向认证。

4.3 重启时initial-cluster-state写错导致数据目录冲突

常见场景是这样的:先在单机上试验性跑过一次 etcd,数据目录 /var/lib/etcd 里已经有了一套 cluster id 和成员信息。后来正式搭三节点集群,把服务文件改成三节点的 initial-cluster,但忘了清空数据目录,启动时 etcd 发现本地的 cluster id 和 initial-cluster 里声明的不一致,直接拒绝启动,日志里能翻到 request cluster ID mismatch 或者数据目录已初始化的报错。

这种情况下,先把 etcd 停掉,确认数据目录里没有需要保留的内容,然后清空 /var/lib/etcd 下所有文件,重新用 --initial-cluster-state=new 启动。反过来说,如果是集群已经在跑、某台节点掉线需要恢复,那就要用 --initial-cluster-state=existing,并保证它所在的数据目录是从集群里正常成员同步过的。new 和 existing 的区别,本质上是"我这个节点是从零加入一个新集群"还是"我是老成员回归",写反了必炸。

4.4 证书权限、属主和节点时间

证书私钥的权限问题也踩过。有次把证书分发过去之后,etcD 服务用的是独立的系统账号运行,结果私钥文件属主是 root 权限 600,服务账号读不了,启动直接失败。报错信息是 open 私钥文件 permission denied。解决方式是让 etcd 的运行账号能读取证书目录,并把私钥权限设成 600 或者 640,属主改成运行账号,千万不能给 644,否则私钥等于公开了。

另外一个小细节:节点时间偏差也会让证书校验失败。TLS 校验会检查证书的 notBefore 和 notAfter,如果某台机器时间漂移严重,握手时会被判定为证书不在有效期内。三台机器务必都配置好时间同步服务,比如 chrony 或 ntp,部署前先检查一遍 timedatectl 的输出,确保时间一致再开机验证集群。

证书和 etcd 这一关过了,后面的 Kubernetes 控制面组件配置反而轻松。我个人体会是,花点时间把证书体系和 etcd 集群彻底搞懂,比拿 kubeadm 快速拉起集群再慢慢补课要值得多。尤其是当你需要做证书轮换、故障恢复、集群迁移的时候,这些底层的细节会直接决定你处理问题的速度。最后再分享一个小建议:每次签发完证书,顺手把命令、CSR 文件和生成的文件名存档,标清楚日期和有效期。半年之后你再回来维护这套集群,会发现这份记录比你的记忆可靠一百倍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询