在 AWS 上部署三层应用程序的实用指南
这篇文章最初发表于Practical Cloud。
点击此处查看更长的原始版本。
多层架构已成为云端设计和构建应用程序的最流行方式。这主要是因为它们提供了高可用性、复制、灵活性、安全性以及许多其他优势。这与单层架构截然不同,单层架构通常将软件应用程序的所有必需组件打包到单个服务器中。
最流行的多层设计模式是三层架构。三层架构由以下层组成:
- 表示层:这是应用程序的最外层,提供与用户交互的接口。它还提供与其他层的安全通信通道。
- 逻辑层:这是处理信息和执行应用程序逻辑的地方。它处理来自表示层的输入,并在必要时与数据层通信。它也被称为应用层或中间件。
- 数据层:这是数据库管理系统所在的位置,从而为其提供一个安全、隔离的环境来存储和管理应用程序信息。
在本指南中,我们将使用三层架构设计模式在 AWS 上设计一个容错性极强、可扩展性极强的 Flask 应用程序。
建筑设计
表示层将由 Cloudfront、弹性负载均衡器、互联网网关、NAT 网关和两台堡垒主机组成。
应用(逻辑)层将由基于 EBS 卷的 EC2 实例组成,并通过 Auto Scaling 组进行配置。
数据层将由带有只读副本的 PostgresQL 数据库组成。在应用层中配置的 EC2 实例将连接到弹性文件系统进行数据存储。因此,从技术上讲,EFS 也位于此层。
奖金:
- AWS Route 53将用于为应用程序提供域名。
- 我们将把ClodFront与应用程序负载均衡器集成,以提供全球加速内容交付并减少延迟。
- Terraform将用作基础设施即代码 (IAC) 工具,以实现整个过程的端到端自动化。
要从头到尾自动创建此架构,请单击此链接获取 Terraform 代码。
这是一个由三个系列组成的项目的第一部分。
在第二个项目中,我们将通过CodePipeline、CodeBuild和CodeDeploy在 AWS 上实现 DevOps。 第三个项目在架构中引入了报告层。 本部分主要介绍如何在 AWS 上设计和部署 Flask 应用程序的三层架构。
步骤1:创建环境。
首先,我们将创建一个VPC。虚拟私有云 (VPC) 是一个托管在公有云中的安全、隔离的网络环境。VPC 相当于云中的虚拟数据中心。我们的大多数应用程序资源都将托管在这里。
我的 VPC 的名称标签为 project-x。这意味着在此 VPC 内创建的所有其他资源都将带有“project-x”前缀。
您还应该注意到,我为我的 VPC 分配了一个 10.0.0.0/16 的 CIDR 块。这是一个私有 IP 地址块,我的 VPC 资源将从中获取其本地地址。
请注意,我位于 us-east-1 区域(北弗吉尼亚)。
我们的 VPC 将在三个可用区中配置。总共将创建 6 个子网,包括三个公有子网和三个私有子网。公有子网之所以是公有子网,是因为将连接一个互联网网关。
另请注意,我正在创建一个 NAT 网关。托管我们应用程序的 EC2 实例将使用此 NAT 网关连接到互联网(例如:用于更新)。
步骤2:创建安全组
安全组的作用类似于防火墙,决定流量如何进出实例。
由于我们的 Web 服务器将托管在逻辑层,因此限制进入这些服务器的流量类型至关重要。
我们的安全组的名称将是“project-x-logic-tier-sg”
安全组必须允许端口 5000上的入站流量,因为这是 Flask 监听的端口。
步骤 3:创建启动模板
启动模板是一种指定重要配置细节的方式,以便我们可以使用模板中的详细信息启动实例。自动伸缩组将使用此模板在应用程序层中创建实例。
我为模板指定了名称和描述。另请注意,我已将环境标记为“prod”。
我使用的是“t3.xlarge”实例类型。
请务必选择“project-x-logic-tier-sg”安全组。
其他所有设置保持不变。在“高级详细信息”
下,我将在用户数据下粘贴以下内容:
#!/bin/bash
# Mount EFS
fsname=fs-093de1afae7166759.efs.us-east-1.amazonaws.com # You must change this value to represent your EFS DNS name.
mkdir /efs
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport $fsname:/ /efs
# install and set up Flask
apt update
apt upgrade -y
apt install python3-flask mysql-client mysql-server python3-pip python3-venv -y
apt install sox ffmpeg libcairo2 libcairo2-dev -y
apt install python3-dev default-libmysqlclient-dev build-essential -y
步骤 4:创建自动扩展组、弹性负载均衡器和目标组
负载均衡器是应用程序的入口点。位于表示层
的应用 程序负载均衡器将通过AutoScaling 组将流量路由到位于逻辑层的逻辑层实例。
我将此自动伸缩组命名为“project-x-asg”,
点击“下一步”。选择我们之前创建的“ project-x-vpc ”。另外,请确保仅选择三个可用区中的私有子网。这一点至关重要,因为我们的 VPC 将在逻辑层启动。子网不能是公有的。
点击“下一步” 。
在“配置高级选项”下,选择“连接到新的负载均衡器”。同时选择“创建目标组”。
在下一页,我们将配置 ASG,使其最小容量为 2,期望容量为 4,最大容量为 6。我们还将设置基于目标跟踪指标的扩展,使其基于平均 CPU 利用率进行扩展。
您可以决定添加标签。我将添加一个名为“Environment”的标签,其值为“Prod”。这将在 CodeDeploy 阶段用到。
创建您的 ASG。
步骤5:附加弹性文件系统
AWS EFS是云端完全托管、高度可扩展的共享存储解决方案。它兼容 NFS。
该 Elastic 文件系统将为我们所有的应用层服务器提供共享存储。由于 EFS 提供存储功能,因此它位于三层架构的数据层。
首先创建一个新的安全组。此安全组应仅允许来自逻辑层实例安全组的入站 NFS 流量。您可以在此处
获取有关如何创建的详细指南 **
转到 EFS 控制台。单击“创建文件系统* ”,然后单击**自定义*。
为您的 EFS 指定一个名称。其他设置保留默认设置。点击“下一步”。
在网络访问页面,选择您的project-x VPC。选择您已创建的 EFS 安全组。点击下一步。
跳到“查看”,然后创建文件系统。
现在我们必须更新用户数据,如下所示:
#!/bin/bash
# Use Google's DNS
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
# Force apt to use IPV4
apt-get -o Acquire::ForceIPv4=true update
# Change hostname
echo "project-x-app-server" > /etc/hostname
# Install efs-utils
apt-get install awscli -y
mkdir /efs
sudo apt-get -y install git binutils
git clone https://github.com/aws/efs-utils
cd /efs-utils
./build-deb.sh
apt-get -y install ./build/amazon-efs-utils*deb
# Mount EFS
fsname=$(aws efs describe-file-systems --region us-east-1 --creation-token project-x --output table |grep FileSystemId |awk '{print $(NF-1)}')
mount -t efs $fsname /efs
# Get DB credentials
DB=$(aws rds describe-db-instances --db-instance-identifier --region us-east-1 database-1 --output table |grep DBName |awk '{print $(NF-1)}')
HOST=$( aws rds describe-db-instances --db-instance-identifier --region us-east-1 database-1 --output table |grep Address |awk '{print $(NF-1)}')
ARN=$(aws secretsmanager list-secrets --region us-east-1 --filters "Key=tag-value, Values=project-x-rds-mysqldb-instance" --output table |grep ARN |awk '{print $(NF-1)}')
USER=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id $ARN --output table |grep -w SecretString |awk '{print $3}' |cut -d: -f2 |sed 's/password//' |tr -d '",')
PRE_PASSWORD=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id $ARN --output table |grep -w SecretString |awk '{print $3}' |cut -d: -f3 |tr -d '"')
PASSWORD=${PRE_PASSWORD%?}
# install and set up Flask
apt-get update -y && apt-get upgrade -y
apt-get install python3-flask mysql-client mysql-server python3-pip python3-venv -y
apt-get install sox ffmpeg libcairo2 libcairo2-dev -y
apt-get install python3-dev default-libmysqlclient-dev build-essential -y
# Clone the app
cd /
git clone https://github.com/Kelvinskell/terra-tier.git
cd /terra-tier
# Populate App with environmental variables
echo "MYSQL_ROOT_PASSWORD=$PASSWORD" > .env
cd /terra-tier/application
echo "MYSQL_DB=$DB" > .env
echo "MYSQL_HOST=$HOST" >> .env
echo "MYSQL_USER=$USER" >> .env
echo "DATABASE_PASSWORD=$PASSWORD" >> .env
echo "MYSQL_ROOT_PASSWORD=$PASSWORD" >> .env
echo "SECRET_KEY=08dae760c2488d8a0dca1bfb" >> .env # FLASK EXTENSION KEY. NOT NECESSARILY A "SECRET".
echo "API_KEY=f39307bb61fb31ea2c458479762b9acc" >> .env
# YOU TYPICALLY DON'T ADD SECRETS SUCH AS API KEYS AS PART OF SOURCE CONTROL IN PLAIN TEXT.
# THIS IS BEIGN ADDED HERE SO THAT YOU CAN EASILY REPLICATE THIS INFRASTRUCTURE WITHOUT ANY HASSLES.
# YOU CAN REPLACE IT WITH YOUR OWN MEDIASTACK API KEY.
# Setup virtual environment
cd /terra-tier
python3 -m venv venv
source venv/bin/activate
# Run Flask Application
pip install -r requirements.txt
export FLASK_APP=run.py
export FLASK_ENV=production
flask run -h 0.0.0.0
您可以在此处找到文件系统的 DNS 名称。请务必将“ fsname ”变量 的值更改为您自己的文件系统的 DNS 名称。
步骤6:创建堡垒主机
堡垒主机是一种特殊的服务器,用于管理从外部网络访问内部网络中的服务器或其他私有 AWS 资源。堡垒主机位于公有网络中,为管理员提供有限的访问权限,以便他们登录到隔离网络中的服务器。它通常也被称为跳转盒 (Jump Box) 或跳转服务器 (Jump Server)。
从堡垒主机,我们将能够获得进入应用层服务器的 SSH 访问权限,以用于管理目的。
这里有一个关于如何创建堡垒主机并通过它连接到逻辑层服务器的优秀资源。
安全警告:使用 SSH 密钥对连接到堡垒主机不再是推荐的做法。请使用AWS Systems Manager建立更安全的连接,并通过堡垒主机建立隧道连接到您的私有实例。
步骤7:创建数据库
数据库与 Elastic 文件系统一起稳固地位于数据层。
我们的 Flask 应用程序需要连接到关系数据库。我们将使用 MYSQL 来实现此架构。MYSQL
是一个广泛使用的关系数据库管理系统 (DBMS),免费且开源。MYSQL 以其支持大型生产工作负载的能力而闻名,因此非常适合我们的项目。
不过,我们将使用Amazon RDS for MYSQL。它是一个完全托管的云数据库解决方案。
在 RDS 控制台上,单击数据库,然后单击“创建数据库”。
选择您的主用户名和数据库实例类。我们将使用 AWS SEcrets 管理器来管理数据库凭证。
在“连接”下,选择project-x-vpc。点击“创建新的安全组”。
创建一个安全组,仅允许来自应用层服务器安全组的3306 端口的传入流量。选择该安全组。
在“数据库身份验证”下,选择“密码”。
进入“高级选项”,在“数据库名称”下,选择“ newsreadb ”。(必须选择与此完全相同的名称,Flask 应用才能连接到数据库)。
单击创建数据库。
为了连接到数据库,我们的应用程序将执行对 AWS Secrets Manager 的 API 调用以获取数据库凭证。因此,我们必须创建一个允许其执行此操作的IAM角色。我们还将修改启动模板,将该角色作为应用层服务器的实例配置文件附加。
步骤 8:创建 IAM 角色并修改启动模板
前往 IAM 仪表板,点击“角色”。
点击“创建角色”。在“用例”下,选择“EC2”,然后点击“下一步”。
搜索 secrets,然后选择弹出的权限。
单击“下一步”,然后单击“创建角色”。
接下来,我们需要修改启动模板以包含此角色,以便我们的逻辑层服务器可以假定它与 AWS Secrets Manager 进行通信。
转到 EC2 控制台,选择启动模板、操作,然后单击“修改启动模板”
转到“高级详细信息”,单击IAM 实例配置文件下的框,然后选择新创建的角色。点击创建。
最后,请务必将新版本设置为默认版本。
您已经完成了!!!!!!!
我们的三层应用程序现在应该已经启动并运行了。
步骤 9:访问您的应用程序
如果您已完成所有这些步骤,那么恭喜您。
现在要访问您的应用程序,您必须访问 EC2 控制台以获取负载均衡器的域名。
转到EC2 控制台并单击“负载均衡器”。
复制 DNS 名称
现在将其粘贴到网络浏览器中。
就是这样。如果你已经读到这里,恭喜你。
文章来源:https://dev.to/kelvinskell/a-practical-guide-to-deploying-a-complex-product-level-third-tier-architecture-on-aws-2hf0