亚马逊AWS官方博客

App Runner 新增功能 – VPC 支持

借助 AWS App Runner,您可以快速部署任何规模的 Web 应用程序和 API。您可以从源代码或容器映像开始,App Runner 将全面管理所有基础设施,包括应用程序的服务器、联网和负载均衡。如果您愿意,App Runner 还可以为您配置部署管道。

从今天开始,App Runner 使您的服务能够与 Amazon Virtual Private Cloud (VPC) 中托管的数据库和其他应用程序进行通信。例如,您现在可以将 App Runner 服务连接到 Amazon Relational Database Service (RDS) 中的数据库、Amazon ElastiCache 中的 Redis 或 Memcache 缓存,或您在 Amazon Elastic Container Service (Amazon ECS)Amazon Elastic Kubernetes Service (EKS)Amazon Elastic Compute Cloud (Amazon EC2) 中运行的应用程序,或在本地部署并通过 AWS Direct Connect 连接的应用程序。

以前,为了让 App Runner 应用程序连接到这些资源,需要通过互联网公开访问这些资源。有了此功能,App Runner 应用程序可以连接到您的 VPC 中的私有终端节点,您可以通过移除对这些资源的公开访问来实现更安全、更合规的环境。

在 App Runner 中,您现在可以创建 VPC 连接器来指定要用于私有联网的 VPC、子网和安全组。配置完成后,您可以将 VPC 连接器与一个或多个 App Runner 服务结合使用。

当连接到 VPC 时,来自您的 AppRunner 服务的所有出站流量都将根据 VPC 路由规则进行路由。除非通往 NAT 网关的路由允许,否则服务将无法访问公共互联网(包括 AWS API)。您还可以设置 VPC 终端节点以连接到 Amazon Simple Storage Service (Amazon S3)Amazon DynamoDB 等 AWS API,以避免产生 NAT 流量。

App Runner 中的 VPC 连接器的工作方式与 AWS Lambda 中的 VPC 联网类似,它们基于 AWS Hyperplane,后者是 AWS 服务和资源(例如 Network Load BalancerNAT 网关AWS PrivateLink)背后的内部 Amazon 网络功能虚拟化系统。

让我们通过一个连接到 RDS 数据库的 Web 应用程序,看看在实践中是如何运行的。

准备 Amazon RDS 数据库
我首先为我的应用程序配置数据库。为了简化此数据库的容量管理,我使用了 Amazon Aurora Serverless。在 RDS 控制台中,我创建了一个 Amazon Aurora MySQL 兼容数据库。对于容量类型,我选择了无服务器。对于联网,我使用默认 VPC默认安全组。 我不需要让数据库可以公开访问,因为我将使用私有 VPC 联网进行连接。为了简化以后的连接,我启用了 AWS Identity and Access Management (IAM) 数据库身份验证

我在同一 VPC 中启动了一个 Amazon Linux EC2 实例。为了从 EC2 实例连接到数据库,我需要一个 MySQL 客户端。我安装了 MariaDB,这是 MySQL 的社群开发分支:

sudo yum install mariadb

然后,我使用管理员用户连接到数据库。

mysql -h <DATABASE_HOST> -u admin -P

我输入了管理员用户密码进行登录。然后,我创建了一个新用户 (bookuser) 并将其配置为使用 IAM 身份验证。

CREATE USER bookuser IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; 

我创建了 bookcase 数据库,并授予 bookuser 用户查询 bookcase 数据库的权限。

CREATE DATABASE bookcase;
GRANT SELECT ON bookcase.* TO 'bookuser'@'%’;

为了存储有关我的一些书籍的信息,我创建了 authorsbooks 表格。

CREATE TABLE authors (
  authorId INT,
  name varchar(255)
 );

CREATE TABLE books (
  bookId INT,
  authorId INT,
  title varchar(255),
  year INT
);

然后,我在两个表中插入一些值:

INSERT INTO authors VALUES (1, "Issac Asimov");
INSERT INTO authors VALUES (2, "Robert A. Heinlein");
INSERT INTO books VALUES (1, 1, "Foundation", 1951);
INSERT INTO books VALUES (2, 1, "Foundation and Empire", 1952);
INSERT INTO books VALUES (3, 1, "Second Foundation", 1953);
INSERT INTO books VALUES (4, 2, "Stranger in a Strange Land", 1961);

准备应用程序源代码存储库
借助 App Runner,我可以从源代码存储库中托管的代码或使用容器映像部署新服务。在这个例子中,我使用了我在 GitHub 上的一个私有项目。

这是一个非常简单的 Python Web 应用程序,连接到了我刚刚创建的数据库。这是应用程序 (server.py) 的源代码:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
import os
import boto3
import mysql.connector

import os

DATABASE_REGION = 'us-east-1'
DATABASE_CERT = 'cert/us-east-1-bundle.pem'
DATABASE_HOST = os.environ['DATABASE_HOST']
DATABASE_PORT = os.environ['DATABASE_PORT']
DATABASE_USER = os.environ['DATABASE_USER']
DATABASE_NAME = os.environ['DATABASE_NAME']

os.environ['LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN'] = '1'

PORT = int(os.environ.get('PORT'))

rds = boto3.client('rds')

try:
    token = rds.generate_db_auth_token(
        DBHostname=DATABASE_HOST,
        Port=DATABASE_PORT,
        DBUsername=DATABASE_USER,
        Region=DATABASE_REGION
    )
    mydb =  mysql.connector.connect(
        host=DATABASE_HOST,
        user=DATABASE_USER,
        passwd=token,
        port=DATABASE_PORT,
        database=DATABASE_NAME,
        ssl_ca=DATABASE_CERT
    )
except Exception as e:
    print('Database connection failed due to {}'.format(e))          

def all_books(request):
    mycursor = mydb.cursor()
    mycursor.execute('SELECT name, title, year FROM authors, books WHERE authors.authorId = books.authorId ORDER BY year')
    title = 'Books'
    message = '<html><head><title>' + title + '</title></head><body>'
    message += '<h1>' + title + '</h1>'
    message += '<ul>'
    for (name, title, year) in mycursor:
        message += '<li>' + name + ' - ' + title + ' (' + str(year) + ')</li>'
    message += '</ul>'
    message += '</body></html>'
    return Response(message)

if __name__ == '__main__':

    with Configurator() as config:
        config.add_route('all_books', '/')
        config.add_view(all_books, route_name='all_books')
        app = config.make_wsgi_app()
    server = make_server('0.0.0.0', PORT, app)
    server.serve_forever()

该应用程序使用适用于 Python 的 AWS SDK (boto3) 进行 IAM 数据库身份验证,以及 Pyramid Web 框架适用于 Python 的 MySQL 连接器requirements.txt 文件描述了应用程序依赖关系:

boto3
pyramid==2.0
mysql-connector-python

要在连接到数据库时使用 SSL/TLS 加密,我需要下载证书捆绑包并将其添加到源代码存储库中。

在 AWS App Runner 中使用 VPC 支持
App Runner 控制台中,我选择源代码存储库和要使用的分支。

控制台屏幕截图。

对于部署设置,我选择手动。或者,我可以选择自动部署触发器,让每次推送到此分支时都部署我的服务的新版本。

控制台屏幕截图。

然后,我配置构建。这是一个非常简单的应用程序,所以我在控制台中传递构建和启动命令:

构建命令pip install -r requirements.txt
启动命令 python server.py

对于更高级的使用场景,我将向我的存储库添加一个 apprunner.yaml 配置文件,如本示例应用程序所示。

控制台屏幕截图。

在服务配置中,我添加了应用程序用来连接到数据库的环境变量。我不需要在这里传递数据库密码,因为我使用了 IAM 身份验证。

控制台屏幕截图。

安全部分中,我选择了一个 IAM 角色,该角色授予使用 IAM 数据库身份验证连接到数据库的权限,如为 IAM 数据库访问创建和使用 IAM 策略中所述。

控制台屏幕截图。

下面是 IAM 角色的语法。我在 RDS 控制台的配置选项卡中找到数据库资源 ID

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds-db:connect"
            ],
            "Resource": [
                "arn:aws:rds-db:<REGION>:<ACCOUNT>:dbuser:<DB_RESOURCE_ID>/<DB_USER>"
            ]
        }
    ]
}

对于角色信任策略,我按照 App Runner 如何与 IAM 配合使用中有关实例角色的说明进行操作。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "tasks.apprunner.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

对于联网,我选择了为出站网络流量使用自定义 VPC 的新选项,然后添加了一个新的 VPC 连接器。

控制台屏幕截图。

要添加新的 VPC 连接器,我需要记下名称,然后选择要使用的 VPC、子网和安全组。在这里,我选择了默认 VPC 和默认安全组的所有子网。这样,App Runner 服务将能够连接到 RDS 数据库。

控制台屏幕截图。

下次配置具有相同 VPC 联网要求的其他应用程序时,我只需选择之前创建的 VPC 连接器即可。

控制台屏幕截图。我检查所有设置,然后创建并部署服务。

几分钟后,服务正在运行,我选择了默认域以在浏览器中打开一个新选项卡。应用程序使用 VPC 联网连接到数据库,并执行 SQL 查询以联接 booksauthors 表并提供一些阅读建议。成功了!

浏览器屏幕截图。

可用性和定价
VPC 连接器在提供 AWS App Runner 的所有 AWS 区域中均可用。有关更多信息,请参阅区域服务列表。使用此功能不会产生额外成本,但您需要为数据传输或您设置的任何 NAT 网关或 VPC 终端节点支付标准定价。您可以使用 AWS 管理控制台AWS 命令行界面 (CLI)AWS SDK 以及 AWS CloudFormation 设置 VPC 连接器。

借助 VPC 连接器,您可以使用 App Runner 部署应用程序,并将它们连接到私有数据库、缓存,以及在 VPC 中运行或在本地部署并通过 AWS Direct Connect 连接的应用程序。

构建和运行任何规模的 Web 应用程序,并使用 AWS App Runner 连接到您的私有 VPC 资源。

Danilo