了解如何将 CI/CD 添加到您的应用程序中
欢迎在推特上关注我,我很乐意接受您对话题或改进方面的建议。/克里斯
CI/CD。你可能不止一次听说过这个词,甚至可能每天都在用。无论如何,我们将解释它是什么,以及为什么它是每个开发人员工具箱中不可或缺的工具。敬请期待。
简而言之,本文将解释什么是 CI/CD。我们还将向您展示如何使用 Azure 为您的应用程序设置一个简单的 CD 流程。本文内容较为详尽,但会带您从源代码开始,逐步完成部署设置,并教您如何使用部署槽进行 A/B 测试和蓝绿部署。
这是一系列文章。
- 第一部分,部署我们的 GitHub 代码库,我们在这里
- 第二部分 - Azure DevOps,我们将学习如何使用管道、构建管道、发布管道,以及如何配置 YAML 文件来帮助我们 -待编写
最后,我们将学习如何使用部署槽进行蓝绿部署和 A/B 测试。
需要说明的是,我们可以使用两种方法在 Azure 中设置持续交付 (CD)。然而,只有一种方法可以同时实现持续集成 (CI) 和持续交付 (CD),那就是使用 Azure DevOps。
本文将介绍一种更简单的实现持续交付 (CD) 的方法。如果您希望同时实现持续集成 (CI) 和持续交付 (CD),恐怕您需要等到本系列的第二部分。
但别担心,即使这种方法更简单,并且无法像 Azure DevOps 那样实现那么多功能,它仍然可以为开发人员提供很多价值。
参考
- 设置持续部署本文档页面介绍了如何通过 AppService 和 Azure DevOps 设置持续部署。
- 下载 Node.js我们即将部署的应用将使用 Node.js。如果您的计算机上没有安装 Node.js,您可以轻松地进行安装。
- 免费 Azure 帐户为此,我们将使用 Azure。如果您还没有帐户,注册非常简单。
- Azure DevOps 概述
- 部署槽位
什么是 CI/CD?我为什么需要它?
CI/CD 代表持续集成 (CI) 和持续部署 (CD)。
听起来不错,但能解释一下吗?
CI 是指将团队中不同开发人员的更改尽快合并到主线(通常是 master 分支)中,最好一天合并几次。
在持续集成(CI)中,有两个集成方面的问题需要解决:
- 该术语的定义
- 目标
定义
我们先来谈谈第一点,也就是这个术语本身。不同的开发人员负责编写代码的不同部分。你肯定希望他们的修改能尽快合并到主分支。如果时间过长,就可能导致耗费大量时间在合并和解决合并冲突上。
目标
持续集成 (CI) 的主要目标是确保所有人的更改都能尽快合并到主分支。其次,我们还需要保证代码的可运行性。任何人都不希望合并到有问题的代码。作为这一流程的一部分,我们希望进行自动化测试,代码审查也是确保最终合并的代码质量足够好的一种手段。
您可以在这里阅读更多相关信息:
https://codeship.com/continuous-integration-essentials
https://dev.to/quii/gamifying-continuous-integration-o1d
明白了吗?
太好了,我喜欢高质量的工作。那持续部署呢?别告诉我它意味着我一把代码推送到代码库就立刻部署?这听起来很危险。
实际上,过去我们发布版本之间会间隔几个月。我们有庞大的QA团队对每个细节进行测试,几周后他们会签字确认所有内容,每次发布都会像传递奥运火炬一样,变成一场漫长的脚本传递仪式。
这有什么问题吗?听起来很负责,有质量保证团队,测试也很充分等等。当然,我也希望能够更频繁地部署,但安全第一。
是啊,现在是2020年。这意味着我们看待事物的方式不同了。我们应该以一种能够一键构建所有必要组件的方式来设置软件和流程,最终你应该得到一个可以运行的软件成品。
听起来像做梦一样。但你知道,我们有不同的团队负责不同的组件,他们都有自己的待办事项、优先级和策略。我有没有提到我们还有运维人员,还有运维和开发人员……嗯……我不确定这能不能实现?
没错,持续集成(CI)相对容易,对大多数人来说,在软件中添加测试并在每次推送代码时运行测试是完全可以实现的。而持续部署(CD)则更复杂,因为问题通常不在于技术层面,而在于流程、人员之间的沟通以及使用工具来实现目标。
好的,假设我的开发部门能够组织得井井有条,让所有组件团队都能互相沟通,制定出可靠的版本控制策略等等,那我还能实现持续交付吗?
或许如此,但这需要持续不断的努力,不仅要确保各个组件团队之间沟通,还要确保开发团队和运维团队之间沟通协作。因为归根结底,关键在于人、流程和工具。
你说过你会教我怎么做,对吧?
是的,没错。我们选择使用 Azure 作为我们的首选工具。希望我接下来要展示的原则和模式具有足够的通用性,以便您可以轻松地将其应用到您偏好的任何系统和工具中。
两种方法
在 Azure 上处理 CI/CD 时,很容易将其视为我们可以采取两种不同的方法或路径来将 CI/CD 添加到我们的代码项目中。
- 本文将介绍一种更简便的方法,即如何将代码仓库连接到 Azure。这样,每次向分支推送代码时,它都会自动部署。此外,本文还会介绍部署槽位及其用途。
- 更高级的方法中,我们会将代码仓库连接到 Azure DevOps 项目,并设置构建管道和发布管道,以便您能够真正掌控每个步骤。我们将在后续文章中详细介绍这种方法。
演示
正如我们在上一节中所述,我们将展示如何使用更简单的方法设置 CI/CD 。这意味着我们将从一个 GitHub 代码库开始。在此之前,让我们先构建一些东西:一个使用 Express 的 Node.js 应用。它将成为一个 REST API,我们可以通过 HTTP 和部署 URL 与之交互。
创建我们的项目
为此,您需要安装 Node.js。以下是安装页面的链接:
让我们从电脑开始。找到一个目录,然后输入以下内容:
npm init -y
这将使用智能默认值启动一个 Node.js 项目。接下来,创建一个应用程序文件app.js:
touch app.js
让我们添加以下代码app.js:
// app.js
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on ${port} port!`))
之后,express使用以下命令安装我们的 Web 库:
npm i express
这将把它安装到一个名为 . 的目录中node_modules。
添加 Git
现在我们来创建一个 Git 仓库。要初始化它,请输入:
git init
.gitignore同时创建一个文件:
touch .gitignore
请将以下内容添加到.gitignore:
node_modules
package-lock.json
以上措施将确保我们不会对不需要的文件和目录进行版本控制。
好的,请前往 GitHub 并创建一个代码仓库。因为我们还没有推送代码到该仓库,所以它应该会显示类似这样的辅助信息:
echo "# name of app" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/<your user>/<your app>.git
git push -u origin master
由于我们已经完成了大部分步骤,所以只需输入(请记住将用户名和仓库名称替换为您的数据):
git remote add origin https://github.com/<your user>/<your app>.git
在将代码推送到新的 GitHub 仓库之前,我们需要添加第一个提交。请输入以下命令:
git add .
git push -m "first commit"
现在,让我们把代码推送到代码仓库:
git push -u origin master
在 Azure 中创建 Web 应用
太好了!现在我们的代码已经推送到 GitHub 代码库了。接下来需要添加 CI/CD 流程。如果您还没有 Azure 帐户,请点击此链接注册一个:
好的,我们登录到 Azure 门户。
portal.azure.com
我们将做两件事:
- 在配置过程中,我们将为我们的应用创建一个资源。我们将选择一个模板
Web app。这将为我们提供一个专属的应用运行环境。根据我们的选择,系统会自动安装一些库,以确保应用流畅运行。关键在于,我们只需选择一些选项,其余的都由系统自动完成。这是一个平台即服务 (PaaS),无需任何管理。 - 创建好 Web 资源后,我们就可以将其与 GitHub 代码库连接起来了。接下来,我们将借助 Azure 应用服务 ( App
App ServiceService)。Azure 应用服务是 Azure 上的一项服务,它可以为我们部署和运行Web 应用。它还可以处理更多任务,例如扩展、安全等等。不过,就本文而言,它主要用于托管我们的 Web 应用。
提供我们的网络资源
登录后,我们要创建一个Web应用程序。在我们将代码推送到该应用程序之前,它只是一个空壳。
在门户网站的左上角,你会看到一个类似这样的按钮:
点击该按钮,然后Web App在搜索框中输入内容。点击Create后,您将进入如下所示的页面:
- 订阅,请选择您要使用的订阅方案。
- 资源组是一个逻辑存储桶。您可以将所有相关的 Azure 资源(例如数据库、Web 应用、存储帐户等)放置在此处。您可以选择创建新的资源组或使用现有的资源组。
- 名称必须唯一,因为它将构成一个任何人都可以访问的全局 URL。完整的 URL 将是
<name>.azurewebsites.net: - 发布
Code选项有“发布”和“发布”两个选项Docker Container。这次我们将选择“发布”Code,但我们将在另一篇文章中介绍如何使用“发布”Docker Container选项。 - 运行时堆栈,在这里我们可以选择不同的编码环境,例如
Node.js.NETASP.NET Core、Python.NET 等。这意味着我们的 Web 应用将部署到的机器上,会安装与你的选择相对应的库。我们选择 .NETNode.js 12 LTS。 - 操作系统方面,我们暂且选择Linux。当然,Windows也是个不错的选择。
- 地区,请选择离您最近的地区
- 应用服务计划,选择默认
现在,点击Review and Create,然后在接下来的最后一步点击Create。
连接到我们的存储库
这大概需要一分钟左右的时间,但配置完成后,您应该会看到类似这样的界面:
我们Deployment Center从左侧菜单中进行了选择,如果向右看,会看到标题“持续部署”。向下滚动一点,我们就能看到该标题下的所有选项:
如您所见,代码来源有四个主要选项可供选择。我们将选择其中一个GitHub选项。
接下来,我们会被要求选择build provider。我们可以在App Service build service和之间进行选择Azure Pipelines。我们将选择第一个选项:
接下来,我们需要进行配置。我们通过选择来完成此操作。
- 组织,我们在 GitHub 上所属的组织。
- 仓库,这是我们刚刚创建的仓库。
- 分支,这很有意思。我们最初创建代码库时,只有一个
master分支。但随着代码库的增长,我们会拥有大量的分支,这在进行蓝绿部署和 A/B 测试时非常有用。目前,请选择master。
填写完所有信息后,您将进入摘要页面。点击Finish button。
如上图所示,接下来显示的是应用程序的运行状态和提交历史记录页面。点击“日志”下方的图标可以了解更多应用程序状态,让我们点击查看:
好的,上面我们看到一些系统日志,最后一条日志告诉我们Deployment successful:
太好了,我们的应用现在上线运行了吗? :)
好,我们来看看。点击Overview左侧菜单,在标题下方输入地址URL,然后就会出现一个提示音(此处应有鼓声)。第一次操作可能需要几秒钟,因为它需要安装一些库文件,提示音继续;)
现在怎么样?:)
还没完全到,再过几秒钟就到了:
旁白——这是一张白纸。
怎么了? :/
你能猜到问题出在哪里吗?
不,所以我才问,到底出了什么问题?
你有一个 Node 应用,而 Node 应用需要运行什么?
某种启动命令?
他的名字叫宾果。
所以我需要在 package.json 文件中添加一个启动指令。
是的。请在您的scripts部分添加:
"start": "node app.js"
接下来怎么办?
现在,我们需要将其提交到代码仓库并推送到 GitHub。由于我们之前的设置,Azure 将会识别到它并重新部署,这样我们就能得到一个可以正常运行的应用。请执行以下操作:
- 将上述代码更改添加到
package.json git add .git commit -m "adding this change cause the author of the article tricked me"git push
太好了,真的管用,不过我不会忘记你骗了我。
置信区间
CI 代表持续集成,意味着我们会尽快将代码集成到共享代码库中。此外,我们希望在代码发生更改后立即运行额外的自动化测试。我们运行这些测试是为了确保我们正在开发的组件仍然能够正常工作,并且可能还能与其他组件协同工作。
那么我们如何将 CI 添加到其中呢?
我知道我知道。我可以安装 Jest,编写测试,添加
test到scriptsin 中package.json,如果测试失败,部署也会失败,对吗?
不,不行,抱歉。我们需要 Azure DevOps 来实现这个功能。另外,你需要在 YAML 文件中指定要运行这些测试,仅仅创建一些测试并指望 Azure DevOps 会自动识别是不够的。这些内容在第二部分都有详细介绍。
那么下一篇文章是什么呢? :)
你真是个令人失望的人,呸!
对不起 :)
除了CD之外肯定还有其他选择吧?
是的,有部署槽位 :)
它们真的有效吗?
它们确实有效。我们接下来就来谈谈它们。
部署槽位
那么,那些是什么呢?
想象一下,你可以将资源部署到不同的插槽,但使用同一个 URL。
我为什么要那样做?
假设你想控制应用的流量,让 50% 的流量流向一个位置,50% 的流量流向另一个位置。明白我们能用这个做什么了吗?
嗯,我想是这样的,如果是为了测试新版本或做实验,我可以把一半发送到一个槽位,另一半发送到另一个槽位?
没错!:)
创建插槽
所以,点击Deployment slots左侧菜单,它应该看起来像这样:
如上所示,我们只有一个名额,即生产。
现在我们来思考一下。我们希望另一个位置放什么?
这取决于我们想用它做什么。不如我们做个实验吧?
好的。那我们来做个实验,把实验代码放到一个特性分支上。
所以这意味着我们需要:
- 在 Git 中创建分支
- 我们的改变
- 将分支推送到 GitHub
- 创建一个看起来几乎与生产分支相同的槽位,但我们希望它从我们的新分支部署。
创建分支
git checkout -b feature/new-experiment
我们的改变
好的,我们来回顾一下应用程序的代码。它目前看起来是这样的:
// app.js
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
const products = [
{
id: 1,
name: "Star Wars"
}
];
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on ${port} port!`))
为了方便起见,我们修改一下,添加一条额外的路由/products。修改后的代码应该如下所示:
// app.js
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
const products = [
{
id: 1,
name: "Star Wars"
}
];
app.get('/', (req, res) => res.send('Hello World!'))
app.get('/products', (req, res) => products)
app.listen(port, () => console.log(`Example app listening on ${port} port!`))
将更改推送到 GitHub
好的,我们提交这个:
git add .
git commit -m "adding new route /products"
并将其推送到我们的代码仓库:
git push
好的,我们已经将这个分支推送到 GitHub,但是由于我们的持续交付 (CD) 配置监听的是这个master分支,所以部署没有任何进展。是时候通过创建一个新的部署槽来改变这种情况了。
创建插槽
让我们返回门户网站和 Web 服务资源。Deployment slots在左侧菜单中选择。接下来,点击Add slot顶部菜单,如下所示:
现在,克隆我们现有的生产槽位,因为它包含了我们想要的大部分内容。
不过我们需要更改一个细节,即它应该查看哪个分支上的更改。
1.请在列表中再次点击选择我们的分行。这将带您进入一个新页面。
Deployment center请从左侧菜单中选择。- 点击
Github并Continue。 - 点击
App Service Build Service,然后Continue。
现在填写Organization与生产环境相同的内容。Repository与生产环境相同,最后将其更改Branch为我们的特性分支:
现在保存这个新槽位。它应该会立即开始建造。
控制交通
现在我们有两个部署位,可以决定如何控制网站流量了。我们可以通过更改部署位旁边的百分比文本框来实现。
因为我们正在进行一项实验,所以我们希望将 x 个用户引导至生产环境 URL,并将 y% 的用户引导至我们的功能分支。实验成功与否的具体衡量标准取决于您自己。不过,让我们先来探讨一下 A/B 测试的运作方式,以便更好地理解它。A/B 测试旨在解答某个问题。通常,这意味着我们会提出诸如“这个设计是否比那个设计更好”之类的问题。“更好”通常定义为用户是否通过输入或点击等方式与特定内容进行交互。此时,您可以选择修改现有页面的部分内容,或者完全替换整个页面。
另一种 A/B 测试类型是看看用户对逻辑更改的看法,例如——如果我们更改网站上的折扣百分比,作为一项实验,用户还会购买该商品吗?
正如你所看到的,部署槽位确实能帮到我们。
- 不同的内容可以部署到不同的插槽中
- 流量控制可以帮助我们将一定比例的用户引导至特定的实验。
蓝/绿部署 - 交换槽位
我们来看部署槽位的另一个应用场景:零停机部署。零停机是什么意思呢?这意味着我们已经更新了网站,现在想要部署最新版本。我们希望以负责任的方式完成部署,确保用户不会感觉到网站宕机,也就是零停机。而部署槽位恰好可以实现这一点。
我们所说的“负责任”是什么意思呢?持续部署不仅仅意味着频繁部署,还意味着我们拥有快速纠正错误的工具。能够快速纠正错误让我们更有信心频繁部署。那么,我们如何纠正错误呢?答案是蓝绿部署。这意味着我们有两个容器或槽位。一个容器存放着在生产环境中运行的软件,我们称之为 PROD。另一个容器存放着我们想要发布的软件,我们称之为 CANARY。我们希望采用以下策略:
- 迁移用户,逐步将用户发送到 CANARY 存储桶。
- 请监控我们的应用程序和错误日志,以发现任何错误。
- 如果出现错误,请将 CANARY 用户比例设置为 0%,从而将 CANARY 用户送回生产环境。
- 修正错误,然后从第一步重新开始。
- 否则,如果没有错误,请逐步增加 CANARY 用户数量。在某个阶段,您可能会对 CANARY 版本充满信心,并选择将其作为新的生产环境。您现在可以执行的操作是选择“
swap将 CANARY 版本设为新的生产环境”。
频繁且自信地部署——是不是很棒?:)
概括
让我们总结一下学习内容。本次学习的主题是学习如何为我们的应用程序添加持续部署功能。为此,我们需要……
- 创建一个应用程序,
- 将应用推送到 GitHub 代码库。
Web App在 Azure 中创建资源。- 将存储库与我们的
Web App资源连接起来
此外,我们还学习了如何使用名为部署槽的概念进行 A/B 测试,以及进行蓝绿部署。
不过需要指出的是,如果你只是想做一些小测试,而且项目规模很小,只有一两个开发人员,那么这种方法就非常合适。原因在于它的功能比较有限。如果你需要持续集成(CI),那么你可能还需要门控和管道之类的概念。Azure DevOps 支持这种方法所缺乏的所有功能,而这恰好也是本系列下一篇文章的主题。
文章来源:https://dev.to/azure/learn-how-you-can-add-ci-cd-to-your-app-2o5a














