http://ju.outofmemory.cn/entry/70264
Amazon最初始推出AWS时候,提供给用户的是虚拟机(EC2),存储(Volume),弹性IP(Elastic IP)等这些在云计算中被划分为基础设施层(I层)的资源。
稍后AWS又推出了RDS(Relation Database Service),用户可以申请MySQL,Oracle,Postgres,SQLServer这些数据库实例(DBInstance)。这个在云计算中被划分为平台层(P层)。
到目前位置,AWS的利润也只是上面说到的I层和P层资源得到,用户只有使用了这些资源,才需要付费。
AWS为了方便用户申请这些资源。开发了CloudFormation这个工具。
CloudFormation实现的功能是维护一个资源申请模版的生命周期。包括资源的申明,创建,销毁,监控(通过CloudWatch监控,CloudWatch是AWS提供的监控服务)。
这个模板在AWS中命名为Stack。
因此我们学习CloudFormation,就是需要掌握Stack的含义。
在学习Stack之前,需要再补充说明亮点:
我们以Wordpress的Stack模板,讲解如何通过Stack申请资源(I层和P层资源)。我们以注解方式说明,绿色为注解。
讲解使用的Sample Stack下载地址:https://s3.amazonaws.com/cloudformation-templates-us-east-1/WordPress_Single_Instance_With_RDS.template
Stack是一个JSON文件。
{
//Stack的版本信息,下面的JSON格式是2010-09-09版本的。
“AWSTemplateFormatVersion” : “2010-09-09″,
//Stack描述信息
“Description” : “AWS CloudFormation Sample Template WordPress_Single_Instance_With_RDS: WordPress is web software you can use to create a beautiful website or blog. This template installs a single-instance WordPress deployment using an Amazon RDS database instance for storage. It demonstrates using the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time. **WARNING** This template creates an Amazon EC2 instance and an Amazon RDS database instance. You will be billed for the AWS resources used if you create a stack from this template.”,
//Stack的参数。这些参数会在执行Stack时候,生成界面,让用户输入。
//参数可以被Stack中其他元素通过名称引用。
“Parameters” : {
“KeyName”: {
“Description” : “Name of an existing EC2 KeyPair to enable SSH access to the instances”,
“Type”: “String”,
“MinLength”: “1″,
“MaxLength”: “255″,
“AllowedPattern” : “[\\x20-\\x7E]*”,
“ConstraintDescription” : “can contain only ASCII characters.”
},
“InstanceType” : {
“Description” : “WebServer EC2 instance type”,
“Type” : “String”,
“Default” : “m1.small”,
“AllowedValues” : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","m3.xlarge","m3.2xlarge","c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"],
“ConstraintDescription” : “must be a valid EC2 instance type.”
},
“DBClass” : {
“Default” : “db.m1.small”,
“Description” : “Database instance class”,
“Type” : “String”,
“AllowedValues” : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
“ConstraintDescription” : “must select a valid database instance type.”
},
“DBName” : {
“Default”: “wordpress”,
“Description” : “The WordPress database name”,
“Type”: “String”,
“MinLength”: “1″,
“MaxLength”: “64″,
“AllowedPattern” : “[a-zA-Z][a-zA-Z0-9]*”,
“ConstraintDescription” : “must begin with a letter and contain only alphanumeric characters.”
},
“DBUsername” : {
“Default”: “admin”,
“NoEcho”: “true”,
“Description” : “The WordPress database admin account username”,
“Type”: “String”,
“MinLength”: “1″,
“MaxLength”: “16″,
“AllowedPattern” : “[a-zA-Z][a-zA-Z0-9]*”,
“ConstraintDescription” : “must begin with a letter and contain only alphanumeric characters.”
},
“DBPassword” : {
“Default”: “password”,
“NoEcho”: “true”,
“Description” : “The WordPress database admin account password”,
“Type”: “String”,
“MinLength”: “8″,
“MaxLength”: “41″,
“AllowedPattern” : “[a-zA-Z0-9]*”,
“ConstraintDescription” : “must contain only alphanumeric characters.”
},
“DBAllocatedStorage” : {
“Default”: “5″,
“Description” : “The size of the database (Gb)”,
“Type”: “Number”,
“MinValue”: “5″,
“MaxValue”: “1024″,
“ConstraintDescription” : “must be between 5 and 1024Gb.”
},
“SSHLocation” : {
“Description” : ” The IP address range that can be used to SSH to the EC2 instances”,
“Type”: “String”,
“MinLength”: “9″,
“MaxLength”: “18″,
“Default”: “0.0.0.0/0″,
“AllowedPattern”: “(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})”,
“ConstraintDescription”: “must be a valid IP CIDR range of the form x.x.x.x/x.”
}
},
//EC2的配置与CPU架构的映射关系。t1.micro是EC2的一个配置,用户只能选择某个EC2配置,而不能随意指定。
//EC2的配置包含CPU内存的配置。
“Mappings” : {
“AWSInstanceType2Arch” : {
“t1.micro” : { “Arch” : “64″ },
“m1.small” : { “Arch” : “64″ },
“m1.medium” : { “Arch” : “64″ },
“m1.large” : { “Arch” : “64″ },
“m1.xlarge” : { “Arch” : “64″ },
“m2.xlarge” : { “Arch” : “64″ },
“m2.2xlarge” : { “Arch” : “64″ },
“m2.4xlarge” : { “Arch” : “64″ },
“m3.xlarge” : { “Arch” : “64″ },
“m3.2xlarge” : { “Arch” : “64″ },
“c1.medium” : { “Arch” : “64″ },
“c1.xlarge” : { “Arch” : “64″ },
“cc1.4xlarge” : { “Arch” : “64HVM” },
“cc2.8xlarge” : { “Arch” : “64HVM” },
“cg1.4xlarge” : { “Arch” : “64HVM” }
},
//AMI与CPU架构和AWS Zone的映射关系。AMI是AWS Machine Image,对应传统服务器就是镜像。
“AWSRegionArch2AMI” : {
“us-east-1″ : { “32″ : “ami-31814f58″, “64″ : “ami-1b814f72″, “64HVM” : “ami-0da96764″ },
“us-west-2″ : { “32″ : “ami-38fe7308″, “64″ : “ami-30fe7300″, “64HVM” : “NOT_YET_SUPPORTED” },
“us-west-1″ : { “32″ : “ami-11d68a54″, “64″ : “ami-1bd68a5e”, “64HVM” : “NOT_YET_SUPPORTED” },
“eu-west-1″ : { “32″ : “ami-973b06e3″, “64″ : “ami-953b06e1″, “64HVM” : “NOT_YET_SUPPORTED” },
“ap-southeast-1″ : { “32″ : “ami-b4b0cae6″, “64″ : “ami-beb0caec”, “64HVM” : “NOT_YET_SUPPORTED” },
“ap-southeast-2″ : { “32″ : “ami-b3990e89″, “64″ : “ami-bd990e87″, “64HVM” : “NOT_YET_SUPPORTED” },
“ap-northeast-1″ : { “32″ : “ami-0644f007″, “64″ : “ami-0a44f00b”, “64HVM” : “NOT_YET_SUPPORTED” },
“sa-east-1″ : { “32″ : “ami-3e3be423″, “64″ : “ami-3c3be421″, “64HVM” : “NOT_YET_SUPPORTED” }
}
},
//资源的申明。必选。
//AWS定义了一个资源清单,每个资源有一个Type,Type的值只能从已有的资源类型选择,不能随意指定。
“Resources” : {
//申请一个EC2实例。这个实例的逻辑名称为WebServer。
//每个资源有一个逻辑名称,在Stack中唯一;当资源创建出来之后,有一个全局唯一的物理ID(PhysicalID),由AWS分配。逻辑名称与PhysicalID对应。
“WebServer”: {
“Type”: “AWS::EC2::Instance”,
“Metadata” : {
“AWS::CloudFormation::Init” : {
“config” : {
“packages” : {
“yum” : {
“httpd” : [],
“php” : [],
“php-mysql” : []
}
},
“sources” : {
“/var/www/html” : “http://wordpress.org/latest.tar.gz”
},
“files” : {
“/var/www/html/wordpress/wp-config.php” : {
“content” : { “Fn::Join” : ["", [
"<?php\n",
"define('DB_NAME', '", {"Ref" : "DBName"}, "');\n",
"define('DB_USER', '", {"Ref" : "DBUsername"}, "');\n",
"define('DB_PASSWORD', '", {"Ref" : "DBPassword" }, "');\n",
"define('DB_HOST', '", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Address"]},”‘);\n”,
“define(‘DB_CHARSET’, ‘utf8′);\n”,
“define(‘DB_COLLATE’, ”);\n”
]] },
“mode” : “000644″,
“owner” : “root”,
“group” : “root”
}
},
“services” : {
“sysvinit” : {
“httpd” : { “enabled” : “true”, “ensureRunning” : “true” },
“sendmail” : { “enabled” : “false”, “ensureRunning” : “false” }
}
}
}
}
},
“Properties”: {
//在属性中指定EC2的镜像包AMI。Stack支持FindInMap函数和Ref函数。
//ImageId的值就是通过在AWSRegionArch2AMI这个Map中找指定Zone的镜像。
//其中Zone的名称引用引用AWS::Region这个全局函数返回的值,就是获取当前租户的Zone。
“ImageId” : { “Fn::FindInMap” : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
//EC2实例的类型,引用前面Paramters定义的InstanceType值,这个值由用户输入。
“InstanceType” : { “Ref” : “InstanceType” },
“SecurityGroups” : [ {"Ref" : "WebServerSecurityGroup"} ],
“KeyName” : { “Ref” : “KeyName” },
//Stack还支持用户钩子脚本执行配置EC2的操作
“UserData” : { “Fn::Base64″ : { “Fn::Join” : ["", [
"#!/bin/bash\n",
"yum update -y aws-cfn-bootstrap\n",
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServer ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"/opt/aws/bin/cfn-signal -e $? '", { "Ref" : "WaitHandle" }, "'\n",
"# Setup correct file ownership\n",
"chown -R apache:apache /var/www/html/wordpress\n",
"# Add keys and salts to the config file\n",
"wp_config=/var/www/html/wordpress/wp-config.php\n",
"GET https://api.wordpress.org/secret-key/1.1/salt/ >> $wp_config\n",
"echo \"define('WPLANG' , '');\" >> $wp_config\n",
"echo \"define('WP_DEBUG' , false);\" >> $wp_config\n",
"echo \"\\$table_prefix = 'wp_';\" >> $wp_config\n",
"echo \"if ( !defined('ABSPATH') )\" >> $wp_config\n",
"echo \" define('ABSPATH', dirname(__FILE__) . '/');\" >> $wp_config\n",
"echo \"require_once(ABSPATH . 'wp-settings.php');\" >> $wp_config\n"
]]}}
}
},
“WaitHandle” : {
“Type” : “AWS::CloudFormation::WaitConditionHandle”
},
“WaitCondition” : {
“Type” : “AWS::CloudFormation::WaitCondition”,
“DependsOn” : “WebServer”,
“Properties” : {
“Handle” : {“Ref” : “WaitHandle”},
“Timeout” : “600″
}
},
//数据库实例。AWS提供给用户的是数据库实例,而不是某个数据库。用户得到数据库实例的信息之后,可以自行创建数据库。
//AWS还支持创建实例的时候创建数据库,这种场景通常是一个实例一个数据库。下面的DBName参数是可选的。
“DBInstance” : {
“Type”: “AWS::RDS::DBInstance”,
“Properties”: {
“DBName” : { “Ref” : “DBName” },
“Engine” : “MySQL”,
“MasterUsername” : { “Ref” : “DBUsername” },
“DBInstanceClass” : { “Ref” : “DBClass” },
“DBSecurityGroups” : [{ "Ref" : "DBSecurityGroup" }],
“AllocatedStorage” : { “Ref” : “DBAllocatedStorage” },
“MasterUserPassword”: { “Ref” : “DBPassword” }
}
},
“DBSecurityGroup”: {
“Type”: “AWS::RDS::DBSecurityGroup”,
“Properties”: {
“DBSecurityGroupIngress”: { “EC2SecurityGroupName”: { “Ref”: “WebServerSecurityGroup”} },
“GroupDescription” : “Frontend Access”
}
},
“WebServerSecurityGroup” : {
“Type” : “AWS::EC2::SecurityGroup”,
“Properties” : {
“GroupDescription” : “Enable HTTP access via port 80 and SSH access”,
“SecurityGroupIngress” : [
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
]
}
}
},
//用户自定义的输出。这个是Stack创建完成了之后,暴露给外部访问的入口。
//如这里的一个Output为Wordpress安装好了之后的访问地址。
//同学们可能会由疑问,Wordpress在哪里安装好的呢?在AMI镜像包中包含了Wordpress安装包!
“Outputs” : {
“WebsiteURL” : {
“Value” : { “Fn::Join” : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicDnsName" ]}, “/wordpress”]] },
“Description” : “WordPress Website”
}
}
}