《Redis Cluster Operator容器化技术方案.docx》由会员分享,可在线阅读,更多相关《Redis Cluster Operator容器化技术方案.docx(9页珍藏版)》请在第一文库网上搜索。
1、RedisC1usterOperator容器化方案AA【导读】对于RediSC1USter的容器化,民生银行已做了先期的探索和使用,但是,在RediSPaaS使用过程中,出现了一些问题,本文对此进行分析,并讨论使用OPeratOr的解决方案,希望能为同行进行RediSC1uster容器化提供参考。对于RedisC1uster的容器化,我行已在RedisPaas中做了先期的探索和使用。在RediSPaaS中实现了RediS哨兵模式、集群模式的容器化部署,结合IPAAS使得项目可依据自身需要自助申请并实时交付。但是,在RediSPaaS使用过程中,出现了RedisCIUSter主从POd被调度在同
2、一节点,RedisMaster节点所在的容器发生重启导致数据丢失的问题,而且在功能上难以支持RediS集群扩缩容、主从节点差异化配置、定时持久化等需求。本文针对RediSC1uster容器化遇到的问题进行分析,并讨论使用Operator的解决方案。RedisC1uster主从分布RedisC1USter从节点除了分担主节点的读压力,也是RediS高可用性重要的一部分。RediS作为一个内存数据库,为了保证高性能不会实时将数据刷盘进行持久化存储,所以RediS节点宕机可能会造成数据丢失。在集群模式中,分片中的从节点不仅可以分担主节点的读压力,而且也具有保证数据完整性的重要作用。所以在容器化部署时
3、,同一分片的主从节点Pod不能调度在同一K8S节点,防止由于K8S节点宕机分片整体下线导致数据丢失。Kubernets中可以使用Pod反亲和性配置,将同一类型的Pod分散在不同的节点。下面yam1配置定义所有符合Redis标签的Pod以软反亲和性的方式分布部署在不同的节点上。Imatch1abeIS:IRED1S_POD_1ABE1:RED1S_POD_VA武先期ReC1iSPaaS中,同一项目的所有RediSPoC1由一个StatefU1Set管理,对同一StatefU1Set中所有POd配置反亲和性。在实际使用中发现,这种配置方法在项目RediSPod比较多或者容器平台节点比较少的情景下,
4、会出现同一分片的主从POd被调度在同一主机节点的情况。在RediSC1usterOPeratOr的设计中,将每一个RediSC1USter每个分片部署成一个StatefUISet并在Statefu1set内配置POd反亲和性,这种部署方法能很好的保证RediSC1uster分片主从POd处于不同节点。RedisMaSter容器快重启在容器环境中部署的RediSC1uster,数据丢失除了可能发生在主从节点同时下线的情况外,还存在另外一种情景。RedisC1uster中,Master节点下线必须经过c1uster-node-timeout时间才会启动fai1over机制。在容器环境中,如果主节点
5、所在的容器由于某种原因被杀死,再被KUberneteS自动拉起,这个时间非常短暂以至于集群不会启动fai1over流程。但在这种情况下,RediS进程下线又上线原先内存中的数据会被全部清空,S1ave节点不执行fai1over流程继续同步Master会导致整个分片数据丢失。该种情况某种意义上可以看作是Kubernetes的高可用机制和RediSCIUSter的发生了冲突。在设计OPerator方案时,为避免类似情况的发生,我们需要明确KUbernetes、OPerator和RediS在整个方案中的作用,划定KuberentesOperator和RedisC1uster的功能边界:1. KUbe
6、rneteS和OPeratOr不去介入RediSC1USter的高可用机制,若有冲突以RediSCIUSter的为准2. Redis容器启动和ReCIiS进程启动相分离,KUberneteS只负责为RediS分配资源,Operator监听Redis容器启动情况并在合适的时机启动RediS进程,将RediS加入集群在先前RediSPaaS中,RediS进程随容器启动而启动,RediS进程自动读取本地nodes,conf文件重新回到集群。在OPeratOr中,需要监听RediS容器启动,对节点加入集群的时机做把控: Case1:分片中有MaSter节点,则启动容器RediS进程加入集群 Case2
7、:分片中无MaSter节点,但有SIaVe节点,则等待RediS高可用机制提升S1ave为Master,然后依Case1操作 Case3:分片中没有节点。该种情况下,为保持集群的完整性,可以待所有分片包含的容器启动后,根据各容器持久化的nodes,conf文件,选出CIUSterepoch最大的首先启动其RediS进程,然后其余RediS进程依照前两种情况启动前两种情况可以保证RediS的数据安全,第三种情况由于分片全部下线,若没有在退出时对数据进行持久化保存则无法保证数据完整。除此之外,还有一种极坏的情况RedisCIUSter中存活的MaSter不足一半,此时RediSC1uster的fa
8、i1over机制已无法正常运行。此种情况可参照上述第三种情况处理,在该种情况下可能需要执行C1USterfai1overtakeover命令才能使集群恢复正常,OPeratOr不做高危险操作,此时由运维人员手工介入处理。容器化环境不同于物理环境或者虚拟机环境,容器环境的容器IP不固定,而且容器平台使用。VerIay网络,网络IP对集群外不可见。在这种情景下,若应用与RediS同集群部署,可以使用为RediSCIUSter建立的SerViCe来访问,但是如果有集群外访问的需求,该种方式则不能满足。对此,需要为每个单独的RedisPod建立NOdePOrt型的SerViCe,并且在RediS中增加
9、如下配置:kdusnnounc3REDIERC0DEP0RTc1uster-announce-ipRedisC1usterOperatorOperator的核心是CRD(CUStomReSOUrCeDefinitiOn)和自定义ControI1ero在项目中,我们使用KUbebUiIder进行RediSCIUSterOPerator开发,项目整体结构如下所示:底层使用KUbebUi1der生成的OPeratOr框架,根据资源定义生成CRD模板、并且完成与容器集群交互、监听资源变动等功能。左边RediSC1USter资源定义部分根据需求定义资源实体右边为ControIIer部分,对资源实例进行解
10、析和操作RedisC1usterCRD建立RediSCIUSterCRD资源,首先将RediSCIUSter的需求进行抽象,如下所示:ImasterSize:IC1usterRep1icas:2IexposeService:truimage:redis:6.0.4该SPeC描述了部署一个RediSCIUSter的基本需求,包含分片数、每个分片从副本数量、是否需要集群外访问、使用的RediS镜像版本和每个RediS节点的最大内存大小。然后,我们使用CRD将该需求定义扩展到KUbernetes,成为KUberneteS支持的资源:ipiVersion:apiextensions.k8s.iov1b
11、eta1kind:CustomResourceDefinition!metadata:Iname:redisc1usters.redis.C.Cn1Igroup:redis.Cmbc.COn1IVerSion:VInames:Ikind:RediSCIUSterIp1ura1:redisc】”。一ISingU1.ar:redisc1usterISCOPe:NamOCPQC。该yam1文件定义了KUberneteS支持的一个资源,资源的GroUP是,Versionv1a1pha1,KindRedisC1ustero接下来就可以使用如下yam1在Kubernetes中创建RedisC1uster资
12、源的实例:apiVersion:redis.CIT),cn/v1a1pha1kind:RedisC1usImetadata:Iname:demoredisc1usternamespace:redispec:RedisC1usterContro11er在Kubernetes中注册了种类为RedisC1uster的资源后,可以使用kubect1app1y/Create命令在容器集群中创建RediSCIUSter的实例。此时,容器集群仅仅做到了“认识”该资源,而对该资源的SPeC内容的解析和实际的管理需要开发Contro11eroOperator的理念是将专业领域知识注入Kuberneteso在Re
13、disC1usterOperator中,Contro11er通过协调操作Redis和Kubernetes完成Redis集群的创建和维持。如上图所示,ControIIer部分包含两层:1 .组件管理层。该部分使用RediS和KUberneteS客户端,分别完成对Redis集群的管理和对KUberrIeteS原生资源的操纵,并形成调用接口2 .在组件管理层上,根据不同的需求和资源状态,组合调用RediS和Kubernetes管理接口,实现功能需求Contro11er操作本质上是一个状态机操作,整体操作流程如下所示:对于一个三分片、每个分片一个S1aVe的RediSCIUSter需求,COntrOI1er按照下图部署集群并保持集群状态:1 .每个分片部署一个StatefUIset,并配置POd反亲和性,保证分片主从节点不被调度在同一主机上2 .使用Configmap为所有RedisPod注入配置文件3 .使用Secret保存Redis密码4 .为某个RediSC1USter建立一个CIUSterIP型的SerViCe,集群内通过Service访问5 .若有集群外访问需求,则为每个Pod建立NodePort型的SerViCe,集群外通过NodePort进行访问-全文完一