大家好,我是谢瑶瑶,来自阿利云目前是Kubernetes开源子项目Alibaba Cloud Provider的项目Maintenor今天由我和我的同事顾静一起为大家分享如何不停机的迁移Kubernetes机群顾静同学是阿利云一位非常优秀的直升容器开发工程师同样他也是Kubernetes开源子项目Alibaba Cloud Provider的一个Maintenor一个非常优秀的北大财女今天我们会从以上方面来分享如何不停机的迁移Kubernetes机群首先我们会为大家介绍一下为什么需要做机群迁移进行迁移的一个需求以及应用场景然后我们会着重介绍如何实现不停机的PBS机群迁移如何进行迁移前的一个前置检查如何做应用的数据迁移与流量迁移等等我们简单列举了四个需要做不停机迁移的场景或者说有些使用不停机迁移的场景第一个是容器化的应用迁移场景第二个是混合运场景下应用的跨运同步与迁移第三个是应用的备份灾难恢复场景下的选量应用迁移第四个是当需要使用到新版本进行特性或者机群配置发生了一个Break Change的情况下这时候是无法通过简单的升级来解决问题的那么就需要通过机群迁移来实现不中断的应用服务首先我们来看一下容器化的应用场景应用迁运场景随着容器化的一个不断发展运源深的理念已经逐渐深容到了各大公司当中具相关调查统计将近有65%的应用已经实现了容器化并逐步从线下的数据中心迁移到了云上从而充分利用云的弹性来实现企业的一个降本增效那么如何实现迁移过程中应用的一个平稳切换并且实现应用的不停机迁移这直接决定了用户业务云化的一个意愿所以不停机迁移不停机的应用迁移对用户容器化的应用迁运就有了一个非常重大的价值其次呢是混合云场景下的一个跨云的流量迁移对用户来讲如果云是一个极具性价比的选择的话那么混合云和多云的策略这进一步为用户提供了一个低成本全球可达的一个应用服务多云会让用户的应用部署到多个云厂商然后避免厂商的一个锁定同时呢它能够提供更高的一个一价能力一个更强的一个备份灾难恢复能力和相当可观的一个稳定性同时呢还可以为全球用户提供基于位置的一个临近服务体验上图展示了一个混合了一个AWS阿里巴巴claw的和自建数据中心的一个混合云在这个混合云中集群与应用需要实现跨云的同步实现应用的迁移服务之间的一个互相调用因此混合云策略对集群以应用的不停计签议也提出了一个巨大的挑战接下来是集群新特性与Break Change的一个场景一般来说更高的一个KBS版本会带来更多的新特性但是呢这些新特性并不是完全没有代价的首先如果你需要使用新特性那就必须升级到对应的一个新版本这通常不是一件非常容易的事情首先如果你的集群版本太低那么你需要多次升级集群才能到达预期的版本比如从1.141.14升级到1.16然后是1.18然后才是1.20这样来避免单次升级集群版本过大造成的兼容性问题并且这些新特性所引入的兼容性问题还可能潜在地造成服务中断除了升级困难以及兼容性问题升级1.16集群无法实现一些配置变更类的需求比如你无法直接变更一个1.16集群的网络模式比如IPvS到IPTablesFlanow到TurwayClass of CRD2的这些会造成整个集群1.16节点或者Port的重建造成服务不可用甚至是整个集群的一个配置被污染因此不停机前以K8s集群的应用在这种情况下可能是一个更好的一个选择接下来我们介绍一下如何进行不停机前移不停机前移总体上分为三个阶段第一个阶段是前置检查Pre-check它可以提前暴露前载的风险第二个阶段是应用前移这里的阶段需要新建一个目标版本的集群并将应用及其数据签议到新的集群当中第三个阶段是流量前移这个阶段至关重要它决定了如何无损的不停机的向线上流量导入到新建的集群当中并使用新建的集群为用户提供服务首先是在前置检查阶段我们需要尽早的暴露前移风险因此我们开发了一套前置检查框架用来检查集群是否做好了前移准备比如不同版本的集群一个API Group的兼容性因此需要提前处理比如说Label的兼容性也需要提前处理不同版本的组件的行为的差异等等如Couple Proxy处理SLB流量转发的行为差异会直接影响流量迁移的成功因此前置检查是一项非常重要的一个步骤等前置检查项都通过之后接下来就是一个前移与流量的前移应用的前移可以通过开源组件Valera进行官方有详细的文档来说明应用的前移阿利云也专门为其提交了阿利云相关的驱动这里我们主要介绍一下如何做数据前移数据前移是实现不停即前移的重要余环这里我们会以磁盘存储和有状态应用Messico EDCD的前移为例来说明如何进行数据的前移云上的存储主要有NFSOSS对象存储CloudDisk云盘等等这一类的如右下图所示通常各大云厂商都为磁盘类型的存储提供了一个完善的快照方法及其恢复的一个方法用途展示了如何将上海锐警的应用数据前移到杭州锐警的一个方法对于磁盘存储的类型首先在上海锐警构建一个磁盘快照然后将快照通过云厂商的一个网络同步到带恢复的一个地域杭州然后通过快照恢复的功能创建一块磁盘然后挂得到节点上后应用即可以随时使用第二类是对自建Messico EDCD一类的应用数据尤其持续读写可能造成潜在的数据的不一致的情况我们可以通过为该应用在目标锐警构建多个或者说用来进行实时的一个数据同步当在流量低峰期到来的时候执行一个主从的切换或者说是强制的一个选注流程一旦目标锐警的选注完成则代表切换完成然后可以逐步下线原锐警的一个Messico或者EDCD副本这就是一个简单的数据迁移流程接下来有我的同事给大家进一步重点介绍一下流量的迁移相关的操作及原理大家好 我是顾敬接下来将有我来介绍一下流量迁移部分流量迁移是集群迁移中十分重要的一个环节流量迁移是指业务在流量五中端的情况下从一个集群迁移到另外一个集群扣护端应当对流量迁移整个过程完全无感DNS是实现无损流量迁移的一种方式分别在两个集群当中创建两个low balance类型的service然后将这两个sob加入到一个DNS的后端然后基于DNS的流量挥度测流量挥度能力来实现将流量转发到两个不同的集群当中去这种方式它是比较简单但是有一个比较大的缺陷就是因为DNS的缓存它是有过期时间的在流量切换后它需要等待30分钟左右才能生效当新集群中进行一个业务回滚操作的时候这种延迟是不可接受的另外一种流量迁移方式就是基于East2去做East2方式它是比较复杂它的学习成本比较高需要新建一个East2集群并且修改已有的应用的一种部署方式然后是基于East2的挥度能力进行流量迁移那么有没有一种方式可以操作简单又可以实现无损流量迁移呢为了解决这个问题我们还得从服务暴露的方式入手Low Balance 类型的Service实际上是通过云上负载均衡器对外暴露服务的负载均衡器它实际上是由个云服务提供商通过部署在集群中的Controller 去创建的创建出来的一个Low Balance 类型的负载均衡器的信息它会体现在Service的StatersLow Balance 自断这里请求访问云上Low Balance 服务器是由个云厂商负责具体怎么将流量重定向到后端迫得上的Called Control Manager 简称CCM 就是这样的一个Controller它是阿里云融器服务部署在KBS集群中的CCM 负责对接KBS资源及云上技术产品如 SOB, VBC, DNS 等等对於 SOBCCM 支持两种转发模式一种是 ECS 模式一种是 INI 模式对于 ECS 模式CCM 会将Node IP 及 NodePort挂载到 SOB 后端请求来的时候流量进入 SOB转发到 Node 上然后进入 Node 上的Cuborx 以转发到对应的 Port 上对于 INI 模式CCM 会将Port IP 及 Tucket Port挂到 SOB 后端请求进入 SOB直接转到 Port 上去 ECS 模式与 INI 模式对比它是明显少了一层转发所以它的网络性能会更好那么究竟是 ECS 模式还是 INI 模式它是由 KBS 中的网络插件决定的对于 Flano 网络插件来说默认就是这种 ECS 模式对于通位网络插件默认是 INI 模式那么 CCM 到底是怎么管理 SOB 的呢对于 Low Balance 类型的 ServiceCCM 会为该 Service 创建或者配置一个 Low Balance首先 CCM 会去KBS 集讯中查询这个 Service 具体的信息然后根据这些信息创建一个 Local Model接着它通过 Open API去查询云上 Low Balance 的信息根据这些信息去创建一个 Remote ModelCCM 会在这两个 Model 之间进行同步根据 Local Model 去同步远程的 Remote Model直到两个 Model 一致为止当 Service 对应的 End Point发生变更或者集群节点发生变更之CCM 会自动同步 Low Balance虚拟服务期组中的后端CCM 还提供了很丰富的注解去支持很丰富的负载均衡能力当用户在集群内访问 Service 的时候这样它的流量是如下的流量渐到 Service然后进入 End Point走到 Node 上的 Cubroxy最终转发到 Port当用户访问 Low Balance IP 的时候流量是进入 Low Balance经过虚拟服务期组然后转发到后端的 Node或者 Port 上面了解 Low Balance Service工作原理之后那么能不能通过 CCM 去实现实施无损流量迁移呢答案是可以的将两个集群的节点都加入到同一个 SOB 的同一个端口中然后通过修改两个集群所占权重即可实现挥度流量迁移由于它是通过调用 Open API去实施修改 SOB 后端的因此它是完全实施的是没有一个缓存的问题的而且对于客户端来讲它访问的仍然是以前的 SOB 的 IP 和 Port因此是完全无感的具体操作如下首先在 1.14 集群中创建一个 Service通过 Annotation 去指定使用一用的 SOB 及端口以及虚拟服务期组然后在 1.20 集群中创建一个同样的 Service去指定相同的一个 SOB ID虚拟服务期组及端口通过 Alibaba Cloud Low Balance Weight这个 Annotation去为集群设置权重配置完成的一个效果就如图所示大概有 80% 的流量会流向 1.14 这个集群然后有 20% 的流量会流向 1.20 这个集群通过修改 Service 里面刚提到的Wate Annotation 是可以实施可以实现动态实施修改流向两个集群的权重的然后从而实现一个灰度的流量迁移当整个迁移过程完成之后可以从 1.14 集群中直接删除掉这个 Service 即可新的集群仍然使用以前的 SOB IP 集破的所以客户端是完全无感的设置 Annotation 之后如何保证集群内破的负载均衡呢对于 External Traffic Policy为 Class 的 Service 而言System 会将所有节点加入到 SOB 后端每个节点的权重计算方式就是整个集群的权不权重除以它的 Node 数量以图示为例 整个集群的权重为 80 它一共有三个节点因此每个节点的权重就是 80 除以 3由于权重必须为整数因此这里取了 27Node 1 Node 2 和 Node 3 的权重都为 27 但是旗上的破的数量分别为 5 3 和 0那么他们是如何做到他们的负载均衡是依赖节点上的 Queue Proxy 去做的对于 Class 的模式Queue Proxy 会将所有破的信息写到本地的路由转发规则当中去因此当请求来到节点 3 的时候它会根据采用轮身的方式将请求转发到 Node 1 或者 Node 2 上去对于 External Traffic为 Local Service 而言System 仅会将有破的这些 Node加入到 SOB 后端因为如果这个节点上没有破的的话Queue Proxy 不会写对应的转发规则所以当流量转发到这个节点上时这个请求会直接被丢弃掉在 Local 模式下需要首先计算每个破的权重这个集权的整体权重为 80 然后它有 8 个破的因此每个破的权重那么节点 1 的权重它就是每个破的权重成义 Node 上的破的数量所以 Node 1 它的权重就是 5 成义 10 就是 50同样的原理 Node 2 的权重就是 30 由于每个破的权重都为 10 因此在 Local 模式下可以实现破的的负载均衡基于 CCM 的这套流量歉意方案它不仅适用于云上的集群歉意还适用于混合云跨 region 以及跨云等等场景的歉意和混合云场景为例客户可以将线下的 ECS 的加入到 SOB 的后端然后通过Wate 那个权重去设置流向云上集群以及云下的 ECS 的一个流量的权重逐步的然后通过动态去调整这个Wate 的 Annotation逐步的将流量从线下集群迁入到线上集群中这套方案是完全就是无锡进行业务改造的然后对于客户端来说也是完全无感的在新集群中测试时不可避免的会遇到一个应用更新的场景如何保证应用更新的过程中流量无损呢应用更新大概分为两第一步是创建新的 POD然后等待 POD running 之后将舊的 POD 删除掉新的 POD 创建成功之后System 就会将其挂到 SOB 的后端如果新建的 POD 无法提供服务那么这样的话请求就会处理失败因此需要为 POD 添加就去检测紧当 POD 可以对外提供服务时采将这个 POD 添加到 SOB 后端在删除 POD 时也会遇到同样的场景因为 POD 删除和从 SOB 后端移除这个 POD它是异部的如果 POD 已经删除但是这个 POD 还未从 SOB 后端移除的话那么这个请求转到节点上去因为没有对应的 POD 可以处理所以这个请求必然是失败的针对这个场景的话我们需要为 POD 添加一个 PRISTOB 后端具体 demo 如图所示这个 PRISTOB 是写在 Lifecycle 这个 Specific 下面的然后图上是一个以 Engines 镜像为例的一个 demo它是先执行了一个 Engines Creed 操作然后是等 Engines 所有的应用进行全部退出之后再等待 30 秒之后POD 后端就执行结束了POD 的 UR 退出图图所示首先 Cublate 触发 Delete POD 事件然后 API Server 收到事件之后尝试去更新 POD 信息Endpoint Controller 去更新 POD 所在的 Endpoints在更新完毕之后Cubrox 也会去清理掉节点上关于这个 POD 路由转发规则CCM 收到 Endpoint 的更新事件之后会尝试从 SOB 后端移除这个 POD在 API Server 去更新 POD 状态之后Cublate 也会进入到 POD 清理流程它会触发 POD 执行 Pristop Hook在 Pristop 执行完毕之后会向 POD 中发送 Sictum 的信号进入 GRISP 下档的过程等待 GRISP Terminating 时间完成之后会向容器中发 SICCure 的信号接着 API Server 会真正的从 EDCD 当中去删除这个 POD接着这个 POD 的状态就被置为 Deleted从删除 POD 开始一直到 CCM 从 SOB 后端移除这个 POD在这整个过程中一直会有流量进入到 POD然后从图中我们可以看出Cubroxy 和 CCM 它是一个异不进行的因此会出现当 SOB 还未移除 POD 的时候节点上的 Cubroxy 规则就已经被清理掉了如左图所示此时如果有请求进入到 SOB 的话它仅接着转发到对应的 Node 上由于 Node 上面的 IPvS 规则已经被清理掉了所以它没有办法对这个请求进行转发从而导致这个请求处理失败针对这个问题 我们有多种处理方式第一种方法是将 Service 改为 CAS模式这样的话请求进入到 SOB 之后它会转发到这个节点的 Cubroxy 上由于前面我们讲到在 CAS模式下本地会记录所有 POD 转发规则因此即使这个节点上的 POD 被删除本地的 Cubroxy 还可以将这个请求转发到其他节点上进行处理但是 CAS模式有一个缺陷它就是没有办法保留 VIP如果 Service 为 Local 模式的话那么一定要保证这个节点上有多个可以正常运行的 POD也就是说它需要实现一个原地升级当请求进入到 Low Balance 的时候这样的话 即使然后这个请求就会被转发到对应的 Note 上去即使以前的 要删除的那个 POD它对应的路由转发规则已经被清理掉因为这个节点上还有其他的 POD 可以正常处理所以这样的本地规则还可以将这个请求转发到一个正彩运行中的 POD 中所以这个请求还是可以被正常的处理的前面提到的 ENI 模式也可以解决这一问题ENI 模式是直接将 POD 挂在 SOB 后端的因此 流量进来的时候进入 SOB 直接转到 POD 上面就绕过了节点 Cubroxy 的那一段路因此即使 Cubroxy 的规则被删除也对这样的一个流量转发过程无影响总结一下整体的集群签议可以分为楼下的三个步骤前置检查应用签议及流量签议前置检查需要检查不同集群间KBS APINode LabelCubroxy等行为的兼容性应用签议可以使用一些开源工具进行基于 CCM 的一个流量签议可以实现实施无损流量签议本次分享到此结束谢谢各位的聆听