etcd 安全加固实战:TLS 加密与访问控制配置指南

etcd 安全加固是 Kubernetes 集群与分布式系统防护的核心议题。etcd 作为集群的键值存储中枢,保存着 ServiceAccount 密钥、ConfigMap、Pod 定义等全部敏感数据,若未配置认证,攻击者一条 curl 命令即可读取整个集群。本文从 TLS 双向认证、RBAC 权限与网络隔离三个层面,给出完整的 etcd 安全加固配置方案。

适用场景

  • Kubernetes 集群 etcd 未配置认证,存在未授权访问风险
  • 生产环境 etcd 集群需要传输加密与身份验证
  • 多租户或多人运维场景下需要对 etcd 操作进行权限隔离
  • 安全基线检查(如 Kube-bench)中 etcd 项不达标需要修复

前置条件

  • etcd 3.4+(含 Kubeadm 部署的 kube-system/etcd 容器)
  • OpenSSL 1.1+,用于生成证书
  • 具备 etcd 数据目录所在节点的 root 权限

原理说明

etcd 的安全模型包含三层:传输加密(TLS)保证客户端与 etcd、etcd 节点之间的通信不被窃听;身份认证通过 --client-cert-auth 强制客户端提供 CA 签发的证书,实现双向 TLS;授权(RBAC)在认证通过后按用户、角色控制读写权限。加固目标就是让”无证书者进不来、有证书者不能越权”。Kubeadm 部署的集群默认已启用 peer 证书,但 client 侧仍可能仅启用单向 TLS,需按本指南补全。

操作步骤

1. 生成 CA 与各类证书

mkdir -p /etc/etcd/pki && cd /etc/etcd/pki
# 1) 自建 CA
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -days 3650 -subj "/CN=etcd-ca" -out ca.crt
# 2) 签发 server 证书(IP 填本机地址,SAN 需含 client 连接用域名/IP)
openssl genrsa -out server.key 2048
cat > server.cnf <<'EOF'
[req]
distinguished_name=dn
req_extensions=v3_req
[dn]
[alt_names]
IP.1 = 127.0.0.1
IP.2 = 10.0.0.10
EOF
openssl req -new -key server.key -subj "/CN=etcd-server" -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial   -days 3650 -out server.crt -extensions v3_req -extfile server.cnf
# 3) 签发 peer 证书(每个 etcd 节点一份,CN 填节点名)
openssl genrsa -out peer.key 2048
openssl req -new -key peer.key -subj "/CN=etcd-node1" -out peer.csr
openssl x509 -req -in peer.csr -CA ca.crt -CAkey ca.key -CAcreateserial   -days 3650 -out peer.crt
chmod 600 *.key

2. 配置 etcd 启动参数(TLS 双向认证)

etcd \
  --name etcd-node1 \
  --data-dir /var/lib/etcd \
  --listen-client-urls https://10.0.0.10:2379,https://127.0.0.1:2379 \
  --advertise-client-urls https://10.0.0.10:2379 \
  --client-cert-auth --trusted-ca-file=/etc/etcd/pki/ca.crt \
  --cert-file=/etc/etcd/pki/server.crt --key-file=/etc/etcd/pki/server.key \
  --listen-peer-urls https://10.0.0.10:2380 \
  --peer-client-cert-auth --peer-trusted-ca-file=/etc/etcd/pki/ca.crt \
  --peer-cert-file=/etc/etcd/pki/peer.crt --peer-key-file=/etc/etcd/pki/peer.key

关键参数:–client-cert-auth 开启客户端证书校验,–peer-client-cert-auth 开启节点间证书校验,二者缺一不可。

3. 验证未授权访问被拒绝

# 不带证书访问应失败
curl --cacert /etc/etcd/pki/ca.crt https://10.0.0.10:2379/version
# 预期输出证书错误或 handshake failure
# 带证书访问成功
curl --cacert /etc/etcd/pki/ca.crt --cert /etc/etcd/pki/server.crt --key /etc/etcd/pki/server.key \
     https://10.0.0.10:2379/version

4. 启用 RBAC 用户与角色

export ETCDCTL_API=3
alias ec="etcdctl --endpoints=https://10.0.0.10:2379 --cacert=/etc/etcd/pki/ca.crt --cert=/etc/etcd/pki/server.crt --key=/etc/etcd/pki/server.key"
# 创建 root 用户并启用认证
ec user add root
ec auth enable
# 创建只读用户与角色
ec role add read-only
ec role grant-permission read-only read / --prefix=true
ec user add viewer
ec user grant-role viewer read-only
# 测试:viewer 可读不可写
ec --user viewer:password get / --prefix=true --limit=5
ec --user viewer:password put /test x
# 预期写入返回 13 (permission denied)

认证启用后,之前未指定 –user 的访问将全部返回 401,这是预期行为。

5. 防火墙限制 2379 访问来源

# 仅允许 kube-apiserver 节点与运维网段访问 2379
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.20 port port=2379 protocol=tcp accept'
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 port port=2379 protocol=tcp reject'
firewall-cmd --reload

6. Kubernetes 场景同步配置 apiserver

# kube-apiserver 启动参数(Kubeadm 修改 /etc/kubernetes/manifests/kube-apiserver.yaml)
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
--etcd-servers=https://10.0.0.10:2379

配置验证

  • 无证书 curl 访问 2379 返回证书校验失败,有证书访问成功返回 {“etcdserver”:”3.5.x”}
  • ec user list 显示 root 与 viewer;ec role list 显示 read-only
  • viewer 用户 get 成功、put 返回 permission denied
  • 防火墙规则生效后,非白名单来源连接 2379 被拒
  • Kubeadm 集群可执行 kubectl get pods -A 确认 apiserver 与 etcd 通信正常

常见问题

FAQ 1:证书即将过期如何轮换?

用同一 CA 重新签发有效期更长的 server/peer 证书替换,重启 etcd 即可,无需重建 CA;若 CA 也过期,则需为全部 etcd 节点与所有客户端(kube-apiserver、etcdctl)重新签发,属重大变更,建议在维护窗口内按”先节点后客户端”的顺序滚动替换。

FAQ 2:启用 RBAC 后 etcdctl 报 401,数据是否损坏?

数据未损坏,只是认证拦截。用 root 用户重新认证:etcdctl user get root 验证,或查看 etcd 日志确认 401 来源。注意不要删除 root 用户或忘记密码,否则需以 --auth-token 或恢复快照方式处理。

FAQ 3:云厂商托管 etcd(如 ACK、EKS)还需要加固吗?

托管集群的控制面 etcd 由云厂商负责加固,用户侧重点是:确认 apiserver 已启用 RBAC、禁止将 system:masters 组随意授予用户、限制对 kube-system 命名空间的写权限,并定期用 Kube-bench 复查 etcd 相关项。

总结

etcd 加固遵循”加密、认证、授权、隔离”四步:TLS 双向认证杜绝明文与伪造客户端,RBAC 最小化权限降低越权风险,防火墙将访问收敛到受信网段。生产集群务必先完成 TLS 与 RBAC 再对外开放 2379 端口,并将证书轮换纳入日常运维计划,才能从根上堵住集群数据泄露通道。