我在另一个答案中提到的第二个解决方案是
增加然后收缩 etcd 集群
这种方法的缺点是etcd quorum size是临时增加的,如果多个节点故障,etcd集群可能break。为避免这种情况,您可能需要先删除一个现有的 etcd 集群成员,然后再添加另一个。
以下是该过程的简要概述:
- 使用 etcd
ca.crt 和 ca.key 从现有 etcd 节点文件夹 (/etc/kubernetes/pki/etcd/) 为所有其他成员生成证书。
- 使用
etcdctl 命令向集群添加新成员
- 为新成员创建 etcd 配置
- 使用新的密钥和配置启动新的 etcd 成员
- 检查集群运行状况
-
重复步骤 2-5,直到添加所有必需的 etcd 节点
- 使用 etcdctl 命令删除一个多余的 etcd 集群成员
- 检查集群运行状况
-
重复步骤 7-8,直到达到所需的 etcd 集群大小
- 调整所有 etcd 集群成员的所有 etcd.yaml 文件。
- 调整所有 kube-apiserver.yaml 清单中的 etcd 端点
另一个可能的顺序:
- 使用 etcd
ca.crt 和 ca.key 从现有 etcd 节点文件夹 (/etc/kubernetes/pki/etcd/) 为所有其他成员生成证书。
- 使用 etcdctl 命令删除一个 etcd 集群成员
- 使用 etcdctl 命令向集群添加新成员
- 为新成员创建 etcd 配置
- 使用新的密钥和配置启动新的 etcd 成员
- 检查集群运行状况
-
重复步骤 2-6,直到完成所需的 etcd 配置
- 调整所有 etcd 集群成员的所有
etcd.yaml 文件。
- 调整所有 kube-apiserver.yaml 清单中的 etcd 端点
如何生成证书:
注意:如果你有 etcd 集群,你可能在某个地方有 etcd-CA 证书。考虑将它与 etcd-CA 密钥一起使用,为所有其他 etcd 成员生成证书。
注意:如果您选择手动生成证书,通常 Kubernetes 证书的参数是:
- 签名算法:sha256WithRSAEncryption
- 公钥算法:rsaEncryption
- RSA 公钥:(2048 位)
- CA 证书有效期:10 年
- 其他证书年龄:1 年
您可以使用以下命令检查证书的内容:
find /etc/kubernetes/pki/ -name *.crt | xargs -l bash -c 'echo $0 ; openssl x509 -in $0 -text -noout'
(有关变量和别名定义,请参阅我的另一个答案,第 3 步)
e3 member list
b67816d38b8e9d2, started, kube-ha-m3, https://10.128.0.12:2380, https://10.128.0.12:2379
3de72bd56f654b1c, started, kube-ha-m1, https://10.128.0.10:2380, https://10.128.0.10:2379
ac98ece88e3519b5, started, kube-etcd2, https://10.128.0.14:2380, https://10.128.0.14:2379
cfb0839e8cad4c8f, started, kube-ha-m2, https://10.128.0.11:2380, https://10.128.0.11:2379
eb9b83c725146b96, started, kube-etcd1, https://10.128.0.13:2380, https://10.128.0.13:2379
401a166c949e9584, started, kube-etcd3, https://10.128.0.15:2380, https://10.128.0.15:2379 # Let's remove this one
e2 member remove 401a166c949e9584
会员将立即关闭。为防止进一步尝试加入集群,请从 /etc/kubernetes/manifests/ 移动/删除 etcd.yaml 或关闭 etcd 成员节点上的 etcd 服务
e3 member add kube-etcd3 --peer-urls="https://10.128.0.16:2380"
输出显示启动新的 etcd 集群成员所需的参数,例如:
ETCD_NAME="kube-etcd3"
ETCD_INITIAL_CLUSTER="kube-ha-m3=https://10.128.0.15:2380,kube-ha-m1=https://10.128.0.10:2380,kube-etcd2=https://10.128.0.14:2380,kube-ha-m2=https://10.128.0.11:2380,kube-etcd1=https://10.128.0.13:2380,kube-etcd3=https://10.128.0.16:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.128.0.16:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"
注意: ETCD_INITIAL_CLUSTER 变量包含所有现有的 etcd 集群成员以及新节点。如果您需要添加多个节点,则应一次添加一个节点。
注意: All ETCD_INITIAL_* 变量和对应的命令行参数仅在第一个 etcd Pod 启动时需要。成功将节点添加到 etcd 集群后,这些参数将被忽略,并且可以从启动配置中删除。所有需要的信息都存储在 etcd 数据库文件的/var/lib/etcd 文件夹中。
默认的 etcd.yaml 清单可以使用以下 kubeadm 命令生成:
kubeadm init phase etcd local
最好将etcd.yaml文件从/etc/kubernetes/manifests/移到某处进行调整。
同时删除/var/lib/etcd 文件夹的内容。它包含新 etcd 集群的数据,因此不能用于向现有集群添加成员。
然后根据member add命令输出进行调整。 (--advertise-client-urls, -initial-advertise-peer-urls, --initial-cluster, --initial-cluster-state, --listen-client-urls, --listen-peer-urls) 例如:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.128.0.16:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.128.0.16:2380
- --initial-cluster=kube-ha-m3=https://10.128.0.15:2380,kube-ha-m1=https://10.128.0.10:2380,kube-etcd2=https://10.128.0.14:2380,kube-ha-m2=https://10.128.0.11:2380,kube-etcd1=https://10.128.0.13:2380,kube-etcd3=https://10.128.0.16:2380
- --initial-cluster-state=existing
- --key-file=/etc/kubernetes/pki/etcd/server.key
- --listen-client-urls=https://10.128.0.16:2379
- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-peer-urls=https://10.128.0.16:2380
- --name=kube-etcd3
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
image: k8s.gcr.io/etcd:3.3.10
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
name: etcd
resources: {}
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/pki/etcd
type: DirectoryOrCreate
name: etcd-certs
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
保存文件后,kubelet 会重启 etcd pod。检查 etcd 容器日志以确保它已加入集群。
如何检查集群的健康状况
$ e2 cluster-health
member b67816d38b8e9d2 is healthy: got healthy result from https://10.128.0.15:2379
member 3de72bd56f654b1c is healthy: got healthy result from https://10.128.0.10:2379
member ac98ece88e3519b5 is healthy: got healthy result from https://10.128.0.14:2379
member cfb0839e8cad4c8f is healthy: got healthy result from https://10.128.0.11:2379
member eb9b83c725146b96 is healthy: got healthy result from https://10.128.0.13:2379
cluster is healthy
$ e2 member list
b67816d38b8e9d2: name=kube-ha-m3 peerURLs=https://10.128.0.15:2380 clientURLs=https://10.128.0.15:2379 isLeader=true
3de72bd56f654b1c: name=kube-ha-m1 peerURLs=https://10.128.0.10:2380 clientURLs=https://10.128.0.10:2379 isLeader=false
ac98ece88e3519b5: name=kube-etcd2 peerURLs=https://10.128.0.14:2380 clientURLs=https://10.128.0.14:2379 isLeader=false
cfb0839e8cad4c8f: name=kube-ha-m2 peerURLs=https://10.128.0.11:2380 clientURLs=https://10.128.0.11:2379 isLeader=false
eb9b83c725146b96: name=kube-etcd1 peerURLs=https://10.128.0.13:2380 clientURLs=https://10.128.0.13:2379 isLeader=false
$ e3 endpoint health
# the output includes only etcd members that are specified in --endpoints cli option or corresponded environment variable. I've included only three out of five members
https://10.128.0.13:2379 is healthy: successfully committed proposal: took = 2.310436ms
https://10.128.0.15:2379 is healthy: successfully committed proposal: took = 1.795723ms
https://10.128.0.14:2379 is healthy: successfully committed proposal: took = 2.41462ms
$ e3 endpoint status
# the output includes only etcd members that are specified in --endpoints cli option or corresponded environment variable. I've included only three out of five members
https://10.128.0.13:2379 is healthy: successfully committed proposal: took = 2.531676ms
https://10.128.0.15:2379 is healthy: successfully committed proposal: took = 1.285312ms
https://10.128.0.14:2379 is healthy: successfully committed proposal: took = 2.266932ms
如何在不使用 kubectl 的情况下查看 etcl Pod 日志?
如果您只使用 kubelet 运行 etcd 成员,您可以使用以下命令检查其日志:
docker logs `docker ps -a | grep etcd | grep -v pause | awk '{print $1}' | head -n1` 2>&1 | less
注意: 通常只能在同一个节点上同时运行一个 etcd Pod,因为它使用宿主目录/var/lib/etcd/ 中的数据库,不能在两个 Pod 之间共享。此外,etcd Pod 使用节点网络接口与 etcd 集群通信。
当然,您可以将 etcd Pod 配置为使用不同的主机目录并使用不同的主机端口作为解决方法,但上述命令假设节点上只有一个 etcd Pod。