我有一些docker服务器与他们之前的负载均衡器。 现在我想更新我的应用程序没有停机。 当一个docker停机并且不再可达时,负载均衡器将自动从列表中删除,所以这不是问题。
主要的问题是避免停机时间:所以,我必须确保一次只有一个docker重新启动 – 或者确保至less有N个docker在线!
目前,我正在使用一个简单的bash脚本,我需要手动等待一个docker重新上线,然后再重新启动下一个docker,等等。
现在bash对于这种东西并不是最理想的,我希望有更好的工具可以使整个任务自动化。 例如,如果第n个docker在线,我可以使用一个简单的ping URL http://jetty-number-n.com/ping来响应OK(200)。
我怎么能解决这个任务,并用哪个工具?
感谢@ceejayoz我find了可靠的滚动更新 。 但它仍然不是最理想的,因为我需要设置一个固定的超时时间。
Ansible相当简单。 粗糙的伪支持剧本:
--- - hosts: your_server_group sudo: yes serial: 1 tasks: - shell: reboot now - wait_for: port=22
盐有一个方便的批次选项。
salt -G 'os:RedHat' --batch-size 25% service.restart jetty
一次在25%的RedHat服务器上重新启动docker服务。
salt -N group1 -b 2 system.restart
在预定义的“group1”中重新启动服务器,每次2个。
木偶具有服务和订购的概念。 但木偶运行在一台服务器上。 所以它没有洞察到它运行的其他系统。
如果你想使用木偶,你可以这样做,所以一个主控服务器有一个初始化脚本来pipe理每个服务器的服务。 所以初始化脚本会在每台服务器上运行重新启动并返回状态码。 你可以做到这一点,并链接每个服务重新启动从这一台服务器和一个sorting,链接或通知和订阅转移到下一个。
您也可以为puppet编写一个自定义库,将一个服务器当作主控服务器,而不是使用init脚本。 它可以使用一个自定义的ruby库来pipe理每个服务器的服务。 设置起来有点复杂,但可以工作。
我现在正在使用Puppet,但是当第一个海报回复时,这听起来不像是木偶的理想首要任务。 我不能说话(虽然我想开始尝试)。
Puppet更倾向于同时推出更改/重新启动系统 – Puppet守护程序在每个客户端上运行,并按照预定间隔(默认每半个小时)在中央服务器上进行检查。 如果你想减less默认的时间安排,你通常使用不同的机制来调用木偶。
如果可以同时重启,那么重启一个服务就是定义一个清单
file { 'your_war_file.war': ensure => file, source => "puppet:///...", } service { 'jetty': subscribe => File['your_war_file.war'], hasrestart => True, }
资源指令,然后推出清单,让木偶做它的事情。 这假设你可以打电话
/etc/init.d/jetty restart
这可能是也可能不是可以接受的甚至是不可能的。
您也可以为此定义自己的自定义资源types,这绝对超出了简单的首次puppet任务的范围。
看看http://forge.puppetlabs.com/ ,但是,看看是否有其他人已经解决了类似的问题。
你想做的任务可以使用完整的,它绝对可以使用Puppet来完成。 我要专注于如何用木偶来实现它。
您可以使用puppet将WAR文件部署到docker,方法是使用正常的“文件”资源和为每个应用程序初始化的已定义资源。
木偶将从您指定的URL(在您的木偶大师)下载。 如果WAR文件修改时间改变,则Jetty能够重新部署WAR文件而不重新启动。 因此,如果您的清单在$JETTY_HOME/webapps创build一个副本,它应该由Jetty自动提取。 这样(或通过触摸context.xml),您不需要手动重新启动Jetty。
为了将WAR文件从Puppet Master下载到应用程序目录中,您将需要以下清单(replace$ JETTY_HOME):
define jetty::deployment($path) { notice("Deploying ${name} to http://$hostname:${appserver-jetty::port}/"), include jetty, file { "$JETTY_HOME/webapps/${name}.war": owner => 'root', source => $path, } }
并且您需要指示您的节点一个接一个地获取您的应用程序的特定版本(在确定它已经在其中一个节点上成功启动之后)。 这可以使用ENC(外部节点分类器)完成,或者,如果您不使用ENC,则可以通过修改每个节点(或一组节点)的site.pp节来完成:
node jetty-node1 { jetty::deployment { "servlet": path => '/srv/application/Servlet-1.2.3.war' } }, node jetty-node2 { jetty::deployment { "servlet": path => '/srv/application/Servlet-2.0.1.war' } }
include jetty线是必要的,只有当你想pipe理你的dockerconfiguration通过木偶使用例如。 https://github.com/maestrodev/puppet-jetty ,这个定义的资源需要一个appserver-jetty :: $ portvariables。 这个例子展示了最简单的方法,可以准确地控制哪个版本的应用程序由哪个节点提供服务。 这样,只有在节点1成功运行新版本之后,您才可以根据您的运行状况检查对节点进行脚本编写,并在node2上进行部署。
这个例子只是为了展示这个概念。
您可能想要查看这些额外资源以获取更多信息和想法:重新加载上下文: https : //stackoverflow.com/questions/13965643/auto-reloading-war-in-jetty-standalone
这是为了部署和pipe理tomcat,但是想法(和清单)是类似的: http : //www.tomcatexpert.com/blog/2010/04/29/deploying-tomcat-applications-puppet
这是一个IMO更好的select,可以直接复制WAR文件 – 使用本地软件包(例如RPM)来部署应用程序: http : //www.slideshare.net/actionjackx/automated-java-deployments-with-rpm