一年前,我用一个外部etcd集群(3个成员)创建了一个Kubernetes集群。
有一次,我不知道可以在内部创建etcd,所以我制作了一个外部集群并将Kubernetes连接到它。
现在我看到一个内部集群是一个东西,它是一个更干净的解决方案,因为当您更新Kubernetes集群时,etcd节点也会更新。
我找不到将外部etcd集群迁移到内部集群的干净解决方案。我希望有一个零停机时间的解决方案。你知道是否可以吗?
感谢您的回复,祝您有愉快的一天!
答案 0 :(得分:0)
据我所知,从Kubernetes集群的角度来看,您有3个etcd集群成员。预期的结果是使所有三个成员都在Kubernetes主节点上运行。 还有一些未公开的信息,因此我尝试解释几种可能的选择。
首先,有几种合理的方法可以运行etcd进程用作Kubernetes控制平面键值存储:
/etc/kubernetes/manifests/etcd.yaml
文件中具有启动配置/etc/systemd/system/etcd.service
或类似文件中定义的系统服务运行出于实验目的,您还可以运行etcd:
我的个人建议是有5个成员etcd集群:3个成员在3个主kubernetes节点上作为静态容器运行,另外2个成员在外部(独立于Kubernetes集群)主机上作为静态容器运行。在这种情况下,如果至少有一个主节点正在运行,或者由于任何原因使两个外部节点松动,则仍将达到法定人数。
至少有两种方法可以将etcd集群从外部实例迁移到Kubernetes集群主节点。它也以相反的方式工作。
迁移集群非常简单。在此过程中,成员被关闭(一次一个),移至另一台主机,然后再次启动。当您在etcd群集中仍然有仲裁时,您的群集应该没有任何问题。我的建议是至少有3个或5个以上节点的etcd群集,以使迁移更安全。对于较大的群集,使用第二个答案中的其他解决方案可能更方便。
在official documentation中描述了将etcd成员移动到另一个IP地址的过程:
要迁移成员,请执行以下操作:
- 停止成员进程。
- 将now-idle成员的数据目录复制到新计算机上。
- 根据运行时重新配置说明更新替换成员的对等URL,以反映新计算机。
- 使用相同的配置和数据目录的副本在新计算机上启动etcd。
现在让我们仔细看看每个步骤:
0.1确保您的etcd集群健康,并且所有成员都状况良好。我还建议您检查所有etcd成员的日志,以防万一。
(要成功运行以下命令,请参阅第3步以获取auth变量和别名)
# last two commands only show you members specified by using --endpoints command line option
# the following commands is suppose to run with root privileges because certificates are not accessible by regular user
e2 cluster-health
e3 endpoint health
e3 endpoint status
0.2检查每个etcd成员配置,并找出etcd数据目录的位置,然后确保在etcd进程终止后仍可访问。在大多数情况下,它位于主机上的/ var / lib / etcd下,可以直接使用,也可以作为卷安装到etcd pod或docker容器中。
每个etcd集群成员的0.3 Create a snapshot ,最好不要使用它,而不要拥有它。
1。停止etcd成员进程。
如果按照建议的here使用kubelet
启动etcd,请将etcd.yaml
文件移出/etc/kubernetes/manifests/
。在那之后,etcd Pod将被kubelet
终止:
sudo mv /etc/kubernetes/manifests/etcd.yaml ~/
sudo chmod 644 ~/etcd.yaml
如果您启动etcd进程as a systemd service,则可以使用以下命令将其停止:
sudo systemctl stop etcd-service-name.service
对于docker容器,您可以使用以下命令将其停止:
docker ps -a
docker stop <etcd_container_id>
docker rm <etcd_container_id>
如果从命令行运行etcd进程,则可以使用以下命令将其杀死:
kill `pgrep etcd`
2。将now-idle成员的数据目录复制到新计算机上。
这里没有太多复杂性。将etcd data-dir压缩到文件中,然后将其复制到目标实例。如果您打算以相同的方式在新实例上运行etcd,我还建议复制etcd清单或systemd服务配置。
tar -C /var/lib -czf etcd-member-name-data.tar.gz etcd
tar -czf etcd-member-name-conf.tar.gz [etcd.yaml] [/etc/systemd/system/etcd.service] [/etc/kubernetes/manifests/etcd.conf ...]
scp etcd-member-name-data.tar.gz destination_host:~/
scp etcd-member-name-conf.tar.gz destination_host:~/
3。根据运行时重新配置说明,为替换的成员更新对等URL ,以反映新的成员IP地址。
使用etcd API
或运行etcdctl
实用程序有两种方法。
这就是etcdctl
的样子:
(用正确的etcd集群成员ip地址替换etcd端点变量)
# all etcd cluster members should be specified
export ETCDSRV="--endpoints https://etcd.ip.addr.one:2379,https://etcd.ip.addr.two:2379,https://etcd.ip.addr.three:2379"
#authentication parameters for v2 and v3 etcdctl APIs
export ETCDAUTH2="--ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key"
export ETCDAUTH3="--cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key"
# etcdctl API v3 alias
alias e3="ETCDCTL_API=3 etcdctl $ETCDAUTH3 $ETCDSRV"
# etcdctl API v2 alias
alias e2="ETCDCTL_API=2 etcdctl $ETCDAUTH2 $ETCDSRV"
# list all etcd cluster members and their IDs
e2 member list
e2 member update member_id http://new.etcd.member.ip:2380
#or
e3 member update member_id --peer-urls="https://new.etcd.member.ip:2380"
这就是etcd API
的样子:
export CURL_ETCD_AUTH="--cert /etc/kubernetes/pki/etcd/peer.crt --key /etc/kubernetes/pki/etcd/peer.key --cacert /etc/kubernetes/pki/etcd/ca.crt"
curl https://health.etcd.istance.ip:2379/v2/members/member_id -XPUT -H "Content-Type: application/json" -d '{"peerURLs":["http://new.etcd.member.ip:2380"]}' ${CURL_ETCD_AUTH}
4。使用调整后的配置和数据目录的副本在新计算机上启动etcd 。
在新主机上解压缩etcd数据目录:
tar -xzf etcd-member-name-data.tar.gz -C /var/lib/
根据需要调整etcd启动配置。此时,很容易选择另一种运行etcd的方式。根据您的选择,准备清单或服务定义文件,并将旧的IP地址替换为新的IP地址。例如:
sed -i 's/\/10.128.0.12:/\/10.128.0.99:/g' etcd.yaml
现在是时候通过将etcd.yaml
移至/etc/kubernetes/manifests/
或运行以下命令(如果您将etcd
作为systemd
服务运行)来启动etcd
sudo systemctl start etcd-service-name.service
5。检查更新的etcd进程日志和etcd集群运行状况,以确保成员运行状况良好。
为此,您可以使用以下命令:
$ e2 cluster-health
$ kubectl logs etct_pod_name -n kube-system
$ docker logs etcd_container_id 2>&1 | less
$ journalctl -e -u etcd_service_name
答案 1 :(得分:0)
我在另一个答案中提到的第二个解决方案是
此方法的缺点是etcd仲裁数量会暂时增加,并且在多个节点出现故障的情况下,etcd群集可能会break。为了避免这种情况,您可能需要在添加另一个现有的etcd集群成员之前将其删除。
这是该过程的简要概述:
ca.crt
和ca.key
从现有etcd节点文件夹(/etc/kubernetes/pki/etcd/
)中为所有其他成员生成证书。 etcdctl
命令将新成员添加到集群中另一个可能的顺序:
ca.crt
和ca.key
从现有etcd节点文件夹(/etc/kubernetes/pki/etcd/
)中为所有其他成员生成证书。 etcd.yaml
文件。注意:如果您拥有etcd集群,则可能在某处拥有etcd-CA证书。考虑将其与etcd-CA密钥一起使用,以为所有其他etcd成员生成证书。
注意::如果您选择手动生成证书,则通常的Kubernetes证书的参数为:
您可以使用以下命令检查证书的内容:
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
文件夹中。
可以使用以下kubeadm命令生成默认的etcd.yaml
清单:
kubeadm init phase etcd local
最好将etcd.yaml
的文件从/etc/kubernetes/manifests/
移到某处进行调整。
还删除/var/lib/etcd
文件夹的内容。它包含新的etcd集群的数据,因此不能用于将成员添加到现有集群。
然后应根据成员添加命令输出对其进行调整。 (--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
如果仅使用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/
中的数据库,并且不能在两个目录之间共享豆荚。另外etcd Pod使用节点网络接口与etcd群集进行通信。
当然,您可以将etcd Pod配置为使用不同的主机目录并使用不同的主机端口作为一种解决方法,但是以上命令假定节点上仅存在一个etcd Pod。