如何在DigitalOcean Ubuntu 16.04 Droplets上自动扩展您的Web应用程序

在本教程中,我们将演示如何使用DigitalOcean API来横向扩展您的服务器设置。要做到这一点,我们将使用** DOProxy **,一个相对简单的Ruby脚本,一旦配置,它提供了一个命令行界面,以扩展或缩小您的HTTP应用程序服务器层。 本教程的主要目的是教授通过API以编程方式扩展DigitalOcean服务器体系结构所需的最低限度所需的概念。

介绍

在本教程中,我们将演示如何使用DigitalOcean API使用DOProxy (一个配置完成后提供命令行界面来扩展或缩小HTTP应用程序服务器层)的DOProxy来水平扩展您的服务器设置。

DOProxy是专门为本教程编写的,它提供了一种使用DigitalOcean API创建和删除应用程序服务器Droplet的简单方法,并管理其HAProxy负载平衡器的成员资格。 这种基本的缩放模型允许用户通过HAProxy服务器访问您的应用程序,然后将这些服务器以负载均衡的方式转发到后端应用程序服务器。

DOProxy执行三个主要功能:

- 创建Droplet,并将其添加到负载平衡器
- 删除Droplet并将其从负载平衡器中移除
- 保留一个已经创建的Droplet清单,直到它们被删除

DOProxy创建

注意:本教程的主要目的是教授通过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 configUserdata )部分在此服务器上安装DOProxy。 请务必替换DOproxy配置文件中的YOUR_DO_API_TOKENYOUR_SSH_KEY_FINGERPRINT值,否则脚本将不起作用。

现在您的服务器上已经安装了DOProxy和HAProxy,我们试着扩展环境。

运行DOProxy

root身份登录到DOProxy服务器,并进入克隆DOProxy的目录。

不带任何参数运行DOProxy:

ruby doproxy.rb

这应该打印出可用的命令:

Commands:
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的成功消息:

Success: 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一起):

控制面板中的Droplet

让我们仔细看看通过查看DOProxy的库存创建的Droplet。

DOProxy提供了一个print命令,可以打印出属于其库存的所有Droplet:

ruby doproxy.rb print

你应该看到如下所示的输出:

0) 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

过了一会儿,你会看到确认信息:

Success: 4205675 deleted and removed from backend.

delete命令通过API删除Droplet,将其从HAProxy配置中删除,并将其从清单中删除。 请随时通过使用DOProxy打印命令或通过检查DigitalOcean控制面板来验证Droplet是否被删除。 您还会注意到它不再是负载平衡器的一部分。

HAProxy配置

我们尚未讨论的最后一块DOProxy是如何配置HAProxy的。

运行createdelete DOProxy命令时,会检索清单中每个Droplet的信息,并使用一些信息修改HAProxy配置文件。 具体来说,Droplet ID和私有IP地址用于将每个Droplet添加为后端服务器。

查看生成的haproxy.cfg文件的最后几行,如下所示:

tail haproxy.cfg

你应该看到这样的东西:

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

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地址替换其默认配置文件:

用户data.yml
#!/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部分:

haproxy.cfg.erb
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:

haproxy.cfg
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描述的缩放设置是信息性的,但是通过与我们的监控系统一起使用,可以大大提高。 这将允许您根据某些条件(如服务器资源利用率)自动扩展和缩小应用程序服务器层。