~kubctlvrsionClintVrsion:vrsion.Info{Major:"",Minor:"",GitVrsion:"v..4",GitCommit:"3cc4a8b44f03d0cdadf5a55d0aa",GitTStat:"clan",BuildDat:"0-08-T8:6:05Z",GoVrsion:"go.6.7",Compilr:"gc",Platform:"darwin/amd64"}SrvrVrsion:vrsion.Info{Major:"",Minor:"",GitVrsion:"v..4",GitCommit:"3cc4a8b44f03d0cdadf5a55d0aa",GitTStat:"clan",BuildDat:"0-08-T8:0:Z",GoVrsion:"go.6.7",Compilr:"gc",Platform:"linux/amd64"}
三从需求出发下面我们从一个实际的需求出发,来看看如何在k8s上部署Rdis服务。部署一个Rdis服务支持高可用提供统一的EndPoint访问地址部署单机版如果我们想在k8s上部署一个单机版本Rdis,我们执行下面的命令即可:~kubctlrundis--imag=dispod/discatd~kubctlgtpodsNAMEREADYSTATUSRESTARTSAGEdis/Running05s
可以用kubctlxc来进入到Pod内部连接Rdis执行命令:~kubctlxc-itdis--bashroot
dis:/data#dis-cli7.0.0.:pingPONG7.0.0.:那么Pod和Rdis是什么关系呢?这里的Rdis其实是一个Dockr进程启动的服务,但是在k8s中,它叫Pod。Pod与Dploymnt我们来讲下第一个k8s的概念Pod,Pod是k8s中最小的调度单元,一个Pod中可以包含多个Dockr,这些Dockr都会被调度到同一台Nod上,这些Dockr共享NtWorkNamspac,并且可以声明共享同一个Volum来共享磁盘空间。这样的好处是什么呢?其实在真实的世界中,很多应用是有部署在同一台机器的需求的,比如Rdis日志采集插件要采集日志,肯定需要和Rdis部署在同一台机器上才能读到Rdis的日志,我们前面讲述背景的时候说到了DockrSwarm存在一些问题,其中之一就是它只是基于Dockr调度,虽然也可以设置亲和度让两台Dockr调度在同一个机器上,但是因为不能一起调度,所以会存在一个Dockr提前被调度到了一个资源少的机器上,从而导致第二个Dockr调度失败。例如我们一共有台容器,A和B,分别为Rdis和日志采集组件,各需要g内存,现在有两台nod,nod3.5内存,nod4g内存,在DockrSwarm的调度策略下,先调度Rdis,有可能被调度到了nod上,接下来再来调度日志采集组件,发现nod只有.5g内存了,调度失败。但是在k8s中,调度是按照pod来调度的,两个组件在一个pod中,调度就不会考虑nod。虽然Pod已经可以运行Rdis服务了,但是他不具备高可用性,因为一旦一个Pod与一个节点(Nod)绑定,除非这个绑定发生了变化(pod.spc.nod字段被修改),否则它永远都不会离开这个节点,这也就意味着,如果这个宿主机宕机了,这个Pod也不会主动迁移到其他节点上去。为了让服务可以一直在,需要使用Dploymnt这样的控制器。~kubctlcatdploymntdis-dploymnt--imag=disdploymnt.apps/dis-dploymntcatd~kubctlgtpodsNAMEREADYSTATUSRESTARTSAGEdis/Running03mdis-dploymnt-c4c6cf9-8z8k5/Running08s~
dis-dploymnt-c4c6cf9-8z8k5就是刚才通过kubctlcat创建的新的Dploymnt,为了验证高可用,我们把用kubctldltpod把dis和dis-dploymnt-c4c6cf9-8z8k5都删掉看会发生什么。~kubctldltpoddisdis-dploymnt-c4c6cf9-8z8k5pod"dis"dltdpod"dis-dploymnt-c4c6cf9-8z8k5"dltd~kubctlgtpodsNAMEREADYSTATUSRESTARTSAGEdis-dploymnt-c4c6cf9-zskkb/Running00s~
dis已经消失了,但是dis-dploymnt-c4c6cf9-zskkb换了个名字又出现了!Dploymnt可以定义多副本个Pod,从而为应用提供迁移能力,如果单纯使用Pod,实际上当应用被调度到某台机器之后,机器宕机应用也无法自动迁移,但是使用Dploymnt,则会调用RplicaSt(一种控制器)来保证当前集群中的应用副本数和指定的一致。3k8s使用yaml来描述命令k8s中,可以使用kubctl来创建简单的服务,但是还有一种方式是对应创建复杂的服务的,就是提供yaml文件。例如上面的创建Pod的命令,我们可以用下面的yaml文件替换,执行kubctlcat之后,可以看到disPod又被创建了出来。~catpod.yamlapiVrsion:vkind:Podmtadata:nam:disspc:containrs:-nam:disimag:dis~kubctlcat-fpod.yamlpod/discatd~kubctlgtpodsNAMEREADYSTATUSRESTARTSAGEdis/Running06sdis-dploymnt-c4c6cf9-zskkb/Running06m3s
四k8s组件调用流程下面我们看下kubctlcatdploymntdis-dploymnt--imag=dis下发之后,k8s集群做了什么。首先controllr-managr,schdulr,kublt都会和apisrvr开始进行List-Watch模型,List是拿到当前的状态,Watch是拿到期望状态,然后k8s集群会致力于将当前状态达到达期望状态。kubctl下发命令到apisrvr,鉴权处理之后将创建信息存入tcd,Dploymnt的实现是使用RplicaSt控制器,当controllr-managr提前拿到当前的状态(pod=0),接着接收到期望状态,需要创建RplicaSt(pod=),就会开始创建Pod。然后schdulr会进行调度,确认Pod被创建在哪一台Nod上。之后Nod上的kublt真正拉起一个dockr。这些步骤中,apisrvr的作用是不言而喻的,所以说上接其余组件,下连ETCD,但是apisrvr是可以横向扩容的,然后通过负载均衡,倒是ETCD在k8s架构中成了瓶颈。最开始看这架构的时候,会想着为啥apisrvr,schdulr,controllr-managr不合成一个组件,其实在GooglBorg中,borgmastr就是这样的,功能也是这些功能,但是合在了一起,最后他们也发现集群大了之后borgmastr会有些性能上的问题,包括kublt的心跳就是很大一块,所以k8s从一开始开源,设计中有三个组件也是更好维护代码吧。五部署主从版本上面我们已经部署了Rdis的单机版,并通过Dploymnt实现了服务持续运行,接下来来看下主从版本如何部署,其中一个比较困难的地方就是如何确定主从的同步关系。StatfulStk8s为有状态应用设计了StatfulSt这种控制器,它主要通过下面两个特性来服务有状态应用:拓扑状态:实例的创建顺序和编号是顺序的,会按照nam-indx来编号,比如dis-0,dis-等。存储状态:可以通过声明使用外部存储,例如云盘等,将数据保存,从而Pod重启,重新调度等都能读到云盘中的数据。下面我们看下Rdis的StatfulSt的例子:apiVrsion:apps/vkind:StatfulSt#类型为statfulstmtadata:nam:dis-sfs#app名称spc:srvicNam:dis-sfs#这里的srvic下面解释plicas:#定义了两个副本slctor:matchLabls:app:dis-sfstmplat:mtadata:labls:app:dis-sfsspc:containrs:-nam:dis-sfsimag:dis#镜像版本