容器界从最初的单体时代已经走入编排引擎时代,目前已经形成了k8s、mesos、swarmkit三足鼎立之势。在所有编排引擎之下,基础设施资源主要就是容器化主机、容器网络以及容器存储等,通过对这些基础设施服务的解耦和拆分,并像乐高玩具一样重新组装,就可以在其之上构建k8s、mesos、swarmkit等编排引擎。
首先,我们需要对容器基础设施服务下一个定义,每个容器要运行起来所需要的基础资源以及围绕容器周边的各种基础服务,这些都可以被认为是基础设施服务,比如:
1. 主机容器化,为docker daemon提供运行载体。
2. 容器网络,它包含基础物理网络和我们经常使用的SDN容器网络。
3. 容器存储,为有状态与无状态容器提供额外的存储资源。
4. 容器日志,系统性的收集容器日志,并整理分析。
5. 容器监控,收集容器的性能数据,可以为autoscale动作提供参考依据。
6. 服务发现,在微服务场景下,可以帮助服务之间灵活的找到访问地址。
7. 负载均衡,由于微服务基本都是多实例场景,所以负载均衡的使用量会非常之大。
8. 健康检查,检查微服务的状态(端口)是否可用,并关联业务恢复机制。
9. 元数据服务,可以查看整体集群的host信息、微服务信息、容器信息等等,可以在微服务之间的联动上起到很好的作用。
当然这些基础服务不是割裂的,相互之间肯定会存在调用关系,此外再考虑基础服务的部署维护,需要一套管理机制,也就是我们需要定义一套简单的编排引擎(当然它不会像k8s、mesos那么庞大负载)来进行维护。调研了开源的容器管理平台Rancher,发现其管理理念就是如此,Rancher已经发布到了v1.2版本,所以后续我们就基于v1.2版本分析其基础设施管理机制。
在v1.2版本的整体架构(如下图所示)上,Cattle引擎向下深入演化成了基础设施引擎,这一点上在v1.1时代也早有体现。Cattle更多得作为基础设施的管理工具,可以用它来部署其他服务和编排引擎,当然它本身编排能力还是可以使用的,习惯了stack-service的朋友仍然可以继续使用它,同时rancher scheduler的引入也大大增强了其调度能力。Rancher已经可以在Docker1.12上部署,之前在使用时不小心装错Docker版本的朋友这回可以放心了。
基础设施服务的基础引擎就是Cattle,同时一般标准的基础服务包括healthcheck、ipsec、network-services、scheduler,这些都是从原先agent-instance服务中分离出来的,这些服务可以任意组合,也可以自己做一些定制。healthcheck用于对容器服务的健康检查,ipsec用于构建容器网络(当然一定条件下也可以用vxlan替换),network-services主要是提供rancher-dns和rancher-metadata以及CNI插件管理,scheduler是从原先rancher-server分离出来专门用于做容器调度。
有了我们之前定义的基础设施服务,那么如何对其管理也是个不小的挑战。Rancher提出了一个environment template的理念,我们可以自己去创建模版来指定需要组合的基础设施服务。如下图:
我们可以根据自身需求,选择IPsec网络或是VXLAN网络,存储方面默认集成了NFS、EBS、EFS的支持,有相关需求也可以enable对应的模块。这个模版定义可以参考: https://github.com/rancher/ran ... lates 。
在之前的Rancher版本上,用户经常诟病Rancher的网络只有IPsec,没有其他选择。而容器社区的发展是十分迅猛的,各种容器网络插件风起云涌,欲在江湖中一争高下。Rancher v1.2版本中与时俱进,对之前的网络实现进行了改造,支持了CNI标准,除IPsec之外又实现了呼声比较高的VXLAN网络,同时增加了CNI插件管理机制,让我们可以hacking接入其他第三方CNI插件。下面这张对比图可以看到,原先容器内网卡多ip的实现已经去掉了,取而代之的是CNI标准实现:
新的IPSec网络是基于CNI Bridge之上实现的,CNI的配置信息可以metadata方式动态传入,这样用户就可以做一些自定义网络的操作,整个原理图如下:
但是由于IPSec有加密解密的性能损耗,所以Rancher也提供了VXLAN的实现,VXLAN的实现同样是基于CNI bridge,使用rancher提供的rancher-cni-bridge、rancher-cni-ipam,网络配置信息以metadata方式注入。区别就在于rancher-net容器内部,rancher-net激活的是vxlan driver,它会生成一个vtep1042设备,并开启udp 4789端口,这个设备基于udp 4789构建vxlan overlay的两端通信,对于本机的容器通过eth0走bridge通信,对于其他Host的容器,则是通过路由规则转发到vtep1042设备上,再通过overlay到对端主机,由对端主机的bridge转发到相应的容器上。整个过程如图所示:
此外,目前容器CNI网络方案其实是非常多,。而CNI的插件很多种,Calico、Weave等之流,每个插件的部署方式都不一样。能够灵活的接入这些插件,也应当是容器基础设施服务应该满足的需求点。Rancher为了简化网络插件部署提出了network-manager, https://github.com/rancher/plugin-manager ,它可以做到兼容主流的CNI插件,它实际上定义了一个部署框架,让CNI插件在框架内部署。network-manager是以容器方式部署,由于每种插件在初始化时可能需要暴露端口或加入一些NAT规则,所以network-manager能够动态设置不同插件的初始化规则,它的做法是以metadata作为 host port和host nat规则的数据源,然后获取数据后生成相应的Iptables规则加入的Host中。而对于真正的CNI插件,需要在network-manager容器内/opt/cni目录下部署对应cni插件的执行程序(calico/weave),/etc/cni目录下部署cni插件的配置,这两个目录映射了docker卷rancher-cni-driver,也就是Host上的/var/lib/docker/volumes/rancher-cni-driver目录下。
在v1.2版本中,存储卷管理上的改动也比较大,基本上放弃了先前的convoy组件,采用了新的Rancher Storage https://github.com/rancher/storage 。这种考虑主要是为了和社区做更好的兼容,rancher-storage兼容docker 原生的volume plugin以及k8s flexvolume规范,目前已经实现了对nfs efs ebs的支持。
容器的运行需要载体,这个载体我们都了解就是常用的Linux OS,Linux可以运行在裸机上,也可以运行在虚拟机上。对主机容器化,其实我们首先就会想到使用docker-machine,docker-machine中默认集成了很多驱动,这也我们可以在本地环境或是在云环境中快速创建容器化的主机。但是在实际使用中,我们通常会有两个痛点:
1. machine driver非常多,如何对其进行管理。
2. machine driver的参数通常很多,且非特定人员很难识别,最好需要一个UI,可以让更多人方便使用。
Rancher基于docker-machine之上进行了包装,我们可以对各种驱动进行管理,可以添加或是删除。同时,还能为每种驱动定制UI。如果没有设置定制UI,则会根据driver的支持参数生成参数对应的表单。
像AWS EC2驱动设置比较复杂,所以在UI上做了很大优化,可以让用户填写key和secret后,一步一步进行设置:
比如OpenStack驱动,则就会根据相关驱动参数自动生成表单项:
在v1.2版本上,Rancher延续了自身的产品特色,就是对多编排引擎的支持。Rancher仍然支持Kubernetes、Mesos、Swarm三大编排引擎,Kubernetes可以支持到较新的v1.4.6版本,最近几天k8s v1.5也发布了,Rancher也很快做了兼容支持,想尝试新版k8s的朋友可以利用Rancher来进行快速部署并体验。由于所有的部署过程的代码都是开放的,用户依然可以自己定制部署版本。UI上也可以做一些简单部署细节修改,比如k8s的版本,Cloud Provider设置,Etcd的数据备份机制等等。如下图所示:
另外值得一提的是,Rancher支持了新版的Swarm Mode也就是Swarmkit引擎。目前支持的版本是v1.12.3,所以在部署时,请安装对应的Docker Engine。与Kubernetes的支持类似,这里也同样支持一些参数设置,比如Swarm集群中manager的数量:
其实现原理,Rancher实现了一个swarmkit-mon,其中内置了docker,并映射了Host上的docker.sock,这样可以在swarmkit-mon容器中控制docker创建swarmkit集群。swarmkit-mon的实现比较简单,主要包括两个shell脚本:run.sh负责swarmkit集群的管理和Rancher的联动,agent节点信息需要通过rancher-metadata读取,设置Host Label则直接调用Rancher API;health.sh负责监控swarmkit节点的状态(通过与docker.sock通信读取Swarm.LocalNodeState的状态),并与giddyup协作暴露健康检查端口,这样可以利用Rancher Cattle的healthcheck来保证swarmkit-mon服务的高可用性,每个Host的swarmkit-mon出问题时可以进行自动重建恢复。原理如图:
本实战选择在MBP上,使用Mac Docker Engine RancherOS VM来搭建。为什么选择RancherOS?主要是考虑其与Rancher的兼容性比较好,这样可以在初期少遇到点兼容性问题,快速进入产品特性的体验阶段。
首先打开Docker,并配置registry mirror,配置完成后重启Docker。mirror的服务可以去各个公用云厂商申请一个,比如我这里使用的是阿里云的registry mirror,如图所示:
打开terminal,安装Rancher Server:
$ docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable
若要添加Host节点,则需要通过docker-machine创建Host,这里使用的规格是2核2G(具体可根据自身MBP的性能调整),脚本(add_ros_host.sh)参考如下:
#!/usr/bin/env bash ROS_ISO_URL='http://127.0.0.1/rancheros.iso' ROS_CPU_COUNT=2 ROS_MEMORY=2048 docker-machine create -d virtualbox / --virtualbox-boot2docker-url $ROS_ISO_URL / --virtualbox-cpu-count $ROS_CPU_COUNT / --virtualbox-memory $ROS_MEMORY / $1 docker-machine ls
添加节点则需执行:
$ ./add_ros_host.sh ros-1
添加完成后,可以进入虚机内进行设置:
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS ros-1 - virtualbox Running tcp://192.168.99.100:2376 v1.12.3
$ docker-machine ssh ros-1
$ sudo ros config set rancher.docker.extra_args /
"['--registry-mirror','https://s06nkgus.mirror.aliyuncs.com']"
$ sudo system-docker restart docker
由于我们要使用VirtualBox的虚机组成一个小集群,所以建议把Rancher的Host Registration URL设置为 http://192.168.99.1:8080 ,如下图所示:
添加Rancher agent的时候也要注意,CATTLE_AGENT_IP参数要设置成虚机内192.168.99.0/24网段的IP,如下图所示:
如此就可以基本完全解锁Rancher v1.2的各种功能了,完整演示各种特性。