首页 理论教育 微服务运维实战第2卷:定义流水线步骤

微服务运维实战第2卷:定义流水线步骤

时间:2023-11-05 理论教育 版权反馈
【摘要】:很显然,是通过Shell执行的git pull命令。更确切地说,我们将使用Jenkins流水线git步骤,这个步骤在后台使用一个Git插件。Pipeline的Pull阶段如下:git步骤是通过流水线域特定语言提供的许多步骤之一,它用于克隆代码。你可以在流水线步骤参考页面中找到更多信息。采取这种方式的原因在于当事情失败时Jenkins的表现。具体来说,我们定义了Docker客户端连接到在远程主机上运行的Docker Engine所需的全部内容。

微服务运维实战第2卷:定义流水线步骤

在开始执行这些步骤之前,必须简要地提一下,人们一般使用几种不同的方法来定义Jenkins的作业。有些人更喜欢使用Jenkins插件,更极端的情况下,这种方法会导致每个动作都通过插件执行。需要执行Gradle任务吗?有一个(或两个)Gradle插件。需要对Docker做些什么吗?很可能有一打Docker插件。如何使用Ansible进行配置管理?也有一个Ansible插件。

我不认为过分依赖插件是一件好事。我相信,即使没有Jenkins,也应该有能力创建大部分(如果不是全部)的自动化。毕竟,使用一个能够让我们少写一行命令的插件就更有意义了?我不这么认为。这并不意味着我们不应该使用插件,但只有当其带来真正的和具体的额外价值时才应该使用它们。例如Git插件,它可以评估代码是否应该克隆还是拉取,它可以帮助管理认证,并且提供一些自动填充的能够与其他步骤结合使用的环境变量

应该总是使用Git插件吗?不是的。假设我们要做的只是在已克隆的代码库中进行简单的拉取操作,不需要身份验证并且在后面的步骤中不会使用某些拉取信息(例如,提交ID)。在这种情况下,最简单的做法可能就是最好的选择。从Git代码库拉取代码的最简单方法是什么?很显然,是通过Shell执行的git pull命令。

只有当我们知道正在做什么,并且以与CI/CD工具无关的方式完成流程时,才应该使用Jenkins(或任何你选择的工具)并将整个流程结合在一起。这样就能理解流程,并且能够牢牢掌控要做的事情,不仅是从纯粹的自动化角度,而且可以从工具、流程和体系结构选择的角度。所有的部件都需要以一种有机和高效的方式协同工作。如果能够做到这一点,Jenkins就像胶水一样将它们联系在一起,而不是作为我们开始工作时的基础。

现在来定义第一阶段所需的步骤。目标非常简单,从Git存储库获取代码。为了使事情稍微复杂一点,可能需要克隆或拉取代码。由于第一次构建时什么都没有,所以必须克隆代码。所有后续的构建只要将更新拉取到已克隆的代码中。虽然编写执行该逻辑的脚本代码相对简单,但这是使用Jenkins插件的一个绝好例子。更确切地说,我们将使用Jenkins流水线git步骤,这个步骤在后台使用一个Git插件。

Pipeline的Pull阶段如下:

git步骤是通过流水线域特定语言(Domain Specific Language,DSL)提供的许多步骤之一,它用于克隆代码。如果代码已经被克隆过,那么将会直接拉取。你可以在流水线步骤参考(https://jenkins.io/doc/pipeline/steps/)页面中找到更多信息。

请注意,在现实世界中,我们会在代码库中创建一个web hook。无论何时有了新的提交,都会触发此作业。现在,我们将通过手动触发作业来模拟web hook。

可以通过从scripts/go-demo-pull.groovy(https://github.com/vfarcic/cloud-provisioning/blob/master/scripts/go-demo-pull.groovy)复制并粘贴代码来替换现有的流水线定义。完成后,请运行作业并观察构建日志。

让我们继续。

接下来的代码是前面章节中使用的命令的变体,用来运行单元测试并构建一个新的Docker镜像

我们将整个阶段封装在定义COMPOSE_FILE变量的withEnv块中。这样,每次执行docker-compose时,都不需要重复-f docker-compose-test-local.yml参数。请注意,马上要定义的所有其他阶段也应该位于withEnv块内。

Unit阶段内的步骤与我们在手动执行流程时所采用的步骤相同。唯一的区别是,这一次,我们把这些命令放在sh DSL的步骤中。它的目的很简单,用来运行一个shell命令。

现在将跳过这个作业并进入下一个阶段:

Staging阶段有点复杂,这些命令位于try/catch/finally块中。采取这种方式的原因在于当事情失败时Jenkins的表现。如果前一阶段Unit中的某个步骤失败,则整个流水线构建将终止。当没有额外的动作时,这很适合我们。但是,在Staging步骤的情况下,要移除所有依赖容器并释放资源以做他用。换句话说,无论Staging测试的结果如何,docker-compose down命令都应该被执行。如果你是程序员,则可能已经知道finally语句总是被执行,而不管try语句是否产生错误。在我们的例子中,finally语句会停止构成此Docker Compose项目的所有容器。

现在进入发布阶段:

这个阶段没有神秘的东西,只是重复前几章中执行的相同命令,镜像被标记并推送到注册表中。

请注意,我们使用BUILD_NUMBER向标签提供唯一的版本号。它是Jenkins内置的环境变量之一,用于保存当前正在执行的构建的ID值。

Prod-like阶段将引入额外的警告,如下所示:(www.xing528.com)

由于使用滚动更新来替换旧版本,所以必须在整个过程中都运行测试。虽然可以创建一个脚本来验证是否更新了所有实例,但(这次)又不想搞得太复杂,所以我们直接运行十次测试。根据你测试的平均持续时间和更新所有实例所需的时间,可能要根据需要对其进行调整。出于演示的目的,在类生产环境中进行十轮测试应该足够了。

总之,在这个阶段,我们正在使用新版本更新服务,并在更新过程中运行十轮测试。

请注意,我们声明了更多的环境变量。具体来说,我们定义了Docker客户端连接到在远程主机上运行的Docker Engine所需的全部内容。

我们差不多完成任务了,现在已在类似生产环境中测试了该服务,可以将其部署到生产集群中。

唯一的区别是,这一次,DOCKER_HOST和PROD_IP变量都指向生产集群中的一台服务器。其余的与Prod-like阶段的相同。

请使用脚本/go-demo.groovy中的代码替换现有的流水线定义。完成后,请运行作业并观察构建日志。

稍等片刻,将执行完成作业,新版本将在生产群集中运行,如图6-11所示。可以通过执行service ps命令确认新版本的服务更新确实成功了:

图6-11 Jenkins流水线阶段视图界

service ps命令的输出如下(为简洁起见,删除了ID):

就是这样!我们有了一条完整可用的(活蹦乱跳的)持续部署流水线。如果将WebHook添加到托管代码的GitHub存储库中,则每次有新的提交时,都会运行流水线。因此,除非流水线中的某个步骤失败,否则新版本将部署到生产环境中。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈