使用 CDK 在 AWS(ECS、EFS、RDS、ELB)上运行容器 WordPress 的最佳实践
AWS 无服务器 WordPress
介绍
最近,我帮助我的朋友将她的网店从 WordPress.com 迁移到 AWS。由于她的业务规模不断扩大,第三方电商托管平台已无法满足她的业务需求。为了满足日益增长的业务需求,我为她的 WordPress 电商业务设计、改造、增强并迁移到 AWS 上的高可用性架构。
为了重用基础设施并简化部署,我使用了 AWS CDK。Cloud Development Kit 是一个开源框架,可以使用熟悉的编程语言将基础设施定义为代码。我使用 Typescript 编写了基础设施,CDK 编译完成后,将生成一个 CloudFormation 模板并将其部署到 AWS 上。
AWS CDK
在迁移过程中,我发现关于在 AWS 上托管 WordPress 的文档或信息并不多,这就是我写这篇博文的原因。
在这篇文章中,我不会过多解释这些 AWS 服务的用途和优势,而只会谈谈我使用它的原因以及我如何配置它。这篇博文更像是WordPress:AWS 最佳实践的延伸。

AWS 提供了最佳实践文档WordPress: Best Practices on AWS。我读完文档后发现它还有很多需要改进的地方,而且对 WordPress 应用的安全性照顾得也不够。
除此之外,我还在这个解决方案中实现了一些有趣的想法。例如:
- 如何保护管理页面(wp-admin)的安全?
- 如何确保面向互联网的应用程序负载均衡器仅允许来自 CloudFront 的流量?
❗❗❗在继续阅读之前,请确保您已通读最佳实践文档。❗❗❗
❗❗❗另外,请确保您具备 AWS 云或任何其他云提供商的基本知识。❗❗❗
建筑学

基本上,该架构可以分为多个支柱:
- 计算
- 贮存
- 数据库
- 缓存
- CDN
- DNS
- 安全
- 备份
计算
根据最佳实践文档,它使用 EC2 进行托管。但我选择将 WordPress 应用程序容器化,因为 Docker 运行在操作系统之上,这意味着容器比 EC2 实例轻量级得多,启动速度也更快,占用的内存也更少。
为了在 AWS 上运行容器化应用程序,我使用 Fargate 在 ECS 上托管 WordPress 应用程序。使用 Fargate,我无需配置和管理任何 EC2 服务器,只需为容器分配 vCPU 和内存即可。最近,Fargate Spot宣布可节省高达 70% 的成本。
AWS Fargate
该架构充分利用 ECS 集群上容量提供程序的功能,使用默认容量提供程序策略启动多个混合 Fargate 和 Fargate Spot 启动类型的任务。服务中的前 3 个任务将采用标准 Fargate 启动类型,这为高可用性奠定了基础。其余任务中,每 3 个任务中将有 2 个采用常规 Fargate 启动类型,其余 1 个采用 Fargate Spot 启动类型。此策略在提供高可用性服务的同时,还能最大程度地优化成本。
为了将传入的请求均匀地分发到多个正在运行的容器中,我设置了一个应用程序负载均衡器。我选择使用 LOR 算法,而不是常规的循环算法。由于循环算法不考虑目标容器的容量或利用率,当请求的处理时间较长时,这会导致目标容器的利用率过高或利用率不足。使用 LOR 算法后,应用程序负载均衡器现在可以将请求路由到数量最少的未完成请求,从而进一步缩短响应时间并平衡每个容器的利用率。

每个任务有 3 个容器:Nginx、PHP FPM 和 X-Ray 守护进程。我选择 Nginx 而不是 Apache 的原因是 W3 Total Cache 插件支持在 Nginx 上设置页面缓存,而不是在应用程序级别。X-Ray 守护进程是为 WordPress 中的 AWS X-Ray 插件创建的,该插件会收集每个请求的性能和信息,并通过守护进程将其发送到 AWS X-Ray。
贮存
WordPress 是一个有状态的应用程序,这意味着每次你修改配置时,WordPress 的文件都会被更改。但 Docker 是一个无状态服务,每次重启容器时,所有的修改都会丢失。如果 WordPress 应用程序运行在这样的环境中,它的配置在规模缩减或扩展时都会丢失。为了处理这种情况,我使用了 AWS EFS 来存储 WordPress 应用程序。EFS 是一个分布式文件系统,这意味着每次 WordPress 应用程序文件发生更改时,其他正在运行的容器仍将使用相同的文件,而不是本地隔离的文件。此外,我还为过去 90 天内未使用的文件设置了生命周期规则,将存储类别更改为不频繁访问,以降低成本。
亚马逊 EFS
WordPress 应用程序包含大量静态文件,例如 Javascript、CSS、图片、视频等。为了降低 WordPress 应用程序的响应时间和请求次数,我使用了插件 WP Offload Media 将静态文件卸载到 S3。每当我上传任何图片或视频时,此插件都会将新创建的媒体文件上传到 S3。
数据库
要启动 WordPress 应用程序,需要一个 MySQL 数据库。Amazon RDS 是一项托管数据库服务,这意味着我无需费心设置、修补和备份数据库。RDS 支持多种数据库,Aurora 是 RDS 支持的数据库之一。Amazon Aurora 由 AWS 开发,是一个兼容 MySQL 和 Postgres 的关系数据库,它的速度比常规 MySQL 数据库快 5 倍,并且具有与商业数据库相当的安全性、可用性和可靠性,而成本仅为后者的十分之一。
亚马逊 RDS
Aurora 有两种类型的数据库 - Provisioned 和 Serverless。预配置集群是一个常规数据库集群、一个主节点和多个只读副本。另一种类型是 Serverless,我选择使用 Aurora Serverless 来运行 MySQL 数据库,因为我不确定应该使用多大大小的节点类型。Aurora Serverless 与预配置类型略有不同,它类似于 Fargate。我只需要在启动时分配它需要多少 ACU 以及它可以扩展的最大 ACU,它本身会根据数据库的 CPU 使用率和连接数提供自动扩展功能。此外,Aurora Serverless 支持自动暂停,当您的数据库在一段时间内没有任何活动时,数据库将关闭,当数据库有活动时,数据库将重新联机。我已经禁用了自动暂停功能,因为当数据库进入睡眠状态时,它需要至少 30 秒才能重新联机。
但需要注意的是!Aurora Serverless 数据库分为 3 层:
- 代理人
- 计算
- 存储虽然代理和存储层是多可用区,但计算层是单可用区,这意味着当您的数据库在计算层出现故障时,与配置的集群相比,它需要更多时间才能恢复在线。
亚马逊 Aurora
亚马逊 Aurora 无服务器
如果您需要运行高可用性数据库,请不要使用 AURORA SERVERLESS。请使用 AURORA PROVISIONED CLUSTER。
缓存
我选择 Memcached 作为内存缓存存储,而不是 Redis。并使用 Amazon ElastiCache 运行 Memcached 集群。Amazon ElastiCache 是一个完全托管的内存数据存储,兼容 Redis 和 Memcached,这意味着我无需费心设置和修补。
适用于 Memcached 的 Amazon ElastiCache

根据这两篇博客文章,Memcached 的性能优于 Redis。
我应该使用 Memcached 还是 Redis 进行 WordPress 缓存?
以及在 VPS 或云上为 WordPress 使用 Redis 和 Memcached 缓存
为了缩短响应时间,并将 WordPress 的缓存放入 Memcached,我在 WordPress 中安装了 W3 Total Cache。这个插件可以将不同的缓存,例如Page Cache
、Database Cache
、Object Cache
和 ,Fragment Cache
放入 Memcached。如上所述,我使用 Nginx 运行 WordPress 应用程序,并且 W3TC 支持Page Cache
在 Nginx 级别(而不是 WordPress 应用程序级别)设置 ,这意味着当请求到达时,Nginx 会首先在 Memcached 中搜索页面缓存,如果缓存命中,Nginx 将返回命中的页面缓存,而不是将请求转发给 PHP-FMP,从而进一步缩短响应时间。
W3 总缓存
CDN
为了进一步缩短响应时间,在应用程序负载均衡器前端设置了一个 CloudFront 分发点。该分发点会将静态内容或请求缓存到遍布全球的边缘站点。当任何用户浏览 WordPress 应用程序时,如果请求的内容在边缘站点被命中,分发点将返回命中缓存,而不是将请求转发到服务器。边缘站点通常位于用户附近,以提供最低的延迟和更快的交付速度。
亚马逊CloudFront
DNS
Route 53 中有两个托管区域:一个公共区域和一个私有区域。公共托管区域将包含多条记录,包括 WordPress 的别名 A 记录和 CloudFront 分发的静态文件的别名 A 记录。
私有托管区域与 VPC 关联,并在私有托管区域中为不同的 AWS 资源主机名创建了多个 A 记录,包括 Aurora Serverless 集群、EFS 文件系统、ElastiCache Memcached 集群、Elasticseach 域和私有应用程序负载均衡器。这些记录为创建的各种 AWS 资源提供了相同且易记的名称。
Amazon Route 53
与私有托管区域协作
安全
网络安全
与通常的子网划分不同,VPC 包含三种类型的子网:Public
、Private
和Isolated
。前两种类型的子网与通常的子网相同,子网内的出站流量Public
通过互联网网关路由,子网内的出站流量Private
通过 NAT 网关路由。子网内的流量Isolated
不会访问任何互联网,仅具有本地路由可达性,从而确保子网内的资源绝对安全,并与互联网隔离。
具有公共子网和私有子网的 VPC (NAT)
此外,已为创建的 VPC 设置了网络访问控制列表,可确保任何进入的流量都用于浏览 WordPress 应用程序。
网络 ACL
加密
为了加密传输中的数据,应用程序负载均衡器和 CloudFront 分发版均已在 ACM 中使用签名的 TLS 证书进行设置。借助 CDK 中的 L2 构造函数,这些 TLS 证书将在 ACM 中创建,并在 Route 53 托管区域中创建 DNS 记录以供验证。为了进一步限制用户必须使用 HTTPS 连接到 WordPress 应用程序,CloudFront 分发版和应用程序负载均衡器均已设置将 HTTP 重定向到 HTTPS。
出于安全考虑,所有存储的数据都将使用 AWS KMS 中的 AWS 托管密钥进行加密。AWS 托管密钥完全由 AWS 管理,包括轮换。Aurora Serverless 集群、EFS 文件系统、S3 存储桶中的静态文件存储桶和日志文件存储桶均使用 KMS 中不同的 AWS 托管密钥进行加密。
AWS 证书管理器
应用程序安全
为了保护 WordPress 应用程序免受常见的 Web 漏洞攻击,我们在 CloudFront 发行版上设置了 Web ACL。对于 CloudFront 发行版上的 Web ACL,我分配了多个 AWS 托管规则组,分别是、、、、CommonRuleSet
和。KnownBadInputsRuleSet
请注意,某些规则组中的部分规则已被排除,否则将阻止大部分发往 WordPress 应用程序的请求。借助上述规则组,Web ACL 现在可以针对各种常见威胁和漏洞提供通用保护。WordPressRuleSet
PHPRuleSet
SQLiRuleSet
AmazonIpReputationList
AWS WAF
适用于 AWS WAF 的 AWS 托管规则
DDoS 保护
DDoS 是互联网上最常见的攻击,AWS Shield 可提供始终在线的检测和自动内联缓解措施,从而最大限度地减少应用程序停机时间和延迟。AWS Shield Standard 已为 CloudFront 发行版和 Route 53 托管区域自动启用,可防御所有已知的基础设施(第 3 层和第 4 层)攻击。
AWS Shield
记录和评估配置
AWS Config 已启用记录和评估已创建资源配置的功能。AWS Config 中已配置多条托管规则。aws-config:cloudformation:stack-name
在 CDK 部署期间,每个创建的资源都会关联一个标签。AWS Config 中的每条规则都已设置为使用基于标签的策略来记录已标记的资源。如果 AWS Config 记录了任何配置更改,且存在与更改后的配置不相符的情况,它将使用 SNS 向管理员发送电子邮件,通知不合规情况。
AWS Config
高级安全性
在下一节中,我将讨论
- 如何确保面向互联网的应用程序负载均衡器仅允许来自 CloudFront 的流量?
- 如何保护管理页面(wp-admin)的安全?
如何确保面向互联网的应用程序负载均衡器仅允许来自 CloudFront 的流量?

自定义标头的值将在 CDK 部署期间定义,它将是公共托管区域的 base64 编码域名,哈希值将在 CloudFront 分发和关联的 WAF Web ACL 中相同,否则所有请求都将被阻止。
如何保护管理页面(wp-admin)的安全?
用过WordPress的人都知道wp-admin
,它的管理页面存在巨大的网络安全漏洞,让黑客可以利用类似无限循环的暴力破解手段,破解管理员密码。
解决方案中实现了两种方法来保护管理页面的安全。第一种是添加白名单 IP 地址列表,第二种是设置客户端 VPN 来访问私有应用程序负载均衡器。
白名单 IP 地址
对于第一种方法,需要在部署 CDK 之前填写白名单 IP 地址列表。部署完成后,WAF 中会创建一个 IP 集。与应用程序负载均衡器关联的 WAF Web ACL 将检查来自 CloudFront 分发的入站请求,并验证请求的 IP 地址路径中是否包含“admin”前缀。任何不在白名单中的 IP 地址尝试进入管理页面都会被阻止。
这应该是保护 WordPress 管理页面最简单的方法,但它要求最终用户拥有一个静态的公共 IPV4 地址。每当 IP 地址更新或更改时,白名单也需要更新。
使用客户端 VPN
对于第二种方法,它应该是最安全、最可行、最灵活的。AWS 客户端 VPN 是一种基于客户端的托管 VPN 服务,允许最终用户安全地访问 AWS 或本地的私有或受限资源,并且可以在任何基于 OpenVPN 的客户端上运行。我们将在 VPC 中创建一个 AWS 客户端 VPN,每个连接到此 VPN 的最终用户都可以通过 NAT 访问互联网并访问私有资源。我们还为连接的 VPN 最终用户创建了一个私有应用程序负载均衡器,允许其安全地访问 WordPress 应用程序(包括管理页面)。
AWS 客户端 VPN
备份
尽管 Aurora Serverless 集群快照并返回到 RDS,但 AWS Backup 设置为管理 WordPress 使用的 AWS 服务中的备份,包括 Aurora Serverless 集群和 EFS 文件系统。
AWS 备份
部署
AWS 无服务器 WordPress
介绍
请阅读博客文章以了解介绍和解释Dev.to:使用 CDK 在 AWS 上运行 WordPress 的最佳实践
使用的 WordPress 插件
- W3 总缓存
- WP Offload Media Lite
- ElasticPress
- 多域
- HumanMade - AWS-XRay(正在努力使其工作......)
架构图

部署 -(待更新)
开始之前
请确保您有/正在
- 使用 bash
- Node.js 已安装
- 已安装 NPM 和 Yarn
- 安装并运行 Docker
- 安装并配置 AWS CLI
- 安装了最新版本的 AWS CDK CLI
请注意,此堆栈只能部署到 us-east-1 0。您应该在 Route 53 中拥有一个公共托管区域
- 初始化CDK项目,运行
make init
- 将 CDK 工具包堆栈部署到目标区域,运行
cdk bootstrap aws://AWS_ACCOUNT_ID/AWS_REGION --profile AWS_PROFILE_NAME
- 复制
config.sample.toml
并重命名为config.toml
- 运行
make easy-rsa-init gen-cert import-cert
以生成客户端 VPN 的证书
- 修改…
继续阅读:https://dev.to/aws-builders/best-practices-for-running-wordpress-on-aws-using-cdk-aj9