1. 首页 > 热点 >

etcd备份 etcd备份还原原理

详解kubernetes备份恢复利器 Velero - 深入了解Carina系列第三期

Gyuho Lee (, Amazon Web Servs, Inc.), Joe Betz (, Google Inc.)

传统的数据备份方案主要有两种, 一种是利用存储数据的服务端实现基于快照因为成员添加可能会改变etcd的高可用基本有三种思路:quorum(大多数)的值的大小,所以首先用“成员删除”去替换那些不健康的。的备份,另一种是在每台目标上部署专有备份 agent 并指定备份数据目录,定期把数据到外部存储上。这两种方式的备份机制相对固化,在云原生时代无法适应容器化后的弹性、池化等部署场景。

etcd备份 etcd备份还原原理etcd备份 etcd备份还原原理


etcd备份 etcd备份还原原理


Etcd的learner设计翻译

添加 MemberPromote API

成员变更是系统其中挑战性的作之一。我们重新回顾一下那些挑战。

kubeadm init phase kubeconfig all

一个新的成员加入是没有数据的,因此需要从leader那里获取更新日志,直到追赶上leader的日志。所以啊,leader的网络可能更容易负载高,可能会阻塞或者丢失leader发给follower的心跳包。在这种情况下,follower可能会出现 选举超时,进而开始一轮新的leader选举。也就是新成员加入到集群可能更容易造成leader选举。leader选举和后续的更新传递给新成员都容易引起集群间断的不可用。

这三种思路均可以实现etcd高可用的目标,但是在选择过程中却要根据实际情况做出一些判断。简单来讲预算充足但保守的项目选方案一, 想一步到位并愿意承担一定风险的项目选方案三。折中一点选方案二。各个方案的优劣以及做选择过程中的取舍在这里就不详细展开了,对这块有疑问的朋友可以私下联系交流。

网络分区的场景,如果网络分区了,取决于leader的分区。如果leader仍旧能够收到大多数的心跳响应,集群仍旧可以继续作。

如果leader和其它剩余的隔离了?Leader会每一个follower的状态。当leader失去和大多数的链接,他转换回follower身份,这样会影响集群的可用性。

当一个加入到一个3的集群中,集群大小变成4,这时多数的个数就是3。此时如果发生网络分区会发生什么?这取决于在分区之后新加入的分区。

如果这个新碰巧加入到了和leader同在的分区。leader仍旧可以和活跃的3个保持大多数。不会发生重新选举,也不会影响到集群的可用性。

如果集群是2-2分区了,那么任何一个分区都达不到大多数3。在这种情况下,leader选举是会发生的。并且如果分区一直持续,那么leader会一直选,并且选不出来。

如果网络分区先发生,然后一个成员要加入。一个已经分区的3集群已经和一个follower失去链接了。当一个新的加入(我:为什么此时还能加入新成员呢?因为当前和还是有leader的,可以提交成功成员变更请求),因此大多数从2改变成3。现在这个集群4个只有2个活跃的(我:因为新成员还没加进来),因此失去大多数并且开始一个新的选举。

更坏的情况是当我们添加一个成员的时候配置错了。成员变更是一个两阶段处理的过程:

也就是说,"member add" 命令被应用时(我:这里的应用可以理解是写wal,应用状态机)会忽略这个URL,即使URL值是不合法的。当阶段将不合法的URL应用了之后,第二阶段甚至不能启动这个新的etcd,(我:因为这个会和老进行通信,验证集群的成员信息,如果不匹配的话,就不能启动)一旦集群失去了大多数活跃,就没有办法再切回到原来的成员配置了(我:因为没办法进行日志提交)。

在多的集群中也会有相同的场景。举个例子,集群有两个成员down了(一个挂了,另一个是配置配错了),另外有两个成员活着,但是它现在是需要最少3个投票去改变集群成员。

像上述看到的,一个简单的配置错误,可以导致整个集群进入一个不可作的状态。在这种情况下,需要手动重新创建集群通过 etcd --force-new-cluster 标志。如今etcd已经成为了一个在k8s中不可缺失的服务,甚至一个轻微的停服就可能导致很明显的对用户的影响。怎么样才能使得这些作更简单些?除此之外,leader选举是影响集群可用性的最关键的因素:有没有可能我们可以使成员变更不改变quorum(大多数这个值的大小),这样就可以更少地产生破坏性。

为了减轻上述描述的可用性间隔,Raft 4.2.1 介绍了一个新的状态称为"Learner",它加入集群内但不参与投票,直到它赶上了leader的日志

在添加一个learner的时候,应该做尽可能少的工作。member add --learner 命令可以添加一个新的learner,这样新加入的就会是以一个不参与投票的,只是从leader收到所有的数据。也不计算在quorum中。

当一个learner追赶上leader的进度,learner可以被提升称为一个可投票的成员,使用member promote API,后续就成为多数派的计数之一了。

etcd 服务会在提升身份的请求中检查合法性去确保它的作安全性。只有在它的日志已经追赶上leader的,learner才能被提升称为一个可投票的成员。

Learner在提升之前只作为一个备份的存在。权不能转给learner。Learner会拒绝客户端的读和写请求(client的均衡器不应该将请求路由到learner)。这也就意味着,learner不需要发出Read Index 请求给Leader。这些限制简化了在V3.4版本中learner的初步实现。

另外,etcd限制了一个集群可以有的最多的learner的数量,避免了leader日志过载。Learner从不会自己提升自己的身份。由于etcd提供了learner状态信息和安全性检查,集群作者必须做决定是否提升learner或不提升。

让learner状态成为默认和:默认一个新加入的成员的状态是learner将极大改善成员变更的安全性,因为learner不会改变quorum的大小。配置错了也可以回退,集群不会丢失大多数。

让提升为可投票身份完全自动起来:一旦learner追赶上了leader的log,集群可以自动地提升learner的身份。etcd需要用户定一个确切的阈值,一旦这个阈值需求满足了,learner提升自己成为一个可投票的成员。从用户的角度来说,"member add" 命令在今天会以同样的方式工作不过更加的安全,因为提供了learner特性。

让Learner成为一个备份的故障恢复:一个Learner加入是作为备份,并且自动地提升当集群的可用性受到影响的时候。

让Learner只读:一个Learner可以作为一个只读提供只读服务而从不被提升。在一个弱一致性模式下,learner只从leader接收数据,并不提供写。在不需要一致性的前提下提供读将极大减少leader的负载,但有可能会返回过期数据。在强一致性模式下,learner向leader请求read index来提供最新数据,但是仍旧拒绝写。

etcd 实现了"ror maker"(镜像同步) 使用了watch 机制去持续地转发key创建和更新到其它的集群。一旦完成了初始的同步情况下,镜像同步就是低延迟的。Learner和镜像同步都可以被用于同步已存在的数据。然而镜像同步不保证线性一致性。在网络失去连接期间,先前的kv可能已经被废弃了,客户端需要去验证watch的响应顺序的正确性。因此镜像没有顺序性保证。为了低延迟(跨数据中心)以一致性为代价。使用Learner去保持所有历史的数据和它的顺序。

Etcd客户端给MemberAdd的API添加了一个标志,标志是为了添加一个learner。Etcd服务处理成员变更的条目的类型是 pb.ConfChangeAddLearnerNode 。一旦这个命令被应用了,服务加入集群使用 etcd --initial-cluster-state=existing 标志。这个learner既不投票也不被算成大多数。

etcd服务一定不能将leader转给learner,因为它可能仍旧落后并且不被计算为大多数。

etcd服务限制了learner的数量:learner越多,leader就需要传送的数据越多。client可能和learner有交流,但learner拒绝所有的请求,除了序列化读和成员状态API。这是为了简化的一个初步实现。将来,learner可以被扩展成为一个只读的服务,持续同步映射集群的数据。客户端的负载均衡器必须提供帮助函数排除learner。否则,请求发送到learner可能失败。客户端同步成员信息的调用应该考虑learner的类型。所以应该客户端更新调用。

MemberList和MemberStatus的响应应该指明哪个是learner。

在Raft内部,第二次MemberAdd添加learner的调用提升它成为一个可投票成员。leader维护每一个follower和learner的进展状况。如果learner还没有完成它的快照消息,拒绝提升请求。接受提升请求仅在:

windlees

2020-04-04 23:08

k8s The connection to the server was refused 问题解决记录

最近公司的 k8s 集群出现了一个问题:在执行任何 kubectl 命令时都会出现以下错误,本文就记录一下该问题的溯源过程以及解决方式,希望对大家有帮助:

相信很多朋友都遇到过这个问题, 6443 是 k8s API 的默认端口,出现访问被拒绝肯定是 kubelet 有问题或者被防火墙拦截了,这里先看一下这个端口上的 kubelet 是不是还或者:

运行之后什么都没有返回,也就是说 API 完全没有提供服务 ,那我们就去查看一下 kubelet 的日志,大家都知道使用 kubeadm 搭建的 k8s集群里,API 都是在 docker 里运行的,这里我们先找到对应的容器,记得加 -a ,因为该容器可能已经处于非正常状态了:

这里能看到两个容器,可以看到 容器的状态已经是 Exited 了 ,注意下面的 paus重新生成证书e 容器,这个只是用来 API 的,并不是服务的实际运行容器,所以看不到日志,所以查看日志时不要输错容器 id 了。接下来查看 API 的日志:

从一行可以看到,是 API 在尝试创建存储时出现了问题,导致无确启动服务,由于 k8s 是使用 etcd 作为存储的,所以我们再来查看 etcd 的日志。

注意,我这里 etcd 也是运行在 docker 里的,如果你是直接以 serv 的形式运行的话需要使用 ctl status etcd 来查看日志,下面是 docker 的 etcd 日志查看:

可以看到 etcd 一直在循环输出上面的错误日志直到超时退出,从里面可以提取到一条关键错误,就是 error "tls: failed to verify client's certificate: x509: certificate has expired or is not yet valid 。这个错误对于经常维护 k8s 集群的朋友可能很熟悉了,又是证书到期了。

这个集群有三台 ,分别是 171 、 181 和 1 ,可Kubeadm安装的K8S集群1年证书过期问题的解决思路以从错误信息前看到是在请求 181 时出现了证书验证失败的问题,我们登陆 181 机器来验证错误:

经过排查,发现 k8s 的相关证书都没事,但是 etcd 的证书都到期了。关于 k8s 需要的证书可以看这篇文章,接下来我们就来解决问题:

如果版本相过大的话请进行百度,相关的解决方案还是挺多的,下面解决方案请先配合 -h 使用, 注意:以下作会导致服务停止,请谨慎执行 :

备份原始文件

重新生成证书需要集群初始化时的配置文件,我的配置文件 kubeadm.yaml 如下:

其中 192.168.100.170 是 VIP, 171 、 181 、 1 分别对应 1 、 2 、 3 主机。接下来使用配置文件重新签发证书,每个管理都要执行:

重新生成配置文件

重启管理的 k8s

重启 etcd,apiserver,controller-mar,scheduler 容器,一般情况下 kubectl 都可以正常使用了,记得 kubectl get nodes 查看的状态。

重新生成工作的配置文件

如果上一步查看的工作的状态还是为 NotReady 的话,就需要重新进行生成,如果你根证书也更换了的话就会导致这个问题,这个命令也需要每个管理都执行一次,被重新生成的配置文件包括下列几个:工作的证书也会失效,直接备份并移除下面的证书并重启 kubelet 即可:

如果不行的话就直接把管理的 /etc/kubernetes/pki/ca.crt 到对应工作的相同目录下然后再次启动 kubelet。等待三分钟左右应该就可以在管理上看到该工作的状态变为 Ready 。

k8s 的证书只有一年的设置确定有点坑,虽然为了让使用者更新到最新版本的本意是好的。如果你现在 k8s 集群还是正常但是并没有执行过证书更新作的话,请及时查看你的证书到期时间,等到证书到期就为时已晚了。

k8s 1.14版本证书过期问题解决

说起来,都是泪,从三年前和这个问题作斗争,证书过期和自动续期这个大问题,始终是一个心头的伤。

现在要想到一刀切的方案,还是自己更改Kubeadm源码,全部改成100年,最洒脱。

但,如果线上已运行了这些东东,且是10年1年证书二是在Kubernetes Master上用static pod的形式来运行etcd,并将多台Kubernetes Master上的etcd组成集群。 在这一模式下,各个的etcd实例被注册进了Kubernetes当中,虽然无法直接使用 kubectl 来管理这部分实例,但是以及日志搜集组件均可正常工作。在这一模式运行下的etcd可管理性更强。过期的都有,那啷个弄嘛?

先用如下命令,看看k8s的哪些证书何时到期

输出pki下的证书情况:

输出/etc/kubernetes下的证书情况

cp -R /etc/kubernetes /etc/kubernetes$(date "+%Y%m%d")

又或者一条命令搞定

这里有个注意的细节,在使用kubeadm命令之前,它会到外网查找此K8s集群的版本信息,如果我们的机器是纯企业内网,不能访问外面,这里就会卡住。

BUT,还是可以离线进行的。

先从本集群生成一个config view类型文件。

kubeadm config view > kubeadm.conf

然后,在之后生成证书时,加上这个文件作为--conf根据上面通信的介绍我们会产生一个疑问, 这个看起来好复杂的样子。 臣妾看不懂呀。 如果想进一步了解集群中详细的工作流程请移驾 kubectl创建pod背后发生了什么 探索背后的秘密ig参数即可。如

(上面是kueadm 1.10版本的命令,新版本已从alpha转正式命令,-h可找出来)

如果生疏了,可能看看命令

1,仍然先备份哟,备份使得万年船~~

cp -R /etc/kubernetes /etc/kubernetes$(date "+%Y%m%d")

2,先将要过期的证书作更名

3,生成k8s的config view,然后使用kubeadm生成新的证书对

4,依次升级完其它几个要过期的证书,包括与etcd连接的证书对。

5,注意,有三个根证书对,是20年过期的,我没有更新(关键我不清楚更新之后,会发生什么事)。

6,根据不同版本,查看证书过期的命令还不一样呢,再作个重复记录。

查看/etc/kubernetes/pki目录证书过期

查看/etc/kubernetes/目注意,由于 k8s 版本问题,这一部分的内容可能和你的不太一样,我所使用的版本如下:录下的几个conf里的证书过期

kubernetes的和node

往一个只有一个成员的集群中添加会改变quorum大小成2,当之前的leader发现大多数(我:此时大多数的值已经是2了)不是active的时候立刻会引起leader重新选举。(我:这里我尝试分析一下,C(old,new) 会在老集群提交,那么老集群立刻使用C(old,new)的配置,此时quorum变成了2,那么就不能对外提供服务了)这是因为“member add”作是一个两阶段处理的过程,即用户需要先执行 "member add" 命令,之后启动新的进程。

kubernetes集群中的是集群的控制, 负责整个集群的管理和控制。执行的控制命令都是发送给。 Master上运行的主要组件如下:

上图为kubernetes中所有组件一起工作时的示意图,由此我们可以得出以下几个通信流程,

要求结果为所有的 Kubernetes Master 没有单点故障,任何一台当机均不影响Kubernetes的正常工作。

为了实现没有单点故障的目标,需要为以下几个组件建立高可用方案:

etcd是Kubernetes当中带状态的服务,也是高可用的难点。Kubernetes选用etcd作为它的后端数据存储仓库正是看重了其使用分布式架构,没有单点故障的特性。

虽然单的etcd也可以正常运行。但是的部署方案均是采用3个或者5个组成etcd集群,供Kubernetes使用。

一是使用的etcd集群,使用3台或者5台只运行etcd,维护和升级。甚至可以使用CoreOS的 update-engine 和 lockith ,让完全自主的完成升级。这个etcd集群将作为基石用于构建整个集群。 采用这项策略的主要动机是etcd集群的增减都需要显式的通知集群,保证etcd集群稳定可以更方便的用程序完成集群滚动升级,减轻维护负担。

三是使用CoreOS提出的 self-hosted etcd方案 ,将本应在底层为Kubernetes提供服务的etcd运行在Kubernetes之上。 实现Kubernetes对自身依赖组件的管理。在这一模式下的etcd集群可以直接使用 etcd-operator 来自动化运维,Kubernetes的使用习惯。

apiserver本身是一个无状态服务,要实现其高可用相对要容易一些,难点在于如何将运行在多台上的apiserver用一个统一的外部入露给所有Node。

说是难点,其实对于这种无状态服务的高可用,我们在设计业务系统的高可用方案时已经有了相当多的经验积累。需要注意的是apiserver所使用的SSL证书要包含外部入口的地址,不然Node无常访问apiserver。

apiserver的高可用也有三种基本思路:

一是使用外部负载均衡器,不管是使用公有云提供的负载均衡器服务或是在私有云中使用 LVS 或者 HaProxy 自建负载均衡器都可以归到这一类。 负载均衡器是非常成熟的方案,在这里略过不做过多介绍。如何保证负载均衡器的高可用,则是选择这一方案需要考虑的新问题。

二是在网络层做负载均衡。比如在Master上用 BGP 做 ECMP ,或者在Node上用 iptables 做NAT都可以实现。采用这一方案不需要额外的外部服务,但是对网络配置有一定的要求。

三是在Node上使用反向对多个Master做负载均衡。这一方案同样不需要依赖外部的组件,但是当Master有增减时,如何动态配置Node上的负载均衡器成kubeadm alpha phase kubeconfig scheduler --config kubeadm.conf为了另外一个需要解决的问题。

从目前各个集群管理工具的选择来看,这三种模式都有被使用,目前还没有明确的方案产生。建议在公有云上的集群多考虑种模式,在私有云环境中由于维护额外的负载均衡器也是一项负担,建议考虑第二种或是第三种方案。

这两项服务是Master的一部分,他们的高可用相对容易,仅需要运行多份实例即可。这些实例会通过向apiserver中的 Endpoint 加锁的方式来进行leader election, 当目前拿到leader的实例无常工作时,别的实例会拿到锁,变为新的leader。

严格来说kube-dns并不算是Master组件的一部分,因为它是可以跑在Node上,并用 Serv 向集群内部提供服务的。但在实际环境中, 由于默认配置只运行了一份kube-dns实例,在其升级或是所在当机时,会出现集群内部dns服务不可用的情况,时会影响到线上服务的正常运行。

为了避免故障,请将kube-dns的 replicas 值设为2或者更多,并用 anti-affinity 将他们部署在不同的Node上。这项作比较容易被疏忽,直到出现故障时才发现原来是kube-dns只运行了一份实例导致的故障。

上面介绍了Kubernetes Master各个组件高可用可以采用的策略。其中etcd和kube-apiserver的高可用是整个方案的重点。由于存在多种高可用方案,集群应当根据集群所处环境以及其他限制条件选择适合的方案。

这种没有的通用方案,需要集群建设者根据不同的现状在多个方案中做选择的情况在Kubernetes集群建设过程中频频出现, 也是整个建设过程中最有挑战的一部分。容器网络方案的选型作为Kubernetes建设过程中需要面对的另外一个大问题也属于这种情况,今后有机会再来分享这个话题。

在实际建设过程中,在完成了上述四个组件的高可用之后,采取实际关机检验的方式来验证高可用方案的可靠性,并根据检验的结果不断调整和优化整个方案。

此外将高可用方案与系统自动化升级方案结合在一起考虑,实现高可用下的系统自动升级,将大大减轻集群的日常运维负担,值得投入精力去研究。

虽然本篇主要在讲Kubernetes Master高可用的方案,但需要指出的是,高可用也并Node时kubernetes集群中的工作负责,Node上的工作负载由分配, 当某个Node宕机时,Master会将上面的工作负载转移到其他上去, Node上运行的主要组件如下:不是必须的,为了实现高可用所付出的代价并不低, 需要有相应的收益来平衡。对于大量的小规模集群来说,业务系统并没有实现高可用,贸然去做集群的高可用收益有限。这时采用单Master的方案,做好etcd的数据备份,不失为理性的选择。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 12345678@qq.com 举报,一经查实,本站将立刻删除。

联系我们

工作日:9:30-18:30,节假日休息