介绍
在本教程中,我们将演示如何使用DigitalOcean API使用DOProxy (一个配置完成后提供命令行界面来扩展或缩小HTTP应用程序服务器层)的DOProxy来水平扩展您的服务器设置。
DOProxy是专门为本教程编写的,它提供了一种使用DigitalOcean API创建和删除应用程序服务器Droplet的简单方法,并管理其HAProxy负载平衡器的成员资格。 这种基本的缩放模型允许用户通过HAProxy服务器访问您的应用程序,然后将这些服务器以负载均衡的方式转发到后端应用程序服务器。
DOProxy执行三个主要功能:
- 创建Droplet,并将其添加到负载平衡器
- 删除Droplet并将其从负载平衡器中移除
- 保留一个已经创建的Droplet清单,直到它们被删除
注意:本教程的主要目的是教授通过API以编程方式扩展DigitalOcean服务器体系结构所需的最低限度所需的概念。 您不应该在生产环境中运行DOProxy,因为它没有考虑到弹性设计,而只执行非常基本的错误检查。 据说,熟悉这个脚本是让你开始学习DigitalOcean API横向扩展的好方法。
先决条件
本教程使用以下技术,在继续之前可能需要阅读:
因为DOProxy是用Ruby编写的,所以Ruby的知识是有益的。 为了更多地熟悉Ruby,可以阅读我们关于如何在Ruby中编写代码的系列文章 。 如果您对Ruby不太熟悉,我们提供一些伪代码来解释DOProxy代码的要点。 为了简化我们对API的调用,我们使用了官方的DigitalOcean Ruby包装器DropletKit 。
在深入讨论DOProxy的工作细节之前,我们将在服务器上安装和使用它。
现在,让我们在Ubuntu 16.04 Droplet上安装DOProxy。
安装DOProxy
首先,在NYC3地区创建一个Ubuntu 16.04 Droplet,该地区默认使用DOProxy。 如果您希望使用其他区域,则在安装DOProxy后,需要在doproxy.yml
文件中配置region
变量。 该Droplet将运行HAProxy负载平衡器和DOProxy缩放脚本,因此请选择您认为足够满足您所需的缩放比例的尺寸。 因为这个教程是一个缩放的基本演示,没有真正的流量预期,512MB的大小可能是足够的。
对于本文档的长度,我们将把这个Droplet作为DOProxy服务器 。
接下来,登录到服务器并按照DOProxy GitHub存储库自述文件中的安装和配置 (包括doproxy config和Userdata )部分在此服务器上安装DOProxy。 请务必替换DOproxy配置文件中的YOUR_DO_API_TOKEN
和YOUR_SSH_KEY_FINGERPRINT
值,否则脚本将不起作用。
现在您的服务器上已经安装了DOProxy和HAProxy,我们试着扩展环境。
运行DOProxy
以root身份登录到DOProxy服务器,并进入克隆DOProxy的目录。
不带任何参数运行DOProxy:
ruby doproxy.rb
这应该打印出可用的命令:
OutputCommands:
doproxy.rb print # Print backend Droplets in inventory file
doproxy.rb create # Create a new backend Droplet and reload
doproxy.rb delete <LINE_NUMBER> # Delete a Droplet and reload
doproxy.rb reload # Generate HAProxy config and reload HAProxy
doproxy.rb generate # Generate HAProxy config based on inventory
在这一点上,DOProxy还没有创建任何Droplet。 让我们创建一些让我们的HTTP服务在线,并扩大规模。
放大(创建)
运行create
命令创建由DOProxy管理的第一个Droplet:
ruby doproxy.rb create
返回提示之前需要一些时间(因为脚本通过API创建了一个新的Droplet并等待它启动)。 我们将在通过伪代码的时候讨论如何调用API。
脚本完成后,您应该看到包含Droplet ID的成功消息:
OutputSuccess: 4202645 created and added to backend.
建议您在提示符返回之后等待几分钟,然后再继续执行下一步,因为用户数据脚本可能还没有运行,因此HAProxy可能没有开始传输流量。
一旦准备好继续,请在Web浏览器中访问DOProxy服务器的公共IP地址。 您应该看到一个页面,列出您新的Droplet的主机名 , ID和公共IP地址 。
我们将使用DOProxy创建两个Droplet,总共三个。 随意创建更多,如果你想要的:
ruby doproxy.rb create
ruby doproxy.rb create
现在再次访问Web浏览器中的DOProxy服务器的公共IP地址。 如果刷新页面,您将会注意到,在通过您创建的“Droplet”循环时,页面上的信息会发生变化。 这是因为它们都是通过HAProxy进行负载均衡的,这些HAProxy在使用DOProxy创建时将每个Droplet添加到其配置中。
如果您碰巧在DigitalOcean控制面板中查看,您会注意到这些新的Droplet将会在那里列出(与其他Droplet一起):
让我们仔细看看通过查看DOProxy的库存创建的Droplet。
打印清单
DOProxy提供了一个print
命令,可以打印出属于其库存的所有Droplet:
ruby doproxy.rb print
你应该看到如下所示的输出:
Output0) auto-nginx-0 (pvt ip: 192.0.2.175, status: active, id: 4202645)
1) auto-nginx-1 (pvt ip: 192.0.2.176, status: active, id: 4205587)
2) auto-nginx-2 (pvt ip: 192.0.2.172, status: active, id: 4205675)
在示例输出中,我们看到有关我们创建的三个Droplet的信息,包括主机名,状态和Droplet ID。 当您访问HAProxy负载均衡器(通过DOProxy的公共IP地址)时,主机名和ID应与您在Web浏览器中看到的内容相匹配。
正如您可能已经注意到的那样,DOProxy只会打印它创建的有关飞沫的信息。 这是因为它维护了它创建的Droplet的清单。
现在查看inventory
文件的内容:
cat inventory
你应该看到每个滴的ID,每行一个。 每次创建Droplet时,其ID都存储在此清单文件中。
正如您可能已经猜到的那样,DOProxy的print
命令遍历库存文件中的Droplet ID并执行API调用来检索关于它们中的每一个的信息。
应该注意的是,将服务器清单存储在单个文件中并不是最好的解决方案 - 它可能很容易被损坏或删除,但它演示了一个简单的实现。 分布式密钥值存储(如etcd )将是更好的解决方案。 您还希望在库存中保存的不仅仅是Droplet ID(因此,您不必每次都需要查看某些Droplet信息时进行API调用)。
缩小(删除)
DOProxy也有一个delete
命令,可以让你删除库存中的Droplet。 delete
命令要求您提供要删除的Droplet的行号(如print
命令所显示的那样)。
在运行此命令之前,您可能需要打印清单:
ruby doproxy.rb print
所以,例如,如果你想删除第三个Droplet,你需要提供2
作为行号:
ruby doprorxy.rb delete 2
过了一会儿,你会看到确认信息:
OutputSuccess: 4205675 deleted and removed from backend.
delete
命令通过API删除Droplet,将其从HAProxy配置中删除,并将其从清单中删除。 请随时通过使用DOProxy打印命令或通过检查DigitalOcean控制面板来验证Droplet是否被删除。 您还会注意到它不再是负载平衡器的一部分。
HAProxy配置
我们尚未讨论的最后一块DOProxy是如何配置HAProxy的。
运行create
或delete
DOProxy命令时,会检索清单中每个Droplet的信息,并使用一些信息修改HAProxy配置文件。 具体来说,Droplet ID和私有IP地址用于将每个Droplet添加为后端服务器。
查看生成的haproxy.cfg
文件的最后几行,如下所示:
tail haproxy.cfg
你应该看到这样的东西:
frontend www-http
bind 203.0.113.43:80
reqadd X-Forwarded-Proto:\ http
default_backend www-backend
backend www-backend
server www-4202645 192.0.2.175:80 check # id:4202645, hostname:auto-nginx-0
server www-4205587 192.0.2.176:80 check # id:4205587, hostname:auto-nginx-1
frontend
部分应包含DOProxy服务器的公共IP地址, backend
部分应包含引用创建的每个Droplet的行。
注意:此时,您可能需要删除使用DOProxy创建的其余Droplet( ruby doproxy.rb delete 0
直到所有服务器都不见了)。
现在您已经看到了DOProxy的缩放,让我们仔细看一下代码。
DOProxy代码
在本节中,我们将看看使DOProxy工作的相关文件和代码行。 看看DOProxy是如何实现的,应该给你一些关于如何使用API来管理和自动化你自己的服务器基础架构的想法。
由于您已将存储库克隆到服务器,因此可以查看这些文件,或者查看DOProxy存储库中的文件(https://github.com/scanevari/doproxy) 。
重要文件:
-
doproxy.rb
:DOProxy Ruby脚本。 提供DOProxy背后的命令行界面和逻辑 -
doproxy.yml
:DOProxy配置文件。 包含API令牌并指定Droplet创建选项 -
haproxy.cfg.erb
:HAProxy配置模板。 用于使用适当的后端服务器信息生成负载均衡器配置 -
inventory
:Droplet库存文件。 存储创建的飞沫的ID -
user-data.yml
:用户数据文件。 创建时将在新Droplet上运行的云配置文件
我们先来看看配置文件。
doproxy.yml
这些是doproxy.yml
中的重要doproxy.yml
:
token: YOUR_DO_API_TOKEN
ssh_key_ids:
- YOUR_SSH_KEY_FINGERPRINT
...
droplet_options:
hostname_prefix: auto-nginx
region: nyc3
size: 1gb
image: ubuntu-16-04-x64
token
属性是必须持有读写 API令牌的属性。
其他行指定DOProxy创建新Droplet时将使用的选项。 例如,安装指定的SSH密钥(通过ID或指纹),并在主机名前添加“auto-nginx”。
有关有效Droplet选项的更多信息可以在DigitalOcean API文档中找到 。
用户data.yml
这是在创建每个新Droplet时将由cloud-init执行的文件。 这意味着您可以提供一个云配置文件或脚本来在每个新的Droplet上安装您的应用程序软件。
示例userdata文件包含一个简单的bash脚本,用于在Ubuntu服务器上安装Nginx,并使用Droplet的主机名,ID和公共IP地址替换其默认配置文件:
#!/bin/bash
apt-get -y update
apt-get -y install nginx
export DROPLET_ID=$(curl http://169.254.169.254/metadata/v1/id)
export HOSTNAME=$(curl -s http://169.254.169.254/metadata/v1/hostname)
export PUBLIC_IPV4=$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
echo Droplet: $HOSTNAME, ID: $DROPLET_ID, IP Address: $PUBLIC_IPV4 > /var/www/html/index.html
这些curl
命令使用DigitalOcean元数据服务检索关于Droplet(主机名,ID和IP地址)的信息。
在生产实现中,该文件将包含用于安装和配置应用程序的命令。 您也可以通过自动安装SSH密钥以及连接到您的配置管理或监控工具来使用此功能,将您的Droplet集成到整个基础架构中。
要详细了解userdata,cloud-config和metadata,请查看以下链接:
haproxy.cfg.erb
HAProxy配置模板包含大部分负载均衡器配置,一些Ruby代码将被后端Droplet信息替换。
我们将看看生成后端配置的Ruby部分:
backend www-backend
<% @Droplets.each_with_index do |droplet, index| %>
server www-<%= droplet.id %> <%= droplet.private_ip %>:80 check # id:<%= droplet.id %>, hostname:<%= droplet.name -%>
<% end %>
此代码遍历清单中的每个Droplet,并为其中的每一个(基于私有IP地址)添加一个新的HAProxy后端条目。
例如,像这样的一条线将被生成每个Droplet:
server www-4202645 192.0.2.175:80 check # id:4202645, hostname:auto-nginx-0
无论何时创建或删除Droplet,DOProxy都会生成一个新的HAProxy配置文件,其中包含更改。
doproxy.rb
这个Ruby脚本主要由一个DOProxy类组成,该类包含执行Droplet创建和删除,库存管理和HAProxy配置生成的方法。
如果您了解Ruby,请查看GitHub上的文件: https : //github.com/scanevari/doproxy/blob/master/doproxy.rb 。
如果你不了解Ruby,下面是一些解释每种方法的简化的pseudocode
。 将它与实际的Ruby代码进行比较可能会有所帮助,从而帮助您了解发生的情况。
def initialize
每次执行DOProxy都有任何有效的参数:
- 阅读
doproxy.yml
配置文件并获取API令牌和Droplet选项。
def get\_inventory
检索清单文件中每个Droplet的信息。 必须在执行任何其他方法之前执行。
- 阅读库存文件(其中包含Droplet ID)
- 对于每个Droplet ID,使用API检索Droplet信息
def print\_inventory
此方法在清单文件中为每个Droplet ID打印Droplet信息。 它使用doproxy.rb print
命令调用。
- 对于清单中的每个Droplet,打印主机名,私有IP地址,状态和ID
def create\_server
当通过doproxy.rb create
命令调用时,此方法创建一个新的Droplet并将其添加到清单文件。 然后,它调用reload_haproxy
重新生成HAProxy配置文件并重新加载负载均衡器。
- 阅读userdata文件
- 使用API根据提供的用户数据和选项创建一个Droplet
- 等待Droplet状态变为“活动” - 使用API每15秒检索一次Droplet信息,直到状态改变
- 状态为“活动”时,将Droplet ID添加到清单文件
- 调用
reload_haproxy
重新生成HAProxy配置文件并重新加载负载平衡器
def delete\_server(line\_number)
当使用doproxy.rb delete
命令时,此方法将删除指定的Droplet并从清单文件中删除其ID。 然后调用reload_haproxy
重新生成HAProxy配置文件并重新加载负载均衡器。
- 从清单文件中删除指定的行(删除Droplet ID)
- 使用API通过其ID删除Droplet
- 调用
reload_haproxy
重新生成HAProxy配置文件并重新加载负载平衡器
def generate\_haproxy\_cfg
这是一种支持方法,可根据清单中的Droplet创建新的HAProxy配置文件。
- 打开HAProxy配置模板(
haproxy.cfg.erb
) - 对于清单中的每个Droplet,添加相应的后端服务器条目
- 将生成的
haproxy.cfg
文件写入磁盘
def reload\_haproxy
这是另一种支持方法,将HAProxy配置文件复制到适当的位置并重新加载HAProxy。 这依赖于generate_haproxy_cfg
。
- 将HAProxy配置文件
haproxy.cfg
复制到HAProxy将在重新加载时查找的位置 - 重新加载HAProxy
这就是DOProxy工作的重要代码。 我们将要讨论的最后一件事是DropletKit,我们在DOProxy中使用的API包装器。
DropletKitGem
DOProxy使用DropletKit gem ,这是官方的DigitalOcean API v2 Ruby包装器,可以方便地调用DigitalOcean API。 DropletKit允许我们轻松地编写Ruby程序来执行如下操作:
- 创建新的飞沫
- 删除现有的飞沫
- 获取有关现有的Droplet的信息,例如状态,IP地址,Droplet ID,区域等
本教程重点关注这些特定的API端点,但请记住,还有许多其他端点可以帮助促进DigitalOcean服务器基础架构的编程管理。
结论
现在您已经看到了一个简单的脚本如何通过利用DigitalOcean API,云配置和元数据来帮助扩展服务器环境,您可以应用所有这些概念来扩展自己的服务器设置。 尽管DOProxy不适用于生产用途,但它应该为您提供一套完整的解决方案。
请记住,这里用DOProxy描述的缩放设置是信息性的,但是通过与我们的监控系统一起使用,可以大大提高。 这将允许您根据某些条件(如服务器资源利用率)自动扩展和缩小应用程序服务器层。