在Jenkins上为多个环境构建工件并将它们上传到S3

时间:2013-07-29 00:56:47

标签: java deployment amazon-s3 jenkins

环境:

  • 大约十几项服务:WAR和JAR(使用Tanuki包装器运行)
  • 每个服务都被部署到开发,登台和生产:环境使用不同的web.xml文件,Spring配置文件(在Tanuki包装器上设置),...
  • 我们希望将工件存储在AWS S3上,以便我们的EC2实例可以轻松获取这些工件:一些服务在多台计算机上运行,​​AutoScaling实例在引导后自动获取最新版本,开发工件应在部署后自动部署更新,...

我们当前的部署过程如下所示:

  1. Jenkins构建并测试我们的代码
  2. 一旦我们满意,我们会使用Artifactory plugin进行发布(仅适用于生产部署;开发和暂存工件基于普通的Jenkins构建)
  3. 我们为每个项目(开发,登台,制作)使用Promoted Builds plugin和3个不同的促销作业来构建所需环境的工件,然后将其上传到S3
  4. 这种方式大多没问题,但是我们遇到了多种烦恼:

    1. 由于无法提交到存储库,Artifactory插件无法标记和更新源代码(这可能特定于CloudBees,我们的Jenkins提供程序)。没关系 - 我们可以手动做到这一点。
    2. Jenkins S3 plugin无法正常使用多个上传目标(我们为每个环境使用一个) - 它会尝试上传到所有目标并在保存配置时复制设置:{{ 3}}。没关系 - 我们使用shell脚本进行上传,工作正常。
    3. 促销作业有时会失败,因为它们可以在与原始构建不同的实例上运行 - 导致失败(构建因为文件丢失)或者过时的构建(因为旧版本正在使用)。同样,由于CloudBees提供的特定设置,可能会发生这种情况。这可以通过再次运行构建来修复,并希望促销作业在与此次构建相同的实例上运行(这在我的理解中是纯粹的运气)。
    4. 我们已经被CloudBees建议在运行促销作业之前进行代码检查,因为工作区是短暂的,并且不保证它存在或者它是最新的。但是,促销作业中的shell脚本似乎不尊重另一个JENKINS-18563中所述的环境变量,即使它们链接在textarea字段下面。所以svn checkout ${SVN_URL} -r ${SVN_REVISION}不起作用。

      我很确定这可以通过一些解决方法来解决,但我肯定必须做一些非常错误的事情。我假设许多其他人正在以类似的方式部署他们的应用程序,必须有更好的方法 - 没有各种解决方法和烦恼。

      感谢您的任何指示并阅读所有内容!

1 个答案:

答案 0 :(得分:2)

  • 您面临的最大问题是您确实希望在促销活动中进行构建。升级的构建插件旨在执行一些小操作,主要是在构建的存档工件上,或者执行标记或其他此类操作。

    • 设计确保它在奴隶上获得工作空间。但是(这是Jenkins的一般情况,而不是特定于CloudBees)首先,您获得的工作空间不必是用于您尝试推广的构建的工作空间。它可能是:

      1. 空白工作区
      2. 项目最新版本的工作区(可能是比您尝试推广的版本更新)
      3. 项目旧版本的工作区(当你无法进入拥有该项目最新版本的奴隶时)
      4. 现在,您完全取决于Jenkins群集所承受的负载。在CloudBees上运行时,您通常最有可能遇到上述两种情况之一。

      5. 因此,您在促销活动中所采取的行动应“自给自足”。因此,例如,他们会将存档的工件复制到特定的目录中,然后使用这些复制的工件来完成他们的工作#39;或者它们将触发从提升的构建中传递参数的下游构建。或者他们将在不使用任何本地状态的情况下在远程服务器上执行某些操作(即在蓝绿色部署中翻转交换机)

  • 在你的情况下,你正在多方面战斗。你正在争夺的第二个战线就是你在和Maven战斗。

    • 当活动的构建配置文件产生不同的,非等效的工件时,Maven不喜欢它。
    • Maven可能会使用release配置文件生成一个版本的工件,JavaScript缩小并且可能调试信息被剥离(尽管如果可以避免它会更好)......但这是因为两个工件是等价的。 JavaScript缩小的webapp应该与未缩小的webapp一样好(除非缩小引入错误)
    • 您使用配置文件来构建完全不同的工件。这很糟糕,因为Maven不会将活动配置文件存储为部署到Maven存储库的信息的一部分。因此,当您声明对其中一个工件的依赖关系时,您不知道在构建该工件时哪个配置文件处于活动状态。这种常见的副作用是你最终得到了裂脑工件,其中复合工件的一部分与开发数据库通信,而另一部分与生产数据库通信。当开发人员在他们想要切换到构建生产版本时,他们可以通常运行mvn clean install -Pprod && mvn clean install -Pprod,因为他们过去已经被裂脑工件烧毁了。这是一个糟糕设计的症状,而不是Maven的问题(除了能够创建Maven工件的特定于体系结构的构建之外会很好......但是它们可以构成自己的问题)。
    • 处理为不同部署环境创建不同工件的“Maven方法”是使用单独的模块重新打包“通用”工件。正如Maven处理不良体系结构的微妙方法一样,您需要为要定位的每个环境添加重新包装模块...这会阻止具有许多不同的目标环境...(即,如果您有10个不同的目标环境...)要部署的webapps / services和三个目标部署环境,你将拥有10个通用模块和3x10目标特定模块......提供40个模块构建)并希望鼓励你找到一种方法让工件在部署时自行发现其正确的配置
  • 我怀疑破解解决方案的最安全方法是依赖复制存档的工件。

    1. 在主构建期间,创建一个文件,该文件将检出与正在构建的版本相同的修订,例如。

      echo '#!/usr/bin/env sh' > checkout.sh
      echo "svn revert . -R" >> checkout.sh
      echo "svn update --force -r ${SVN_REVISION}" >> checkout.sh
      

      虽然您可能想要写一些更强大的东西,例如确保您使用SVN工作副本,确保工作副本使用正确的远程URI,删除任何不需要的文件等

    2. 确保您创建的脚本已存档。

    3. 在促销过程开始时添加,将已存档的checkout.sh复制到工作区,然后运行该脚本。您应该能够像以前一样完成所有后续的促销步骤。

  • 更好的解决方案是为每个促销流程创建构建作业,并将SVN修订版作为构建参数传递(但需要更多工作才能为您设置(因为您已经有了促销流程)设置)

  • 最佳解决方案是修复您的体系结构,以便生成从目标环境中发现其正确配置的工件,因此您可以将相同的工件部署到每个所需的环境,而无需重建工件。