我们需要找到一种方法在运行服务的容器之外保存状态。
可以挂载主机上的一个卷。如果容器发生故障并在同一节点上重新运行,这将允许我们保留状态。问题是这样的方案限制太多。除非我们对服务进行约束,否则无法保证Swarm会将服务重新调度到同一个节点上。如果这样做的话,Swarm就无法保证服务的可用性。当该节点发生故障时(每个节点迟早都会发生故障),Swarm无法重新运行服务。只要服务器在运行,就会有容错能力。
可以通过将NFS挂载到每个服务器来解决节点故障的问题。这样,每个服务器都可以访问相同的数据,并且可以为其安装一个Docker卷。
我们将使用Amazon弹性文件系统(EFS)(https://aws.amazon.com/efs/)。由于本书不是专门讨论AWS的,所以将跳过不同AWS文件系统的比较,只会强调选择EFS是因为可以跨多个可用性区域使用它。
请打开EFS的主页(https://console.aws.amazon.com/efs/home):
给Windows用户的说明
Git Bash可能无法使用open命令。如果是这样,则请将$AWS_DEFAULT_REGION替换为你的集群正在运行的区域(例如,us-east-1),然后在浏览器中打开它。
单击“Create File System”按钮。对于每个可用性区域,使用docker(早些时候使用Terraform创建的)替换默认的安全组。点击“Next Step”两次,然后点击“Create File System”。
应该等到每个区域的生命周期状态设置为可用为止。
现在,已经准备好在每个节点上挂载EFS。最简单的方法是点击Amazon EC2安装指令链接。我们只对挂载你的文件系统这部分的第三点中的命令感兴趣。请复制一下。
剩下的就是登录每个节点并执行挂载EFS卷的命令:
我们登录第一个manager并创建了/mnt/efs目录。
粘贴从EC2挂载指令页面复制的命令。在执行之前,我们会做一点小小的修改。请将目标路径从efs更改为/mnt/efs并执行它。
在我的例子中,命令如下(你的命令会有所不同):
我们还应该创建一个子目录来保存Jenkins的状态:
我们创建了目录/mnt/efs/jenkins,为每个人提供了全部的权限,并退出了服务器。因为Swarm可能决定在任何节点上创建服务,所以应该在其他服务器上重复相同的过程。请注意,你的挂载将与此不同,所以不要简单地粘贴下面的sudo mount命令:
最后,可以再次尝试创建jenkins服务。希望这一次,在发生故障时,状态将被保存下来:
这个命令与我们之前使用的命令的唯一区别是--mount参数。它告诉Docker在容器中将主机目录/mnt/efs/jenkins挂载为/var/jenkins_home。因为在所有节点上将/mnt/efs挂载为EFS卷,所以jenkins服务可以访问相同的文件,不管它会在哪个服务器上运行。
请稍等,直到服务开始运行。请执行service ps命令以查看当前状态:
让我们在浏览器中打开Jenkins UI:
给Windows用户的说明
Git Bash可能无法使用open命令。如果是这样,则请执行terraform output swarm_manager_1_public_ip来查找manger的IP,并在你选择的浏览器中直接打开URL。例如,应将前面的命令替换为以下命令:
如果输出为1.2.3.4,则应该在浏览器中打开http://1.2.3.4/jenkins。
这一次,由于Jenkins主目录被挂载为/mnt/efs/jenkins,因此,找到密码要容易很多。我们只需要从其中一个服务器输出文件/mnt/efs/jenkins/security/ initialAdminPassword的内容:
请复制密码并将其粘贴到Jenkins UI的管理员密码字段中。完成设置,如图14-3所示。(www.xing528.com)
图14-3 初始设置后的Jenkins主页面
我们将再模拟一次故障,并观察其结果。下面的命令与我们之前执行的命令相同,所以不用再解释了:
将看到登录页面,而不是返回到初始设置。状态得以保存,我们的Jenkins服务具有了容错能力。在最坏的情况下,当服务或整个节点发生故障时,将有短暂的停机时间,直到Swarm重新创建了发生故障的服务的副本。你可能会想:为什么要求你通过手动步骤来创建一个EFS并挂载它呢?这不是应该通过Terraform自动完成的吗?原因很简单。这个方案不值得自动化。它有很多缺点。
我们需要将所有服务的状态放到同一个EFS驱动器中。更好的方案是为每个服务创建一个EFS卷。这种方法的问题在于,每当有人向集群添加新的有状态服务时,都需要更改Terraform的配置。这种情况下,Terraform帮不上什么忙,因为这并不意味着要使用服务特定的配置。它应该作为一种方法来设置可以运行任何服务的群集。即使我们接受了所有服务都使用一个EFS卷,也仍然需要为每个服务创建一个新的子目录。把Terraform作为创建与服务相关的所有任务的基础设施和Docker的工具,难道不是更好吗?
幸运的是,有更好的方法来创建和挂载EFS卷。
在探索替代方案之前,请删除jenkins服务并退出服务器:
没有理由保留我们先前创建的EFS卷,所以请返回到EFS控制台(https://console.aws.amazon.com/efs),选择文件系统,然后单击“Actions”按钮,再单击“Delete File System”按钮。其余步骤,请按照界面上的说明操作。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。