跳转至

第34章:使用AWS进行部署

亚马逊网络服务(AWS)是目前最大的云服务提供商。它提供了许多服务产品,简化了应用程序的部署和维护。在本章中,你将学习如何使用其中的一些服务来部署Vapor应用。

开始之前

要执行本章的步骤,你必须有一个AWS账户。如果你还没有,请按照https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/上的说明创建一个。

设置你的AWS实例

你的第一步是启动一个EC2实例。EC2AWS的一个虚拟机产品。这给你一个普通的Linux机器,你可以用它来运行你的Vapor应用程序。

在这个例子中,你将创建一个Ubuntu 20.04实例。20.04Ubuntu的最新LTS(长期服务)版本。

首先,你必须决定你要使用哪个地区。点击你名字旁边的下拉菜单,选择离你最近的地区。

img

选择区域后,点击ServicesEC2

img

在你启动你的实例之前,你必须创建一个Security Group。这基本上是你的实例的防火墙,允许你指定服务器上哪些端口是开放的。

点击Security Groups,然后点击Create Security Group

在出现的对话框中,输入一个Security group nameDescription,这将使你很容易把它与你的应用程序联系起来。在这个例子中,将你的组命名为vapor-til

Inbound部分,点击Add Rule来添加一个新规则。使用Type下的下拉菜单,选择SSH。在Source下,选择My IP。重复HTTPHTTPS的过程,但把Source设置为Anywhere。你的屏幕应该与下面类似:

img

点击页面底部的Create security group来创建你的安全组。

你现在准备好创建你的实例了。点击InstancesLaunch Instances。这就开始了配置和启动EC2实例的七步程序。

首先,你必须选择一个亚马逊机器图像(AMI)作为你的EC2实例的基础。为了简化寻找正确的AMI,在搜索框中输入20.04,并勾选Free tier only。选择一个名为Ubuntu Server 20.04 LTS的,点击其行中的Select

img

接下来,你将选择你的Instance TypeAWS突出了默认的t2.micro。这是Free tier eligible,意味着在你拥有账户的前12个月,你可以免费获得1GB内存和1vCPU。你将坚持这个选择。

点击Next: Configure Instance Details

在这一页,你可以为你的实例设置各种细节。在这个例子中,只需让一切保持原样。

img

点击Next: Add Storage

在这一页,你将为你的应用程序配置卷。将Size改为20;这将为你的应用程序提供足够的空间。

img

点击Next: Add Tags

这个页面允许你为你的实例添加标签。这一步是可选的,但随着使用量的增加,这样做将简化对AWS资源的管理。单击Add Tag,并输入以下值:

  • Key: Name
  • Value: vapor-til

这使得该实例被命名为vapor-til

img

单击Next: Configure Security Group

在这一页,你将把你之前创建的安全组附加到你的实例上。点击Select an existing security group单选按钮。然后,选择你的vapor-til组:

img

最后,点击Review and Launch

在这个页面上,你可以验证你之前选择的选项。当你满意时,点击LaunchAWS将提示你选择一个现有的密钥对或创建一个新的。你需要一个密钥对来允许你对你的实例进行SSH访问,所以不要跳过这个步骤。如果你创建一个新的密钥对,记得点击Download Key Pair

一旦你配置并保存了你的密钥对,点击Launch Instances

img

AWS将确认它正在启动你的实例。点击View Instances,返回到你的实例摘要页面。如果你足够快,你的实例将显示Instance StatePending,有一个黄色指示灯。过了一会儿,它将显示为Running,并有一个绿色指示灯。

复制IPv4 Public IP。你将用它来登录到你的实例。

SSH要求你把你的私钥设置为对其所有者只读,也就是你,其他人不能访问。如果该文件有任何其他保护设置,SSH将拒绝使用它。在终端,输入以下命令设置保护你的私钥:

chmod 600 /path/to/your/ssh/key

Note

一般来说,SSH密钥和其他相关文件应该放在隐藏目录~/.ssh中。如果你没有把你的钥匙放在那里,请在设置其保护之前考虑这样做。

现在,在终端,输入以下命令:

ssh -i /location/to/your/ssh/key ubuntu@your-aws-ip

这将使你登录并进入你的实例中的shell提示。

为了简化对实例的访问,你可以在~/.ssh/config中为它创建一个条目。使用你喜欢的文本编辑器--nanoviSublime Text都是不错的选择--在该文件中添加以下内容:

Host vapor-til
    HostName <your public IP or public DNS name>
    User ubuntu
    IdentityFile </path/to/your/key/file>

现在,你可以通过在终端输入以下命令连接到你的实例:

ssh vapor-til

下面的命令都是假设你已经登录到你的EC2实例并有root权限。

在一个新的系统中,确保所有软件包都是最新的,总是一个好主意。要更新你的系统,请输入以下命令:

sudo apt-get update
sudo apt-get upgrade -y

安装Swift

为了构建你的Vapor应用,你必须在你的EC2实例上安装SwiftSwift支持许多Linux平台,包括UbuntuCentOS。请访问https://swift.org/getting-started/,了解为你的平台安装的细节。

首先,为你的平台下载工具链。你可以在https://swift.org/download/#releases找到最新的工具链。例如,在终端,运行:

wget https://swift.org/builds/swift-5.3.2-release/ubuntu2004/swift-5.3.2-RELEASE/swift-5.3.2-RELEASE-ubuntu20.04.tar.gz

这就把Swift 5.3.2的工具链下载到你的本地目录。接下来,解压下载的文件:

tar -xzf swift-5.3.2-RELEASE-ubuntu20.04.tar.gz

这样就把下载的文件解压到当前工作目录中。

接下来,安装你的系统所需的依赖项。对于Ubuntu 20.04,在终端输入:

sudo apt-get install binutils git gnupg2 libc6-dev \
  libcurl4 libedit2 libgcc-9-dev libpython2.7 \
  libsqlite3-0 libstdc++-9-dev libxml2 libz3-dev \
  pkg-config tzdata zlib1g-dev -y

最后,将Swift工具链添加到你的路径中,这样你就可以从命令行中使用它。在终端,运行:

echo "export PATH=/home/ubuntu/swift-5.3.2-RELEASE-ubuntu20.04/usr/bin:${PATH}" >> .profile
source .profile

Note: If you download a newer version of the toolchain, be sure to update the path to reflect the new version.

This adds the directory to the Swift binary to your profile and reloads it. Important: remember to set the directory to the path where your Swift installation exists.

You can verify your installation by entering:

Note

如果你下载了较新版本的工具链,请确保更新路径以反映新版本。

这将把Swift二进制文件的目录添加到你的配置文件中,并重新加载它。

Tips

记得将目录设置为你的Swift安装所在的路径。

你可以通过输入验证你的安装:

swift --version

你应该看到返回的是正确的版本:

img

系统内存

Swift编译器可以使用大量的内存。小的云实例,如t2.micro,不包含足够的内存让Swift编译器工作。你可以通过启用交换空间来解决这个问题。在终端,输入以下内容:

sudo su -
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
exit

这些命令切换到一个超级用户,并创建一个2GB的交换文件。这应该足够让编译器工作了。

设置你的应用程序

为了设置你的应用程序,你将首先从GitHub克隆它。要从本书的其余部分建立TILapp的例子,请输入以下命令:

# 1
git clone https://github.com/raywenderlich/vapor-til.git
# 2
cd vapor-til
# 3
swift build -c release --enable-test-discovery

下面是这个的作用:

  1. 克隆GitHub上的vapor-til项目。
  2. 切换到vapor-til文件夹。
  3. 以发布模式构建项目。

构建项目后,你可以尝试通过输入来启动应用程序:

./.build/release/Run

这将不会起作用,因为你还没有设置数据库或必要的环境变量。

设置一个PostgreSQL服务器

对于你的数据库,你将使用亚马逊关系型数据库服务(RDS)。这个AWS数据库服务支持几个流行的关系型数据库系统,包括PostgreSQL

在创建你的数据库之前,你需要配置另一个安全组。点击你的AWS页面顶部的Services,在搜索栏中输入VPC。这将带你到VPC仪表板。点击Your VPCs,显示你的VPC(虚拟私有云)信息。选择你之前为EC2实例选择的VPC。在描述部分,记下你的IPv4 CIDR。它将是类似于172.31.0.0/16的东西。

现在,在控制台中点击左侧列表中的Security Groups。现在出现的屏幕应该看起来很熟悉。点击Create Security Group。将该组命名为vapor-til database

Inbound标签上,点击Add Rule。从Type下拉选择PostgreSQL,在Source框中输入你的IPv4 CIDR

你的屏幕应该看起来像这样:

img

点击Create security group

AWS控制台,点击Services,找到RDS。点击Create Database。这将显示Select engine页面。选择PostgreSQL作为你的引擎。

img

接下来,你必须选择你的用例。在本教程中,选择Dev/Test。在这下面,你被要求指定关于你的数据库的一些细节。在Settings下,输入以下信息:

  • DB instance identifier:vapor-til
  • Master username:vaportil
  • Master password和Confirm password:你的选择

img

接下来,在DB instance size下,选择Burstable classes单选按钮并从下拉列表中选择db.t3.micro

img

然后,在Connectivity下,确保你选择与你的EC2实例相同的VPC。接下来,将Public accessibility设置为Yes。这将允许你从你的本地机器访问数据库,如果你愿意的话。

Note

如果你确实希望从你的本地机器访问你的数据库,你将需要在你的安全组中添加一条规则,以允许访问。

VPC security groups设置为Choose existing VPC security groups。点击Default旁边的X,删除该组,并从下拉菜单中添加vapor-til database。将其他设置保持在默认状态。

img

最后,展开Additional configuration。在Database options下,输入vaportil作为Initial database name。将所有其他选项保留为默认值。

滚动到页面底部,点击Create database。这将需要一些时间来完成。点击数据库列表中的数据库,查看其详细信息。在Connectivity & security部分找到Endpoint,并记下它。你很快就会需要它。

img

安装和配置nginx

nginx是一个流行的网络服务器,通常用作其他网络应用程序前面的代理服务器。对于Vapor应用程序来说,这很有用,因为它提供了额外的功能,如压缩、缓存、HTTP/2支持、TLS(HTTPS)等等。

这里的例子非常简单,只是让你开始。然而,它很容易定制,可以实现更多的功能。

首先,在你的EC2实例上安装nginxSSH进入你的EC2实例,输入以下命令:

sudo su -
apt-get install nginx -y

这将切换到超级用户,并从APT资源库中安装nginx。为了设置nginx配置,在/etc/nginx/sites-available创建一个文件,名为vapor-til,用你喜欢的编辑器添加以下内容:

server {
  listen 80;

  root /home/ubuntu/vapor-til/Public;
  try_files $uri @proxy;

  location @proxy {
    proxy_pass http://localhost:8080;
    proxy_pass_header Server;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 3s;
    proxy_read_timeout 10s;
  }
}

然后运行以下命令:

# 1
rm /etc/nginx/sites-enabled/default
# 2
ln -s /etc/nginx/sites-available/vapor-til \
  /etc/nginx/sites-enabled/vapor-til
# 3
systemctl reload nginx

以下是这样做的原因:

  1. 禁用默认网站。
  2. 启用你的vapor-til网站。
  3. 重新加载nginx以激活你的改变。

在测试所有这些之前,你需要一种方法来启动你的应用程序。

以系统服务的形式运行你的应用程序

你希望你的应用程序在实例启动时运行,并在由于关键错误而崩溃时重新启动。实现这一目标的最简单方法是将其整合为一个系统服务。大多数Swift--因此也包括Vapor--支持的Linux版本都使用一个叫做systemd的服务来完成这个任务。

你需要在你的运行系统中添加两个文件。一个是包含你的应用程序所需的所有环境变量,另一个是定义你的应用程序的服务。

Note

你可以在一个文件中完成所有的工作,但这样的划分使你在必要时更容易调整环境变量。

首先,SSH到你的EC2实例,如果你还没有成为root的话。在终端,输入:

sudo su -

接下来,用你喜欢的编辑器创建/etc/vapor-til.conf,并在其中添加以下内容:

DATABASE_HOST='<your AWS RDS endpoint>'
DATABASE_USERNAME='vaportil'
DATABASE_NAME='vaportil'
DATABASE_PASSWORD='<your chosen password>'
SENDGRID_API_KEY='test'
GOOGLE_CALLBACK_URL='test'
GOOGLE_CLIENT_ID='test'
GOOGLE_CLIENT_SECRET='test'
GITHUB_CALLBACK_URL='test'
GITHUB_CLIENT_ID='test'
GITHUB_CLIENT_SECRET='test'
SIWA_REDIRECT_URL='test'
IOS_APPLICATION_IDENTIFIER='test'
WEBSITE_APPLICATION_IDENTIFIER='test'

这设置了TILapp用来寻找其数据库并与其他服务集成的环境变量。它们与你在其他章节中在Xcode中创建的环境是相同的。

Note

为了让TILapp的所有部分正常工作,你需要为所有的SENDGRIDGOOGLEGITHUBSIWA值替换有效值。关于如何配置这些值,见第22-26章。现在,任何非空的字符串都将允许应用程序运行。

接下来,用你喜欢的编辑器创建/etc/systemd/system/vapor-til.service,并在其中添加以下内容:

# 1
[Unit]
Description="Vapor TILapp"
After=network.target

# 2
[Service]
User=ubuntu
EnvironmentFile=/etc/vapor-til.conf
WorkingDirectory=/home/ubuntu/vapor-til

# 3
Restart=always

# 4
ExecStart=/home/ubuntu/vapor-til/.build/release/Run \
  --env production

[Install]
WantedBy=multi-user.target

下面是这个的作用:

  1. systemd将其管理的项目称为unit。本节为你的应用程序定义了这个单元,并规定它在网络启动后才能启动。
  2. 为你的应用程序的服务指定参数。你可以让应用程序以任何有效用户的身份运行。注意,在这一节中,你使用你先前创建的配置文件来描述环境。
  3. 告诉systemd,如果你的应用程序失败了,它应该总是尝试重新启动。
  4. 指定systemd将执行的命令来启动你的应用程序。如果有必要,你可以在这里添加其他参数。

在保存了服务定义文件的修改后,你必须告诉systemd读取该文件,以便让它识别服务。输入以下命令:

systemctl daemon-reload

这将使vapor-til.service作为一个选项可用。通过下面的命令,你会发现标准的键盘快捷键,如tab完成,与你的新服务一起工作,就像它们与现有的系统服务一样。

要启动你的应用程序并使其在重启后自动启动,请输入以下命令:

systemctl start vapor-til.service
systemctl enable vapor-til.service

你的应用程序应该启动。你可以通过输入来检查其状态:

systemctl status -l vapor-til.service

你应该看到服务器正在启动:

img

一旦你的应用程序运行,你应该能够通过在浏览器中输入你的EC2实例的公共DNS名称(与你用于SSH的名称相同)来访问它。

img

如果你需要手动重启你的应用程序,请使用以下命令:

systemctl restart vapor-til.service

而且,如果你想停止你的应用程序,下面的命令会起到作用:

systemctl stop vapor-til.service

接下来去哪?

你现在已经掌握了如何在AWS上设置Vapor应用程序的基本知识。AWS允许的事情还有很多,如扩展、IP池、自动备份、复制等等。你可以添加负载均衡器和带有TLS证书的自定义DNS名称。还有其他部署选项,如在Docker中运行,甚至使用AWS Lambda。涵盖AWS的所有内容本身就是一整本书! 花一些时间阅读AWS的文档和教程,以了解更多。

当你完成了本章的EC2实例和RDS数据库后,一定要Delete数据库实例和Terminate EC2实例,这样AWS就会删除它们,你就不会为它们支付任何(额外)费用。