容器云最佳实践:Docker、微服务、应用容器化之Kubernetes实践

在移动互联网时代,企业须要寻找新的软件交付流程和IT架构,从而实现架构平台化,交付持续化,业务服务化。容器将成为新一代应用的标准交付件,容器云将帮助企业用户构建研发流程和云平台基础设施,缩短应用向云端交付的周期,下降运营门槛。加速企业向互联网技术和业务的双转型。“容器时代”的到来无疑为整个IT界带来了福音,今天咱们就跟你们一块儿看看它的新宠——CaaS容器云。redis

容器是一种轻量级的虚拟化技术,拥有持续集成、版本控制、可移植性、隔离性和安全性等优势,愈来愈多的应用跑在容器里面。但也有其缺陷,并非全部场景都适合如高性能计算,已经满负荷运行的应用没有必要虚拟化,一些对IO等运行环境要求比较高应用不适合容器化如Oracle数据库。

容器给应用程序提供了一个独立的运行环境,并非像虚拟机那样提供一套完整的操做系统,这是容器和虚拟机最大的区别,因此在用户在使用虚拟化如KVM、Vmware时候不多会担忧到应用能不能跑到虚拟机里面,一般只是针对虚拟化环境作性能调优,如KVM的CPU绑定、内存气球以及巨型页等。但应用Docker化更加复杂,除了解决虚拟机存在的计算、存储、网络之外问题,还须要解决Docker自身的问题,如:Docker相对与虚拟机的脆弱性、应用程序依赖的系统调用在Docker中没有作限制,还有Docker镜像制做以及应用Docker化以后日志和性能采集等问题。

Docker经过cgroup限制CPU和内存的使用,CPU限定一般是设置权重,并不能让一个容器得到肯定1Ghz的CPU,固然你也可使用cpuset绑定到指定的物理核上,内存使用中不只要设置内存大小还要限定交换分区的大小,这点很重要,譬如MongoDB在内存不足时大量使用交换分区。

Docker相对短暂的生命周期决定了不会使用持久存储,容器挂了,存储的数据也会相应的丢失。若是数据须要持久化如MySQL的DBData数据,则须要把数据输出到外部的存储设备上,能够经过挂载NFS或者GlusterFS或者AWS存储等,在Kubernetes的PV的后端存储已经能够支持上述文件系统。用户也能够根据不一样存储去实现Docker volume plugin,比较流行有Rancher/Convoy和Flocker,后者支持数据迁移,这为容器的迁移奠基了数据基础。

容器应用之间相互依赖:Web应用访问数据库,API接口调用等,因此网络必须可以互通而且支持多租户隔离,当前Docker网络有两大阵营,CNM和CNI。其中Calico能够算是脚踏两只船的,它能够与Kubernetes集成,相比Overlay网络在网络传输过程仍是有明显优点的,以下图所示,减小了包封装提升了网络传输和包处理效率。
mongodb

calico-package.png

Docker OVS SDN的方式达到容器和容器以及容器和主机之间的网络互通也是很是好的设计思想,经过实现Docker的Network Drivers接口将容器挂到OVS上,经过ryu、Floodlight或者OpenDaylight等SDN控制器动态下发流表的达到网络互通;再结合iptables实现网络隔离。若是想实现大二层跨机房网络互通,能够集合Vxlan等Overlay技术。
sdn_ovs.png

天云skyform ECP平台是基于Kubernetes Calico的容器管理平台,具备日志采集分析、性能监控、镜像管理等一套完整的容器管理平台。上面介绍了Docker相关的一些相关知识,下面介绍具体的应用在Kubernetes平台上的集成。我把应用集成难度分三个等级:最容易是应用自己具备服务发现机制如Dubbo,自然的支持自动扩缩容,那么在Kubernetes集成将会变的很是简单;大部分应用属于须要修改配置就能在容器里面运行,最困难的是须要对应用进行二次开发或者对平台二次开发的应用。

ZooKeeper

ZooKeeper是一个高性能、高可用的分布式协调服务。整个ZooKeeper集群的对外提供2181服务端口,节点之间数据同步和选主分别使用的2888和3888端口。每个ZooKeeper节点都须要个其余节点通讯,因此都须要一个固定的IP地址,经过Kubernetes服务提供的虚IP(若是使用集群内已经部署DNS则配置域名便可)互相通讯,结构以下图所示:
zookeepr-service.png

Yaml文件以下
zookeeper-yaml.png

存储使用nfs共享存储,这样ZooKeeper容器重建后就能恢复数据。
zookeeper-nfs.png

Kafka

Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被普遍使用。目前愈来愈多的开源分布式处理系统如Cloudera、Apache Storm、Spark都支持与Kafka集成。整个结构图以下所示:
kafka-arch.png

Yaml文件以下,这里面有三个地方须要注意:
  1. 每个Kafka的broker都有一个集群内惟一的broker_id,因此不能把整个Kafka集群放到一个RC里面,而必须经过不一样RC去分别定义每个broker;
  2. Kafka依赖ZooKeeper,在这里咱们经过环境变量的方式将域名传递到容器内;
  3. 这里没有配置Kafka的持久化存储,由于每一个Topic包含一个或多个partition,若是单个broker宕调不会影响集群,而且当broker重建后会自动同步数据,速度很是快。
    kafka-yaml.png

Redis

Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它能够用做数据库、缓存和消息中间件。Redis容器测试过程当中,有几点性能问题须要注意,第一是Redis最大内存,若是不设置可能会出现将内存耗尽的现象,第二是数据ttl时间设定以及清理keys策略,这些都是为了不内存不足时使用交换分区致使性能降低,第三是数据持久化使用RBD,相对于较大文件aof持久化,RBD更适合快照恢复。若是是业务量不大的场景可使用redis主从结构,以下图所示:
redis-arch.png

Resis Master的Yaml文件以下,其中为了数据的迁移恢复和重建使用Glusterfs存储,固然你也能够换成其余存储,单个主从集群可能没法承载过多的请求,能够经过当前比较成熟的一个方案Twemproxy,经过代理实现数据分片,也能达到一个不错的效果:
redis-yaml.png

当前咱们正在测试的是Redis 3.x的集群功能,每个Redis都是一个service(slave默认不接受读写,须要执行readonly才能读),省去proxy代理提升效率。这个集群方案经过redis-trib.rb的create子命令构建, 在客户端配置全部service地址就能够操做集群里面的数据,但整个操做过程有两个地方必须经过手工完成,尚待完善:
  1. 整个集群建立redis-trib.rb是经过手动完成,没有服务发现和自动化;
  2. 增长加点必须手动执行redis-trib.rb reshard分配slot。

redis-cluster.png

MongoDB

MongoDB是由C 语言编写的,是一个基于分布式文件存储的开源数据库系统。MongoDB已经不推荐使用主从,集群能够选择副本集或者分片。下图展现的每个MongoDB对外是一个service,组成副本集的集群,相似mongodb这种对磁盘IO要求比较高的可使用SSD加速,经过标签选择建立到有SSD机器上面提升性能。
mongodb-yaml.png

若是是MongoDB的分片集群,结构以下所示:
mongos.png

每个configsvr配置服务和Mongos路由服务都是经过service提供固定的访问接口。mongos经过configsvr域名配置。经过服务发现的脚本动态配置将副本集转成分片,这个分片的功能测试已经经过,但性能测试还在进行中。

上面一些应用都是经过容器外部传递配置参数或者启动脚本修改应用的配置,但有的应用经过这种方式是没法完成的,必须经过对应用或者对平台的改造才能完成,譬如IBM的任务调度平台OpenLava,它经过/proc/meminfo和/proc/cpuinfo获取内存和CPU,Docker这部分经过是挂载的主机proc文件系统,致使应用在容器内读取是主机的CPU和内存,此时经过修改OpenLava代码使其从/sys/fs/cgroup/cpu/cpu.shares 获取CPU核数从/sys/fs/cgroup/memory/memory.limit_in_byte获取内存值,有的应用(多个pod)之间须要共享IPC,这部分功能Kubernetes是没有的,须要经过平台改造去达到应用需求,还有应用须要根据IO去调度,这些都是咱们ECP平台基于Kubernetes添加的功能。

Q&A

Q:请问在Kubernetes架构下 搭建分布式服务框架如Dubbo 须要将主机地址和暴露端口注册到ZooKeeper上,这个主机地址和暴露的端口大家是怎么处理的,即容器内的应用如何获取Docker宿主机地址?

A:Dubbo服务不须要暴露主机的IP和地址,只须要知道容器地址便可。这些服务都是注册到ZooKeeper上面,经过ZooKeeper完成服务发现,Kubernetes可以根据暴露端口进行调度,固然有些应用要求容器能获取到宿主机的IP地址,这块咱们对Kubernetes作了一些修改,能够动态注入诸如宿主机IP,宿主机主机名信息到容器的环境变量中。
Q:ECP的定位和解决目标相比较目前你们在用传统的云平台解决方案来说下? 
A:ECP产品定位是一套完整的容器解决方案,从容器生命周期管理,资源监控到日志分析处理,相比与云平台解决方案管理的对象再也不是虚拟机,而是容器,面向的对象是服务。
Q:关于容器自己的资源性能监控,是用的cAdvisor+Heapster吗,如何能保持pod重启(重启后pod名称变化)后的数据连续性,谢谢。
A:资源监控用的不是Heapster,ECP的资源监控是用cAdvisor+咱们本身研发的采集Agent+Ceilometer+MongoDB+HBase等技术。复用了咱们在作CMP产品时的技术,rc中的pod重建后会重命名,这块对于单一pod数据的连续性尚未考虑,咱们是把rc当作一个总体考虑的 。
Q:大家对外服务的负载均衡如何作的?是直接用Kubernetes的service吗?
A:对外负载均衡现阶段用的是Kubernetes的service,考虑到iptables带来的性能损耗,后续咱们会考虑使用别的方案,在集群内部直接把流量转发到对于的pod上。
Q:请问Kubernetes容器和在其中运行的应用程序监控是如何作的?能介绍下吗?谢谢!
A:ECP的资源监控是用cAdvisor+咱们本身研发的采集Agent+Ceilometer+MongoDB+HBase等技术。复用了咱们在作CMP产品时的技术。简单来讲就是用cAdvisor采集原始数据,而后经过Ceilometer持久化,提供实时数据查询、告警等功能。数据会按期转存到hbase作历史数据分析。
Q:请问,有基于Kubernetes的多租户和用户配额开源实现嘛?
A:如今开源的方案比较少,咱们的ECP产品是结合Keystone实现的多租户管理以及租户的配额管理。
【docke学习参考】

一、【容器技术】很是详细的 Docker 学习笔记-爱编程 http://www.w2bc.com/article/152095docker

二、10个精选的容器应用案例 http://www.infoq.com/cn/minibooks/10-Container-studies (推荐下载)数据库