云原生大爆发,Day2运营与K8s集群生命周期的交织

嘉宾丨郭至为  整理丨张雪蕊

出品丨CSDN云原生

Wojciech Urbański指出,在当今的专业IT媒体中有一个非常突出的话题,那就是在软件生命周期中的“第0天/第1天/第2天”。

2022年3月12日在CSDN云原生meetup长沙站直播中,中国移动金融科技公司云团队的郭至为关于生产化集群的Day2运营思考做出了分享。

Day2运营的意义

Day2来源于云时代软件生命周期中的概念,指软件或应用系统在上线、服务于生产以后不断的优化、运营,一直到生命周期终结的一长段时间。下图引用于Jimmysong老师博文的一张图片,Day2并不特指某一天,运营的过程包括了系统上线一直到系统终结的整个生命周期。

云原生大爆发,Day2运营与K8s集群生命周期的交织_第1张图片

在IT领域,从最左边Day0,指应用系统从需求到架构到设计的阶段,还只是停留在纸面;到Day1阶段是开发,部署以及配置应用系统,还包括一些基础设施、外部服务等;到Day2是系统上线提供给客户的时间阶段,这个阶段更多精力放在维护监控、优化系统上,最关键的是分析系统的行为并作出反应。这个周期会一直持续到整个系统生命周期的终结。

K8s平台的生产化

结合上文提到的Day2概念,K8s平台生产化指K8s集群从生产就绪一直到生命周期结束的整个时间。随着技术生态的快速发展,云原生已经进入了大爆发的时期,主要的开源项目已经进入了成熟阶段,这大幅降低了企业应用这些系统的门槛。得益于K8s的优秀设计,极大的降低了开发者对于庞大复杂的技术生态的心智负担,甚至通过几条简单的指令,就可以在10分钟之内搭建起一套生产就绪的K8s集群。

然而Day2的运营还有非常多的工作要做,比如围绕K8s集群搭建pass平台。K8s核心的功能是容器的编排,并且提供了非常丰富的扩展接口,比如传说中的三大件计算存储网络csi、cri、cni,以及cpi(provider),甚至目前比较火的Service Mesh技术,也有相应类似的通用接口(SMI);还有device plugin等接口,可以通过web hook扩展K8s的认证机制;以及admission control准入控制,可以通过调度框架扩展K8s调度器;甚至还有极其灵活的operator的框架扩展能力,更进一步还可以通过API聚合层实现自定义的API向K8s暴露。

由于接口和插件模型的广泛采纳,原来K8s里核心的功能逐渐被移除到out of tree项目,与核心的项目代码解耦,而pass平台却越来越依赖于扩展插件的能力构建平台级的服务。构建了基本的pass平台之后就到了服务于业务系统,上生产的阶段。相当多的K8s用户,处于刚上生产不久的初级阶段,后续还需要借助社区力量和自身团队的不断努力加强pass平台的建设。

在构建pass平台和强化pass平台的整个过程中,需要跟开发团队不断的密切协作。对平台的功能迭代,类似于软件工程中的DevOps过程,经历无数个功能,从需求到设计到开发到测试到上线到运维的生命周期的闭环。

基础设施运营中的思考

集群环境及节点规划

云原生大爆发,Day2运营与K8s集群生命周期的交织_第2张图片

上图从纵向来看,是根据组织架构的要求以及业务形态,把集群分成不同的环境。不同的环境意味着不同的SLA和SLO,比如poc环境、开发&测试环境、预发布环境和生产环境。poc环境着重于基础设施功能的提供,以及新的feature的应用测试;开发测试、预发布和生产环境,是业务系统的运行环境,从开发测试到预发布到生产的不同的阶段。在有一些环境集群数量比较少的情况,可以用命名空间来区分这4种环境,或者若干个环境,当然也可以用不同的物理集群直接进行隔离。

从横向来看,会有不同规格的节点组成不同的节点池。首先基于特性的节点池,有CPU性能型节点、内存密集型节点或者异构硬件,如GPU,或者FPGA芯片等。还有一些基于角色的节点,按角色的功能定位来划分,如基于网络规划的要求,会有ingress和egress节点,作为集群网络南北向出入口节点专门运行网关。这样的好处就是网络规划方便,更便于维护监管。

这样一交叉就形成了多种组合形式。首先单集群多节点池,这种组合形式相当于一个集群里面有5种节点。这样的形式优点是减少了多集群管理的负担,缺点有三点:

  • 第一,工作负载需要添加node selector,开发团队必须知道底层的硬件规划。

  • 第二,节点需要加上污点属性以及工作负载需要附加相应的容忍度,才能调度到对应的节点上。

  • 第三,节点扩容或者缩容时,要单独进行规划。

还有一种多节点多集群的方案,需要在K8s之上添加集群管理层,大多数商用的K8s方案都有所支持,如果有基于特性节点的需求,可以考虑用单独集群来实现,并纳入多集群的管理。

大集群的优势是资源利用率更高,满足部署更少的集群以及简单的集群管理的要求;小集群的优势是更小的故障域,更好的租户隔离以及灵活性,没有大集群管理平面的优化的问题,比如说集群的规模到达几百个以上,可能控制平面的压力是非常大的,小集群更便于集群升级。

控制面的部署形式

云原生大爆发,Day2运营与K8s集群生命周期的交织_第3张图片

上图是K8s官方的高可用部署架构图。其中worker node的请求从load balancer负载均衡进来,把控制面的调用分布到不同的API server,每个节点分别有controller-manager和scheduler,下面的etcd集群是单独的集群。

控制面的部署形式,首先要考虑几个点。

  • etcd的部署形式

    基于网络的考量,默认的etcd在单数据中心内,必须要求比较低的相互通信的延迟。跨数据中心分布式部署则需要测试etcd member之间的延迟,调整心跳间隔以及选举的超时参数,一般不推荐跨地区部署etcd集群。etcd还有单独部署和控制平面共置两种方式,比如三个控制节点,每个控制节点其实都有一个etcd实例,但是当集群规模变大,就需要考虑单独把etcd集群挪出来,单独的机器跑etcd,并且要考虑配备单独的高速SSD存储以及低延迟的网卡。

  • K8s控制面的部署形式

    K8s控制面有很多组件,包括apiserver、controller-manager、scheduler,甚至共置部署的时候还有etcd,如果是容器化部署,由kubelet通过static pod管理。推荐通过自定义kubeadn配置文件的方式控制自定义集群的引导参数和配置,避免直接修改static pod。

  • APIServer的负载均衡

    传统的方式部署要单独有load balance的实例,或者是把load balance用keepa live结合ha proxy运行在控制节点上面。但这种情况会有load balance的压力过大的问题,跟业务的负载均衡要分离,K8s控制平面的负载均衡要单独部署;另外可能存在单点的问题,当然可以从keepalive用VIP的形式来实现高可用,但终究它只有少数的负载均衡实力来承载流量。还可以考虑用客户端负载均衡的方式,比如在worker node节点上面跑lvs把控制面的流量以及上报的心跳消息,通过客户端负载均衡分布到不同的控制节点的APIServer上。

  • Add-ons的部署形式

    集群的附加组件属于集群部署,包括网络插件、CSI等等,跟核心组件一起构成了整个的部署,需要将其与集群本身一起版本化管理,为集群保证一致性。有两种部署的方式,第一种通过CI/CD工具,不同于直接提交到git触发webhook流水线更新版本,创建新集群是直接触发Add-ons的部署;第二种就是operater的方式。

集群管理

K8s原生的管理能力停留在单集群的方案,每一个集群可以稳定的自治运行,但是缺乏贯穿于多个集群之间生命周期的管理能力。这对公共云厂商来说已经不存在太多的问题,比如阿里、华为,可以一键运行出一个K8s集群,实现多集群的管理。但是对于私有云部署的这种场景要特别设计。

社区有一个项目叫Cluster API,Cluster API提供了一系列的operater分别控制对应K8s集群的crd,以此来声明式的控制k8s集群及组件的生命周期。一般将Cluster API部署到专门的管理集群,用来管理其他的K8s集群,当然这个模式有一定的缺陷。

下图部署了两种Cluster API。管理集群的Cluster API是管理一个集群的生命周期,比如调用基础设施的控制平面启停某一个集群。单个工作集群自身也有个Cluster API,对接基础设施控制平面,主要服务于Cluster的Autoscaler,是集群自动扩缩容的控制器,控制集群节点数量的增删。这个过程就实现了从管理集群的Cluster API控制新集群的创建、更新、升级和删除。各自工作集群的Cluster API控制自己本身集群节点的缩扩容,这样就完成了针对集群的自动化控制,以及其生命周期的完整的管理。

云原生大爆发,Day2运营与K8s集群生命周期的交织_第4张图片

维护和升级

K8s社区版本的更迭非常快,我们应该怎样做升级和维护?

  • 平台版本化

给平台定义版本并文档记录下所有软件的版本号,包括操作系统以及所有安装的软件版本、容器运行时的版本、K8s组件的版本、平台附加组件的版本。用语义化版本单独定义平台版本号,与K8s的版本号区分开,这样针对上层的业务和应用,就有集中化版本控制的逻辑。

  • 备份

K8s本身有状态的部分都是在etcd里,所有的API resource都保存在etcd,因此可以考虑定时的备份快照,或者通过velero备份。直接通过API资源的方式备份,可以做到更高的精细度,还有非常多备份的逻辑及恢复的逻辑。

  • 集成测试

Sonobuoy提供了平台一致性测试的能力。通常在集群上线之后、业务系统入驻之前进行测试,以保证平台的功能特性满足期望。

  • 升级策略

升级的策略有三种:集群替换,节点替换,原地升级。集群替换的方式可以在老集群一直跑生产业务的同时部署一个新的集群,在这个时间窗口内,新的集群里部署起原来的业务通过负载均衡的方式把入口流量切换到新集群,这种方式成本最高,风险最低且可以回退。但这种方式有两个问题,首先是要全局的负载均衡,其次是持久化的存储区,因为老新两个集群都需要访问后端存储。节点替换,需要集群规模较大,并且对集群兼容性有全面的认知。原地升级,在生产环境上有一个比较大的问题就是极难回退,一旦开始会出现API难跟踪的情况。

高可用的镜像仓库

当有了完整的集群后,要考虑高可用的镜像仓库的问题。因为生产环境实际上可能有上百台机器,镜像如果都从公网上拉,出口带宽是绷不住的。而且相当多的生产环境,镜像要保存在本地,直接跟外网隔离限制入口,必须要考虑高可用的技能仓库的问题。

首先是镜像仓库组建高可用的问题。harbor本身有状态的部分都放在了关系型数据库,PostgreSQL,这是它默认的数据库,还有redis集群存放部分状态数据。harbor会共享底层的分布式对象存储,单个harbor集群可以通过k8s控制器来维护它的高可用状态。

当要建立多个harbor集群的时候,就要考虑多数据中心仓库之间同步的问题。harbor集群本身提供了同步复制的一些策略,包括推送和拉取的方式,甚至可以支持三种不同的触发方式,手动触发、定时触发及事件触发。

其次要考虑镜像安全扫描的问题。因为很多基础镜像来自于公网,有一些是开源社区来维护的,里面有可能会有些恶意代码,所以要用到一些扫描器,尽可能减少安全风险。

最后是镜像加速的问题,当集群规模或业务数量大到一定程度时,持续部署一个应用的时候,可能一瞬间就要部署到上百个pod。如果这时这个镜像是重新构建,在worker node的节点上面没有这个镜像的话,并发的下载镜像的动作就会给镜像仓库一个巨大的并发压力。可以考虑用一些社区开源的镜像加速,以P2P技术为依托的镜像加速的工具。比如阿里的开源dragonfly,还有 Uber的Kraken,这两种P2P镜像加速的工具都可以比较好的跟harbor做集成。

多租户

Kubernetes对多租户提供有限支持。小一点的集群会考虑用命名空间做租户隔离,通过Kubernetes的命名空间可以达到对用户做隔离、为用户分配配额、为资源定制访问策略、部署相似的应用或单个应用的不同版本的目的。但是当业务复杂后,集群规模越来越大,用命名空间做租户隔离或者定义租户的这种方式就不合适了。

如下图所示,左下一个租户,运行一个service和一个deployment。deployment有三个副本,有一堆的ConfigMap挂载进来。到集群规模变大以后,可能多个租户要共用一个命名空间,就带来了极大的管理成本。多租户的时候,命名空间跑了各种各样异构的应用以后,权限控制、配额控制、版本滚动更新、灰布控制,都会成为问题。

云原生大爆发,Day2运营与K8s集群生命周期的交织_第5张图片

服务路由

有了企业生产化集群的基础设施,就要考虑业务系统入驻。业务系统入驻首先要考虑的就是服务路由的问题。容器网络只处理了pod之间的底层流量转发,服务路由提供了更高层的连接机制。东西向的service提供了将一系列pod(deployment)组合成网络服务的机制,能提供负载均衡的流量转发能力,并支持应用的服务发现。南北向三四层的暴露机制(Load balancer)供集群外客户端访问。南北向的Ingress在集群内提供了一个服务流量的入口点,负责七层的负载均衡能力。结合了东西向和南北向的Service Mesh服务网格,提供了高级路由、安全、可观测性等功能,同时提供东西向和南北向的服务路由功能。在网格中的工作负载被服务代理劫持流量并转发,而实现服务路由的功能。

有了上述南北向的load balancer和7层的负载均衡以后,是否要考虑上Service Mesh?服务网格在原本比较复杂的K8s基础上增加了整个系统复杂性,所以建议刚刚使用K8s作为生产系统的厂商,未明确需求不要贸然使用,应该逐步的将应用微服务化,并从ingress开始,根据需求逐步进行架构演进。

使用服务网格需要考虑的因素:

  • 首先,从最急需的功能着手,专注于服务网格的单方面的功能开始用,再逐渐的扩展开应用需求首先,从最急需的功能着手,专注于服务网格的单方面的功能开始用,再逐渐的扩展开应用需求。

  • 第二,尽量在新集群部署服务网格。如果必须在原有的集群部署,那就要做好完整的业务端到端的测试。

  • 第三,服务网格本身也有升级的问题,需要同时考虑控制面和数据面。

  • 第四,服务网格会带来一些资源的损耗,尤其是在sidecar的模式下面会带来一些资源损耗,另外还会提高服务链调用的延迟。

  • 第五,证书授权和mTLS。

在Kubernetes中,使用load balancer类型的服务,将后端的工作负载暴露在外部,是一个常见的方式。云厂商尤其是公共云厂商,提供了云上的load balancer,有的是通过sdn的方式来实现的,有的是通过自己的基础设施来实现的。但是对于裸机部署方式来说是比较困难的,因为很多集群环境是没有sdn的,尤其是在裸金属或者边缘的方案中,K8s本身并不提供load balancer方案。传统的负载均衡的厂商往往提供K8s控制器来向LB硬件设备发布load balancer的服务,下图是比较典型的逻辑示意图。

云原生大爆发,Day2运营与K8s集群生命周期的交织_第6张图片

以上是郭至为对于生产化集群的Day2运营思考和对基础设施运营的理解分享,生产化集群基础设施的整个运营的思路,要和软件工程的思路结合起来,不断的优化,不断的迭代,不断的投入工程力量去优化整个系统。

云原生志愿者计划正在招募 

精准把握技术趋势,深度学习新技术、新实践

云原生大爆发,Day2运营与K8s集群生命周期的交织_第7张图片

扫描图片二维码立即申请加入

你可能感兴趣的:(云原生,运维)