使用Kubernetes来管理Docker扩展Kubernetes是一款开源的项目,管理Linux容器集群,并可将集群作为一个单一的系统来对待。其可跨多主机来管理和运行Docker容器、提供容器的定位、服务发现以及复制控制。它由Google发起,现在得到了如微软、红帽、IBM和Docker等众多厂商的支持。Google使用容器技术有着超过十年的历史,每周要启动超过2亿台容器。通过Kubernetes,Google分享了他们关于容器的专业经验,即创建大规模运行容器的开放平台。一旦用户开始使用Docker容器,那么问题就来了,一、如何跨多个Docker主机扩展和启动容器,且能够在主机间平衡这些容器。二、还需要高度抽象出API来定义如何从逻辑上组织容器、定义容器池、负载均衡以及关联性。该项目就是为了解决这两个问题而生的。相关厂商内容基于Docker和微服务的持续交付实践从SOA到微服务,我的血泪总结证券行业的Docker应用实践你离成为一位合格的技术领导者还有多远?你了解技术领导与技术管理的差别吗?相关赞助商CNUTCon全球容器技术大会北京站,9月9日-10日,喜来登长城饭店,点击了解详情!Kubernetes仍然处于早期阶段,这也就意味着会有很多新的变化进入到该项目,目前还仅有比较简单的实例,仍需要加入新的功能,但是它正在一步一步地平稳发展,也得到了很多大公司的支持,前途无量。Kubernetes概念Kubernetes的架构被定义为由一个master服务器和多个minons服务器组成。命令行工具连接到master服务器的API端点,其可以管理和编排所有的minons服务器,Docker容器接收来自master服务器的指令并运行容器。Master:KubernetesAPI服务所在,多Master的配置仍在开发中。Minons:每个具有Kubelet服务的Docker主机,Kubelet服务用于接收来自Master的指令,且管理运行容器的主机。Pod:定义了一组绑在一起的容器,可以部署在同一Minons中,例如一个数据库或者是web服务器。Replicationcontroller:定义了需要运行多少个Pod或者容器。跨多个minons来调度容器。Service:定义了由容器所发布的可被发现的服务/端口,以及外部代理通信。服务会映射端口到外部可访问的端口,而所映射的端口是跨多个minons的Pod内运行的容器的端口。kubecfg:命令行客户端,连接到master来管理Kubernetes。(点击图片可放大显示)Kubernetes由状态所定义,而不是进程。当你定义了一个pod时,Kubernetes会设法确保它会一直运行。如果其中的某个容器挂掉了,Kubernetes会设法再启动一个新的容器。如果一个复制控制器定义了3份复制,Kubernetes会设法一直运行这3份,根据需要来启动和停止容器。本文中所用的例子应用是Jenkins持续集成服务,Jenkins是典型的通过主从服务来建立分布式的工作任务的例子。Jenkins由jenkinsswarm插件来配置,运行一个jenkins主服务和多个jenkins从服务,所有的Jenkins服务都以Docker容器的方式跨多个主机运行。swarm从服务在启动时连接到Jenkins主服务,然后就可以运行Jenkins任务了。例子中使用的配置文件可以从Github上下载到,而该Docker镜像可以从casnchez/jenkins-swarm获取,对于Jenkins主服务来说,可以通过swarm插件来扩展官方Jenkins镜像。对于jenkins从服务来说,可以从csanchez/jenkins-swarm-slave获取,它只是在JVM容器中运行了jenkins从服务而已。创建Kubernetes集群Kubernetes提供了多个操作系统和云/虚拟化提供商下创建集群的脚本,有Vagrant(用于本地测试)、GoogleComputeEngine、Azure、Rackspace等。本文所实践的例子就是运行在Vagrant之上的本地集群,使用Fedora作为操作系统,遵照的是官方入门指南,测试的Kubernetes版本是0.5.4。取代了默认的3个minion(Docker主机),而是使用了2个minion,两台主机就足以展示Kubernetes的能力了,三台有点浪费。当你下载了Kubernetes,然后将至解压后,即可在本地的目录下运行这些示例了。初学者创建集群仅需要一个命令,即./cluster/kube-up.sh。$exportKUBERNETES_PROVIDER=vagrant$exportKUBERNETES_NUM_MINIONS=2$./cluster/kube-up.sh获取示例配置文件:$gitclone集群创建的快慢取决于机器的性能和内部的带宽。但是其最终完成不能有任何的错误,而且它仅需要运行一次。命令行工具和Kubernetes交互的命令行工具叫做kubecfg,此脚本位于cluster/kubecfg.sh。为了检验我们刚才创建的两个minons已经启动并运行了,只需运行kubecfglistminions命令即可,它的结果会显示Vagrant的两台虚拟机。$./cluster/kubecfg.shlistminionsMinionidentifier----------10.245.2.210.245.2.3Pod在Kubernetes的术语中,Jenkins主服务被定义为一个pod。在一个pod中可以指定多个容器,这些容器均部署在同一Docker主机中,在一个pod中的容器的优势在于可以共享资源,例如存储卷,而且使用相同的网络命名空间和IP地址。默认的卷是空的目录,类型为emptyDir,它的生存时间就是pod的生命周期,而并非是指定的容器,所以如果一个容器失效了,但是其持久性的存储仍然在。另外一个卷的类型是hostDir,它是将主机的一个目录挂载到容器中。在这个具体的Jenkins示例中,我们所创建的pod是两个容器,分别是Jenkins主服务和MySQL,前者作为实例,后者作为数据库。然而我们只需要关心jenkins主服务容器即可。为了创建一个Jenkinspod,我们运行定义了Jenkins容器pod的kubecfg,使用Docker镜像csanchez/jenkins-swarm,为了能够访问Jenkins的Web界面和从服务的API,我们将主机的端口8080和50000映射到容器,以及将/var/jenkins_home挂载为卷。读者可从Github下载到示例代码。JenkinsWeb界面的pod(pod.json)的定义如下:{id:jenkins,kind:Pod,apiVersion:v1beta1,desiredState:{manifest:{version:v1beta1,id:jenkins,containers:[{name:jenkins,image:csanchez/jenkins-swarm:1.565.3.3,ports:[{containerPort:8080,hostPort:8080},{containerPort:50000,hostPort:50000}],volumeMounts:[{name:jenkins-data,mountPath:/var/jenkins_home}]}],volumes:[{name:jenkins-data,source:{emptyDir:{}}}]}},labels:{name:jenkins}}然后使用下面命令来创建:$./cluster/kubecfg.sh-ckubernetes-jenkins/pod.jsoncreatepodsNameImage(s)HostLabelsStatus--------------------------------------------------jenkinscsanchez/jenkins-swarm:1.565.3.3name=jenkinsPending这需要等待一段时间,具体时间的长短要视你的网络而定,因为它会从DockerHub上下载Docker镜像到minion,我们可以查看它的状态,以及在那个minion中启动了。$./cluster/kubecfg.shlistpodsNameImage(s)HostLabelsStatus--------------------------------------------------jenkinscsanchez/jenkins-swarm:1.565.3.310.0.29.247/10.0.29.247name=jenkinsRunning如果我们使用SSH登录到minion中,此minion即是pod被分配到的minion-1或minion-2,我们就可以看到Docker按照所定义的那样启动起来了。其中还包括了用于Kubernetes内部管理的容器(kubernetes/pause和google/cadvisor)。$vagrantsshminion-2-cdockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES7f6825a80c8agoogle/cadvisor:0.6.2/usr/bin/cadvisor3minutesagoUp3minutesk8s_cadvisor.b0dae998_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_28df406a5c02249c0b3ccsanchez/jenkins-swarm:1.565.3.3/usr/local/bin/jenk3minutesagoUp3minutesk8s_jenkins.f87be3b0_jenkins.default.etcd_901e8027-759b-11e4-bfd0-0800279696e1_bf8db75ace51fda15f55kubernetes/pause:go/pause10minutesagoUp10minutesk8s_net.dbcb7509_0d38f5b2-759c-11e4-bfd0-0800279696e1.default.etcd_0d38fa52-759c-11e4-bfd0-0800279696e1_e4e3a40fe6f00165d7d3kubernetes/pause:go/pause13minutesagoUp13minutes0.0.0.0:8080-8080/tcp,0.0.0.0:50000-50000/tcpk8s_net.9eb4a781_jenkins.default.etcd_901e8027-759b-11e4-bfd0-0800279696e1_7bd4d24e7129fa5dccabkubernetes/pause:go/pause13minutesagoUp13minutes0.0.0.0:4194-8080/tcpk8s_net.a0f18f6e_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_659a7a52还有,我们一旦拿到了容器的ID,就可以通过如vagrantsshminion-1-cdockerlogscec3eab3f4d3这样的命令来查看容器的日志了。我们也可以访问Jenkins的Web界面,至于要访问的URL是