资源编排可通过资源编排模板定义您需要创建的阿里云资源的组合,并依据您的配置来完成对资源的配置和一键销毁,快速方便的构建您的应用。本文将引导您如何基于资源编排服务快速构建一个应用。
首先引入三个概念:Meta-Data、Cloud-Init 和 User-Data。
- Meta-Data
Meta-Data 主要包括虚拟机自身的一些常用属性,如 hostname、网络配置信息、资源 InstanceId 等,其主要的形式为键值对。可以通过访问下面的地址查询 Meta-Data 信息 - Cloud-Init
Cloud-Init 是一个在云主机启动时操作和定制云主机环境的包。它可以在云主机启动时实现如设置主机的语言环境,设置主机 Hostname,配置网络,下载一些包并进行安装等功能,免去了用户自己手动设置的麻烦。Cloud-Init 实现这些功能的基础是 User-Data。 - User-Data
User-Data 是实现云主机个性化定制的基础,用户通过 User-Data 设置一些定制化数据,如启动某项服务,下载一些包并设置这些包的安装脚本等,Cloud-Init 在云主机启动时加载并执行这些数据,从而完成对云主机的个性化定制。更多的详情可参考Cloud-Init文档。对于创建云主机的时候设置过 User-Data 的 Instance,可以通过访问下面的地址查询 User-Data 信息
本文正是利用了 Cloud-Init 的实现方式,结合资源编排,将构建应用的脚本写入到 User-Data 中,从而实现对应用的一键构建。
基于资源编排一键构建应用的大致步骤如下:
- 熟悉在云服务器上搭建应用的流程,并编写出该流程对应的 Shell 脚本
- 定义资源编排基础模板,用于搭建应用运行的基础服务
- 将已编写好的搭建应用的 Shell 脚本添加到基础模板的资源类型
ALIYUN::ECS::Instance
的 UserData 属性中 - 完成模板的创建,输入定义的参数,完成基于资源编排的应用构建
目前云资源构建的网络类型只支持 VPC,可选区域仅支持华南1、华北2和华东2,即RegionId
只支持cn-shenzhen
、cn-beijing
和cn-shanghai
。其它的 Region 和网络类型,我们也会尽快的上线。
为了便于说明,本文将以在 Centos 6上构建 WordPress 作为构建应用的示例。
编写构建WordPress的运行脚本
搭建 WordPress,首先需要安装 WordPress 所依赖的基础服务:Apache、MySQL 以及 PHP,然后下载最新版本的 WordPress 包并进行安装,最后根据 WordPress的搭建需求,对基础依赖服务进行相应的配置。
以下是在 Centos 6上搭建 WordPress 的详细 Shell 脚本:
#!/bin/bash
DatabaseUser='root'
DatabasePwd='rootadmin'
DatabaseName='wordpress'
WebRootPath='/var/www/html'
ApacheIndex='Options Indexes FollowSymLinks'
ApacheIndexReplace='Options -Indexes FollowSymLinks'
# 安装Wordpress所依赖的服务
yum install -y curl httpd mysql-server php php-common php-mysql
yum install -y php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc
# 设置apache和mysql服务为开机自启动
chkconfig httpd on
chkconfig mysqld on
# 下载Wordpress最新安装包,并配置其对数据库的访问
wget http://wordpress.org/latest.tar.gz
tar -xzvf latest.tar.gz
sed -i "s/database_name_here/$DatabaseName/" wordpress/wp-config-sample.php
sed -i "s/username_here/$DatabaseUser/" wordpress/wp-config-sample.php
sed -i "s/password_here/${DatabasePwd:-$DatabasePwdDef}/" wordpress/wp-config-sample.php
# 设置WordPress安装位置
mv wordpress/wp-config-sample.php wordpress/wp-config.php
cp -a wordpress/ $WebRootPath
rm -rf wordpress* latest.tar.gz
# 将Wordpress目录及其里面文件的所有者和所有组更改为 apache 用户和 apache 组
service httpd stop
usermod -d $WebRootPath apache
chown apache:apache -R $WebRootPath
# 为了安全起见,关闭目录浏览功能
sed -i "s/$ApacheIndex/$ApacheIndexReplace/" /etc/httpd/conf/httpd.conf
service httpd start
# 新建wordpress数据库,新增mysql用户,并赋权给它对应为 wordpress 数据库全部权限
service mysqld start
chmod 400 /etc/my.cnf
mysql -u root << EOF
CREATE DATABASE $DatabaseName default charset utf8 COLLATE utf8_general_ci;
CREATE USER $DatabaseUser IDENTIFIED by '$DababasePwd';
grant all on $DatabaseName.* to $DatabaseUser@localhost identified by '$DatabasePwd';
EOF
定义构建WordPress的ROS模板
定义一个资源编排模板,并基于该模板构建 WordPress 应用。
创建一个ECS资源模版
首先我们创建一个 ECS 资源模板。在模板中定义我们需要创建的资源:
- ALIYUN::ECS::EIPAssociation
- 绑定一个公网 IP
- ALIYUN::ECS::EIP
- 申请一个弹性公网 IP
- ALIYUN::ECS::SecurityGroup
- 创建一个安全组
- ALIYUN::ECS::SecurityGroupIngress
- 创建安全组 In 方向的访问规则,出于安全考虑,该安全组只开放80端口
- ALIYUN::ECS::Instance
- 创建一个 ECS 实例
值得注意的是,目前云资源的构建只支持 VPC 环境,所以在模板中您可以直接使用已有 VPC 环境或者构建新的 VPC 环境。新建 VPC 环境时,模板中应该增加对如下资源类型的定义:
- ALIYUN::ECS::VPC
- 新建专有网络
- ALIYUN::ECS::VSwitch
- 新建交换机
更多有关构建 VPC 的信息可参考通过资源编排创建一个完整的VPC网络。
添加构建WordPress的脚本
将已编写好的构建 WordPress 的运行脚本加入到资源类型ALIYUN::ECS::Instance
的 UserData 属性中,以完成对构建 WordPress 模板的创建。
为了安全和方便起见,将数据库的名称、用户名及其密码作为输入参数。
以下是利用已有 VPC 环境构建 WordPress 的模板:
{
"ROSTemplateFormatVersion": "2015-09-01",
"Parameters": {
"DBName": {
"AllowedPattern": "[a-z]{1}[a-z0-9-_]*[a-z0-9]{1}",
"ConstraintDescription": "由 2~64 个字符的小写字母、数字、下划线或中划线组成,开头需为字母,结尾需为字母或数字。",
"Default": "wordpress",
"Description": "WordPress的数据库名称",
"MaxLength": "64",
"MinLength": "2",
"Type": "String"
},
"DBPassword": {
"AllowedPattern": "[a-zA-Z0-9-_]*",
"ConstraintDescription": "由 6~32 个字符的字母、数字、中划线或下划线组成。",
"Default": "wpADMIN123",
"Description": "WordPress数据库密码",
"MaxLength": "41",
"MinLength": "8",
"Type": "String"
},
"DBUser": {
"AllowedPattern": "[a-z]{1}[a-z0-9_]*[a-z0-9]{1}",
"ConstraintDescription": "由 2~16 个字符的小写字母,数字或下划线组成、开头需为字母,结尾需为字母或数字。",
"Default": "wpuser",
"Description": "WordPress数据库用户名",
"MaxLength": "16",
"MinLength": "2",
"Type": "String"
},
"InstancePassword": {
"AllowedPattern": "[a-zA-Z0-9]*",
"ConstraintDescription": "可包含大小写字母,数字和特殊字符",
"Default": "vmADMIN123",
"Description": "ECS实例的登录密码",
"MaxLength": "41",
"MinLength": "8",
"Type": "String"
},
"SecurityGroupName": {
"Description": "安全组名称",
"Type": "String"
},
"VSwitchId": {
"Description": "已创建的VSwitch的ID",
"Type": "String"
},
"VpcId": {
"Description": "已创建的vpc的ID",
"Type": "String"
},
"ZoneId": {
"Default": "cn-shenzhen-a",
"Description": "可用区 Id",
"Type": "String"
}
},
"Resources": {
"EIPBind": {
"Properties": {
"AllocationId": {
"Ref": "NewEip"
},
"InstanceId": {
"Ref": "WebServer"
}
},
"Type": "ALIYUN::ECS::EIPAssociation"
},
"NewEip": {
"Properties": {
"Bandwidth": 1,
"InternetChargeType": "PayByTraffic"
},
"Type": "ALIYUN::ECS::EIP"
},
"SecurityGroup": {
"Properties": {
"SecurityGroupName": {
"Ref": "SecurityGroupName"
},
"VpcId": {
"Ref": "VpcId"
}
},
"Type": "ALIYUN::ECS::SecurityGroup"
},
"SecurityGroupIngress": {
"Properties": {
"IpProtocol": "tcp",
"PortRange": "80/80",
"SecurityGroupId": {
"Ref": "SecurityGroup"
},
"SourceCidrIp": "0.0.0.0/0"
},
"Type": "ALIYUN::ECS::SecurityGroupIngress"
},
"WebServer": {
"Properties": {
"ImageId": "centos6u5_64_40G_cloudinit_20160427.raw",
"InstanceType": "ecs.s2.large",
"IoOptimized": "optimized",
"Password": {
"Ref": "InstancePassword"
},
"SecurityGroupId": {
"Ref": "SecurityGroup"
},
"SystemDiskCategory": "cloud_ssd",
"UserData": {
"Fn::Replace": [
{
"print": "echo"
},
{
"Fn::Join": [
"",
[
"#!/bin/sh",
"\n",
"DatabaseUser=",
{
"Ref": "DBUser"
},
"\n",
"DatabasePwd=",
{
"Ref": "DBPassword"
},
"\n",
"DatabaseName=",
{
"Ref": "DBName"
},
"\n",
"WebRootPath='/var/www/html'\n",
"ApacheIndex='Options Indexes FollowSymLinks'\n",
"ApacheIndexReplace='Options -Indexes FollowSymLinks'\n",
"yum install -y curl httpd mysql-server php php-common php-mysql\n",
"yum install -y php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc\n",
"chkconfig httpd on\n",
"chkconfig mysqld on \n",
"wget http://wordpress.org/latest.tar.gz\n",
"tar -xzvf latest.tar.gz\n",
"sed -i \"s/database_name_here/$DatabaseName/\" wordpress/wp-config-sample.php\n",
"sed -i \"s/username_here/$DatabaseUser/\" wordpress/wp-config-sample.php\n",
"sed -i \"s/password_here/${DatabasePwd:-$DatabasePwdDef}/\" wordpress/wp-config-sample.php\n",
"mv wordpress/wp-config-sample.php wordpress/wp-config.php\n",
"cp -a wordpress/* $WebRootPath\n",
"rm -rf wordpress*\n",
"service httpd stop\n",
"usermod -d $WebRootPath apache &>/dev/null\n",
"chown apache:apache -R $WebRootPath\n",
"sed -i \"s/$ApacheIndex/$ApacheIndexReplace/\" /etc/httpd/conf/httpd.conf\n",
"service httpd start\n",
"service mysqld start\n",
"chmod 400 /etc/my.cnf\n",
"mysql -u root << EOF \n",
"CREATE DATABASE $DatabaseName default charset utf8 COLLATE utf8_general_ci;\n",
"CREATE USER $DatabaseUser IDENTIFIED by '$DababasePwd';\n",
"grant all on $DatabaseName.* to $DatabaseUser@localhost identified by '$DatabasePwd';\n",
"EOF\n"
]
]
}
]
},
"VSwitchId": {
"Ref": "VSwitchId"
},
"VpcId": {
"Ref": "VpcId"
}
},
"Type": "ALIYUN::ECS::Instance"
}
},
"Outputs": {
"InstanceId": {
"Value": {
"Fn::GetAtt": [
"WebServer",
"InstanceId"
]
}
},
"PublicIp": {
"Value": {
"Fn::GetAtt": [
"WebServer",
"PublicIp"
]
}
}
}
}
您也可以通过新建一个 VPC 环境来构建 WordPress:
{
"ROSTemplateFormatVersion": "2015-09-01",
"Parameters": {
"DBName": {
"AllowedPattern": "[a-z]{1}[a-z0-9-_]*[a-z0-9]{1}",
"ConstraintDescription": "由 2~64 个字符的小写字母、数字、下划线或中划线组成,开头需为字母,结尾需为字母或数字。",
"Default": "wordpress",
"Description": "WordPress的数据库名称",
"MaxLength": "64",
"MinLength": "2",
"Type": "String"
},
"DBPassword": {
"AllowedPattern": "[a-zA-Z0-9-_]*",
"ConstraintDescription": "由 6~32 个字符的字母、数字、中划线或下划线组成。",
"Default": "wpADMIN123",
"Description": "WordPress数据库密码",
"MaxLength": "41",
"MinLength": "8",
"Type": "String"
},
"DBUser": {
"AllowedPattern": "[a-z]{1}[a-z0-9_]*[a-z0-9]{1}",
"ConstraintDescription": "由 2~16 个字符的小写字母,数字或下划线组成、开头需为字母,结尾需为字母或数字。",
"Default": "wpuser",
"Description": "WordPress数据库用户名",
"MaxLength": "16",
"MinLength": "2",
"Type": "String"
},
"InstancePassword": {
"AllowedPattern": "[a-zA-Z0-9]*",
"ConstraintDescription": "可包含大小写字母,数字和特殊字符",
"Default": "vmADMIN123",
"Description": "ECS实例的登录密码",
"MaxLength": "41",
"MinLength": "8",
"Type": "String"
},
"SecurityGroupName": {
"Description": "安全组名称",
"Type": "String"
},
"ZoneId": {
"Default": "cn-shenzhen-a",
"Description": "可用区 Id",
"Type": "String"
},
"VpcName": {
"ConstraintDescription": "[2, 128] 英文或中文字符",
"Description": "VPC 名称",
"MaxLength": 128,
"MinLength": 2,
"Type": "String"
},
"SwitchCidrBlock": {
"Default": "192.168.0.0/18",
"Description": "VSwitch网段,可选值 192.168.0.0/16和172.16.0.0/12及它们包含的子网",
"Type": "String"
},
"VpcCidrBlock": {
"Default": "192.168.0.0/16",
"Description": "vpc网段,可选值 192.168.0.0/16和172.16.0.0/12及它们包含的子网",
"Type": "String"
}
},
"Resources": {
"EIPBind": {
"Properties": {
"AllocationId": {
"Ref": "NewEip"
},
"InstanceId": {
"Ref": "WebServer"
}
},
"Type": "ALIYUN::ECS::EIPAssociation"
},
"NewEip": {
"Properties": {
"Bandwidth": 1,
"InternetChargeType": "PayByTraffic"
},
"Type": "ALIYUN::ECS::EIP"
},
"SecurityGroup": {
"Properties": {
"SecurityGroupName": {
"Ref": "SecurityGroupName"
},
"VpcId": {
"Ref": "Vpc"
}
},
"Type": "ALIYUN::ECS::SecurityGroup"
},
"SecurityGroupIngress": {
"Properties": {
"IpProtocol": "tcp",
"PortRange": "80/80",
"SecurityGroupId": {
"Ref": "SecurityGroup"
},
"SourceCidrIp": "0.0.0.0/0"
},
"Type": "ALIYUN::ECS::SecurityGroupIngress"
},
"VSwitch": {
"Properties": {
"CidrBlock": {
"Ref": "SwitchCidrBlock"
},
"VpcId": {
"Fn::GetAtt": [
"Vpc",
"VpcId"
]
},
"ZoneId": {
"Ref": "ZoneId"
}
},
"Type": "ALIYUN::ECS::VSwitch"
},
"Vpc": {
"Properties": {
"CidrBlock": {
"Ref": "VpcCidrBlock"
},
"VpcName": {
"Ref": "VpcName"
}
},
"Type": "ALIYUN::ECS::VPC"
},
"WebServer": {
"Properties": {
"ImageId": "centos6u5_64_40G_cloudinit_20160427.raw",
"InstanceType": "ecs.s2.large",
"IoOptimized": "optimized",
"Password": {
"Ref": "InstancePassword"
},
"SecurityGroupId": {
"Ref": "SecurityGroup"
},
"SystemDiskCategory": "cloud_ssd",
"UserData": {
"Fn::Replace": [
{
"print": "echo"
},
{
"Fn::Join": [
"",
[
"#!/bin/sh",
"\n",
"DatabaseUser=",
{
"Ref": "DBUser"
},
"\n",
"DatabasePwd=",
{
"Ref": "DBPassword"
},
"\n",
"DatabaseName=",
{
"Ref": "DBName"
},
"\n",
"WebRootPath='/var/www/html'\n",
"ApacheIndex='Options Indexes FollowSymLinks'\n",
"ApacheIndexReplace='Options -Indexes FollowSymLinks'\n",
"yum install -y curl httpd mysql-server php php-common php-mysql\n",
"yum install -y php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc\n",
"chkconfig httpd on\n",
"chkconfig mysqld on \n",
"wget http://wordpress.org/latest.tar.gz\n",
"tar -xzvf latest.tar.gz\n",
"sed -i \"s/database_name_here/$DatabaseName/\" wordpress/wp-config-sample.php\n",
"sed -i \"s/username_here/$DatabaseUser/\" wordpress/wp-config-sample.php\n",
"sed -i \"s/password_here/${DatabasePwd:-$DatabasePwdDef}/\" wordpress/wp-config-sample.php\n",
"mv wordpress/wp-config-sample.php wordpress/wp-config.php\n",
"cp -a wordpress/* $WebRootPath\n",
"rm -rf wordpress*\n",
"service httpd stop\n",
"usermod -d $WebRootPath apache &>/dev/null\n",
"chown apache:apache -R $WebRootPath\n",
"sed -i \"s/$ApacheIndex/$ApacheIndexReplace/\" /etc/httpd/conf/httpd.conf\n",
"service httpd start\n",
"service mysqld start\n",
"mysqladmin -u $DatabaseRoot -p password $RootPwd &>/dev/null\n",
"chmod 400 /etc/my.cnf\n",
"mysql -u root << EOF \n",
"CREATE DATABASE $DatabaseName default charset utf8 COLLATE utf8_general_ci;\n",
"CREATE USER $DatabaseUser IDENTIFIED by '$DababasePwd';\n",
"grant all on $DatabaseName.* to $DatabaseUser@localhost identified by '$DatabasePwd';\n",
"EOF\n"
]
]
}
]
},
"VSwitchId": {
"Ref": "VSwitch"
},
"VpcId": {
"Ref": "Vpc"
}
},
"Type": "ALIYUN::ECS::Instance"
}
},
"Outputs": {
"InstanceId": {
"Value": {
"Fn::GetAtt": [
"WebServer",
"InstanceId"
]
}
},
"PublicIp": {
"Value": {
"Fn::GetAtt": [
"WebServer",
"PublicIp"
]
}
}
}
}
创建Stack资源
完成模板的创建后,根据 Stack 资源的创建步骤,输入必要的参数,点击创建
按钮,即可完成资源的创建以及应用的构建。
访问WordPress
资源创建完成后,根据资源创建的输出结果,在浏览器中输入http://[PublicIP]/wp-admin/install.php
即可访问搭建好的 WordPress 应用。在下一篇中我们将使用阿里云的 RDS 来替换 Mysql 来实现应用的交付。