[ECUG专题回顾]《Kubernetes系统架构介绍》-杨章显:(就职于Cisco,云计算开源技术爱好者)

杨章显:大家下午好,今天我给大家演讲的主题就是Kubernetes,我来自Cisco,现在在Cisco是做系统运维的,所以说对这种管理集群空间是比较感兴趣的。



目前我主要关注的还是在云计算这一块,自动化运维,还有GO,Docker这些技术都是目前主要关注的技术。



接下来就是谈一下Kubernetes,其实就是说这个Docker技术在13年年底的时候就是说开源出来的时候我就开始关注这个技术,然后当时研究了一段时间,对它的这个代码,怎么样运行都研究过一段时间,后来发现这个最开始玩这个东西还是只能再一个机器上面玩的,而且是管理起来也是不太方便的,当时就觉得这个管理这个技术的确是一个缺陷,当时的一个短板,自己心里面想的是在不久的将来在管理技术方面会出现的。



后来在今年的4月份谷歌IO大会上面,谷歌就开源了Kubernetes这个项目,我后来看到他那个PPT,然后做了一个Kubernetes的演示,觉得当时这个Kubernetes这个技术在管理的时候非常方便的,而且后来他们是在内部系统运行了多年。目前的话Kubernetes在从它诞生的那一天,就面向各种云服务厂商,后来他们来贡献这个代码,在他自己的PASS上面做管理工具。它的第三个特点就是说比较有可扩展性,目前来说Kubernetes可以跟其他开源的项目结合起来了,比如说Openshift,还有就是网络管理的工具flannel,还有就是可以通过ETCD做自动发现服务的SkyDNS,这个跟Kubernetes结合起来的话在这个服务发现里面的话有一个优点,就是可以用域名DNS的方式发现方式,在0.5后的版本增加了一个服务IP,就是说我们大家知道IP这个跟DNS比起来方便性的话就完全不一样了,最后一个特点是Kubernetes管理集群起来有自我修复的能力,其中有一个就是起了很多的POD(音)如果一台机器挂了然后POD会分发调动到其他的机器上面去,在任何的时候只要集群当中有机器是好的,这个不会死掉的,就算死也会重新的给拉起来。然后接下来就是讲一下Kubernetes里面几个比较关键的概念,第一个就是POD,在Kubernetes里没有直接面向容器的概念,kubernetes是把这个封装起来了,封装成一POD,可以完全的跑起来这个服务。然后下面还有一个是Boundpod,这个和上面的pod主要的区别,上面的这个Pod是一个配置文件,完全的就是放在这个KubernetesAPIserver上面,根本没有分发到集群的机器上去,这个里面是完全的一个逻辑概念性的东西,根本没有运行起来,但是你可以管理它,可以删除创建,但是下面的这个Boundpod,也是Kubernetes的一个容器集合但是这个有一点不一样,已经被分发到集群当中一台机器上面去了,而且这台机器上面会把这个创建起来了,里面包含了你这个需要跟其他容器进行交互,交互时候就需要访问在这个里面的环境变量,就在这个Boundpod全部注入进去了可以和其他的进行交互了。



下面是replication controllers这个是副本里面需要配置2个或者是3的,然后就是说这个在任务的时候因为有了这么一个replicationcontrollers,就是在任何的时候这个集群都是有这么多pod运行起来了,哪怕你的机器死掉之后,然后还是会调度到其他的机器上面运行起来的,待会儿我会讲一下这个调度的时候 是如何调度的,满足哪些条件的时候会自动的把这个死掉的pod重新拉起来?



然后第三个概念就是services,既然玩这个概念就是玩的服务,services其实就是一系列的pod的访问入口,后面的话其实就是说通过这个services的入口,你后面可以访问很多很多其他的pod,可能是10台机器上面的可能是20台,可以通过services这个单一的入口进去,只能从这个地方进去,其他的地方是进去不了的,然后说这个地方一个services的IP,这个是Kubernetes在0.5.0以后就加进去的在最开始的时候是没有这个services的IP概念的,然后既然有了IP,当然就是说这个服务的话就跟它对应的有这个端口的东西,所以说这个services可以表现为像一个负载均衡器一样,所有访问这个服务了就要后面访问pod,都要从services这个入口的地方进去。



还有一个概念是labelS和selector,这样管理起来就是比较方便,如果说没有这个labelS的话,你要全部列出来,然后删除掉那是一件非常痛苦的事情,这个labelS接下来我会讲它再一个地方用来发现这个服务,就是说是你这个pod创建起来,你的services怎么创建起来,怎么找到这个pod后面我会讲的。Kubernetes的架构,主要是在这个地方是有这么几块,这个kubecfg主要是配置工具,在以后的话这个工具可能会被取消掉,现在目前还是有这个东西的,当然也出了一个新的kubectl这个管理工具,最核心的是APIserver,管理所有的pod的信息,所有的都是通过这个API管理的你可以创建或者是删除都是可以做的,你可以调度,这个APIserver在这一块主要包括几个部分,其中一个是APIserver,他主要是管理services的minion为的数量这些东西都是通过这个完成的,还有一个是调度器来当你通过这个kubecfg信息调度起来的话,会调度到后面的minion,这个是通过一些调度的准则会调度进去,然后在这个里面有一个ETCD这个也是APIserve里面一部分,前面桂阳同学讲的很清楚了,这个是用来存储POD所有的配置信息,services的配置信息都是存储在这个里面的,然后在这个minion这边有两个比较重要的组成部分,就是这个kubelet,它会跟这个etcd进行交互的,有一段间隙时间不断的向etcd里面获取最新的你创建pod的信息,如果你有新的信息进来之后,这边会做删除,如果这边删除的话会在机器上面运行这个pod做相应的调整或者是删除,然后还有一个就是说这个proxy,在Kubernetes里面就是跑服务的,就是说跨集群的,跨机器之间的通讯,通过这个proxy做的,这个proxy也会向这个etcd里面获取最新的servicespoint的信息,每当这个地方通过命令创建新的services的之后,会在这个minion上面把服务的端口监听起来,会有一个监听的随机端口,如果这边有新的变化,然后这个地方会把这个删除掉了。还有一个是更新,它会获取services的endpoint,这个是IP加端口的东西,就是服务进行访问的东西。



下面具体介绍一下这个每个组件具体怎么工作的?这个是APIserver有几个比较重要的对象,然后这个minion代表一个机器也就是host,这个在minion里面也配置了资源的信息,比如说总的CPU和总的内存,然后pod就是说配置这个信息,端口暴露给主机的端口都会在pod里面进行体现出来,这个controller就是pod的集合,也是差不多了,然后services就是配置services的端口,最后给这个外面提供了服务外面的services的端口是什么?1234都是在这个里面体现出来,还有一个会配置一个lebel,通过这个可以发现pod里面的配置,然后通过这个配置找到这个endpoint,把服务跟这个进行关联起来,这个endpoint就是IP和端口的集合,这些都是上面都是可以创建各种操作都可以的,然后这个event是最新的版本里面加进来的,以前是当你创建一个pod失败之后,是没有这个日志信息是不好查的,因为这个是分布式系统,然后再这个其他的机器上面大日志是刷的非常快的,几乎就是说看不到,除非非常熟悉代码才知道日志什么意思,不然真的不好看,后面把这个event加了一个regstry的,这个是用来做什么呢?当你在这个minion上面创建一个pod的时候,如果说失败了,他会把你失败的原因是什么失败了,比如说下载image时候没有下载下来,如果是调度的资源不够,也会全部都记载上面,你失败的原因会给你记录下来,然后你在这个APIsever里面把这个对象的信息察看出来,是一个日志信息,然后这个binding也是一个对象,但是有点不同的是,这个对象只能被写,不能被读。这个对象只是调度的时候,当你选择了这个机器,要把这个pod指定到它其中的一台机器上面去的时候,在这个地方的话就会调用这么一个对象,然后把他的host,podip进行绑定起来,把环境变量全部生成好了再起这个,这个里面的才是可以进行运行的,这个pod里面的是没有办法运行的,只是一个定义性的东西,只能是察看信息的,不能提供服务的。然后最下面的这个etcd的registry,这个是非常重要的,因为这个上面的所有的registry都是实现了这个etcd,这个是一个接口,这个是怎么创建的方法,但是具体实现的是etcd做的,所以说你无论创建这个上面的pod,services还有endpoint,都是把这个创建出来的,把这个信息存放在etcd里面,然后其他的整个这些host都是可以通过这个etcd的获取这些信息,然后做相应的一些操作,根据这个发出来是什么样的操作,比如说删除在这个里面调用etcd的删除方法来做,这边这个图就是说是讲的在这个IPservices上创建这个pod,创建services这该的一个步骤和流程,首先就是说这边是这边会发出创建的命令,也需要创建pod和services,从这个地方发出命令,然后把这些命令发送给APIserver,这边只不过是过渡的形式,最终的创建还是在这个地方,然后这个地方最终的创建到这个地方来了,当创建的这个地方创建之后,其实你的这个pod这些信息的话在整个集群里面其实是不知道的,他不知道你做了什么操作,也不知道你怎么做的,所以说在这边就有一个调度器,这个调度器是会说检测你这个里面有多少的minion和host,可以把新建的pod布置上面去,然后到这个etcd里面查找信息,哪些pod需要部署调度,哪些是已经调度的,他会把这些信息查找出来,然后查找出来他会根据一定的策略,就是说到host的端口,还有就是说他这个信息进行调度,最后就把这个调用registry创建新的信息,这个下面还会再讲的。



这个地方的话是Client就是操作podservices的操作,然后这个Controllermanager是一个进程的形式起来的,是同步replicationControllers的信息,确保集群中任何时候指定数量的pod在运行,比如说集群当中有三个pod,通过这个rc创建的,当你发现有两个的时候他就重新调度,当他发现少了一个的时候,他又会说是重新提起来,当然多了以后会删除掉。其实在这个时候services和pod是没有任何关联的,它不知道的,然后这个地方的话,这个是CM就会起了一个方法,就是services和pod同步信息,当你创建这个的时候,他有IP这些信息,然后这个services的就找到了services和pod,然后两个就结合起来,如果说services删除掉之后在这个地方也会更新掉,还有就是从cloudprovider同步一个minion信息或者是创建minion,就是说你在最开始起你的这个services的时候就是看这个当中有多少的minion,如果没有创建的时候就会在这个地方创建起来。



然后APIserver里面有一个etcd,刚刚说的上面的对象,然后这个scheduler调度器,会实时跟踪上面有多少的pod和minion,然后监测这个当中有多少已经调度的pod,还有没有被调度的pod需要重新调度,当他获取到这些信息的时候就根据下面的这些策略来把这个新建的未调度的pod调度到这个里面去,第一种方式就是根据host端口冲突,已经请求资源(内存、CPU)volume冲突(GCEpersistencedisk),如果说他发现你新建的podhost暴露了端口的信息跟前面已经是调度的这个pod的host暴露的端口是一样的,如果说是一样的,这个未调度的pod是不能再调度到这个上面了,因为两个是同一个端口一样的,调度到同一个机器上面去会出问题的,然后就是说不能工作的,它会首先检测这个条件,然后会检测已经请求的资源,包括这个内存跟CPU,为什么这个地方是已经请求的资源呢?在这个里面起来的话是指定了这个minion,这个host上面可以由多少的内存CPU的信息,在这个pod里面也是配置了你这个新起来的需要多少的内存,然后再这个地方会根据你这个地方配置的信息和这个已经请求的资源以前总的资源做一个比较,算一下进行计算,然后再看能不能把这个新建的未调度的pod调度到这台机器上去,如果她发现资源已经不够了,已经被请求的差不多了,就不能再调度到这台机器上了,会寻找其他的机器的,然后这个volume的冲突目前是针对谷歌的硬盘,其他的话就是不支持的,所以说这个是目前可以忽略掉的,然后还有就是节点的selector,这个节点还是有一个的,如果发现他调度已经是这个地方有了,不能再调度到你这个地方来了,当它所有的这些条件都监测完了以后,发现新建的pod可以调度到这个上面来之后,他就指定了host的IP,这个时候就开始做什么呢?然后就是写binding,把这个podid,host写到APIserver,然后把这个pod转换为Boundpod,这个里面服务的环境变量这个步骤就已经给填充进去了,所以说这个里面是可以运行的,因为这个地方有环境变量这些东西你可以跟其他的这些pod里面进行交互了。



然后这部分是kubelet在minion,host是真正运行的进行,然后etcd和client这个主要是从APIserver上面获取新的配置信息,就是Boundpod的信息,然后再这个kubelet里面是调用了一个go-dockerclient里面的工具,这个实现的是Docker所有的IPA,然后重新封装了一下,如启动啊就像起动删除创建这些,etcd就重新封装过了一次,接下来就是这个kubelet,它通过这个etcd,从IPAserver里面获取新的信息之后做状态的同步,比如说是你新创建的pod,在这个里面发现了之后,kubelet会把pod里面的创建起来,这个kubelet主要做操作,就是设置环境变量,就像Docker的LINK的方式,启动Container,然后获取最新的信息,根据这个做下面相应的操作。



下面就是说Proxy,这个是主要做下面的几件事儿,通过etcd的获取services和endpoints的变化,比如说他发现新的endpoint以后会加到loadbalancer里面,可以在下一擦其他访问的时候通过这个roundrobin的方法选择,如果这边删除的话也在这个地方会做这个相应的动作,就是说监听状态,这个地方还有一个步骤就是说初始化IPTABLES,因为这个Proxy使用了iptables删除的方法,访问服务的端口的时候就直接到其他的端口去,所以要初始化iptables。



这个图是从官网上面获取的,这个是services的Proxy,从这个地方获取services的信息,然后endpoint的信息都是从这个地方获取,然后就开始监听,把这些端口监听起来,监听的端口其实是一个随机的端口,然后监听起来,然后就是说初始化这个Iptables的规则,一系列的动作做完以后,这个clinentpod要访问上面的pod,如果是servicesIP是10.0.0.1,端口是1234,这个pod需要访问在后面的这些pod,通过这个servicesIP加端口访问的时候,在这个时候到这个地方的时候,iptables就会起作用了,把这个端口重定向一下,这个端口就是在这个你这个Proxy的端口,这个端口是随机的,然后到这个地方之后找到了这个地方的Proxy之后,你要访问哪个服务,有一个label会访问这个pod,这个pod为是分布在不同的机器上面的,通过这个里面把它选择出来,然后再跟它进行通讯,大致的流程就是这样的。



下面我给大家做一个DEMO,现在有一个环境是三台机器,有两个host,IPIserver。这个机器是APIserver,首先给大家看一下pod跟servicesReplication controllers是什么样的东西?例子就是我就直接看官网的例子,这个地方还有一个labels,能通过这个找到配件的信息,获取endpoint的信息。看一下Replication controllers,这个是Replication controllers的配置信息,这个里面的话有一个比较重要的,就是这个地方有一个副本,在这个里面就是说设置成了改成了2,这个地方也就是说你可以通过这个信息启用多个pod在这个集群里面,这地方配置成了2,然后这个Replication controllers的信息什么名字,然后再这个里面的话,他又配置了这个containers,这个跟刚刚的那个pod差不多 ,这个就是前面的一些pod信息,比如说containerpod,在后面也都定义好了,这个地方还是有labels,这个是通过这个发现endpoints的。再给大家看一下服务,在这个里面主要是配置了几个信息,其中第一个信息这个pod就是说这个services的pod,它的端口就是说最终提供服务的端口是什么,就是最终提供服务的端口,这个Container的pod是什么信息,然后跟这个labels也差不多。这个里面有一个labels,这个是redismaster,这两个services和master,pod之间建立的关系就是通过这个redismaster建立联系的,我先给大家看一下我这个环境里面运行的信息,最后我把这个时间删除之后再做一次给大家看一看。这个命令察看整个里面有多少个Replication controllers,这个整个的里面有两个,一个是前端的psp的东西,这个地方都是副本设置为2,也就是说这个Replication controllers会有两个pod起来,而且这两个pod分布在其他的另外两台机器上面是分布在两台不同的机器上面去的。这个察看是整个里面的运行的pod信息,这个里面我们看一下有4个,一个pod的话有一个master的信息运行起来的,而且是运行在23.4这台机器上面的,你能看到现在是运行在哪一台机器上面的,然后还有就是说有两个psp的redis,现在看是运行在23.4,和23.5的,为什么有两个呢?就是我前面说的Replication controllers里面设置成了2,这个pod设置成2,就是在这个里面起两个不同的pod起来,而且分布在两个不同的机器上面去,这个是redis,这个是跟上面的差不多,也是两个,然后给大家看一下这个里面的服务,services,在这个地方看了一下,其实是只有三个服务,为什么这个地方有5个呢?这个地方是因为前面有两个是系统默认带的服务,这两个就暂时不讲了,我们就讲一个前端的服务,从这个地方看的话有一个IP,就是servicesIP,这个地方定义是21.2,10.21.2,还有一个services的端口,这个地方是80端口,还有一个就是redis也有一个services,这个ip是89,但是这个地方为什么有IP呢?这个地方是在API设置里面配置了一个网络的范围,需要哪个范围的IP地址,这个地址你可以自己随便配的。这个地方下面就是说这个redis的三种服务,我给大家演示一下怎么创建吧,删除掉redismaster的pod,这个地方就代表删除成功了,然后我们再察看的话在这个地方你就会发现少了一个pod,这个时候其实这个操作下去其实就是说是这个pod被删除了,就意味着这个pod里面配置的Container也是被删除掉了,就是说通过那个etcd从这个apiservices里面获取信息,没有的话再从这个Container里面删除掉。演示一下删除这个的操作,首先把这个停止掉,从这个地方可以看到这个地方的副本就变成0,然后再这个时候其实就是Container还没有被真正的删除掉,只是停掉,在这个时候你们看看这个里面的,停掉之后刚刚说的是前端PSP的,发现这个地方的pod相应变少了两个,刚刚那个地方的数字已经从2变成0了,这个地方就变成0了,pod也会被删除掉,配置信息的话完全删除掉,我们创建一个吧,这个-C就是你所需要的配置文件,就是说pod的配置文件,我们这个地方就是要创建redismaster的pod。这样一个命令敲下去,这个时候你刚刚敲完命令,这个host是不知道的,这个时候没有被调度,所以说这个时候你是不知道的,它不知道到底要被分配到哪个host上面去,这个状态还是没有被运行起来,如果说是他起来的话,我们在这个地方敲命令的时候,你看看这个地方已经起来了,然后就是说他被调度到这个230.4这个host上面去,然后给大家创建一个Replication controllers吧,这样一个命令下去首先看到这个地方是Replication controllers的信息,这个地方需要创建几个副本,这个地方现在的四化你在这个listpots,会新增加了几个,这个地方是2,这边就起了两个pod,然后是分别被调度到230.5跟230.4这个host上面去,大致整个操作就是这些,当然还有就是说这个Replication controllers还有一个操作就是可以滚动性的升级,比如说这边有5个pod但是你想改变的时候不想一下子另外把他所有的改掉,你可以设置一个时间限制,设置5分钟,让第一个pod改变升级起来,剩下的4个会在隔了5分钟之后再升级,就是说再隔5分钟把第三个也升级起来,就是这种滚动性的升级,好谢谢大家,我这边讲的就差不多了,大家有甚么问题吗?



PPT:http://qiniuppt.qiniudn.com/yangzhangxian.pptx


视频(桂阳& 杨章显): http://qiniu-opensource.qiniudn.com/ecug-2014-guiyang.mp4