学习 Docker 容器网络模型 - 搭建分布式 Zookeeper 集群

2,341 阅读9分钟
原文链接: mp.weixin.qq.com


查看图片


ZooKeeper是一个流行的分布式协调服务。它提供了两种不同的部署方式:单机模式和分布式模式。其中单机模式的部署非常简单,网上也有很多资料,我们今天会利用Docker搭建分布式Zookeeper集群,并来帮助大家熟悉Docker中容器网络模型的使用。


ZooKeeper集群中所有的节点作为一个整体对分布式应用提供服务。节点中有两个的角色:Leader和Follower。在整个集群运行过程中,只有一个Leader,其他节点的都是Follower,如果ZK集群在运行过程中Leader出了问题,系统会采用选举算法重新在集群节点选出一个Leader。


Zookeeper节点之间是利用点对点的方式互相联结在一起的,这样的点对点部署方式对利用Docker容器搭建ZK集群提出了挑战。这是因为Zookeeper集群中每个节点需要在启动之前获得集群中所有节点的IP信息, 而当使用Docker缺省bridge网络模式启动容器时,Docker Daemon会为容器分配一个新的的IP地址。这样就形成了信息循环依赖。我们需要一些技巧来确保Zookeeper集群配置正确。


利用Host网络模式


自从1.9.1之后,Docker容器支持5种不同的网络模式,分别为bridge、host、container、overlay,none。我们可以在docker run命令中利用“--net”参数来指定容器网络。详解信息请参见 docs.docker.com/reference/r…。 


如果启动容器的时候使用--net host模式,那么这个容器将和宿主机共用一个Network Namespace。这时Docker Engine将不会为容器创建veth pair并配置IP等,而是直接使用宿主机的网络配置,就如直接跑在宿主机中的进程一样。注意,这时容器的其他资源,如文件系统、进程列表等还是和宿主机隔离的。


利用host网络,容器的IP地址和机器节点一致,这样我们在部署容器之前就能确定每个ZK节点的IP地址。我们可以分别在三台的机器上用host模式启动一个ZK容器并配置一个分布式集群。


首先我们需要获得一个ZK的Docker镜像。 


你也可以参照GitHub上代码自己构造
github.com/denverdino/…


我们假设三个节点的主机名:zookeeper1, zookeeper2, zookeeper3


我们分别在三台不同的主机上依次启动zookeeper容器:利用环境变量SERVER_ID指明节点ID,并在/opt/zookeeper/conf/zoo.cfg中添加ZK集群节点配置信息,具体请详见Docker镜像的启动脚本github.com/denverdino/…


登录到zookeeper1上,并执行下列命令启动集群的第一个节点


查看图片


登录到zookeeper2上,并执行下列命令启动集群的第二个节点


查看图片


登录到在zookeeper3上,再执行下列命令启动集群的第三个节点


查看图片


你可以通过docker logs ...来查看容器日志,ZK集群是否搭建成功

采用host网络方式的优点是,配置简单、网络性能与原生进程一样,对于关注性能和稳定性的生产环境,host方式是一个较好的选择。但是需要登录到每台虚机、物理机上操作太过繁琐。


我们可以利用下面的docker-compose模板,一键在一组ESC实例上创建基于host网络方式的ZK集群。注意:下面模板部署要求集群上至少包括3个ECS实例。


查看图片


这里利用Docker Compose支持的变量名替换能力,比如 ${...} 可以在运行时让用户输入下列参数


  • ZOOKEEPER_1:第一个ECS实例的IP地址或域名

  • ZOOKEEPER_2:第二个ECS实例的IP地址或域名

  • ZOOKEEPER_3:第三个ECS实例的IP地址或域名


当部署应用时,会提示用户根据集群实际信息输入下面参数


查看图片


然而容器服务是如何保证特定的zookeeper容器能够确保调度到指定ECS实例上呢?


因为完全支持Docker Swarm的调度约束,比如对于zookeeper1容器,它会调度到满足下面约束的constraint:aliyun.node_index==1ECS实例上。对于容器服务集群中的每一个ECS实例,在加入集群时都会被自动添加一系列的标签(label),比如节点序号、地域(Region)、可用区(Avaliablity Zone)等信息。通过这些约束我们可以控制容器和ECS实例的亲和性,来控制调度过程。 关于Docker Swarm 调度容器服务Compose扩展的信息可以通过连接获得。


查看图片


体验Docker容器网络模型(Container Network Model)的自定义网络


在开发环测试境,为了节省资源,我们经常需要将ZK集群部署在一台主机。这时候我们必须采用手工的方法调整每个Docker容器暴露的服务端口来避免端口冲突,然而这样会导致端口管理的复杂性。那么是否可以有其他方式来解决呢?我们是否可以让每个ZK容器有自己独立的IP,它们之间可以互相发现对方呢?


在Docker 1.9以前,Docker的网络模型有很多限制,比如:不支持跨节点的容器网络,服务发现能力较弱等等。而且不同应用对网络的需求不同,不同的底层网络技术也各有特点。所以Docker在2015年中发布了一个可扩展的容器网络管理项目libnetwork,并引入了新的容器网络模型(Container Network Model CNM)。


CNM在Docker 1.9版本中第一次正式发布,并持续增强。从此network成为了Docker的第一类资源。用户可以创建容器网络,并将容器关联到网络之上。在相同network上的任何容器都可以利用容器名称来解析服务的访问地址。这样不但解决了容器之间网络互联的问题,还简化了容器之间的服务端点发现。


我们下面利用CNM的自定义特性来部署ZK集群


下面我们首先创建一个名为“foo”的网络


查看图片


然后,我们会创建三个ZK节点容器并分别在“foo”的网络将它们命名为"zk1","zk2",和"zk3"。利用CNM的特性,我们可以使用容器名称来访问网络中其他容器。执行命令如下


查看图片


在这里我们利用容器名作为DNS中容器的域名来配置ZK节点。由于3个ZK容器都被挂载到相同的"foo"网络,他们之间可以通过容器名相互访问。这就优雅地解决了ZK配置和动态容器IP地址之间的循环依赖问题。


当然,我们还可以在本地使用下面的docker-compose.yml文件,执行docker-compose up -d来一键部署一个ZK集群。这将大大简化搭建测试环境的工作。


查看图片


在云端,阿里容器服务为集群缺省创建了一个全局跨节点的“multi-host-network”网络,这样在集群内部容器之间的网络是相互连通的。无需指明网络模式,容器之间就可以直接通过容器名进行访问,相应的docker-compose模板被简化如下:


查看图片


利用容器网络模型提供的容器连接


除了上面的方法,我们还可以在自定义网络中利用容器连接。


自从Docker 1.10版本之后,Docker内嵌了DNS服务,还支持在用户定义的网络上使用容器链接别名来访问引用的容器。 比如我们在容器zk1中,定义了连接 --link zk2:zknode2 那么意味着,在容器中可以利用zknode2作为容器zk2的别名来访问,而Docker容器内部的DNS将其动态解析正确的IP地址。注意与经典的容器链接不同,在自定义网络中容器链接并不需要被连接的容器已经启动,所以我们可以方便地描述双向连接或者P2P方式部署的应用。


查看图片


注:在Docker 1.11版本中对容器链接方式进一步增强,支持一对多这种方式的容器链接。并支持DNS轮询来实现简单的负载均衡。


静态分配容器IP


自从Docker 1.10开始,已经允许用户直接指明容器的IP地址。我们也可以利用这种方法来配置ZK集群。


我们首先创建一个网络“bar”,并设置它的子网为“172.19.0.0/16”动态IP分配区域为“172.19.0.0/17”


查看图片


这样,我们就保留了172.19.128.0/17这个子网可以用于静态IP地址分配了,下面我们可以自己选择几个不冲突的IP地址来配置ZK集群。比如:节点1至3的IP地址为,172.19.200.1,172.19.200.2和172.19.200.3。


查看图片


总结


Docker的容器网络模型的出现大大推动了容器网络技术的发展。善用容器网络模型可以解决不同应用的互联互通问题。




阿里百川(baichuan.taobao.com)是阿里巴巴集团“云”+“端”的核心战略是阿里巴巴集团无线开放平台,基于世界级的后端服务和成熟的商业组件,通过“技术、商业及大数据”的开放,为移动创业者提供可快速搭建App、商业化APP并提升用户体验的解决方案;同时提供多元化的创业服务-物理空间、孵化运营、创业投资等,为移动创业者提供全面保障。


                                                                                                 

        关于阿里百川        查看图片




点击【 阅读原文】查看更多精彩!