前幾天做了很多 AWS 服務使用 CDK 部署的介紹,今天我想來介紹一個滿多人都有機會用到的 Blog 服務 WordPress
相信要單獨使用 Instance 建立 WordPress 服務對大家來說應該都滿簡單的,不過要怎樣才可以讓它高負載又安全又穩定呢?所以今天的目標就是如何做出一個高可用性並且安全穩定的 WordPress
今日目標
我們先討論一下如何可以製作一個高可用性的服務,首先我們需要一個可以支撐大流量的入口,遇到流量增加或是 CPU 負載增加情況的時候會自動擴展的系統,而且他們可能需要共用儲存空間,並且通常需要公用資料庫,在 AWS 上面我們要如何滿足以上的情況製作我們的系統呢?我們分開來思考
支撐大流量的入口
可想而知這邊我們需要的服務會是一個負載平衡的服務,那在 AWS 上面可想而知就是 Elastic Load Balancing 拉!
靈活控制系統資源的系統
其實要達成這個需求我們有滿多服務可以選擇的像是
- 使用 EC2 與 EC2 Auto Scaling
- 使用 ECS 與 Fargate
- 使用 ECS 與 EC2
- 使用 EKS 與 Fargate
- 使用 EKS 與 EC2
不過我今天想要選用 ECS 與 EC2 XD
共用儲存空間
這邊可以使用的有 S3 或是還沒有介紹過的 EFS,而這邊的需求是系統掛載硬碟,所以我選用 EFS
公用資料庫
這邊應該就不用說明我們一定是使用 RDS 拉!
攥寫今天的 CDK 程式
竟然思考完了我們就來實作吧!
建立 VPC
跟往常習慣一樣部署一個 3 個 AZ 並且使用單個 NAT Gateway 的 VPC
const vpc = new ec2.Vpc(this, "Vpc", { maxAzs: 3, natGateways: 1 });
建立 MySQL 資料庫
建立一個 WordPress 使用的 MySQL 資料庫,因為是範例關係我們部署最小台的 t3.micro,並且指定儲存空間為 10G 這個部分不用擔心現在設定的太小,如果使用太滿 RDS 會自動幫我們增加空間,不過如果擔心 IOPS 太小也可以再加大
const rdsInstance = new rds.DatabaseInstance(this, "Database", { engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_20, }), vpc, deleteAutomatedBackups: true, instanceType: ec2.InstanceType.of( ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO ), allocatedStorage: 10, });
建立 ECS 系統
基本上 WordPress 不用太多的資源就可以啟動,所以這邊預設配置了 t3a.small 的機型並且指定最大的機器數量為 3,這邊要注意一下如果沒有指定 maxCapacity 預設是 1,這樣機器就不會擴展了呦!
設定機器 CPU 到達 80% 的時候自動擴展機器
const cluster = new ecs.Cluster(this, "EcsCluster", { vpc }); const autoScalingGroup = cluster.addCapacity("ASG", { instanceType: ec2.InstanceType.of( ec2.InstanceClass.T3A, ec2.InstanceSize.SMALL ), maxCapacity: 3, machineImage: ecs.EcsOptimizedImage.amazonLinux2(), }); autoScalingGroup.scaleOnCpuUtilization("KeepCpuHalfwayLoaded", { targetUtilizationPercent: 80, });
建立 WordPress Service
WordPress Docker image
在介紹如何建立 WordPress Service 之前先來看一下這次選用的 WordPress Docker 是直接使用 Docker Official Images 的 Docker 打開來看一下文件可以看到我們需要準備
- WORDPRESS_DB_HOST
- WORDPRESS_DB_USER
- WORDPRESS_DB_PASSWORD
- WORDPRESS_DB_NAME
與掛載一個空間
- wordpress:/var/www/html
而內部的 Container Port 為 80
處理 Load Balanced、EC2 Service 與 Task
今天使用了一個可以快速把 Load Balanced、EC2 Service 與 Task 一次處理完畢的方法
資料庫帳號密碼直接使用 RDS 儲存在 AWS Secrets Manager 的資料
如果對這部分沒有映像可以參考 Day 21 – CDK 建置 Amazon Elastic Container Service(ECS)Service – EC2 與 RDS
並且設定 Task 在 CPU 50% 的時候自動擴展
忘記可以參考 Day 23 – CDK 建置 Amazon Elastic Container Service(ECS) Service – Fargate 與 EC2 混搭
最後一點要注意的是 WordPress 在還沒安裝系統的時候 /
目錄會一直是 302 狀態,因此不可以使用預設的 path 需要對這邊做一點修改改成 WordPress 會回應 200 的頁面,而我這邊使用 /wp-includes/images/blank.gif
使用
const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service( this, "Service", { cluster, memoryLimitMiB: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("wordpress"), environment: { WORDPRESS_DB_NAME: "wordpress", }, secrets: { WORDPRESS_DB_HOST: ecs.Secret.fromSecretsManager( rdsInstance.secret!, "host" ), WORDPRESS_DB_USER: ecs.Secret.fromSecretsManager( rdsInstance.secret!, "username" ), WORDPRESS_DB_PASSWORD: ecs.Secret.fromSecretsManager( rdsInstance.secret!, "password" ), }, }, desiredCount: 2, } ); const scaling = loadBalancedEcsService.service.autoScaleTaskCount({ maxCapacity: 6, }); scaling.scaleOnCpuUtilization("CpuScaling", { targetUtilizationPercent: 50, }); loadBalancedEcsService.targetGroup.healthCheck = { path: "/wp-includes/images/blank.gif", interval: cdk.Duration.minutes(1), };
ECS Auto Scaling
Target groups Path
設定 RDS Security Group
如果漏了設定 WordPress 就連不到資料庫了呦!
rdsInstance.connections.allowFrom( loadBalancedEcsService.cluster.connections, ec2.Port.tcp(3306) );
建立共用檔案系統 EFS
AWS EFS 介紹
今天最特別的就是 AWS EFS 它是一個 NFS 的檔案系統,所以不一定是 ECS 使用 EC2 也是可以掛載的,它與我們平常使用的 NFS 系統完全一樣所以如果是使用 EC2 要使用它只要在 User Data 裡面直接依造平常掛載 NFS 的方法安裝即可
ECS 掛載 EFS
在 ECS Task 上面要掛載 EFS 是有支援的所以我們直接在 Task 新增 EFS 的 system ID 即可,但是只有掛在 Task 上面是不夠的,之前的文章有說明我們的 Container 是設定在 Task 裡面,所以我們還需要把它 mount 到 Container 裡面才有辦法讓我們的 Container WordPress 使用
const fileSystem = new efs.FileSystem(this, "FileSystem", { vpc, encrypted: true, }); fileSystem.connections.allowFrom( autoScalingGroup.connections.connections, ec2.Port.tcp(2049) ); const volumeName = "efs"; loadBalancedEcsService.taskDefinition.addVolume({ name: volumeName, efsVolumeConfiguration: { fileSystemId: fileSystem.fileSystemId, }, }); loadBalancedEcsService.taskDefinition.defaultContainer?.addMountPoints({ containerPath: "/var/www/html", readOnly: false, sourceVolume: volumeName, });
EFS 儲存空間
EFS security group
ECS Task Volume 掛載
ECS Task Container 掛載
結論
以上就是今天的 WordPress 部署介紹,今天的程式碼會提供在 GitHub 給大家使用!
測試系統
執行一下 cdk deploy
來測試今天的結果吧!以下會直接輸出 WordPress 連線的網址
Outputs: CdkWordpressStack.ServiceLoadBalancerDNSEC5B149E = CdkWo-Servi-YSNP5LI748BG-66853377.us-west-2.elb.amazonaws.com CdkWordpressStack.ServiceServiceURL250C0FB6 = http://CdkWo-Servi-YSNP5LI748BG-66853377.us-west-2.elb.amazonaws.com
開啟 Load Balancer 網址試試看吧!
http://CdkWo-Servi-YSNP5LI748BG-66853377.us-west-2.elb.amazonaws.com
- 選取語言
- 設定帳密
- 登入剛剛設定的帳密
- 可以正常的看到我們的 WordPress 後台
- 點選左上角的使用者帳號回到首頁
今天的 WordPress 建置成功拉!
CDK Source Code
如果對於今天的程式介紹不太了解但是想要直接使用歡迎直接到我的 GitHub 下載 https://github.com/clarencetw/cdk-wordpress
今天介紹如何使用 CDK 建立一個高可用性的系統,希望對大家有幫助 ~
終於到達第 29 天拉!!!
好興奮啊! ( ~’ω’)~
《AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC》
第 12 屆 iT 邦幫忙鐵人賽 DevOps 組冠的《用 CDK 定 義 AWS 架構》
第 11 屆 iT 邦幫忙鐵人賽《LINE bot 好好玩 30 天玩轉 LINE API》
一個熱愛分享的雲端工程師!