导航指南:高可用性
注意:这是《导航指南》内容的早期版本,由 DigitalOcean 解决方案工程师提供。 本书的目标是帮助企业客户规划他们的基础设施需求,提供沿途的工作示例,并包括技术细微差别和使某些决策比其他决策更好的“原因”。
这本书和随附的代码将在 GitHub 存储库中公开提供。 因为这是一个早期版本,所以这本书还没有完成,存储库还没有公开,但请继续关注!
无论您运行的是小型博客、大型应用程序还是 API,都无关紧要。 你永远不希望它离线。
单点故障是基础架构的任何部分,如果发生故障将导致停机。 一个例子是使用一台服务器来托管您的 Web 服务器和数据库。 中断通常是由这些单点故障引起的,我们希望设计我们的基础设施来避免这些情况。
高度可用的基础架构没有单点故障。 通常,这意味着您的基础架构按服务划分,并在多个服务器上运行每个服务。 如果一台服务器出现故障,则有其他服务器可用于处理请求。 高度可用的配置不仅对冗余很重要,而且扩展您的基础架构也将更快、更具成本效益。
想象一个托管文件的 Web 服务。 现在想象它在三个独立的服务器上运行。 我们有一些直接的问题。 用户将如何访问这些服务器? 我们可以为每个独立的服务器添加 DNS 记录。 不幸的是,用户会被随机路由到服务器,并且可能会被发送到离线的服务器。
我们可以通过在我们的基础架构中添加负载均衡器来避免这些陷阱。 负载均衡器将对其配置中的每台服务器执行健康检查。 如果服务器离线,负载均衡器不会向它发送任何用户请求。 负载均衡器通过更有效地将用户路由到可用的最佳服务器来提高性能。
在执行此添加时,我们还有一个额外的问题是确保负载均衡器本身不是单点故障。 我们已经考虑到这一点,并拥有两个在负载均衡器层和后端服务器上高度可用的完整解决方案。
我们的设置
在本章中,我们将研究两种使用几个 Web 服务器部署负载平衡解决方案的方法。 在本节结束时(第 4 - 6 章),我们将在 Web 和数据库服务之前设置多个负载平衡器,以确保我们没有单点故障。
有许多不同的方法来设置负载平衡。 我们将通过两个示例设置,都在后端提供 Nginx Web 服务。
第一个解决方案使用 DigitalOcean 负载均衡器 ,这是一种高度可用的服务,可以自动处理故障转移恢复。 它们还包括基于 tags 而不是手动列表将流量引导到 Droplets 的能力,从而简化了扩展。
第二种解决方案是使用 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 负载均衡器以及一些运行 Nginx 的 Droplet。 每个 Web 服务器都会显示一条简单的欢迎消息,其中包含各个 Droplet 的主机名。
根据注释中的说明填写变量,然后将文件重命名为terraform.tfvars
。
mv terraform.tfvars.sample terraform.tfvars
此配置不需要 TLS 证书,但可以将其添加到 DigitalOcean 负载均衡器。 DigitalOcean 负载均衡器功能还与 Let's Encrypt 集成,后者免费提供证书。 Lets Encrypt 需要注册并添加到您的 DigitalOcean 帐户的域名。
接下来,准备并执行 Terraform 部署。 首先,使用 terraform init
解析计划文件和模块。 或者,您可以运行 terraform plan
以查看运行实际脚本时会发生什么。 准备好后,运行 terraform apply
通过 DigitalOcean API 执行创建请求。
terraform init terraform apply
您需要输入yes
确认执行,申请完成后会通知您。
此时,您可以在浏览器中访问负载均衡器的公共 IP 地址(您可以使用 terraform show
获取),以查看来自 Web 服务器的示例内容。
Terraform 还可以使用 destroy
选项自动删除您的集群。 您可以使用此工作流程进行快速测试,但要知道保存到集群的任何数据都将被删除。 destroy 选项将删除您的集群。 这是清理本章工作的最快方法。 您可以重新运行 apply
以生成新的集群。
在您拆除这个示例集群之前,让我们测试一下它实际上是否像我们预期的那样高度可用。
测试集群可用性
为了测试后端 Web 服务器的可用性,我们可以让一台服务器离线,同时不断地从负载均衡器请求连接。 如果连接继续通过,我们将知道尽管服务器出现故障,服务仍保持在线。 (我们无法测试负载均衡器本身的故障转移,因为它作为服务运行,这意味着您没有或不需要直接访问其各个组件。)
在终端中运行以下命令,该终端将每秒连接一次负载均衡器。
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!
尝试关闭后端 Droplets 之一。 在 Droplet 离线的情况下,您仍然应该看到测试从您的其他负载均衡器的后端返回有效响应。 您会注意到您关闭的 Droplet 不再响应。 如果您重新打开它,您将看到它在通过负载均衡器的配置检查后自动添加回轮换中。
(如果需要帮助停止正在运行的测试,可以使用 CTRL-C
键盘命令退出循环)
扩展集群
初始集群设置使用 3 个后端 Droplet。 后端 Droplet 数量的设置在 variables.tf 文件中的默认变量声明中。 我们可以通过在 terraform.tfvars
中添加一行并将变量 node_count
设置为 5 来覆盖。 添加该行后,您将需要重新应用 Terraform 计划。
terraform apply
Terraform 在这里确实大放异彩。 它处理基于此变量更改 Droplet 数量的逻辑,因此它会随着 node_count
变量的增加或减少而自动创建或销毁 Droplet。
在将 curl
运行到负载均衡器的终端中,查看输出。 配置新的 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 负载均衡器目前不支持某些选项。 例如托管多个站点或应用程序作为后端、多个 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
,你可以看到你已经部署的资源。 每组资源(即 Droplets) 根据 Terraform 配置文件中的资源名称放在一个组名中。 在此示例中, haproxy.tf 文件 的资源声明确定了这些组。
这三组分别是 HAProxy 的 load_balancer
、Nginx 的 web_node
和浮动 IP 的 fip
。 您可以使用 terraform-inventory -inventory
查看以获取 INI 格式的 Ansible 库存,或使用 -list
选项输出 JSON。
至此,您需要的 Droplet 已创建并正在运行,但仍需要对其进行配置。
使用 Ansible 配置 Droplet
我们将使用 Ansible 自动配置 Droplets。 我们有一个基本的 Ansible 剧本,它已预先配置为下载一些 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/[ X192X] 目录。 如果查看现有的 vars.yml 文件,您将看到 do_token
和 ha_auth_key
被分配了 vault_do_token
和 [ 的值X135X],分别。 我们将创建一个名为 vault.yml 的辅助文件并初始化 vault_
变量。
在设置变量之前,您需要做两件事。 一个 DigitalOcean API 令牌,用于处理故障转移场景的浮动 IP 分配,以及一个 SHA-1 哈希,用于对集群成员进行身份验证。 我们有一个工具可以帮助您创建它。
cd /root/navigators-guide/example-code/02-scale/ch04/haproxy_loadbalancer/ ./gen_auth_key
创建 auth_key 后,继续创建 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 每次运行我们的剧本时都需要解密密码,这对于自动化来说并不理想。 我们可以将密码存储在系统的其他位置,以便我们通过添加权限控制来保护它。 要创建文件来存储密码,您可以执行 echo 'password' > ~/.vaultpass.txt
或使用文本编辑器手动创建文件。 您要确认非特权用户对此文件没有任何访问权限。 取消注释 /root/navigators-guide/example-code/02-scale/ch04/haproxy_loadbalancer/ansible.cfg 配置文件中的 vault_password_file
行。 这将阻止 Ansible 在您每次运行 playbook 时询问您的保管库密码。 您还可以更改文件的路径和要用于存储密码的文件名,但请确保将其保存在您的 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
现在您可以通过访问您的浮动 IP 地址来访问您的站点,在我们的例子中是一个简单的 html 页面,或者您可以 添加一个指向浮动 IP 地址的域 。
测试集群可用性
为了测试后端 Web 服务器的可用性,我们可以让一台服务器离线,同时不断地从负载均衡器请求连接。 如果连接继续通过,我们将知道尽管服务器出现故障,服务仍保持在线。
在终端中运行以下命令,该终端将每秒连接一次负载均衡器。
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!
尝试关闭后端 Droplets 之一。 在 Droplet 离线的情况下,您仍然应该看到 curl 从您的其他负载均衡器的后端返回有效响应。 您会注意到您关闭的 Droplet 不再响应。 如果您重新打开它,您将看到它在通过负载均衡器的配置检查后重新添加到轮换中。
在测试仍在运行的情况下,关闭主 HAProxy Droplet 的电源,您将看到浮动 IP 地址在几个丢弃请求后重定向到辅助 HAProxy Droplet。 辅助 HAProxy Droplet 会自动启动并继续运行测试。
(如果需要帮助停止正在运行的测试,可以使用 CTRL-C
键盘命令退出循环)
扩展集群
初始集群设置使用 3 个后端 Droplet。 后端 Droplet 数量的设置在 variables.tf 文件中的默认变量声明中。 我们可以通过在 terraform.tfvars
中添加一行并将变量 node_count
设置为 5 来覆盖。
terraform apply
Terraform 在这里确实大放异彩。 它处理基于此变量更改 Droplet 数量的逻辑,因此它会随着 node_count
变量的增加或减少而自动创建或销毁 Droplet。
随着资源计数的每次更改,您将需要再次针对您的 Droplets 运行 Ansible 以配置您的后端 Droplets 并修改 HAProxy 的配置。
ansible-playbook -i /usr/local/bin/terraform-inventory site.yml
在将 curl
运行到负载均衡器的终端中,查看输出。 配置新的 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!
完成后,您可以清理 Terraform 使用 destroy
创建的资源。 当您以这种方式破坏集群时,您将丢失所有数据。
terraform destroy
下一步是什么?
我们采用了一个简单的 Web 应用程序,并通过在多个 Droplet 上运行它并使用两种不同类型的负载均衡器将流量引导到可操作的 Droplet 来使其具有高可用性。 这些是冗余和防止停机的基本概念。
在下一章中,我们将扩展这些概念,涵盖如何维护负载均衡器的配置、如何管理应用程序及其所在的 Droplet,以及如何处理用户会话、文件存储和数据库。 我们将继续使用 Terraform 和 Ansible 来部署一个在 8 个 Droplet 的集群上运行的 WordPress。