Navigator指南:配置管理的部署解决方案

前一章演示了如何通过在基础结构的Web前端层添加冗余来减少停机时间。如果您的服务使用文件和数据,您还需要一个集中的后端 - 这应该是同样多余的,以避免单点故障。

注意 :这是Navigator指南书内容的早期发布版本,这是DigitalOcean Solutions Engineers提供的产品。 本书的目标是帮助企业客户规划他们的基础架构需求,提供工作实例,并包括技术细微差别和“为什么”,使得某些决策比其他决策更好。

本书和随附的代码将在GitHub存储库中公开提供。 因为这是一个早期版本,该书尚未完成,存储库尚未公开,但请继续关注!

前一章演示了如何通过在基础结构的Web前端层添加冗余来减少停机时间。 如果您的服务使用文件和数据,您还需要一个集中的后端 - 这应该是同样多余的,以避免单点故障。

前端和后端都可以使用负载平衡解决方案将流量分配到多个服务器。 这种结构在后端提供了一些独特的好处,例如能够在不引起停机的情况下更新应用程序代码,支持A / B测试,canary部署和蓝/绿部署等功能。 但是,这确实会给您的基础架构带来一些复杂性。 您需要考虑如何维护负载均衡器的配置,如何管理应用程序及其运行的服务器,以及如何处理用户会话,文件存储和数据库等内容的一致性。

无论您使用的是DigitalOcean负载均衡器还是自我管理的负载均衡器,您都需要保持其配置的一致性。 在自我管理的负载均衡器设置中使用配置管理工具管理配置文件更具实际性,需要一些额外的工作,而DigitalOcean负载均衡器是一种自动处理负载均衡器冗余的托管服务。

对于DigitalOcean负载均衡器,配置选项是策划的,但您仍需要确保设置正确且一致。 使用Droplet标签确定Load Balancer的后端是最直接的成功之路,因为它允许您自动添加和删除Droplet(而不是单个IP​​),这意味着您的配置只能由没有Ansible的Terraform处理。

如果您的负载平衡要求更复杂,您可能已选择使用自己的负载均衡器(使用HAProxy,如前一章或其他负载平衡软件)。 在这种情况下,您需要部署一组多个负载均衡器Droplet以及DigitalOcean浮动IP地址,以确保负载均衡层的冗余。

我们的设置

数据一致性是您将使用负载均衡器配置解决的主要复杂问题。 当您的后端可以从多个服务器中的任何一个服务器提供时,您需要确保每个服务器都可以访问相同的一致数据集,或者特定会话将继续连接到特定服务器。

我们将以此为契机,展示配置管理软件的更强大功能。 在我们托管运行WordPress的网站的示例中,我们必须决定如何确保群集中的每个节点都具有正确的数据。 无论哪个节点正在处理请求,最终用户都需要具有一致的体验。 如果一个节点知道我们的WordPress站点中的帖子或图像,但其他节点不知道,最终用户可能会看到零星的结果。

在我们遍历配置以确保一致性时,我们将审查三个相关组件:用户会话,文件存储和数据库。

了解配置

实际配置完成后设置集群是一个相对较短的过程,但了解配置及其中的决策是将这些模式应用于您自己的基础架构的关键。 让我们一块一块地分解它。

负载均衡器配置

DigitalOcean负载均衡器

与前几章一样,我们将使用Terraform来管理Load Balancer配置。 以下条目创建Load Balancer并提供后端Droplet标记,转发规则,要使用的TLS证书以及Load Balancer将使用的运行状况检查。 SSL和其他安全设置超出了本章的范围,但在第13章中对它们进行了深入介绍。

以下是example-code/02-scale/ch05/init_deploy/main.tf文件中的资源块:

...

resource "digitalocean_loadbalancer" "public" {
  name                   = "${var.project}-lb"
  region                 = "${var.region}"
  droplet_tag            = "${digitalocean_tag.backend_tag.id}"
  redirect_http_to_https = true
  depends_on             = ["digitalocean_tag.backend_tag"]

  forwarding_rule {
    entry_port     = 80
    entry_protocol = "http"

    target_port     = 80
    target_protocol = "http"
  }

  healthcheck {
    port                     = 80
    protocol                 = "http"
    path                     = "/"
    check_interval_seconds   = 5
    response_timeout_seconds = 3
    unhealthy_threshold      = 2
    healthy_threshold        = 2
  }
}

因为Load Balancers是服务而不是不可变资源(如Droplet),所以对配置参数的更改不会重新创建整个Load Balancer; 它会更新到位。 有关支持的参数和输出属性的更多详细信息,请查看Terraform文档

我们使用DigitalOcean负载均衡器来处理到我们的Web服务器的公共Web流量的负载平衡。

HAProxy群集

如果您需要更复杂的配置,例如访问较低级别的负载平衡设置或支持多个后端服务,则可以设置自己的负载均衡器群集。 我们将继续前一章中的HAProxy示例。

Ansible使用Jinja2模板系统,简化了创建和更新配置文件的过程。 Jinja2支持使用您在编程语言中找到的变量和控制结构,如if语句,循环,数学运算和内置过滤器的大型库。 这个总结并不公正Ansible中的模板系统。 我们建议您查看Ansible的文档以获取更多详细信息。

配置更改时,有几种方法可以触发更新。 如果您网站上的需求波动不大,或者您知道何时会提前进行更改,则可能不需要或不想设置完全自动缩放。 相反,您可以手动运行Ansible手册或将其设置为在将Terraform部署脚本更改到git存储库时运行。

另一种选择是使用Consul进行服务发现,并在负载均衡器上配置consul-template以自动刷新配置文件。 这会为您的整体基础架构添加额外的Droplet,但您也可以将Consul用于其他服务。

我们使用HAProxy Cluster来处理数据库集群的负载平衡。

用户会话

会议回顾

当用户访问通过负载均衡器托管的站点时,无法保证其下一个请求将由同一后端服务器处理。 对于简单的静态页面,这不是问题,但如果服务需要用户会话的知识(如果他们已经登录),您将需要处理它。 有几个选项可以解决这个问题,可以在的不同位置实现。

您选择处理用户会话的方法取决于您的用例。 以下是一些选项:

IP源关联性将来自同一IP地址的所有请求定向到同一后端。 在用户可以使用NAT从路由器后面连接的情况下,这不是最佳选择,因为它们都具有相同的IP地址。

负载均衡器会话应用程序会话选项类似。 它们都配置负载均衡器以查看IP头信息以确定向哪个后端发送请求。 与IP源关联方法不同,NAT后面的用户将被识别为单个用户。 您可以通过在HAProxy负载平衡器上实施一个棒表来进一步调整,这可以用于根据多个不同的数据点配置用户标识。

文件系统复制会复制存储会话的文件系统中的路径,从而为所有会话提供所有后端访问权限。 要考虑的一个关键方面是复制发生的速度。 根据方法的不同,即使后端节点与需要复制的大量会话之间存在适度的延迟,也会给最终用户带来问题。

使用数据库内存数据存储是类似的。 两者都要求您以将用户会话存储在数据库或内存缓存(如Redis)中的方式创建应用程序。 使用数据库可能很方便,因为您的应用程序已经设置为连接到其他数据请求。 对于高度活跃的站点,这可能会给数据库本身带来更多开销,但是大多数情况下,额外的负载可以忽略不计。 使用像Redis或Memcached这样的内存缓存意味着您需要再创建一些Droplet,但它们是非常快速且通用的解决方案,您还可以使用它们来缓存数据库查询响应以提高性能。

因为WordPress已经配置为使用数据库进行会话,所以我们将使用这个解决方案。

文件存储

文件存储审核:

您的应用程序使用的文件需要保持一致; 所有服务器都需要访问同一组资源。 解决此问题的一个好方法是将存储功能与后端应用服务器分离,而是使用单独的服务进行文件存储。 对于静态资产,您可以使用对象存储解决方案。 DigitalOcean Spaces是一种具有内置冗余的高可用对象存储服务。 我们将在第7章中详细讨论存储选项,尤其是Spaces。

与会话一样,您可以在应用程序节点之间使用本地文件系统复制来处理文件存储。 但是,这确实会为您的基础架构添加其他服务,以及其他配置更改。

一个更简单的解决方案是使用对象存储,如DigitalOcean Spaces,特别是因为WordPress已经有一个DigitalOcean Spaces Sync插件。 由于设置简化为安装和配置单个插件,因此我们将在本章中使用该解决方案。

数据库

数据库审查

与文件存储非常相似,所有后端Droplet都需要访问您的数据库。 如何跨群集复制数据库插入和更新对于功能性群集数据库解决方案至关重要。

此外,您的数据库应该具有高可用性 - 也就是说,它具有冗余和自动故障转移功能。 这可能比仅仅将其置于负载均衡器之后更复杂,因为系统将需要处理数据一致性,例如如果对不同节点进行冲突更新会发生什么。

在我们的示例中,我们使用MariaDB Galera集群来处理这些问题。 Galera处理到每个数据库节点的同步复制,每个数据库节点都充当完整的主数据库服务器。 这意味着您可以读取和写入群集中的每个节点,并且所有节点都保持同步。 还有其他方法可以对涉及主要和辅助复制形式的数据库进行集群,其中特定节点被选为主要写入服务器。

每个集群解决方案都有其优点。 对于我们的练习,Galera为我们带来了最大的好处,因为数据一致性是自动处理的,集群中的每个节点都可以作为主服务器。 没有必要的故障转移或故障恢复步骤。

WordPress依赖于其数据库几乎所有东西,而单个外部数据库服务器是单点故障。 数据库群集有几个选项,根据您的情况最适合的方式,可以混合和匹配不同的部分。

在本章中,我们将构建一个在MariaDB上运行的Galera集群,它是MySQL的一个分支。 这将在几个带有附加的DigitalOcean浮动IP的HAProxy节点后面运行。

您可以在此处访问源存储库: https//github.com/DO-Solutions/galera-tf-mod 它设置到群集的TCP路由,默认情况下有三个节点。 如果我们使用少于三个节点,则需要Galera Arbitrator节点以避免裂脑情况并使群集保持运行。 您可以通过将以下行添加到主要的terraform文件example-code / 02-scale / ch05 / init_deploy / main.tf中的模块代码块来增加节点数 请注意,您需要具有奇数个节点,以便在执行法定投票时群集可以占多数。 一个例子是,如果两个节点认为记录应该存在,而另外两个节点就不应该存在记录,则需要一个额外的节点来进行决定性投票。

module "sippin_db" {
...
   db_node_count = "5"
}

设置WordPress群集

在我们的项目中,设置WordPress群集只需要几个命令。 我们将在控件Droplet上使用/root/navigators-guide/example-code/02-scale/ch05/init_deploy ,其中包含本章的示例代码。

从该目录中,运行我们提供的初始化脚本。 它将引导您完成需要设置的所有设置和变量。

./bin/init_config

您可以在GitHub上查看初始化脚本的代码。 您将看到脚本执行了许多功能。 它真正做的是自动创建必要的Terraform和Ansible变量文件,并确保不存在已知问题。 脚本将要做的第一件事是提示有效的DigitalOcean API令牌。 之后,该脚本将创建群集创建所需的一些唯一密钥。 您将看到的下一个提示是命名项目并选择一个区域。 如果已经配置了SSH密钥(正如我们在第4章中所做的那样),该脚本将告诉Terraform使用它。 如果尚未配置SSH密钥,将创建一个SSH密钥并自动添加到您的DigitalOcean帐户。 最后,脚本将提示输入任何所需的密码。

一旦脚本完成Terraform计划,Ansible playbook就可以执行了。 这与第4章中的示例非常相似,但是创建和配置的资源更多。

如果您手动配置所有内容,则需要在terraform.tvfars文件中为Terraform输入变量。 Ansible在group_vars文件夹中的多个文件夹中需要变量。

初始化脚本将在退出之前打印有关如何继续使用Terraform的说明,但我们也将在此处介绍它。

首先,运行terraform plan将在您的DigitalOcean帐户中创建以下项目:

  1. 一个负载均衡器,可以访问您的WordPress站点。
  2. 三个Droplet将用作WordPress Web节点。
  3. 三个Droplet用作数据库节点。
  4. 数据库群集的两个HAProxy Load Balancer节点。
  5. 数据库负载均衡器的一个浮动IP地址。
terraform plan

接下来,解析计划文件和模块以使用init准备Terraform部署。

terraform init

最后,使用apply通过DigitalOcean API执行创建请求。

terraform apply

Terraform完成创建所有基础架构组件后,使用Ansible配置它们。 要执行三个Ansible角色:一个用于配置数据库服务器,一个用于配置数据库负载平衡器,另一个用于在所有Web节点上设置WordPress。

您可以使用一个命令运行所有三个角色:

ansible-playbook -i /usr/local/bin/terraform-inventory site.yml

一旦剧本完成,您将需要完成WordPress设置。

在浏览器中访问Load Balancer的IP地址,然后按照屏幕上的说明完成WordPress配置。 请注意,第13章介绍了如何使用HTTPS保护WordPress安装。

最后一步是激活和配置默认安装的DigitalOcean Spaces Sync插件。 您需要使用“控制面板”创建一个Space ,然后创建一个Spaces访问键 然后,按照我们关于在Spaces存储WordPress资产的社区文章。

验证安装程序

通过在浏览器中转到Load Balancer IP地址,您可以看到默认的WordPress站点,类似于:

WordPress默认安装截图

最终结果是一个功能齐全的WordPress网站。 您可以通过配置博客或创建帖子进行测试。 您可以关闭两个Web服务器,一个HAProxy服务器和一个数据库节点,并且网站仍应完全正常运行。

完成测试后,您可以使用一个命令从DigitalOcean帐户中删除所有这些基础架构组件。 这将删除整个群集以清理本章中的工作。

terraform destroy

您可以重新运行apply ,然后重新运行Ansible playbook以重新生成群集。

下一步是什么?

我们采用了高可用性示例,并将该概念应用于整个应用程序。 本章中的示例用于创建完全冗余且可扩展的WordPress网站。 这是通过利用配置管理工具实现的。 我们将在下一章中探索一种进一步自动化和改进部署的方法。 本书的其余部分将介绍与存储,监控和安全相关的概念,但更重要的是,它们如何应用于您的业务以及在规划基础架构时应考虑的事项。