使用 puppet、ansible 或 fabric 进行滚动更新

使用 puppet、ansible 或 fabric 进行滚动更新

我有一些码头服务器,前面有一个负载均衡器。现在我想在不停机的情况下更新我的应用程序。当一个码头停机并且无法再访问时,负载均衡器会自动将其从列表中删除,所以这不是问题。

主要问题是避免停机:所以,我必须确保一次只有一个码头重新启动 - 或者确保至少有 N 个码头在线!

目前,我正在使用一个简单的 bash 脚本,我需要手动等待一个码头重新上线,然后再重新启动下一个码头,依此类推。

现在 bash 还不是最适合处理这类事情的,我希望有更适合的工具来使整个任务自动化。例如,我可以使用一个简单的 ping URL,http://jetty-number-n.com/ping如果第 n 个码头在线,它会响应 OK (200)。

我该如何解决这个任务以及使用哪种工具?

感谢@ceejayoz 我找到了滚动更新对于 ansible。但这仍然不是最理想的,因为我需要设置一个固定的超时时间。

答案1

使用 Ansible 可以很容易地做到这一点。粗略的伪 ansible 剧本:

---
  - hosts: your_server_group
    sudo: yes
    serial: 1
    tasks:
      - shell: reboot now
      - wait_for: port=22

答案2

Salt 有一个方便的批量选项。

salt -G 'os:RedHat' --batch-size 25% service.restart jetty

一次性在25%的RedHat服务器上重启jetty服务。

salt -N group1 -b 2 system.restart

重新启动预定义“group1”中的服务器,每次 2 个。

答案3

Puppet 有以下概念服务订购。但是 puppet 在单个服务器上运行。因此它无法洞察正在运行的其他系统。

如果您想使用 puppet,您可以让一个主控制服务器有一个用于管理每个服务器服务的初始化脚本。因此,初始化脚本将在每个服务器上运行重新启动并返回状态代码。您可以这样做,并将每个服务重新启动从这台服务器链接起来,然后排序、链接或通知并订阅以继续下一个服务器。

您还可以为 puppet 编写一个自定义库,它将把一台服务器视为主控制服务器,但不使用 init 脚本。它可以使用自定义 ruby​​ 库来管理每台服务器的服务。设置起来有点复杂,但可以工作。

答案4

您要执行的任务可以使用 ansible 完成,并且绝对可以使用 Puppet 完成。我将重点介绍如何使用 puppet 完成它。

您可以使用 puppet 将您的 WAR 文件部署到 jetty,方法是使用普通的“文件”资源和为每个应用程序初始化的定义资源。

Puppet 将从您指定的 URL(在您的 Puppet Master 上)下载。如果 WAR 文件的修改时间发生变化,Jetty 能够重新部署 WAR 文件而无需重新启动。因此,如果您的清单创建了一份副本,$JETTY_HOME/webappsJetty 应该会自动获取它。这样(或通过修改 context.xml)您就不需要手动重新启动 Jetty。

为了将 WAR 文件从 Puppet Master 下载到应用程序目录,您将需要以下清单(替换 $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仅当您想通过 puppet 管理 Jetty 配置时才需要此行。https://github.com/maestrodev/puppet-jetty并且此定义的资源需要一个 appserver-jetty::$port 变量。此示例显示了您可以精确控制哪个版本的应用程序由哪个节点提供服务的最简单方法。这样,您可以根据健康检查编写部署脚本,并且仅在节点 1 成功运行新版本后才在节点 2 上部署。

这个例子只是为了演示这个概念。

您可能需要查看这些其他资源以获取更多信息和想法:关于重新加载上下文:https://stackoverflow.com/questions/13965643/auto-reloading-war-in-jetty-standalone

这是用于部署和管理 tomcat,但想法(和清单)是类似的:http://www.tomcatexpert.com/blog/2010/04/29/deploying-tomcat-applications-puppet

在我看来,这是一个比直接复制 WAR 文件的更好的替代方法 - 使用本机包(例如 RPM)来部署您的应用程序: http://www.slideshare.net/actionjackx/automated-java-deployments-with-rpm

相关内容