导航器指南:高可用性

如果您运行的是小型博客,大型应用程序或API,则无关紧要;你永远不希望它离线。单点故障是基础架构的任何部分,如果失败将导致停机。高可用性基础架构没有单点故障。高可用性配置不仅对冗余很重要。扩展基础架构也将更快,更具成本效益。

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

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

如果您运行的是小型博客,大型应用程序或API,则无关紧要; 你永远不希望它离线。

单点故障是基础架构的任何部分,如果失败将导致停机。 一个例子是使用一台服务器来托管您的Web服务器和数据库。 中断通常是由这些单点故障引起的,我们希望设计我们的基础设施以避免这些情况。

高可用性基础架构没有单点故障。 通常,这意味着您的基础架构按服务划分并在多个服务器上运行每个服务。 如果一台服务器出现故障,则可以使用其他服务器来处理请求。 高可用性配置不仅对冗余很重要,而且还可以更快,更经济地扩展基础架构。

想象一下托管文件的Web服务。 现在想象它在三个独立的服务器上运行。 我们有一些直接的问题。 用户将如何访问这些服务器? 我们可以为每个独立服务器添加DNS记录。 遗憾的是,用户将被随机路由到服务器,并可能被发送到脱机服务器。

我们可以通过在基础架构中添加负载均衡器来避免这些陷阱。 负载均衡器将对其配置中的每台服务器执行运行状况检查。 如果服务器处于脱机状态,则负载均衡器不会向其发送任何用户请求。 负载均衡器通过更有效地将用户路由到可用的最佳服务器来提高性能。

执行此添加时我们将要考虑的另一个问题是确保负载均衡器本身不是单点故障。 我们已经考虑过这一点,并且在负载均衡器层和后端服务器上有两个完整的解决方案。

我们的设置

在本章中,我们将介绍使用少量Web服务器部署负载平衡解决方案的两种方法。 到本节结束时(第4章至第6章),我们将在Web和数据库服务之前设置多个负载平衡器,确保我们没有单点故障。

有许多不同的方法来设置负载平衡。 我们将通过两个示例设置,两个都在后端提供Nginx Web服务。

第一个解决方案使用DigitalOcean Load Balancers ,它是一种高可用性服务,可自动处理故障转移恢复。 它们还包括基于标签而不是手动列表将流量定向到Droplet的功能,从而简化了扩展。

第二种解决方案是具有HAProxy和DigitalOcean浮动IP的更自定义的负载平衡解决方案,它们是静态IP地址,可以使用控制面板或API自动在区域内分配和重新分配。 如果主服务器出现故障,您可以使用它们将流量重新路由到备用负载均衡器。

因为这是我们第一次在本书中使用Terraform和Ansible,所以我们将手动详细介绍这一部分,为您提供手动创建自己项目的经验。 随着我们在下一章中向更复杂的设置发展,我们将自动化大部分配置。

使用DigitalOcean负载均衡器

设置DigitalOcean负载均衡器

在控制器Droplet上,移动到我们的存储库中本章的目录

cd /root/navigators-guide/example-code/02-scale/ch04/digitalocean_loadbalancer

在此目录中,有一个terraform.tfvars.sample文件 此示例文件包含注释和注释,可帮助您查找所需的信息。 没有评论,文件看起来像这样:

do_token = ""

project = "DO-LB"

region = "sfo2"

image_slug = "debian-9-x64"

keys = ""

private_key_path = ""

ssh_fingerprint = ""

public_key = ""

这样做会创建一个DigitalOcean Load Balancer以及一些运行Nginx的Droplet。 每个Web服务器都将显示一条带有Droplet主机名的简单欢迎消息。

根据注释中的说明填写变量,然后将文件重命名为terraform.tfvars

mv terraform.tfvars.sample terraform.tfvars

此配置不需要TLS证书,但可以将其添加到DigitalOcean负载均衡器。 DigitalOcean Load Balancer功能还与Let's Encrypt集成,后者免费提供证书。 Lets Encrypt需要注册并添加到您的DigitalOcean帐户的域名。

接下来,准备并执行Terraform部署。 首先,使用terraform init解析计划文件和模块。 (可选)您可以运行terraform plan以查看运行实际脚本时会发生什么。 准备就绪后,运行terraform apply以通过DigitalOcean API执行创建请求。

terraform init
terraform apply

您需要输入yes确认执行,并在申请完成时通知您。

此时,您可以在浏览器中访问Load Balancer的公共IP地址(可以通过terraform show获得),以查看Web服务器中的示例内容。

Terraform还可以使用destroy选项自动删除您的群集。 您可以使用此工作流进行快速测试,但要知道保存到群集的所有数据都将被删除。 destroy选项将删除您的群集。 这是从本章的工作中清除的最快方法。 您可以重新运行apply以生成新群集。

在拆除这个示例集群之前,让我们测试它实际上是否像我们期望的那样高度可用。

测试群集可用性

为了测试后端Web服务器的可用性,我们可以使一台服务器脱机,同时不断请求Load Balancer的连接。 如果连接不断完成,我们就会知道尽管服务器出现故障,服务仍然在线。 (我们无法测试Load Balancer本身的故障转移,因为它作为服务运行,这意味着您没有或不需要直接访问其各个组件。)

在终端中运行以下命令,该终端将每秒连接一次Load Balancer。

while true; do curl -k load_balancer_ip; sleep 1; done

你会看到像这样的连续输出:

Welcome to DO-LB-backend-01!
Welcome to DO-LB-backend-02!
Welcome to DO-LB-backend-03!
Welcome to DO-LB-backend-01!
Welcome to DO-LB-backend-02!
Welcome to DO-LB-backend-03!

尝试关闭其中一个后端Droplet。 Droplet脱机后,您仍应看到测试从其他Load Balancer的后端返回有效响应。 您会注意到您关闭的Droplet不再响应。 如果重新打开电源,一旦通过Load Balancer配置的检查,您将看到它自动重新加入旋转状态。

(如果需要帮助停止正在运行的测试,可以使用CTRL-C键盘命令退出循环)

扩展群集

初始群集设置使用3个后端Droplet。 后端Droplet数量的设置在variables.tf文件的默认变量声明中。 我们可以通过在变量node_count设置为5的terraform.tfvars添加一行来覆盖。一旦添加了该行,您将需要重新应用Terraform计划。

terraform apply

Terraform在这里真的很棒。 它处理基于此变量更改Droplet数量的逻辑,因此当node_count变量增加或减少时,它会自动创建或销毁Droplet。

在终端运行curl到Load Balancer时,请查看输出。 配置新的Droplet后,您将看到它们自动开始响应。

Welcome to DO-LB-backend-02!
Welcome to DO-LB-backend-03!
Welcome to DO-LB-backend-01!
Welcome to DO-LB-backend-02!
Welcome to DO-LB-backend-03!
Welcome to DO-LB-backend-04!
Welcome to DO-LB-backend-05!
Welcome to DO-LB-backend-01!
Welcome to DO-LB-backend-02!
Welcome to DO-LB-backend-03!
Welcome to DO-LB-backend-04!
Welcome to DO-LB-backend-05!
Welcome to DO-LB-backend-01!

在继续之前,您将要破坏此测试项目。 Terraform将计划的当前状态保留在当前工作目录中。 当您通过Terraform销毁资源时,它将自动清除状态。

terraform destroy

使用HAProxy和DigitalOcean浮动IP地址

部署自定义负载平衡解决方案可能是正确的选择。 DigitalOcean Load Balancer目前不支持某些选项。 例如,托管多个站点或应用程序作为后端,多个TLS证书,代理协议支持或特定的TCP参数调整。

此示例使用群集在一起的HAProxy v1.8负载平衡器,使用DigitalOcean浮动IP进行故障转移。

设置HAProxy

在控制器Droplet上,移动到我们的存储库中本章的目录

cd /root/navigators-guide/example-code/02-scale/ch04/haproxy_loadbalancer

在此目录中,有一个terraform.tfvars.sample文件 此示例文件包含注释和注释,可帮助您查找所需的信息。 没有评论,文件看起来像这样:

do_token = ""

project = "HAPROXY-LB"

region = "sfo2"

image_slug = "debian-9-x64"

keys = ""

private_key_path = ""

ssh_fingerprint = ""

public_key = ""

根据注释中的说明填写变量,然后将文件重命名为terraform.tfvars

mv terraform.tfvars.sample terraform.tfvars

接下来,准备并执行Terraform部署。 首先,使用terraform init解析计划文件和模块。 (可选)您可以运行terraform plan以查看运行实际脚本时会发生什么。 准备就绪后,运行terraform apply以通过DigitalOcean API执行创建请求。

terraform init
terraform apply

您需要输入yes确认执行,并在申请完成时通知您。

如果您现在运行terraform show ,您可以看到已部署的资源。 每组资源(即Droplet)根据Terraform配置文件中的资源名称放置在组名中。 在此示例中, haproxy.tf文件的资源声明确定了这些组。

这三个组是HAProxy的load_balancer ,Nginx的web_node和浮动IP的fip 您可以使用terraform-inventory -inventory查看以INI格式获取Ansible invintory,或使用-list选项输出JSON。

此时,您创建并运行所需的Droplet,但仍需要配置它们。

使用Ansible配置Droplet

我们将使用Ansible自动配置Droplet。 我们有一个基本的Ansible playbook,它已预先配置为下载一些Ansible角色。 您将在requirements.yml文件中找到这些Ansible角色。 您不需要逐个安装它们; 您可以使用Ansible Galaxy下载所需的角色。

此命令将角色放在roles目录中。

ansible-galaxy install -r requirements.yml

我们需要为此角色设置更多变量。我们将返回/ root / navigators-guide / example-code / 02-scale / ch04 / haproxy loadbalancer / group vars / load_balancer /目录。 如果查看现有的vars.yml文件,您将看到do_tokenha_auth_key分别被分配了vault_do_tokenvault_ha_auth_key的值。 我们将创建一个名为vault.yml的辅助文件并初始化vault_变量。

在设置变量之前,您需要做两件事。 DigitalOcean API令牌,用于处理故障转移方案的浮动IP分配,以及用于对集群成员进行身份验证的SHA-1哈希。 我们有一个工具来帮助您创建这个。

cd /root/navigators-guide/example-code/02-scale/ch04/haproxy_loadbalancer/
./gen_auth_key

创建该auth 密钥后,继续创建** group vars / load_balancer / vault.yml **文件。 该文件应该看起来像这样:

---
vault_do_token: "79da2e7b8795a24c790a367e4929afd22bb833f59bca00a008e2d91cb5e4285e"
vault_ha_auth_key: "c4b25a9f95548177a07d425d6bc9e00c36ec4ff8"

这些密钥的安全性和保密性对我们的基础设施至关重要。 我们希望限制谁可以查看或编辑此vault.yml文件。 Ansible有一个名为ansible-vault的内置加密系统。

使用此命令加密文件:

ansible-vault encrypt vault.yml

此过程将提示输入密码。 每当我们运行Ansible Playbook时,我们也会被提示输入此密码。 如果您需要编辑加密文件,则需要通过ansible-vault Ansible Vault的文档包含该功能的所有功能的完整列表。

ansible-vault edit vault.yml

Ansible每次运行我们的playbook时都需要解密密码,这不太适合自动化。 我们可以将密码存储在我们系统的其他位置,以便我们通过添加权限控制来保护它。 要创建用于存储密码的文件,可以执行echo 'password' > ~/.vaultpass.txt或使用文本编辑器手动创建文件。 您要确认非特权用户对此文件没有任何访问权限。 取消注释/root/navigators-guide/example-code/02-scale/ch04/haproxy_loadbalancer/ansible.cfg配置文件中的vault_password_file行。 这将阻止Ansible每次运行剧本时询问您的保管库密码。 您还可以更改文件的路径以及要用于存储密码的文件名,但请确保将其保留在git存储库之外。 您不希望意外提交和推送任何密码或秘密令牌。

现在我们准备执行主要的Ansible Playbook。 返回到存储库的根目录并执行ansible-playbook -i /usr/local/bin/terraform-inventory site.yml 同样,您将开始在屏幕上看到一个文本流,显示当前正在运行的角色,当前角色的任务,以及是否检测到更改或错误。 在游戏结束时,您将看到每个主机的所有总计的回放,如下所示:

PLAY RECAP *********************************************************************
138.68.50.232              : ok=1    changed=0    unreachable=0    failed=0   
159.65.78.225              : ok=1    changed=0    unreachable=0    failed=0   
165.227.9.176              : ok=40   changed=38   unreachable=0    failed=0   
178.128.128.168            : ok=1    changed=0    unreachable=0    failed=0   
178.128.3.35               : ok=40   changed=38   unreachable=0    failed=0   
206.189.174.220            : ok=1    changed=0    unreachable=0    failed=0   

现在您可以访问您的站点,在我们的示例中是一个简单的html页面,通过访问您的浮动IP地址,或者您可以添加指向浮动IP地址的域

测试群集可用性

为了测试后端Web服务器的可用性,我们可以在连续请求来自负载均衡器的连接的同时使其脱机。 如果连接不断完成,我们就会知道尽管服务器出现故障,服务仍然在线。

在终端中运行以下命令,该终端将每秒连接一次Load Balancer。

while true; do curl -k floating_ip; sleep 1; done

你会看到像这样的连续输出:

Welcome to HAPROXY-LB-backend-01!
Welcome to HAPROXY-LB-backend-02!
Welcome to HAPROXY-LB-backend-03!
Welcome to HAPROXY-LB-backend-01!
Welcome to HAPROXY-LB-backend-02!
Welcome to HAPROXY-LB-backend-03!

尝试关闭其中一个后端Droplet。 Droplet脱机后,您仍应看到curl从其他Load Balancer的后端返回有效响应。 您会注意到您关闭的Droplet不再响应。 如果重新打开电源,一旦通过Load Balancer配置的检查,您将看到它重新加入轮换状态。

在测试仍在运行的情况下,关闭主HAProxy Droplet,您会看到浮动IP地址在几次丢弃请求后重定向到辅助HAProxy Droplet。 辅助HAProxy Droplet自动启动并继续运行测试。

(如果需要帮助停止正在运行的测试,可以使用CTRL-C键盘命令退出循环)

扩展群集

初始群集设置使用3个后端Droplet。 后端Droplet数量的设置在variables.tf文件的默认变量声明中。 我们可以通过在变量node_count设置为5的terraform.tfvars添加一行来覆盖。

terraform apply

Terraform在这里真的很棒。 它处理基于此变量更改Droplet数量的逻辑,因此当node_count变量增加或减少时,它会自动创建或销毁Droplet。

随着资源数量的每次更改,您将需要再次针对Droplet运行Ansible以配置后端Droplet并修改HAProxy的配置。

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

在终端运行curl到Load Balancer时,请查看输出。 配置新的Droplet后,您将看到它们自动开始响应。

Welcome to HAPROXY-LB-backend-02!
Welcome to HAPROXY-LB-backend-03!
Welcome to HAPROXY-LB-backend-01!
Welcome to HAPROXY-LB-backend-02!
Welcome to HAPROXY-LB-backend-03!
Welcome to HAPROXY-LB-backend-04!
Welcome to HAPROXY-LB-backend-05!
Welcome to HAPROXY-LB-backend-01!
Welcome to HAPROXY-LB-backend-02!
Welcome to HAPROXY-LB-backend-03!
Welcome to HAPROXY-LB-backend-04!
Welcome to HAPROXY-LB-backend-05!
Welcome to HAPROXY-LB-backend-01!

完成后,您可以清理使用destroy创建的Terraform资源。 以这种方式销毁群集时,您将丢失所有数据。

terraform destroy

下一步是什么?

我们采用了一个简单的Web应用程序,通过在多个Droplet上运行它并使用两种不同类型的负载平衡器将流量引导到可操作的Droplet,使其高度可用。 这些是冗余和防止停机的基本概念。

在下一章中,我们将扩展这些概念,以涵盖如何维护负载均衡器的配置,如何管理应用程序及其所在的Droplet,以及如何处理用户会话,文件存储和数据库。 我们将继续使用Terraform和Ansible来部署在八个Droplet集群上运行的WordPress。