八、部署

在前面的章节中,您已经学习了如何基于微服务开发应用程序。现在,是时候了解应用程序的部署了,学习自动化和回滚应用程序的最佳策略,并在需要时进行备份和恢复。

依赖关系管理

正如我们在第 5 章微服务开发中提到的,Composer是最常用的依赖关系管理工具;它可以帮助我们在部署过程中将项目从开发环境转移到生产环境。

对于部署过程的最佳工作流是什么,有一些不同的观点,所以让我们看看每种情况的优缺点。

作曲家需要开发

为了在开发环境中使用,Composer 提供了一个关于其composer.json的部分,称为require-dev,当我们需要在应用程序上安装一些不需要在生产环境中使用的库时,我们必须使用它。

正如我们已经知道的,使用 Composer 安装新库的命令是composer require library-name,但是如果我们想安装新库,例如测试库、调试库或任何其他在生产中没有意义的库,我们可以使用composer require-dev library-name。它会将库添加到require-dev部分,当我们将项目部署到生产环境中时,我们应该在执行composer install --no-devcomposer update --no-dev时使用--no-dev参数,以避免安装开发库。

该.gitignore 文件

使用.gitignore文件,可以忽略您不想跟踪的文件或文件夹。尽管 Git 是一个版本控制工具,但许多开发人员在部署过程中使用它。.gitignore文件包含文件和文件夹的列表,这些文件和文件夹在更改时不会在存储库中被跟踪。这通常用于上载包含用户上载的图像或任何其他文件的文件夹,也可用于供应商文件夹,该文件夹包含项目中使用的所有库。

供应商文件夹

vendor文件夹包含应用程序中使用的所有库。如前所述,关于如何使用vendor文件夹,有两种不同的思考方式。为了获得vendor文件夹,在制作中加入作曲家有其优点和缺点部署应用程序或将开发中使用的库下载到生产中时,从存储库中删除文件夹。

部署工作流

根据项目需要,每个应用程序中的部署工作流都可能不同。例如,如果您希望将整个项目(包括vendor文件夹)保留在存储库中,或者如果您希望在项目部署后从 Composer 获取库。在本章中,我们将介绍几个最常见的工作流。

存储库上的供应商文件夹

第一个部署工作流将整个应用程序放在存储库中。这是我们第一次在开发环境中使用 Composer,并将vendor文件夹推送到存储库中,因此所有库都将保存在存储库中。

因此,在生产时,我们将从存储库中获取整个项目,而无需进行 Composer 更新,因为我们的库是在部署时投入生产的。所以,在制作中不需要作曲家。

vendor文件夹包含在存储库中的优点如下:

  • 您知道,同样的代码(包括库)也用于开发。
  • 在生产中破坏更新库的风险很小。
  • 部署过程中不依赖外部服务。有时,这些库在特定时刻不可用。

在存储库中包含vendor文件夹的缺点如下:

  • 存储库必须存储已存储在 Composer 上的库。如果您需要许多或大型库,那么所需的空间可能是一个问题。
  • 您存储的代码不是您的。

制作中的作曲家

第二个部署工作流有两种不同的处理方式,但都不需要将vendor文件夹存储在存储库中;一旦代码部署到生产环境中,他们将从 Composer 获得库。

一旦代码部署到生产环境中,composer update命令将在部署过程中手动执行或自动执行。****

****在生产中运行 Composer 的优点如下:

  • 您正在存储库中节省空间
  • 您可以在生产中执行–优化自动加载,以便映射添加的库

在生产中运行 Composer 的缺点如下:

  • 部署过程将取决于外部服务。
  • 更新包时,在某些情况下存在重大风险。例如,如果库突然被修改或损坏,应用程序将中断。

前端依赖项

有必要知道,前端也可能有管理依赖关系,因此可以选择是否将其放在存储库中。Grunt 和 Gulp 是应用程序中自动化任务最常用的两种工具。此外,如果基于 microservices 的应用程序具有前端部件,则应使用以下工具来管理样式和资产。

咕哝

Grunt是一种自动化应用程序任务的工具。Grunt 可以帮助您压缩或缩小 JS 和 CSS 文件,优化图像,甚至帮助您进行单元测试。

每个任务都是由一个基于 Javascript 开发的 Grunt 插件实现的。此外,它们使用 Node.js,因此它使 Grunt 成为一个多平台工具。您可以在查看所有可用的插件 http://gruntjs.com/plugins

无需学习 Node.js,只需安装 Node.js,就可以使用节点打包模块来安装 Grunt(以及许多其他软件包)。安装 Node.js 后,运行以下命令:

npm install grunt-cli -g

现在,您可以创建一个将由 NPM 命令读取的package.json

    {
      "name": "finding-secrets",
      "version": "0.1.0",
      "devDependencies": {
        "grunt": "~0.4.1"
      }
    }

然后,npm install将安装package.json文件中包含的依赖项。Grunt 将存储在node_modules文件夹中。安装 Grunt 后,需要创建一个Gruntfile.js来定义自动任务,如下代码所示:

    'use strict';
    module.exports = function (grunt) {
    grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
    });
    //grunt.loadNpmTasks('grunt-contrib-xxxx');
    //grunt.registerTask('default', ['xxxx']);
    };

有三个部分可定义自动任务:

  • InitConfig:指将由 Grunt 执行的任务
  • LoadNpmTask:用于加载所需的插件,以完成任务
  • 注册任务:注册将要运行的任务

一旦我们决定安装什么插件并定义所有必要的任务,在终端上运行 grunt 来执行它们。

吞咽

与 Grunt 一样,Gulp也是一个自动化任务的工具,它也是在 NodeJS 上开发的,因此有必要安装 Node.js,以便 NPM 可以安装它。一旦安装了 Node.js,我们就可以通过运行以下命令全局安装 Gulp:

npm install -g gulp

另一种安装 gulp 的方法(推荐选项)是本地安装,您可以使用以下命令执行此操作:

npm install --save-dev gulp

所有任务都应包含在要自动化的根项目上的gulpfile.js中:

    var gulp = require('gulp');
    gulp.task('default', function () {
    });

前面的代码非常简单。如您所见,代码是gulp.task,任务名称,然后是为该任务名称定义的function

一旦定义了函数,就可以运行gulp

SASS

CSS 非常复杂、庞大,而且很难维护。你能想象维护一个有成千上万行的文件吗?这就是可以使用 Sass 的地方。这是一个预处理器,它将变量、嵌套、混合、继承等特性添加到 CSS 中,使 CSS 成为真正的开发语言。

语法上令人敬畏的样式表SASS是 CSS 的元语言。它是一种被翻译成 CSS 的脚本语言。SassScript 是 Sass 语言,它有两种不同的语法:

  • 缩进语法:使用缩进分隔块代码,使用新行字符分隔规则
  • SCSS:这是 CSS 语法的扩展,它使用大括号表示代码块,使用分号分隔块内的行

缩进语法有.sass扩展,SCSS 有.scss扩展。

Sass 运行起来非常简单。安装完成后,只需在终端上运行sass input.scss output.css

凉亭

Bower是一个类似于 Composer 的依赖项管理,但它适用于前端。它也是基于 Node.js 的,所以一旦安装了 Node.js,就可以使用 NPM 安装 Bower。使用 Bower,可以更新所有前端库,而无需手动更新它们。安装 Node.js 后安装 Bower 的命令如下:

npm install -g bower

然后,您可以执行bower init以便在您的项目上创建bower.json文件。

bower.json文件会提醒您composer.json

    {
      "name": “bower-test”,
      "version": "0.0.0",
      "authors": [
        "Carlos Perez and Pablo Solar"
      ],
      "dependencies": {
        "jquery": "~2.1.4",
        "bootstrap": "~3.3.5"
        "angular": "1.4.7",
        "angular-route": "1.4.7",
      }
    }

在前面的代码中,您可以看到添加到项目中的依赖项。可以修改它们,以便在应用程序上安装这些依赖项,就像 Composer works 一样。此外,使用 Bower 的命令与 Composer 非常相似:

  • bower 安装:这是安装bower.json上的所有依赖项
  • bower update:用于更新bower.json中包含的依赖项
  • bower 安装包名称:在 bower 上安装一个包

部署自动化

在某个时候,您的应用程序将部署到生产环境中。如果您的应用程序很小,并且只使用几个容器/服务器,那么一切都会很好,您可以在每次部署中轻松地手动管理所有资源(容器、VM、服务器等)。但是,如果在每次部署中都有数百个资源需要更新,会发生什么情况?在这种情况下,您需要某种部署机制;即使您只有一个小项目和一个容器/服务器,我们也建议您自动化部署。

使用自动部署过程的主要好处如下所示:

  • 易于维护:大多数情况下,部署所需的步骤都可以存储在文件中,以便您进行编辑。
  • 可重复:您可以一次又一次执行部署,每次都会遵循相同的步骤。
  • 不太容易出错:我们是人,作为人,我们在处理多个任务时会犯错误。
  • 易于跟踪:有多种工具可用于记录每次提交中发生的一切。这些工具还可用于创建可以进行部署的用户组。最常用的工具是詹金斯安斯比尔塔大西洋竹子
  • 易于更频繁地发布:部署管道到位将帮助您更快地开发和部署,因为您不会花时间处理将代码推送到生产环境的问题。

让我们看看一些自动化部署的方法,从最简单的选项开始,并越来越多地增加复杂性和功能。我们将分析每种方法的优缺点,以便在本章末尾,您可以为您的项目选择完美的部署系统。

简单的 PHP 脚本

这是实现部署自动化的最简单方法——您可以(在公共位置)向代码中添加脚本,如以下代码所示:

    <?php
    define('MY_KEY', 'this-is-my-secret-key');
    if ($_SERVER['REQUEST_METHOD'] === 
    'POST' && $_REQUEST['key']  === MY_KEY) {
        echo shell_exec('git fetch && git pull origin master');
    }

在前面的脚本中,只有使用正确的键到达脚本时,我们才从 master 执行拉取操作。正如您所看到的,它非常简单,任何知道密钥的人都可以使用它,例如,浏览器。如果您的代码存储库允许设置 Webhook,那么每次在项目中完成推送或提交时,您都可以使用它们来启动脚本。

以下是此部署方法的优点:

  • 如果需要的工作量很小,那么很容易创建,例如,agit pull
  • 跟踪脚本的更改很容易
  • 很容易被您或任何外部工具触发

以下是此部署方法的缺点:

  • web 服务器用户需要能够使用 repo
  • 例如,当您需要处理分支或标记时,它会增加复杂性
  • 当您需要部署到多个实例时,使用起来并不容易,您将需要诸如 rsync 之类的外部工具
  • 不太安全。如果您的密钥被第三方发现,他们可以在您的服务器上随意部署

在一个理想的世界里,你对生产的所有承诺都将是完美和原始的,但你知道真相——在未来的某个时刻,你需要回滚所有的更改。如果您有这种部署方法,并且希望创建回滚策略,那么必须增加 PHP 脚本的复杂性,以便它能够管理标记。另一个不推荐的选项是,您可以执行git undo并再次推送所有更改,而不是向脚本添加回滚。

Ansible 和 Ansistrano

Ansible是一个 IT 自动化引擎,可用于自动化云资源调配、管理配置、部署应用程序或协调服务等用途。这个引擎不使用代理,因此不需要额外的安全基础设施,它是通过 SSH 设计的。描述自动化工作的主要语言(也称为剧本)是 YAML,其语法与英语相似。由于您的所有剧本都是简单的文本文件,因此您可以轻松地将它们存储在存储库中。你可以在 Ansible 中找到一个有趣的特性,那就是它的 Galaxy,一个你可以在剧本中使用的附加组件中心。

责任要求

Ansible 使用 SSH 协议来管理所有主机,您只需要在一台机器上安装此工具——您将使用这台机器来管理您的主机组。控制机器的主要必备组件是 Python2.6 或 2.7(Ansible 2.2 支持 Python3),您可以使用除 Microsoft Windows 之外的任何操作系统。

托管主机上的唯一要求是 Python2.4+,大多数类似 UNIX 的操作系统都默认安装了它。

安全安装

假设您的控制机器上有正确的 Python 版本,在包管理器的帮助下安装 Ansible 非常容易。

在 RHEL 上,CentOS 和类似的 linux 发行版执行以下命令来安装 Ansible:

sudo yum install ansible

Ubuntu 命令如下所示:

sudo apt-get install software-properties-common \
&& sudo apt-add-repository ppa:ansible/ansible \
&& sudo apt-get update \
&& sudo apt-get install ansible

FreeBSD 命令如下所示:

sudo pkg install ansible

Mac OS 命令如下所示:

sudo easy_install pip \
&& sudo pip install ansible

什么是 Ansistrano?

Ansistrano是一个开源项目,由ansistrano.deployansistrano.rollback两个 Ansible Galaxy 角色组成,用于轻松管理您的部署。它被认为是卡皮斯特拉诺的主要港口。

一旦我们的机器上有了 Ansible,就可以很容易地使用以下命令安装 Ansistrano 角色:

ansible-galaxy install carlosbuenosvinos.ansistrano-deploy \ carlosbuenosvinos.ansistrano-rollback

执行此命令后,您将能够在剧本中使用 Ansistrano。

Ansistrano 是如何工作的?

Ansistrano 按照 Capistrano 流程部署应用程序:

  1. 设置阶段:在此阶段,Ansistrano 创建文件夹结构,用于保存应用程序版本。
  2. 代码更新阶段:在这个阶段,Ansistrano 将您的版本放在主机上;它可以使用 rsync、Git 或 SVN 等方法。
  3. 符号链接阶段(见下文):部署新版本后,将当前软链接更改为将可用版本指向新版本位置。
  4. 清理阶段:在此阶段,Ansistrano 将删除主机中存储的旧版本。您可以通过ansistrano_keep_releases参数配置剧本中的版本数量。在以下示例中,您将了解此参数的工作方式

提示

使用 Ansistrano,您可以在每个任务之前和之后钩住要执行的自定义任务。

让我们看一个简单的例子来解释它是如何工作的。假设您的应用程序部署到/var/www/my-application;首次部署后,此文件夹的内容将类似于以下示例:

-- /var/www/my-application
 |-- current -> /var/www/my-application/releases/20161208145325
 |-- releases
 |   |-- 20161208145325
 |-- shared

从前面的示例中可以看到,当前的符号链接指向我们主机中的第一个版本。您的应用程序将始终在同一路径/var/www/my-application/current中可用,因此您可以在任何需要的地方使用此路径,例如,NGINX 或 PHP-FPM。

随着部署的继续,Ansistrano 将为您处理部署。下一个示例将向您展示第二次部署后应用程序文件夹的外观:

-- /var/www/my-application
 |-- current -> /var/www/my-application/releases/20161208182323
 |-- releases
 |   |-- 20161208145325
 |   |-- 20161208182323
 |-- shared

正如您可以从前面的示例中看到的,现在我们的主机中有两个版本,并且 symlink 已更新为指向您的代码的新版本。如果您使用 Ansistrano 进行回滚,会发生什么?简单,此工具将删除主机中的最新版本并更新符号链接。在我们的示例中,您的应用程序文件夹内容与此类似:

-- /var/www/my-application
 |-- current -> /var/www/my-application/releases/20161208145325
 |-- releases
 |   |-- 20161208145325
 |-- shared

提示

为了避免出现问题,如果您尝试回滚,而 Ansistrano 找不到要移动到的以前的版本,它将不起任何作用,使您的主机保持不变。

与 Ansistrano 一起部署

现在,让我们用 Ansible 和 Ansistrano 创建一个小型自动化系统。我们假设您有一个已知的、持久的基础架构,您可以在其中推送应用程序或微服务。在开发环境中创建一个文件夹以保存所有部署脚本。

在我们的例子中,我们之前在本地环境中创建了三个启用 SSH 的 VM。请注意,我们没有介绍这些虚拟机的配置,但是如果您愿意,您甚至可以使用 Ansible 为您完成这项工作。

首先需要创建一个hosts文件。在此文件中,您可以存储和分组所有服务器/主机,以便以后在部署中使用它们:

[servers:children]
 production
 staging
 [production]
192.168.99.200
192.168.99.201

[stageing]
192.168.99.100

在前面的配置中,我们创建了两组主机-–productionstaging。在每一台上,我们都有几个可用的主机;在我们的例子中,我们为测试目的设置了本地 VM 的 IP 地址,但是如果需要,您可以使用 URI。将主机分组的优点之一是,您甚至可以创建更大的组;例如,可以创建由其他组组成的组。例如,我们有一个servers组,它包装了所有的生产和暂存主机;Ansible 支持您,并提供多个连接器,您可以使用这些连接器获取动态基础设施,例如 AWS 或 Digital Ocean 等。

一旦您准备好了hosts文件,就可以创建我们的deploy.yml文件,我们将在其中存储我们希望在部署中执行的所有任务。创建一个包含以下内容的deploy.yml文件:

---
- name: Deploying a specific branch to the servers
 hosts: servers
 vars:
     ansistrano_allow_anonymous_stats: no
     ansistrano_current_dir: "current"
     ansistrano_current_via: "symlink"
     ansistrano_deploy_to: "/var/www/my-application"
     ansistrano_deploy_via: "git"
     ansistrano_keep_releases: 5
     ansistrano_version_dir: "releases"

     ansistrano_git_repo: "git@github.com:myuser/myproject.git"
     ansistrano_git_branch: "{{ GIT_BRANCH|default('master') }}"

 roles:
     - { role: carlosbuenosvinos.ansistrano-deploy }

多亏了 Ansistrano,我们的部署任务非常容易定义,正如您从前面的示例中看到的那样。我们所做的是创建一个新任务,该任务将在标记服务器下包装的所有主机中执行,并定义几个可用于 Ansistrano 角色的变量。在这里,我们定义了在每台主机上部署应用程序的位置、部署(Git)所使用的方法、在主机中保留的发布数量(5)以及要部署的分支。

Ansible 的一个有趣特性是,您可以将变量从命令行传递到通用部署过程。这是我们在以下行中所做的:

ansistrano_git_branch: "{{ GIT_BRANCH|default('master') }}"

这里,我们使用一个GIT_BRANCH变量来定义我们要部署哪个分支;如果 Ansible 找不到此定义的变量,它将使用 master。

你准备好测试我们所做的了吗?打开终端并转到存储部署任务的位置。假设您希望将最新版本的代码部署到生产主机上;可以使用以下命令执行此操作:

ansible-playbook deploy.yml --extra-vars "GIT_BRANCH=master" --limit production -i hosts

在前面的命令中,我们告诉 Ansible 使用我们的deploy.yml剧本,我们还将GIT_BRANCH定义为 master,以便部署该分支。由于我们的所有主机都在 hosts 文件中,并且我们只希望部署到production主机,因此我们使用--limit``production将执行限制到所需的主机。

现在,假设您已经准备好了一个新版本,所有代码都已提交并标记在v1.0.4标记下,您希望将此版本推送到您的暂存环境中。您可以使用一个非常简单的命令:

ansible-playbook deploy.yml --extra-vars "GIT_BRANCH=v1.0.4" --limit staging -i hosts

如您所见,使用 Ansible/Ansistrano 部署应用程序非常容易,而且回滚到以前部署的版本更容易。要管理回滚,您只需要创建一个新的剧本。创建一个包含以下内容的rollback.yml文件:

---
- name: Rollback
 hosts: servers
 vars:
     ansistrano_deploy_to: "/var/www/my-application"
     ansistrano_version_dir: "releases"
     ansistrano_current_dir: "current"
 roles:
     - { role: carlosbuenosvinos.ansistrano-rollback }

在前面的代码中,我们使用 Ansistrano 回滚角色移动到先前部署的版本。如果主机中只有一个版本,Ansible 将不会撤消更改,因为这是不可能的。你还记得我们在deploy.yml文件中设置的变量吗,叫做ansistrano_keep_releases?这个变量对于了解您可以在主机中执行多少次回滚非常重要,因此请根据您的需要调整它。要将生产服务器回滚到以前的版本,可以使用以下命令:

ansible-playbook rollback.yml --limit production -i hosts

正如您所看到的,Ansible 是一个非常强大的工具,您可以将其用于部署,但它不仅仅用于部署;例如,您甚至可以将其用于编排。Ansible 是一个充满活力的社区,RedHat 支持该项目,是一个必要的工具。

提示

Ansible 有一个企业版的 web 工具,可以用来管理所有 Ansible 剧本。即使它需要付费订阅,如果您管理的节点少于 10 个,您也可以免费使用它。

其他部署工具

正如您所想象的,您可以使用多种不同的工具来进行部署,本书无法涵盖所有这些工具。我们想向您展示一个简单的(PHP 脚本)和一个更复杂、功能更强大的(Ansible),但我们不希望您在不了解其他可用工具的情况下完成本章:

  • 厨师:这是一个有趣的开源工具,您可以使用它作为代码管理您的基础设施。
  • Puppet:这是一个开源的配置管理工具,具有付费企业版。
  • Bambol:这是来自 Atlassian 的持续集成服务器,当然,使用此工具需要付费。这是您可以与 Atlassian 产品目录结合使用的最完整的工具。
  • Codeship:这是一个云连续部署解决方案,旨在成为一个专注于运行测试和部署应用程序的端到端解决方案的工具
  • Travis CI:这是一个类似于 Jenkins 用于持续集成的工具;您还可以使用它进行部署。
  • Packer、Nomad 和 Terraform:这些工具与 HashiCorp 不同,您可以使用它们将基础设施编写为代码。
  • Capistrano:这是一款知名的远程服务器自动化和部署工具,易于理解和使用。

先进的部署技术

在上一节中,我们向您展示了一些部署应用程序的方法。现在,是时候使用一些用于大型部署的高级技术来提高复杂性了。

与詹金斯的持续整合

Jenkins 是最著名的连续集成应用程序;作为一个开源项目,您可以创建自己的具有高度灵活性的管道。它是用 Java 构建的,所以如果您想安装这个工具,这是您的主要需求。有了詹金斯,一切都变得更容易,甚至安装也更容易。例如,您可以使用最新版本的 Docker 容器,只需几个命令:

docker pull jenkins \
&& docker run -d -p 49001:8080 -t jenkins

前面的命令将下载并创建一个具有最新 Jenkins 版本的新容器,以便随时使用。

詹金斯背后的主要思想是工作的概念。作业是可以自动或手动执行的一系列命令或步骤。通过作业和使用插件(可从 web UI 下载),您可以创建自定义工作流。例如,您可以创建一个类似于下一个工作流的工作流,该工作流在提交/推送发生时由存储库触发:

  1. 单元测试插件开始测试您的应用程序。
  2. 一旦它通过,一个代码嗅探器插件就会检查你的代码。
  3. 如果前面的步骤没有问题,Jenkins 将通过 SSH 连接到远程主机。
  4. 詹金斯提取远程主机中的所有更改。

前面的例子很简单;您可以进一步改进示例并使其复杂化,使用 Ansible playbook 代替 SSH。

此应用程序用途广泛,您可以在任何需要的情况下使用它。例如,您可以使用它来检查主从数据库的复制状态。在我们看来,此应用程序值得一试,您可以找到适合此软件的任何类型任务的示例。

蓝/绿部署

此部署技术依赖于拥有基础结构的副本,以便可以在当前版本的基础上并行安装应用程序的新版本。在应用程序前面,您有一个路由器或负载平衡器(LB),用于将流量重定向到所需版本。一旦新版本就绪,只需更改路由器/LB 即可将所有流量重定向到新版本。拥有两套发行版可以让您获得轻松回滚的灵活性和优势,还可以让您有时间确保新版本正常工作。请参阅下图:

Blue/Green deployment

微服务上的蓝色/绿色部署

如上图所示,蓝色/绿色部署可以在应用程序的任何级别完成。在我们的示例图中,您可以看到一个准备部署新版本但尚未发布的微服务,您可以看到一些微服务发布了其代码的最新版本,保留了前一个版本以供回滚。

这种技术被大型科技公司广泛使用,没有任何问题;主要的缺点是运行应用程序所需的资源量增加了——更多的资源意味着在基础设施上要花更多的钱。如果您想尝试一下,这种部署中使用最多的负载平衡器有ELBFabioTraefik等。

金丝雀释放

金丝雀版本与蓝/绿版本的部署技术类似,但有细微的区别——只有少量主机同时升级。一旦您使用 cookie、lb 或代理将一部分主机与您想要的版本一起使用,一部分流量将重定向到新版本。

这种技术允许你用一小部分流量来测试你的变化;如果应用程序按预期运行,我们将继续将更多主机迁移到新版本,直到所有流量重定向到应用程序的新版本。请看下图:

Canary releases

微服务的金丝雀版本

如上图所示,有些微服务有四个实例;其中三个保留了应用程序的旧版本,只有一个拥有最新版本。LB 用于在不同版本之间划分流量,将大部分流量发送到v1.0.0,只有一小部分流量发送到v2.0.0。如果一切正常,下一步将增加v2.0.0实例的数量,减少v1.0.0实例的数量,并将更多流量重定向到新版本。

这种部署技术为您当前的基础架构增加了一点复杂性,但允许您使用少量用户/流量开始测试更改。另一个好处是重用现有的基础设施;部署时不需要有重复的主机集。

不变的基础设施

如今,科技行业的一个趋势是使用不变的基础设施。当我们说不可变的基础设施时,我们的意思是,您在开发环境中拥有的东西稍后将部署到生产环境中,而不进行任何更改。多亏了集装箱化技术和一些工具,如 Packer,您可以实现这一点。

使用 Packer,您可以创建应用程序的映像,然后通过您的基础结构分发此映像。这种技术的主要好处是,您可以确保生产环境的行为与您的开发类似。另一个重要方面是安全;假设您的 NGINX 容器中存在安全漏洞,一个具有基本映像更新的新版本将解决此问题,并且它将与您的应用程序一起传播,而无需外部干预。

备份策略

在任何项目中,备份都是避免数据丢失的最重要方法之一。在本章中,我们将学习应用程序中使用的备份策略。

什么是备份?

备份是将代码或数据保存在通常存储代码或数据的不同位置的过程。这个过程可以使用不同的策略来完成,但它们都有相同的目标——不丢失数据以便将来访问。

为什么重要?

进行备份有两个原因。第一种是由于黑客攻击、数据损坏或在生产服务器上执行查询时出错而导致的数据丢失。此备份将有助于恢复丢失或损坏的数据。

第二个原因是政策。法律规定,用户数据必须存储数年。有时,此功能由系统完成,但备份是存储此数据的另一种方式。

总而言之,备份让我们保持冷静。我们确保我们的工作正常进行,并且在发生任何灾难时,我们有一个解决方案来快速修复它们,而不会(严重)丢失数据。

我们需要备份什么以及备份到哪里

如果我们在应用程序中使用一些存储库,例如 Git,那么这可能是文件的备份位置。用户上传的资产或任何其他文件也应进行备份。

查看我们是否正在备份所有必要文件的一个良好做法是查看.gitignore文件,并确保我们已备份该文件夹中包含的所有文件和文件夹。

此外,要备份的最重要和最宝贵的东西是数据库。这应该更频繁地备份。

提示

不要将备份存储在应用程序工作的同一位置。尝试为备份副本设置不同的位置。

备份类型

备份可以是完整备份、增量备份或差异备份。我们将看看它们之间的区别以及它们是如何工作的。应用程序通常结合不同的备份类型:完整备份与增量备份或差异备份。

完全备份

完全备份是基本备份;它包括生成当前应用程序的完整副本。大型应用程序定期使用此选项,小型应用程序可以每天使用它。

优点如下:

  • 完整的应用程序备份在单个文件中
  • 它总是生成完整的副本

缺点如下:

  • 生成它的时间可能很长
  • 备份将需要大量磁盘空间

请注意,通常最好在备份文件名中包含日期/时间,这样您就可以只查看文件名就知道创建时间。

增量备份和差异备份

增量备份复制自上次备份以来已更改的数据。datetime应包含在此类备份中,以便在下次生成新备份时由备份工具进行检查。

优点如下:

  • 它比完全备份快
  • 它占用更少的磁盘空间

缺点如下:

  • 整个应用程序不存储在单个生成的备份中

还有另一种类型,称为差速器。这类似于增量备份(复制自上次备份以来更改的所有数据);它第一次执行,然后将继续复制上次完整备份中所有修改的数据。

因此,在第一次之后,它将生成比增量数据多但比完整数据少的数据。这种类型介于完全和增量之间。它需要更多的空间和时间,而不是增量和不足。

备份工具

可以找到许多备份工具。大型项目中最常用的工具是 Bacula。对于小型项目,也有其他类似的脚本,例如将经常运行的自定义脚本。

杆菌

Bacula是一种备份管理工具。此应用程序管理并自动化备份任务,非常适合大型应用程序。这个工具的设置有点复杂,但一旦准备好了,它就不需要任何其他更改,并且可以正常工作。

Bacula 上有三个不同的部件,每个部件都需要安装在不同的包装中:

  • 主管:管理所有备份流程
  • 存储:这里存储备份
  • 文件:这是我们运行应用程序的客户端机器

在我们基于微服务的应用程序中,我们将有许多文件(每个微服务一个文件)以及许多存储位置(以便有不同的备份位置)和控制器。

此工具适用于守护进程。每个部分都有自己的守护进程,每个守护进程都遵循自己的配置文件工作。配置文件是在安装过程中设置的,只需更改一些小事情,如远程 IP 地址、证书或自动备份计划。

Bacula 的安全性非常惊人——每个部分(控制器、存储和文件)都有自己的密钥,并且根据连接的不同,使用它进行加密。此外,Bacula 允许 TLS 连接以实现更高的安全性。

Bacula 允许您执行完整备份、增量备份或差异备份,并且可以由主管自动执行这些备份。

Percona xtrabackup

XtraBackup是一款开源工具,可以在应用程序上进行热数据库备份,而不会阻塞数据库。这可能是该应用程序最重要的功能。

此工具允许 MySQL 数据库(如 MariaDB 和 Percona)执行流式处理和压缩,并执行增量备份。

优点如下:

  • 快速备份和恢复
  • 备份期间不间断的事务处理
  • 节省磁盘空间和网络带宽
  • 自动备份验证

自定义脚本

创建备份的最快方法是在生产环境中使用自定义脚本。这是一个脚本,当它运行时,它通过执行mysqldump(如果我们使用的是 MySQL 数据库),压缩所需文件,并将其放置在所需位置(理想情况下,远程放置在不同的机器上)来创建备份。

这些脚本应该由 cronjob 执行,可以设置为每天或每周运行这些脚本。

正在验证备份

作为备份策略的一部分,最好使用技术验证存储在备份上的数据。如果您的备份有错误,就好像根本没有任何备份一样。

为了检查我们的备份是否有效、是否损坏,以及它们是否按预期工作,如果我们将来需要恢复它们,有必要经常执行模拟恢复以避免失败。

为世界末日做好准备

没有人希望必须恢复备份,但必须做好准备,以防您的任何微服务损坏或损坏,我们必须快速做出反应。

第一步是了解应用程序的最新备份在哪里,以便尽快恢复。

如果问题与数据库有关,我们必须对应用程序进行维护,恢复数据库备份,检查它是否正常工作,然后使应用程序重新启动。

如果问题与资产或文件等相关,则可以在不维护应用程序的情况下进行恢复。

保持冷静,准备支援。

总结

现在,您知道了如何将应用程序部署到生产环境并自动化部署过程。此外,您还了解了必须部署什么,以及可以从任何依赖关系管理中获得什么,如何在必要时执行回滚,以及备份应用程序的不同策略。****