因为etcd须要TLS认证,在master节点上有访问etcd须要的证书,因此最好在master节点上进行操做。
Etcd各节点地址和证书路径信息能够查看kube-apiserver的启动参数:ps -ef|grep kube-apiserver 启动参数中都会有etcd的节点地址和证书路径信息
Etcdctl命令依赖如下环境变量,操做前需先进行环境变量设置(需根据实际环境进行修改)node
export ENDPOINTS=https://192.168.0.1:2379,https://192.168.0.2:2379,https://192.168.0.3:2379 export CA_FILE=/etc/kubernetes/ssl/ca.pem export CERT_FILE=/etc/etcd/ssl/etcd.pem export KEY_FILE=/etc/etcd/ssl/etcd-key.pem
V2: export ETCDCTL_API=2 etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE member list V3: export ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE member list
V2: export ETCDCTL_API=2 etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE cluster-health V3: export ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE endpoint health
V2: 无此命令 V3: export ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE endpoint status -w table
V2: # export ETCDCTL_API=2 # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE ls /kubernetes # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE ls /kubernetes /kubernetes/network # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE ls /kubernetes/network /kubernetes/network/config /kubernetes/network/subnets # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE get /kubernetes/network/config {"Network":"172.1.0.0/16", "Subnetlen":24, "Backend": {"Type":"vxlan"}} # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE ls /kubernetes/network/subnets /kubernetes/network/subnets/172.1.80.0-24 /kubernetes/network/subnets/172.1.44.0-24 /kubernetes/network/subnets/172.1.66.0-24 /kubernetes/network/subnets/172.1.89.0-24 /kubernetes/network/subnets/172.1.18.0-24 /kubernetes/network/subnets/172.1.42.0-24 /kubernetes/network/subnets/172.1.5.0-24 /kubernetes/network/subnets/172.1.68.0-24 /kubernetes/network/subnets/172.1.71.0-24 /kubernetes/network/subnets/172.1.57.0-24 /kubernetes/network/subnets/172.1.59.0-24 /kubernetes/network/subnets/172.1.9.0-24 /kubernetes/network/subnets/172.1.101.0-24 /kubernetes/network/subnets/172.1.29.0-24 # etcdctl --endpoints=$ENDPOINTS --cert-file $CERT_FILE --key-file $KEY_FILE --ca-file $CA_FILE get /kubernetes/network/subnets/172.1.29.0-24 {"PublicIP":"x.x.x.x","BackendType":"vxlan","BackendData":{"VtepMAC":"96:76:bc:31:b0:00"}}
经过以上步骤,能够查看到flannel的配置子网和后端的配置信息,还能看到各节点flannel.1接口对应的mac和信息和节点IP信息算法
flannel在etcd中保存信息的路径也能够在flannel的配置文件中查看到,可经过cat /etc/flanneld/flanneld或ps -ef|grep flannel查看到数据库
export ETCDCTL_API=3 #获取全部的key值 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE get / --prefix --keys-only #查看pod信息 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE get /registry/pods --prefix --keys-only #查看service信息 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE get /registry/services/specs --prefix --keys-only #以上路径可根据须要进行修改
export ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE alarm list
备份一个节点的数据就能够恢复,实践中,为了防止定时任务配置的节点异常没有生成备份,建议多在几个节点配置定时备份。备份示例脚本以下后端
export ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE snapshot save cluster1_1198_366_49k.db
Etcd可以承受节点的短时间失效。当有节点短时间失效时,集群可以自动恢复。当集群的节点数为N时,可以承受最大(N-1)/2的节点失效后自动恢复;若失效的节点数超过(N-1)/2,将会因为没法使得半数以上节点达成共识而形成整个集群失效
为了恢复失效的集群,etcd提供了快照功能和恢复措施用于重建整个集群而不会致使丢失数据api
恢复一个集群首先须要从一个集群节点获取快照数据。快照能够是经过etcdctl snapshot save从一个存活的节点进行备份或者直接从节点的etcd数据目录复制member/snap/db文件。下面的命令是从一个存活的节点备份快照数据安全
ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE snapshot save snapshot.db
恢复集群只须要一个快照db文件便可。使用etcdctl snapshot restore命令恢复集群时,集群会建立新的数据目录,而且全部的member都必须使用同一个db文件进行恢复
恢复集群时,可选择性地对db文件的完整性进行校验。若是db文件是经过etcdctl snapshot save命令保存获得的,则db文件中会包含一个db文件完整性校验的hash值,这个值可用于etcdctl snapshot restore该db文件时进行校验;若是db文件是从节点的数据目录直接复制过来的,则db文件不会包含这个hash值,在执行etcdctl snapshot restore指令时,须要加上--skip-hash-check选项
etcdctl snapshot restore操做会初始化新的节点数据目录,而且使用新的配置信息,可是会保留快照中的原始key数据和值信息。以下示例命令恢复一个节点,恢复的数据目录在/var/lib/etcd/infra4,目标集群各个节点须要分别执行恢复命令bash
$ etcdctl snapshot restore cluster1_1198_366_49k.db --name=infra4 --data-dir=/var/lib/etcd/infra4 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 --initial-cluster-token=etcd-cluster-2 --initial-advertise-peer-urls=https://$node4:23804
接下来使用恢复获得的数据目录启动各个节点,如下示例命令恢复一个节点,同理,目标集群的各个节点须要分别执行脚本进行启动网络
#!/bin/bash node4=192.168.0.204 node5=192.168.0.204 node6=192.168.0.204 DATA_DIR=/var/lib/etcd/infra4 etcd --name=infra4 --initial-advertise-peer-urls=https://$node4:23804 --cert-file=/etc/kubernetes/pki/etcd/server.crt --key-file=/etc/kubernetes/pki/etcd/server.key --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --client-cert-auth=true --peer-client-cert-auth=true --data-dir=$DATA_DIR --snapshot-count=100 --listen-peer-urls=https://$node4:23804 --listen-client-urls=https://$node4:23794 --advertise-client-urls=https://$node4:23794 --initial-cluster-token=etcd-cluster-2 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806
Etcd集群配置变动须要在集群大多数节点功能正常的状况下进行,而且强烈建议集群的数量必须大于2,若是从一个节点数为2的集群中删除一个节点时,将致使集群不可用app
配置变动须要在集群大多数(1/2以上)节点工做正常的状况下进行,这是任何一种配置变动的先决条件。
对集群作任何一种变动都必须按顺序操做,不能乱序,例如:性能
要更新某个节点的advertise client URLs,只须要在该节点的配置中更新advertise client URLs,而后重启该节点的etcd,重启后,该节点的etcd会以新的client URLs对外提供服务。节点的client URLs更新出现错误时,不会影响集群的健康状态
要更新某个节点的advertise peer URLs,须要显示的经过etcdctl的member命令更新peer-urls参数,而后重启该节点。因为节点peer URLs涉及到的的是集群范围的配置变动,操做不当会影响集群的健康状态,因此要规范操做
etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE member list 6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792 924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793 a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791
etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE member update a8266ecf031671f3 --peer-urls=http://10.0.1.10:2380 Updated member with ID a8266ecf031671f3 in cluster
假设要删除的节点ID是a8266ecf031671f3,使用member remove命令移除节点
etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE member remove a8266ecf031671f3
节点a8266ecf031671f3会自动中止并退出,并输出以下日志
etcd: this member has been permanently removed from the cluster. Exiting.
移除leader节点也是安全的,但在新的leader选举出来前,集群是不可用的
增长一个节点分为两步:
etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE member add infra3 --peer-urls=http://10.0.1.13:2380 输出以下信息: added member 9bf1b35fc7761a23 to cluster ETCD_NAME="infra3" ETCD_INITIAL_CLUSTER="infra0=[http://10.0.1.10:2380](http://10.0.1.10:2380/),infra1=[http://10.0.1.11:2380](http://10.0.1.11:2380/),infra2=[http://10.0.1.12:2380](http://10.0.1.12:2380/),infra3=[http://10.0.1.13:2380](http://10.0.1.13:2380/)" ETCD_INITIAL_CLUSTER_STATE=existing
该命令已通知集群新加入的节点信息,并打印出了新节点加入时须要配置的环境变量信息,新节点须要配置这些环境变量才能成功启动
$ export ETCD_NAME="infra3" $ export ETCD_INITIAL_CLUSTER=”infra0=http://10.0.1.10:2380, infra1=http://10.0.1.11:2380, infra2=http://10.0.1.12:2380, infra3=http://10.0.1.13:2380” $ export ETCD_INITIAL_CLUSTER_STATE=existing $ etcd --listen-client-urls http://10.0.1.13:2379 --advertise-client-urls http://10.0.1.13:2379 --listen-peer-urls http://10.0.1.13:2380 --initial-advertise-peer-urls http://10.0.1.13:2380 --initial-cluster="infra0=http:// 10.0.1.10:2380, infra1=http:// 10.0.1.11:2380, infra2=http:// 10.0.1.12:2380, infra3=http:// 10.0.1.13:2380" --data-dir %data_dir%
新节点启动完成后,就会当即同步其余的节点
注意,"initial-cluster"里面必定要有新成员的peer地址,由于etcdctl执行完毕"etcdctl member add"后,etcd cluster就把这个还未存在的node算进quorum了,第二步必须准确完成
若是要新增多个节点时,最好是一次新增一个,而且须要确保新增的节点正常启动且运行正常后在新增下一个节点。
若是是向只有一个节点的集群新增节点,在执行member add命令后,新节点正常启动并与已存在的节点创建链接以前,集群不会继续执行数据的提交工做,由于此时集群在等待多数节点达成共识
etcd --name infra3 --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 --initial-cluster-state existing 输出信息以下: etcdserver: assign ids error: the member count is unequal exit 1
$ etcd --name infra4 --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra4=http://10.0.1.14:2380 --initial-cluster-state existing 输出信息以下 etcdserver: assign ids error: unmatched member while checking PeerURLs exit 1
Etcd的space quota能够保证集群已可靠的方式运行。若是不配置space quota,etcd的key存储空间可能会过分的增加致使性能降低,甚至在超过磁盘的可用空间时,致使不可预期的行为。若是任何一个节点的后端数据库大小超过space quota时,etcd会产生一个集群范围的告警,使集群进入一种维护状态,在这种状态下,集群只接受key的读取和删除,只有在释放了足够的key值或者对数据库进行碎片整理后,集群才能进入正常工做状态
经过如下启动参数配置keyspace使用的空间限额
# set a very small 16MB quota $ etcd --quota-backend-bytes=$((16*1024*1024))
etcd集群接受一个写请求后,每一个etcd成员都须要把写请求数据固化到cores/bbolt之中,整个过程不要超过50ms。若是超过100ms,则etcd就会打印此条log进行警告。一般状况下是由于磁盘慢,好比磁盘竞争或者譬如虚拟块磁盘这种烂设备。etcd暴露给Prometheus的metrics指标backendcommitduration_seconds就显示了commit的瓶颈时间,这个指标低于25ms便可认为服务正常,若是磁盘自己确实慢则设置一个etcd专用磁盘或者更换成SSD一般就能解决问题。
第二个缘由是CPU计算力不足。若是是经过监控系统发现CPU利用率确实很高,就应该把etcd移到更好的机器上,而后经过cgroups保证etcd进程独享某些核的计算能力,或者提升etcd的priority。
etcd使用了raft算法,leader会定时地给每一个follower发送心跳,若是leader连续两个心跳时间没有给follower发送心跳,etcd会打印这个log以给出告警。一般状况下这个issue是disk运行过慢致使的,leader通常会在心跳包里附带一些metadata,leader须要先把这些数据固化到磁盘上,而后才能发送。写磁盘过程可能要与其余应用竞争,或者由于磁盘是一个虚拟的或者是SATA类型的致使运行过慢,此时只有更好更快磁盘硬件才能解决问题。etcd暴露给Prometheus的metrics指标walfsyncduration_seconds就显示了wal日志的平均花费时间,一般这个指标应低于10ms。
第二种缘由就是CPU计算能力不足。若是是经过监控系统发现CPU利用率确实很高,就应该把etcd移到更好的机器上,而后经过cgroups保证etcd进程独享某些核的计算能力,或者提升etcd的priority。
第三种缘由就多是网速过慢。若是Prometheus显示是网络服务质量不行,譬如延迟过高或者丢包率太高,那就把etcd移到网络不拥堵的状况下就能解决问题。可是若是etcd是跨机房部署的,长延迟就不可避免了,那就须要根据机房间的RTT调整heartbeat-interval,而参数election-timeout则至少是heartbeat-interval的5倍。
etcd会把kv snapshot发送给一些比较慢的follow或者进行数据备份。慢的snapshot发送会拖慢系统的性能,其自身也会陷入一种活锁状态:在很慢地收完一个snapshot后尚未处理完,又由于过慢而接收新的snapshot。当发送一个snapshot超过30s而且在1Gbps(千兆)网络环境下使用时间超过必定时间时,etcd就会打印这个日志进行告警。
etcd cluster启动的时候经过"initial-cluster-token"参数指定集群的名称。若是一个老集群已经tear down,可是还有部分红员活着,此时在老集群之上又部署新的集群以后,那些还活着的老成员会尝试链接新集群的各个成员,由于cluster token不一致新成员接收到请求后会报出这个warning。
避免这个错误的方法就是不要使用老集群的地址。
若是raft集群中有处于unhealthy状态的node,须要先把它剔除掉,而后才能进行替换操做。可是添加一个新的node是一件很是高风险的操做:若是一个3节点的etcd集群有一个unhealthy node,此时没有先把unhealthy node剔除掉,而新添加节点时可能因为配置不当或者其余缘由致使新的node添加失败,则新集群理论上node number为4而当前quorum只可能达到2,失去consensus的集群对任何操做都没法达成共识。
若是按照正确的操做步骤,先剔除 unhealthy node,此时n为2而quorum为2,添加新节点后n为 3,及时添加新节点失败也不会致使集群不可用。
集群的初始状态如上图,集群已通过屡次反复重启,leader选举已发生了1196次
向集群写入一次数据,RAFT INDEX会加1,RAFT TERM表示的是leader选举的轮数,只有从新发生leader选举,RAFT TERM才会增长。Etcd的--snapshot-count=100,以便于观察snap的生成规律,生产环境推荐10000。此时RAFT INDEX为45,snap文件夹下还未生成snap文件
经过如下命令,向集群提交100次写入操做
for i in {1..100} do export ETCDCTL_API=3;etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE put hello world$i done
能够看到,RAFT INDEX增长了100,与提交给集群的写入次数相同,而且集群生成了一个快照文件00000000000004ac-0000000000000065.snap,其中00000000000004ac是RAFT TERM 1196的十六进制表示,0000000000000065是生成snap时,对应的RAFT INDEX的十六进制表示,0x65=101
执行如下命令两次
for i in {1..110} do export ETCDCTL_API=3;etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE put hello world$i done
再向etcd写入220次数据,又生成了两个snap文件,其中文件名的后半部分0xca=202, 0x12f=303,因此当RAFT INDEX能整除--snapshot-count=100这个变量时,就会生成一个snap文件
执行如下命令进行数据备份
export
ETCDCTL_API=3;etcdctl --endpoints=$ENDPOINTS --cert $CERT_FILE --key $KEY_FILE --cacert $CA_FILE snapshot save cluster1_1198_366_49k.db
命令执行成功后,会生成数据文件cluster1_1198_366_49k.db,该文件可用于集群恢复,其中1198是RAFT TERM,366是RAFT INDEX,用于记录集群当前的两个状态
执行下面的脚本,从备份的数据恢复集群,执行成功后,会在各自--data-dir指定的目录中生成数据目录
restore-etcd-cluster.sh etcdctl snapshot restore cluster1_1198_366_49k.db --name=infra4 --data-dir=/var/lib/etcd/infra4 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 --initial-cluster-token=etcd-cluster-2 --initial-advertise-peer-urls=https://$node4:23804 etcdctl snapshot restore cluster1_1198_366_49k.db --name=infra5 --data-dir=/var/lib/etcd/infra5 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 --initial-cluster-token=etcd-cluster-2 --initial-advertise-peer-urls=https://$node4:23805 etcdctl snapshot restore cluster1_1198_366_49k.db --name=infra6 --data-dir=/var/lib/etcd/infra6 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 --initial-cluster-token=etcd-cluster-2 --initial-advertise-peer-urls=https://$node4:23806
其中infra四、infra五、infra6是新生成的3个节点的数据目录
分别执行如下3个脚本,来从恢复的数据目录中启动
start4.sh #!/bin/bash node4=192.168.0.204 node5=192.168.0.204 node6=192.168.0.204 DATA_DIR=/var/lib/etcd/infra4 etcd --name=infra4 --initial-advertise-peer-urls=https://$node4:23804 --cert-file=/etc/kubernetes/pki/etcd/server.crt --key-file=/etc/kubernetes/pki/etcd/server.key --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --client-cert-auth=true --peer-client-cert-auth=true --data-dir=$DATA_DIR --snapshot-count=100 --listen-peer-urls=https://$node4:23804 --listen-client-urls=https://$node4:23794 --advertise-client-urls=https://$node4:23794 --initial-cluster-token=etcd-cluster-2 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 start5.sh #!/bin/bash node4=192.168.0.204 node5=192.168.0.204 node6=192.168.0.204 DATA_DIR=/var/lib/etcd/infra5 etcd --name=infra5 --initial-advertise-peer-urls=https://$node5:23805 --cert-file=/etc/kubernetes/pki/etcd/server.crt --key-file=/etc/kubernetes/pki/etcd/server.key --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --client-cert-auth=true --peer-client-cert-auth=true --data-dir=$DATA_DIR --snapshot-count=100 --listen-peer-urls=https://$node5:23805 --listen-client-urls=https://$node5:23795 --advertise-client-urls=https://$node5:23795 --initial-cluster-token=etcd-cluster-2 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806 start6.sh #!/bin/bash node4=192.168.0.204 node5=192.168.0.204 node6=192.168.0.204 DATA_DIR=/var/lib/etcd/infra6 etcd --name=infra6 --initial-advertise-peer-urls=https://$node6:23806 --cert-file=/etc/kubernetes/pki/etcd/server.crt --key-file=/etc/kubernetes/pki/etcd/server.key --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --client-cert-auth=true --peer-client-cert-auth=true --data-dir=$DATA_DIR --snapshot-count=100 --listen-peer-urls=https://$node6:23806 --listen-client-urls=https://$node6:23796 --advertise-client-urls=https://$node6:23796 --initial-cluster-token=etcd-cluster-2 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23806
恢复集群启动成功后,查看以前写入hello对应的值为world110,正是咱们以前备份前最后写入的值,说明集群恢复是正确的
测试目标:将测试集群中node6的client urls端口由23796改成23797
更改start6.sh脚本中的对应行以下:
--listen-client-urls=https://$node6:23797 --advertise-client-urls=https://$node6:23797
Kill掉node6节点的etcd,后再执行start6.sh启动node6
从新启动后,node6的client urls已经更新
测试目标:将测试集群中node6的peer urls端口由23806改成23807
--initial-advertise-peer-urls=https://$node6:23807 --listen-peer-urls=https://$node6:23807 --initial-cluster=infra4=https://$node4:23804,infra5=https://$node5:23805,infra6=https://$node6:23807
测试结果如上图,node6的peer url更新成功