简介:本文将通过集群迁移的需求、场景以及实践方式,介绍如何基于阿里云容器服务 ACK,在零停机的情况下迁移 Kubernetes 集群。

作者:顾静(子白)|阿里云高级研发工程师;谢瑶瑶(初扬)|阿里云技术专家

导语:随着云原生理念在企业中的深入和践行,应用容器化的比例大幅提升。是否可以保证应用容器化迁移过程中的平稳切换,保证应用不停机迁移,成为影响用户业务云化的一个重要条件。本文整理自阿里云云原生团队在 KubeCon China 2021 线上峰会的分享实录,将通过集群迁移的需求、场景以及实践方式,介绍如何基于阿里云容器服务 ACK,在零停机的情况下迁移 Kubernetes 集群。

大家好,我是谢瑶瑶,来自阿里云,目前是 Cloud-provider 开源子项目 cloud-provider-alibaba-cloud 项目的 Maintainer。今天由我和我的同事顾静一起为大家分享如何不停机的迁移 Kubernetes 集群。顾静同学也是 cloud-provider-alibaba-cloud 项目的 Maintainer。

我们将从上图几个方面来分享如何不停机的迁移 Kubernetes 集群。首先我们会为大家介绍一下集群迁移的需求以及应用场景;接着我们会着重介绍如何实现不停机地 Kubernetes 集群迁移,包括如何进行迁移前的前置检查,如何做应用的数据迁移与流量迁移等等。

为什么要迁移 Kubernetes 集群?

下面简单介绍下集群迁移的应用场景。

容器化的应用迁云

首先我们来看一下容器化的应用迁移场景。近年来云原生理念已经逐渐深入到了各大公司中。据相关调查统计,将近有 65% 的应用已经实现了容器化,并逐步从线下的数据中心迁移到了云上,以便充分利用云的弹性来实现企业的降本增效。是否可以保证应用容器化迁移过程中的平稳切换,保证应用不停机迁移,成为影响用户业务云化的一个重要条件。

跨云同步与迁移

其次是混合云场景下的跨云流量迁移。对用户来讲,如果云是一个极具性价比的选择的话,那么混合云和多云的架构进一步为用户提供了一个低成本全球可达的应用发布平台。多云可以让用户的应用部署到多个云厂商,避免厂商锁定。同时它能够提供更高的议价能力、更强的备份、灾难恢复能力和更强的稳定性。同时还可以为全球用户提供基于地理位置的就近服务体验。如何进行不停机跨云同步机迁移是部署跨云/多云应用的前提。

集群新特性与 BreakingChange 场景

更高的 Kubernetes 版本往往会具有更多的新特性,但是使用这些新特性并不是没有代价的。如果你需要使用新特性,那就必须升级 Kubernetes 到对应的新版本。这通常不是一件容易的事情。如果你的集群版本太低,那么你需要多次升级集群才能到达预期的版本。比如从 1.14 依次升级到 1.16,然后是 1.18,然后才是 1.20,这样来避免单次升级集群版本过大造成的兼容性问题。并且这些新特性所引入的兼容性问题还可能造成服务中断。

除了升级困难以及版本兼容性问题,升级已有集群无法实现一些配置变更类的需求。比如你无法直接变更一个已有集群的网络模式,比如从 IPTables 切换到 IPVS,Flannel 到 Terway,更改 Cluster CIDR 等。这些变更会造成整个集群已有节点及 Pod 的重建,造成服务不可用,甚至是整个集群配置被污染。因此不停止迁移 Kubernetes 集群应用在这种情况下可能是一个更好的选择。

接下来我们介绍一下如何进行不停机迁移。不停机迁移总体上分为 3 个阶段。

第一阶段:前置检查,提前暴露迁移可能存在的潜在风险;第二阶段是应用迁移,这一阶段需要新建一个目标版本的集群,并将应用及其数据迁移到新的集群中;第三阶段是流量迁移,这一阶段至关重要,他决定了如何不停机地将线上流量导入到新建的集群中,并使用新建的集群为用户提供服务。

首先在前置检查阶段,我们需要尽早的暴露迁移风险,因此我们开发了一套前置检查框架,用来检查集群是否做好了迁移准备。比如不同版本的集群会有 API groups 兼容性,需要提前处理 Label 的兼容性,不同版本的组件的行为差异等,如 kubeproxy 处理 SLB 流量转发的行为差异,会直接影响流量迁移的成功。因此前置检查是一项非常重要的步骤。

前置检查项都通过后,接下来就是应用的迁移与流量迁移。

应用的迁移可以通过开源组件 Velero 进行,官方有详细的文档来说明应用的迁移,阿里云也专门为其提交了阿里云相关驱动。这里我们主要介绍一下如何做数据迁移,数据迁移是实现不停机迁移的重要一环,我们会以磁盘存储和有状态应用 MySQL/ETCD 的迁移为例,来说明如何进行数据的迁移。

通常云上的存储主要有 NFS、OSS 对象存储、CloudDisk 云盘等,通常各大云厂商都为磁盘类型的存储提供了完善的快照方法及恢复方法。上图展示了如何将上海 Region 的应用数据迁移到杭州 Region 的方法,对于磁盘存储类型,首先在上海 Region 构建磁盘快照,然后将快照通过云厂商的网络同步到待恢复的地域杭州,然后通过快照恢复功能创建一块磁盘,然后挂在到节点上后应用即可随时使用。

对于自建 MySQL/ ETCD 一类的应用数据,由于其持续读写可能造成潜在的数据不一致的情况,我们可以通过为该应用在目标 Region 构建多个 Slave 副本(或者 quorum 副本),用来进行实时数据同步,当流量低峰期到来的时候,执行主从切换,或者强制选主流程。一旦目标 Region 选主完成,则代表切换完成,可以逐步下线原 Region 的 MySQL 或 ETCD 副本。这就是一个简单的数据迁移流程。

接下来介绍一下流量迁移部分。流量迁移是集群迁移中十分重要的环节。流量迁移是指在业务流量无中断的前提下,将业务流量从一个集群迁移到另一个集群中去。客户端对流量迁移应当完全无感。

DNS 是实现无损流量迁移的一种方式。分别在两个集群中创建两个 LoadBalancer 类型 Service,然后将两个 SLB 添加到 DNS 后端,基于 DNS 的灰度能力实现流量分发到两个不同的集群中。这种方式较为简单,但是有一个比较大的缺陷,DNS 缓存有过期时间,流量切换后需要等待 30 分钟左右才能生效。当在新集群中进行业务回滚时,这个延迟不可接受的。

另外一种流量迁移方式是基于 Istio 实现的。Istio 方式比较复杂,学习成本比较高。需要新建一个 Istio 集群,并且更改已有的应用部署方式,然后基于 Istio 的灰度能力进行流量迁移。

那么有没有一种方式,操作简单又可以实现实时无损流量迁移呢?

如何在零停机的情况下迁移 Kubernetes 集群

为了解决这个问题,我们还得从服务暴露方式入手。LoadBalancer 类型的 Service 实际是通过云上负载均衡器对外部暴露服务的。负载均衡器是由各云服务提供商通过部署在集群中的 controller 创建的,创建出来的负载均衡器的信息会显示在 Service 的 status.loadBalancer 字段中。请求访问云上负载均衡器时,由各云厂商负责将流量重定向到后端 Pod 上。

Cloud Controller Manager(CCM)就是阿里云容器服务部署在 Kubernetes 集群中的 controller,负责对接 Kubernetes 资源及云上基础产品,如 SLB、VPC、DNS 等。对于 SLB,CCM 支持两种流量转发方式,一种是 ECS 模式,一种是 ENI 模式。ECS 模式将 Node IP 和 NodePort 挂载到 SLB 后端,流量经由 SLB 转向 Node,然后经过节点的 kube-proxy 转发至 Pod 上。ENI 模式将 PodIP 及 TargetPort 挂载到 SLB 后端,流量经由 SLB 直接转发到 Pod 上。与 ECS 模式相比,ENI 模式少了一层网络转发,网络性能更好。流量转发模式与 Kubernetes 中网络插件有关,Flannel 网络插件默认为 ECS 模式,Terway 网络插件默认为 ENI 模式。

那么 CCM 是如何管理 SLB 的呢?

对于 LoadBalancer 类型的 Service,CCM 会为该 Service 创建或配置阿里云负载均衡 SLB。CCM 首先会查询 Kubernetes Service 信息,构建 Local model,然后查询 SLB 信息,构建 Remote model。对比两个 model 的差别,根据 Local model 更新 Remote model,直到两个 model 一致。当 Service 对应的 Endpoint 或者集群节点发生变化时,CCM 会自动更新 SLB 的虚拟服务器组中的后端。此外,CCM 还提供了许多阿里云特定注解,支持丰富的负载均衡能力。

当用户访问 service 时,如果在集群内部,经由 service 转发至 Node,经过 kube-proxy 转发到 Pod。如果访问负载均衡 ip 时,则通过 SLB 后转发至节点 Node 或者 Pod上。

了解 LoadBalancer service 工作原理后,能不能通过 CCM 实现实时无损流量迁移呢?答案是可以的。将两个集群的节点加入到同一个 SLB 的同一个端口中,然后通过修改两个集群所占权重即可实现流量迁移。对于客户端来讲,访问的仍然是以前的 SLB ip 和 port,完全无感。

具体操作如下:首先在 1.14 集群中创建一个 Service,指定已有 SLB 及端口,以及端口关联的虚拟服务器组。然后在 1.20 集群中创建一个 Service,指定同样的 SLB、端口及虚拟服务器组。通过 weight annotation 为两个集群设置权重。

配置完成后,流量转发方式如上图所示。有 80% 的流量转发到 1.14 集群中,20% 的流量转发到 1.20 集群中。

两个集群共用 SLB 的同一个端口。通过修改 Service 中的 weight annotation 可以动态实时修改流向两个集群的流量比例,实现灰度流量迁移。当迁移完成后,从 1.14 集群中删除 Service 即可。

设置权重 annotation 后,如何保证集群内 Pod 负载均衡呢?

对于 externalTrafficPolicy 为 Cluster 的 service,CCM 会将所有节点加入到 SLB 后端。每个节点的权重为 weight/NodeNum。此时,Node1,Node2,Node3 权重均为 27,但是三个节点上的 Pod 数量并不均衡,那么如何实现 Pod 负载均衡呢?Cluster 模式是依赖 kube-proxy 实现的。在 cluster 模式下,kube-proxy 会将所有 Pod 信息写入到本地的转发规则中,并以轮训的方式向这些 Pod 转发请求。以 Node3 为例,该节点上没有 Pod,当请求发送到 Node3 节点后,kube-proxy 会将请求转发给 Node1 或者 Node2。

对于 externalTrafficPolicy 为 Local 的 service,CCM 仅会将 Pod 所在节点加入到 SLB 后端。因为如果节点没有 Pod,当请求转发至该节点时,请求会被直接丢弃。Local 模式下,需要先计算每个 Pod 的权重,即 PerPodWeight=Weight/TotalPodNum。节点权重为 NodePodNum*PerPodWeight。Node1 为 50,Node2 为 30。由于每个 Pod 的权重都为 10,因此 Pod 间可以实现负载均衡。

基于 CCM 的流量迁移方案不仅适用于云上集群迁移,还适用于混合云、跨 Region 迁移及跨云迁移场景。以混合云场景为例,客户可以将线下 ECS 加入到 SLB 后端,然后通过设置权重逐步将流量从线下集群迁移到线上集群中,无需进行业务改造,客户端也是完全无感的。

在新集群中测试时不可避免的会遇到应用更新的场景。如果保证应用更新的过程中流量无损呢?

应用更新分为两个步骤,创建新的 Pod,等待 Pod running 后,删除旧的 Pod。新的 Pod 创建成功后,CCM 会将其挂在到 SLB 后端,如果新建的 Pod 无法提供服务,那么请求就会失败。因此,需要为 Pod 添加就绪检测。仅当 Pod 可以对外服务时,才将其加入到 SLB 后端。在删除 Pod 时也会遇到同样的场景。因为 Pod 删除和从 SLB 后端移除 Pod 是异步进行的,如果 Pod 以及删除,但是还未从 SLB 后端移除,就会出现请求转发到后端,但是无 Pod 处理导致请求失败的情况。因此需要为 Pod 添加 prestop hook。

Pod 优雅退出过程如上图所示。首先 kubelet delete pod,然后 endpoint controller 更新 endpoint。更新完毕后,kube-proxy 移除节点转发规则。CCM 检测到 endpoint 更新事件后,从 SLB 后端移除 Pod。在apiserver 删除 Pod 时,kubelet 同时开始删除 Pod 逻辑,触发 Pod prestop。在 prestop 结束后发送 sigterm 信息。在整个 Pod 优雅退出过程中,直到 CCM 从 SLB 后端移除 Pod 之前一直会有新的流量进入。

由于 CCM 与 kube-proxy 是异步进行的,因此会出现 SLB 还未移除 Pod,kubeproxy 已经将节点转发规则清理的情况。此时,请求进入 SLB 后,转发至 Node上,由于 kube-proxy 已经将路由规则清理了,所以该请求无法处理。将 service 改为 cluster 模式可以解决这一问题。如果 Service 一定需要为 local 模式,那么需要保证一个节点上有多个 Pod。也可以通过设置 Service 为 eni 模式解决这一问题。

总结来说,集群迁移可以分为如下三个步骤,前置检查、应用迁移及流量迁移三个步骤。前置检查需要检查不同集群间 api/Node label 等兼容性,应用迁移可以使用开源工具进行,基于 CCM 则可以实现实时无损流量迁移。

原文链接

本文为阿里云原创内容,未经允许不得转载。

如何在零停机的情况下迁移 Kubernetes 集群的更多相关文章

  1. Velero:备份、迁移Kubernetes集群资源和PV

    Velero基本介绍 官方文档:https://velero.io/docs/v1.4/ 基本工作原理: 不管需求是实现什么,比如:集群迁移.恢复.备份,其核心都是通过velero client CL ...

  2. Ubuntu下搭建Kubernetes集群(4)--部署K8S Dashboard

    K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它. 首先我们执行命令: wg ...

  3. Ubuntu下搭建Kubernetes集群(3)--k8s部署

    1. 关闭swap并关闭防火墙 首先,我们需要先关闭swap和防火墙,否则在安装Kubernetes时会导致不成功: # 临时关闭 swapoff -a # 编辑/etc/fstab,注释掉包含swa ...

  4. kubernetes系列—Ubuntu下搭建Kubernetes集群--k8s部署

    1.kubernetes安装介绍 1.1 K8S架构图 1.2 K8S搭建安装示意图 2.安装kubernetes 2.1  关闭防火墙 在每台机器上关闭防火墙: ① 关闭服务,并设为开机不自启 $ ...

  5. Ubuntu 16.04下搭建kubernetes集群环境

    简介 目前Kubernetes为Ubuntu提供的kube-up脚本,不支持15.10以及16.04这两个使用systemd作为init系统的版本. 这里详细介绍一下如何以非Docker方式在Ubun ...

  6. Ubuntu下搭建Kubernetes集群(2)--docker基本操作

    查看当前的容器和images docker ps -a docker images 1.创建新的容器 docker run -it --name 容器名 镜像名 /bin/bash # 挂载目录和端口 ...

  7. Ubuntu下搭建Kubernetes集群(1)--安装docker

    可以使用物理机,也可以使用虚拟机. 首先参考https://docs.docker.com/install/linux/docker-ce/ubuntu/ 官方文档学会安装docker. 1.首先移除 ...

  8. Ubuntu 16.04下Redis Cluster集群搭建(官方原始方案)

    前提:先安装好Redis,参考:http://www.cnblogs.com/EasonJim/p/7599941.html 说明:Redis Cluster集群模式可以做到动态增加节点和下线节点,使 ...

  9. centos6下redis cluster集群部署过程

    一般来说,redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口,比如:slaveof 192.168.10.10 6379,然后启动主从,主从 ...

  10. 在 TKE 中使用 Velero 迁移复制集群资源

    概述 Velero(以前称为Heptio Ark)是一个开源工具,可以安全地备份和还原,执行灾难恢复以及迁移 Kubernetes 群集资源和持久卷,可以在 TKE 集群或自建 Kubernetes ...

随机推荐

  1. 引领汽车营销新趋势,3DCAT实时云渲染助力汽车三维可视化

    当前,汽车产业发展正从电动化的上半场,向智能化的下半场迈进.除了车机技术体验的智能化之外,观车体验的智能化也不容忽视. 这是因为,随着数字化.智能化.个性化的趋势,消费者对汽车的需求和期待也越来越高, ...

  2. 大场景的倾斜摄影三维模型OBJ格式轻量化处理处理关键处理技术分析

    大场景的倾斜摄影三维模型OBJ格式轻量化处理处理关键处理技术分析 大场景的倾斜摄影三维模型是指通过航空或地面摄影获取的大范围.高分辨率的地理环境数据.为了在虚拟环境中加载和渲染这些模型,需要对其进行O ...

  3. openlayers操作分享:如何从容的在vue中食用openlayers6

    这篇文章,分享下我对openlayers的一些经验和理解,会夹杂大量搜索出来得文档,是我正式使用时可以实现的,废话不多说,我们从下载开始 一,openlayers安装且初始化地图 创建vue项目就省略 ...

  4. Vue子组件向父组件传值(this.$emit()方法)

    子组件使用this.$emit()向父组件传值 首先必须在父组件中引用子组件,然后实现传值 第一步在父组件中引入子组件 import UnitByPurchaseAddOrUpdate from '@ ...

  5. CSP:Object as Point同会议论文,相似思想用于人脸和行人检测 | CVPR 2019

    CSP将目标定义为中心点和尺寸,通过网络直接预测目标的中心和寸尺,相对于传统的RCNN类型检测算法轻量化了不少.整体思想与Object as Points撞车了,真是英雄所见略同   来源:晓飞的算法 ...

  6. KingbaseES V8R6 表空间加密

    透明存储加密优势 透明存储加密可确保加密敏感数据满足合规性要求,并提供简化加密操作的功能,优势如下: 作为安全管理员,您可以确保敏感数据已加密,因此在存储介质或数据文件被盗或入侵者试图从操作系统访问数 ...

  7. KingbaseES V8R6 运维案例 -- sys_filenode.map故障案例

    ​ 案例说明: 数据库下的sys_filenode.map文件被破坏,导致此数据库无法连接访问. Nail表(内核系统表)Relfilenode的存储机制: 经过研究发现,在数据目录里存在着pg_fi ...

  8. KingbaseES V8R6运维案例之---pg_statistic toast表故障修复

    ​ 案例说明: 数据库在日常的维护过程中,执行表结构查询语句(\d t1),如下图所示,出现"missing chunk number 0 for toast value 16259 in ...

  9. JVM—运行时数据区

    JVM-运行时数据区 运行时数据区概述 JVM运行时数据区如下图: 整个JVM构成里面,主要由三部分组成:类加载系统.运行时数据区.执行引擎. 按照线程使用情况和职责分成两大类: 线程独享(程序执行区 ...

  10. Go 语言中 For 循环:语法、使用方法和实例教程

    for循环用于多次执行特定的代码块,每次都可以使用不同的值.每次循环执行都称为一次迭代.for循环可以包含最多三个语句: 语法 for 语句1; 语句2; 语句3 { // 每次迭代要执行的代码 } ...