Day 29 – 使用 CDK 創建 WordPress

2020 12th 鐵人賽

前幾天做了很多 AWS 服務使用 CDK 部署的介紹,今天我想來介紹一個滿多人都有機會用到的 Blog 服務 WordPress
相信要單獨使用 Instance 建立 WordPress 服務對大家來說應該都滿簡單的,不過要怎樣才可以讓它高負載又安全又穩定呢?所以今天的目標就是如何做出一個高可用性並且安全穩定的 WordPress

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201015/20117701R9UkhL4TJq.jpg?w=640&ssl=1

今日目標

我們先討論一下如何可以製作一個高可用性的服務,首先我們需要一個可以支撐大流量的入口,遇到流量增加或是 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 ImagesDocker 打開來看一下文件可以看到我們需要準備

  • 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

想要知道詳情可以看 架設 WORDPRESS 中健康偵測 (HEALTH CHECK) 一直失敗的解決方法

使用

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),
};
https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701ley7pJgUWO.png?w=640&ssl=1

ECS Auto Scaling

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701CWxDSLLhtc.png?w=640&ssl=1

Target groups Path

設定 RDS Security Group

如果漏了設定 WordPress 就連不到資料庫了呦!

rdsInstance.connections.allowFrom(
  loadBalancedEcsService.cluster.connections,
  ec2.Port.tcp(3306)
);
https://i0.wp.com/ithelp.ithome.com.tw/upload/images/20201014/201177011NsTF3oEFH.png?w=640&ssl=1

建立共用檔案系統 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,
});
https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701QrW7MG9l8U.png?w=640&ssl=1

EFS 儲存空間

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701aFtjF2LO2C.png?w=640&ssl=1

EFS security group

https://i0.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701Jsvm2tPbfx.png?w=640&ssl=1

ECS Task Volume 掛載

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/201177019beNq6WKwZ.png?w=640&ssl=1

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

  • 選取語言
    https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701Cs2lWvQSVj.png?w=640&ssl=1
  • 設定帳密
    https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701bNHJ1nhpiE.png?w=640&ssl=1
  • 登入剛剛設定的帳密
    https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701Mse6sxDPMy.png?w=640&ssl=1
  • 可以正常的看到我們的 WordPress 後台
    https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701q5mqxUsjRX.png?w=640&ssl=1
  • 點選左上角的使用者帳號回到首頁
    https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20201014/20117701x0x1nUY50J.png?w=640&ssl=1

今天的 WordPress 建置成功拉!

CDK Source Code

如果對於今天的程式介紹不太了解但是想要直接使用歡迎直接到我的 GitHub 下載 https://github.com/clarencetw/cdk-wordpress


今天介紹如何使用 CDK 建立一個高可用性的系統,希望對大家有幫助 ~
終於到達第 29 天拉!!!
好興奮啊! ( ~’ω’)~