部署单点WordPress网站

简介: 在特定场景下编写模板的流程比较固定,本篇文章以《部署单点 WordPress 博客平台》为例,讲述如何完成一个部署成功率高、适配场景广的模板。大多数在 ECS 上部署应用的模板都可以参考此教程来编写。


1. 搭建模板框架

1.1 通用基础模板框架

我们可以把 ROS 模板的基础信息介绍放到基础的框架中,以下示例定义了模板描述、标签等信息。

# 模板版本,固定值
ROSTemplateFormatVersion: '2015-09-01'
# 模板描述,描述模板的功能
Description:
  zh-cn: 在ECS实例上搭建WordPress博客平台。
  en: Build a WordPress blog platform.
Parameters:
  # 这里建议模板中的资源名称都以某个特定的字符串开头
  CommonName:
    Type: String
    Default: wordpress
Metadata:
  ALIYUN::ROS::Interface:
    # 隐藏CommonName参数不允许用户在参数中修改前缀
    Hidden:
      - CommonName
    # 模板标签,ROS服务统计使用
    TemplateTags:
      - acs:developer:gitee:1234-在ECS实例上搭建WordPress博客平台

1.2 OnECS 模板框架

在 ECS 上部署应用这个特定的场景中,可以复用如下内容的框架,以下模板完成了VPC、VSwitch、安全组和 ECS 的创建,为应用提供了云上的基础设施。

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 在ECS实例上搭建WordPress博客平台。
  en: Build a WordPress blog platform.
Parameters:
  # 可用区会影响库存信息,提取到参数中会动态获取支持售卖、有库存的可用区
  ZoneId:
    Type: String
    Label:
      en: Availability Zone
      zh-cn: 可用区
    AssociationProperty: ALIYUN::ECS::Instance::ZoneId
    AssociationPropertyMetadata:
      AutoSelectFirst: true
  # 实例规格也受库存因素影响,需要提取到参数中动态查询
  InstanceType:
    Type: String
    Default: null
    Required: true
    Label:
      en: Instance Type
      zh-cn: 实例类型
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      # 定义实例规格的筛选器,建议使用后付费的实例,部署体验完成之后可以随时释放
      ZoneId: ${ZoneId}
      InstanceChargeType: PostPaid
      SystemDiskCategory: cloud_essd
  InstancePassword:
    Type: String
    NoEcho: true
    Default: null
    Description:
      en: >-
        Server login password, Length 8-30, must contain three(Capital letters,
        lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special
        symbol in)
      zh-cn: >-
        服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/
        中的特殊符号)
    Label:
      en: Instance Password
      zh-cn: 实例密码
    ConstraintDescription:
      en: >-
        Length 8-30, must contain three(Capital letters, lowercase letters,
        numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)
      zh-cn: '长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;''<>,.?/ 中的特殊符号)'
    AssociationProperty: 'ALIYUN::ECS::Instance::Password'
  CommonName:
    Type: String
    Default: wordpress
Resources:
  Vpc:
    Type: 'ALIYUN::ECS::VPC'
    Properties:
      CidrBlock: 192.168.0.0/16
      VpcName: 
        Fn::Sub: ${CommonName}-vpc
  VSwitch:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VpcId:
        Ref: Vpc
      CidrBlock: 192.168.0.0/24
      ZoneId:
        Ref: ZoneId
      VSwitchName:
        Fn::Sub: ${CommonName}-vsw
  SecurityGroup:
    Type: 'ALIYUN::ECS::SecurityGroup'
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupName:
        Fn::Sub: ${CommonName}-sg
      # 根据实际应用选择安全组开放的端口
      SecurityGroupIngress:
        - PortRange: 22/22
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 80/80
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: '-1/-1'
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: icmp
  # ECS资源建议把 ZoneId 和 InstanceType 提取到参数中做为动态查询,其他属性建议直接写到模板中。
  EcsInstance:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      VpcId:
        Ref: Vpc
      ZoneId:
        Ref: ZoneId
      VSwitchId:
        Ref: VSwitch
      SecurityGroupId:
        Ref: SecurityGroup
      # 镜像可以不精确填写,后续镜像更新之后模板不用改。
      ImageId: aliyun_3_9_x64_20G_alibase_
      InstanceName:
        Fn::Sub: ${CommonName}-ecs
      InstanceType:
        Ref: InstanceType
      SystemDiskCategory: cloud_essd
      MaxAmount: 1
      InternetMaxBandwidthOut: 5
      Password:
        Ref: InstancePassword
Outputs:
  # 建议将 ECS 的登录地址放到输出中,方便用户登录 ECS 实例
  EcsLoginAddress:
    Description:
      en: Ecs login address.
      zh-cn: ECS登录地址。
    Value:
      Fn::Sub: https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs&regionId=${ALIYUN::Region}&instanceId=${EcsInstance}
Metadata:
  ALIYUN::ROS::Interface:
    # 设置参数填写顺序
    ParameterGroups:
      - Parameters:
          - ZoneId
          - InstanceType
          - InstancePassword
    Hidden:
      - CommonName
    TemplateTags:
      - acs:developer:gitee:1234-在ECS实例上搭建WordPress博客平台


2. 搭建应用运行环境(可选)

大多数应用的运行都需要 Java、Python、Docker 或 LNMP 等前置的运行环境,在 ROS 模板中我们可以借助OOS 的公共插件标准化的安装所需要的基础运行环境。在 ROS 模板中的具体使用方式如下所示。

Resources:
  # 该模块可以在指定的 ECS 实例中安装 OOS 公共插件
  ModuleInstallDocker:
    Version: default
    Type: 'MODULE::ACS::OOS::Extension'
    Properties:
      # 定义在哪个 ECS 实例上安装环境,示例是基础框架模板中的 ECS 实例
      EcsInstanceIds:
        Fn::GetAtt:
          - EcsInstance
          - InstanceIds
      # 公共插件名称,在 OOS 控制台如下截图位置获取,示例是部署Docker环境
      PackageName: ACS-Extension-DockerCE-1853370294850618


3. 利用 Shell 脚本完成应用的部署

3.1 编写 Shell 脚本

编写 Shell 脚本要注意和操作系统要对应上,在前面的框架中我们使用了Alibaba Cloud Linux系统。在下面的脚本,我们可以在deploy_something中完成应用的部署。

#!/bin/bash
          
# script exit code:
# 0 - success
# 1 - unsupported system
# 2 - failed to deploy ...
# 环境变量配置
export PATH=/usr/local/bin:$PATH
function log_info() {
    printf "%s [INFO] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
}
function log_error() {
    printf "%s [ERROR] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
}
function log_fatal() {
    printf "\n========================================================================\n"
    printf "%s [FATAL] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$2"
    printf "\n========================================================================\n"
    exit $1
}
function debug_exec(){
    local cmd="$@"
    log_info "$cmd"
    eval "$cmd"
    ret=$?
    echo ""
    log_info "$cmd, exit code: $ret"
    return $ret
}
function unsupported_system() {
    log_fatal 1 "Unsupported System: $1"
}
function deploy_something() {
    log_info "start deploy ..."
    # 编写具体部署函数
}
log_info "System Information:"
if ! lsb_release -a; then
    unsupported_system
fi;
echo ""
if ! debug_exec deploy_something; then
    log_fatal 3 "failed to deploy ..."
fi


3.2 在模板中应用 Shell 脚本

如何将写好的 Shell 脚步应用在模板中呢?ROS 提供了云助手的RunCommand资源,可以利用云助手来执行脚本,示例如下。

Resources:
  InstallWordPress:
    Type: 'ALIYUN::ECS::RunCommand'
    # 这里我们设置依赖关系,先安装 Docker
    DependsOn: ModuleInstallDocker
    Properties:
      InstanceIds:
        - Ref: EcsInstance
      Type: RunShellScript
      Sync: true
      Timeout: 3600
      CommandContent:
        Fn::Sub: |-
          #!/bin/bash
                    
          # script exit code:
          # 0 - success
          # 1 - unsupported system
          # 2 - failed to deploy WordPress
          
          # 环境变量配置
          export PATH=/usr/local/bin:$PATH
          
          function log_info() {
              printf "%s [INFO] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
          }
          
          function log_error() {
              printf "%s [ERROR] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
          }
          
          function log_fatal() {
              printf "\n========================================================================\n"
              printf "%s [FATAL] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$2"
              printf "\n========================================================================\n"
              exit $1
          }
          
          function debug_exec(){
              local cmd="$@"
              log_info "$cmd"
              eval "$cmd"
              ret=$?
              echo ""
              log_info "$cmd, exit code: $ret"
              return $ret
          }
          
          
          function unsupported_system() {
              log_fatal 1 "Unsupported System: $1"
          }
          
          function deploy_wordpress() {
              log_info "start deploy WordPress"
              wget 'https://ros-public-templates.oss-cn-hangzhou.aliyuncs.com/file/wordpress-5.6.tar'
              docker load -i wordpress-5.6.tar
              mkdir /wordpress
              docker run --name my-blog --restart=always -v /wordpress:/var/www/html -p 80:80 -d wordpress:5.6
          }
          
          log_info "System Information:"
          if ! lsb_release -a; then
              unsupported_system
          fi;
          echo ""
          
          if ! debug_exec deploy_wordpress; then
              log_fatal 3 "failed to deploy WordPress"
          fi

4. 添加输出信息(可选)

部署完应用之后,我们需要告知用户体验应用的地址,以便用户便捷体验我们的应用。在模板中的输出中,我们可以定义访问地址。

Outputs:
  WordpressUrl:
    Description:
      en: Wordpress url.
      zh-cn: Wordpress 博客访问地址。
    Value:
      # 如果是网页访问,建议以 http(s):// 开头,用户在控制台直接点击即可访问
      Fn::Sub:
        - http://${PublicIp}
        - PublicIp:
            Fn::Select:
              - 0
              - Fn::GetAtt:
                  - EcsInstance
                  - PublicIps

5. 完整模板示例

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 在ECS实例上搭建WordPress博客平台。
  en: Build a WordPress blog platform.
Parameters:
  ZoneId:
    Type: String
    Default: null
    Required: true
    Label:
      en: Availability Zone
      zh-cn: 可用区
    AssociationProperty: ALIYUN::ECS::Instance::ZoneId
    AssociationPropertyMetadata:
      AutoSelectFirst: true
  InstanceType:
    Type: String
    Default: null
    Required: true
    Label:
      en: Instance Type
      zh-cn: 实例类型
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      SpotStrategy: SpotAsPriceGo
      InstanceChargeType: PostPaid
      SystemDiskCategory: cloud_essd
  InstancePassword:
    Type: String
    NoEcho: true
    Default: null
    Description:
      en: >-
        Server login password, Length 8-30, must contain three(Capital letters,
        lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special
        symbol in)
      zh-cn: >-
        服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/
        中的特殊符号)
    Label:
      en: Instance Password
      zh-cn: 实例密码
    ConstraintDescription:
      en: >-
        Length 8-30, must contain three(Capital letters, lowercase letters,
        numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)
      zh-cn: '长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;''<>,.?/ 中的特殊符号)'
    AssociationProperty: 'ALIYUN::ECS::Instance::Password'
  CommonName:
    Type: String
    Default: wordpress
Resources:
  Vpc:
    Type: 'ALIYUN::ECS::VPC'
    Properties:
      CidrBlock: 192.168.0.0/16
      VpcName:
        Fn::Sub: ${CommonName}-vpc
  VSwitch:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VpcId:
        Ref: Vpc
      CidrBlock: 192.168.0.0/24
      ZoneId:
        Ref: ZoneId
      VSwitchName:
        Fn::Sub: ${CommonName}-vsw
  SecurityGroup:
    Type: 'ALIYUN::ECS::SecurityGroup'
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupName:
        Fn::Sub: ${CommonName}-sg
      SecurityGroupIngress:
        - PortRange: 22/22
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 3389/3389
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 80/80
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: '-1/-1'
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: icmp
  EcsInstance:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      VpcId:
        Ref: Vpc
      ZoneId:
        Ref: ZoneId
      VSwitchId:
        Ref: VSwitch
      SecurityGroupId:
        Ref: SecurityGroup
      ImageId: aliyun_3_9_x64_20G_alibase_
      InstanceName:
        Fn::Sub: ${CommonName}-ecs
      InstanceType:
        Ref: InstanceType
      SystemDiskCategory: cloud_essd
      MaxAmount: 1
      InternetMaxBandwidthOut: 5
      SpotStrategy: SpotAsPriceGo
      Password:
        Ref: InstancePassword
  ModuleInstallDocker:
    Version: default
    Type: 'MODULE::ACS::OOS::Extension'
    Properties:
      EcsInstanceIds:
        - Ref: EcsInstance
      PackageName: ACS-Extension-DockerCE-1853370294850618
  InstallWordPress:
    Type: 'ALIYUN::ECS::RunCommand'
    DependsOn: ModuleInstallDocker
    Properties:
      InstanceIds:
        - Ref: EcsInstance
      Type: RunShellScript
      Sync: true
      Timeout: 3600
      CommandContent:
        Fn::Sub: |-
          #!/bin/bash
                    
          # script exit code:
          # 0 - success
          # 1 - unsupported system
          # 2 - failed to deploy WordPress
          
          # 环境变量配置
          export PATH=/usr/local/bin:$PATH
          
          function log_info() {
              printf "%s [INFO] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
          }
          
          function log_error() {
              printf "%s [ERROR] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1"
          }
          
          function log_fatal() {
              printf "\n========================================================================\n"
              printf "%s [FATAL] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$2"
              printf "\n========================================================================\n"
              exit $1
          }
          
          function debug_exec(){
              local cmd="$@"
              log_info "$cmd"
              eval "$cmd"
              ret=$?
              echo ""
              log_info "$cmd, exit code: $ret"
              return $ret
          }
          
          
          function unsupported_system() {
              log_fatal 1 "Unsupported System: $1"
          }
          
          function deploy_wordpress() {
              log_info "start deploy WordPress"
              wget 'https://ros-public-templates.oss-cn-hangzhou.aliyuncs.com/file/wordpress-5.6.tar'
              docker load -i wordpress-5.6.tar
              mkdir /wordpress
              docker run --name my-blog --restart=always -v /wordpress:/var/www/html -p 80:80 -d wordpress:5.6
          }
          
          log_info "System Information:"
          if ! lsb_release -a; then
              unsupported_system
          fi;
          echo ""
          
          if ! debug_exec deploy_wordpress; then
              log_fatal 3 "failed to deploy WordPress"
          fi
Outputs:
  EcsLoginAddress:
    Description:
      en: Ecs login address.
      zh-cn: ECS登录地址。
    Value:
      Fn::Sub: https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs&regionId=${ALIYUN::Region}&instanceId=${EcsInstance}
  WordpressUrl:
    Description:
      en: Wordpress url.
      zh-cn: Wordpress 博客访问地址。
    Value:
      Fn::Sub:
        - http://${PublicIp}
        - PublicIp:
            Fn::Select:
              - 0
              - Fn::GetAtt:
                  - EcsInstance
                  - PublicIps
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - ZoneId
          - InstanceType
          - InstancePassword
    Hidden:
      - CommonName
    TemplateTags:
      - acs:developer:gitee:1234-在ECS实例上搭建WordPress博客平台


点击此处或扫描下方二维码,加入「开源上云」,一起把开源项目「做大做强,再创辉煌」!


海报.jpg



作者介绍
目录