我们会继续使用vfarcic/cloud-provisioning代码库(https://github.com/ vfarcic/cloud-provisioning),它包含了对我们有用的配置和脚本,你已经克隆了它。为了安全起见,我们将获取最新版本:
让我们来创建第一个EC2实例:
定义在环境变量AWS_ZONE[1]的可用区中,我们指定Docker Machine应该使用amazonec2驱动程序来创建一个实例。
我们使用了一个键为type值为manager的标签。该标签主要用于信息目的。
最后指定了实例的名字为swarm-1。
输出如下:
Docker Machine启动了一个AWS EC2实例,为其提供了Ubuntu,并安装和配置了Docker Engine。
现在可以初始化集群了。节点之间的所有通信都应该使用私有IP。不幸的是,docker-machine ip只返回公开的IP,所以必须使用其他方法来获得私有IP。
可以使用aws ec2 description-instance命令来获取有关EC2实例的所有信息,也可以通过添加Name=instance-state-name、Values=running来筛选正在运行的实例。这样做排除了正在终止的或已经终止的实例:
命令describe-instances列出了所有EC2实例。结合--filter将只输出名字标记为swarm-1的实例。
输出的相关样本如下:
即使获得了与swarm-1 EC2实例相关的所有信息,仍然需要将输出限定在PrivateIpAddress的值上。我们将使用jq(https://stedolan.github.io/jq/)过滤输出并得到所需的内容。请下载并安装适合你的操作系统的发行版。
给Windows用户的说明
使用Chocolatey,在管理员命令提示符下通过choco install jq来安装jq。
使用jq来获取数组Reservations中的第一个元素。在其中可以得到第一个实例及其PrivateIpAddresss。-r参数以原始格式返回值(这种情况下,IP没有双引号)。命令的结果保存在环境变量MANAGER_IP中。
为安全起见,可以输出新创建的变量的值:
输出如下:
现在可以采用前面章节中的方式执行swarm init命令:
让我们确认集群确实已经初始化:
输出如下(为简洁起见,移除了ID):
除创建了一个EC2实例外,docker-machine还创建了一个安全组。
安全组充当控制流量的虚拟防火墙。当启动一个实例时,你可以将一个或多个安全组与实例关联起来。你向每个安全组添加规则,允许流量往来于与其关联的实例。
撰写本书时,Docker Machine还没有很好地支持Swarm Mode。因此,它创建了一个名为docker-machine的AWS安全组,并且只打开了入口(输入)端口22和2376。所有端口的出口(输出)都打开了。
为了让Swarm Mode正确运行,应该打开的输入端口如下:
● TCP端口2377用于集群管理通信。
● TCP和UDP端口7946用于节点间的通信。
● TCP和UDP端口4789用于覆盖网络流量。
要修改安全组,需要获得它的ID。可以使用aws ec2 description-security-groups命令查看安全组的信息:
部分输出如下:
将ID赋值给环境变量SECURITY_GROUP_ID的命令如下:
请求安全组docker-machine的信息,并过滤JSON输出,得到位于数组SecurityGroups第一个元素中的GroupId键。
现在可以使用aws ec2 authorize-security-group-ingress命令打开TCP端口2377、7946和4789:
应该执行一条相似的命令打开UDP端口7946和4789:(www.xing528.com)
请注意,在所有情况下,我们指定source-group要与安全组相同。这意味着端口将只对属于同一组的实例开放。换句话说,不能公开访问这些端口。因为这些端口仅用于集群的内部通信,没有理由暴露这些端口来威胁我们的安全。
请重复执行aws ec2 describe-security-groups命令来确认端口确实被打开:
现在在集群中加入更多的节点。我们会先创建两个新的节点,并以manager的身份将它们添加到集群中:
没有必要解释刚才执行的命令,因为它们是以前使用过的命令的组合。
下面还将添加几个worker节点:
让我们确认所有五个节点确实构成了集群:
输出如下(为简洁起见,移除了ID):
就是这样。我们的集群已经准备好了。剩下的唯一的事情就是部署一些服务,并确认集群是否工作正常。
因为已经多次创建了服务,所以将使用Compose文件vfarcic/docker-flow-proxy/docker-compose-stack.yml(https://github.com/vfarcic/docker-flow-proxy/blob/ master/docker-compose-stack.yml)和vfarcic/docker-flow-proxy/docker-compose-stack.yml(https://github.com/vfarcic/docker-flow-proxy/blob/master/docker-compose-stack.yml)来加快这一过程。它们将创建proxy、swarm-listener、go-demo-db和go-demo服务:
非Windows用户不需要登录swarm-1机器,可以从其笔记本电脑上直接部署栈来实现相同的结果。
下载所有的镜像需要花一些时间。一段时间后,service ls命令应该得到如下输出(为简洁起见,移除了ID):
让我们确认go-demo服务是可以访问的:
输出如下:
有些尴尬。尽管所有的服务都在运行,使用与前几章相同的命令,但还是不能访问proxy,也不能通过proxy访问go-demo服务。
这很容易解释。因为从来没有打开端口80和443。默认情况下,AWS EC2实例的所有输入流量都被关闭,我们只打开了正确运行Swarm所需的端口。这些端口只在EC2实例内是打开的,并与docker-machine安全组绑定,在AWS VPC之外并不可访问。
现在将使用aws ec2 authorize-security-group-ingress命令来打开端口80和443。这一次将cidr指定为源,而不是source-group:
aws ec2 authorize-security-group-ingress命令执行了两次;第一次是端口80,第二次是端口443。
让我们再次发送请求信息:
这次的输出和预期的一样。我们得到了回应:
使用Docker Machine和AWS CLI在AWS中建立了完整的Swarm集群。这是我们所需要的吗?这取决于为集群所定义的需求。我们应该增加一些弹性IP地址(Elastic IP addresses)。
弹性IP地址是为动态云计算而设计的静态IP地址。它与你的AWS账户相关联。使用弹性IP地址,可以通过快速地将地址重新映射到你账户中的另一个实例来屏蔽实例或软件的故障。弹性IP地址是可以从Internet访问的公开的IP地址。如果你的实例没有公开的IP地址,则可以将弹性IP地址与其关联,以启用与Internet的通信;例如,从本地计算机连接到你的实例。
换句话说,我们应该至少设置两个弹性IP,并将它们映射到集群中的两个EC2实例。这两个(或更多)IP将被设置为DNS记录。这样,当一个实例失效时,可以用一个新的实例代替它,可以在不影响用户的情况下重新映射弹性IP。
还可以做很多其他改进。但是,这会使我们陷入尴尬的境地。我们会使用一个并不是用来配置复杂的集群的工具。
创建虚拟机是很慢的。Docker Machine花了很多时间为它配置Ubuntu并安装Docker Engine。创建我们自己的Amazon Machine Image(AMI),并预装好Docker Engine,这样可以节省一些时间。但是这么做的话,使用Docekr Machine的理由就不存在了。Docker Machine的主要用处是简单化。一旦开始使用其他的AWS资源来使配置复杂化,就会意识到简单性正被太多的即时命令所取代。
当应对小型集群时,特别是想创建一些快速且临时性的东西时,使用docker-machine和aws命令是非常有效的。最大的问题是,到目前为止,我们所做的一切都是即时命令。我们很可能无法在第二次时重复执行相同的步骤。基础设施没有文档记录,所以我们的团队无法知道集群的构成。
我的建议是使用docker-machine和aws作为一种快捷实用的方式来创建集群,其主要用于演示目的。只要集群的规模相对较小,这种方法对生产系统也是有用的。
如果想要建立一个复杂的、更大的、可能更持久的方案,就应该考虑其他选项。
让我们删除创建的集群,并重新开始探索其他方案:
唯一剩下的就是删除创建的安全组docker-machine:
如果实例尚未终止,最后一条命令可能就会失败。如果是这样,就请稍等片刻,然后重复该命令。
让我们继续探索AWS中的Docker。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。