定义
AWS CloudFormation 提供了一种简便地创建和管理一批相关的 AWS 资源的方法,并通过有序且可预测的方式对其进行资源配置和更新。可以使用 AWS CloudFormation 的示例模板或自己创建模板来描述 AWS 资源以及应用程序运行时所需的任何相关依赖项或运行时参数。可以不需要了解亚马逊 AWS 服务需要配置的顺序,也不必弄清楚让这些依赖项正常运行的细枝末节。 当设置完成后,可通过按受控制、可预测的方式修改和更新 AWS 资源,可以像软件版本控制一样对 AWS 基础结构进行版本控制。无需为 CloudFormation 支付额外的费用,只需支付支持应用程序 的 AWS 资源费用。
堆栈
使用 AWS CloudFormation 时,可将相关资源作为一个称为“堆栈”的单元进行管理。换句话说,我们可以通过创建、更新和删除堆栈来创建、更新和删除一系列资源。堆栈中的所有资源均由堆栈的 AWS CloudFormation 模板定义。
使用
AWS根据一些用户典型场景,定义了一些典型场景下的Stack模版,供用户使用。下面主要一个 WordPress 服务器的模板为例。
Stack支持两种格式JSON和YAML:
// 模板格式的版本信息,下面的是 2010-09-09 版本的。如果不指定,AWS CloudFormation 将使用最新版本
AWSTemplateFormatVersion: '2010-09-09'
//模板描述信息,Description 必须紧随 AWSTemplateFormatVersion 部分之后。且长度是介于 0 和 1024 个字节之间的文字字符串,目前貌似不支持中文
Description: My First Cloudformation Stack
//参数,要在运行时 (创建或更新堆栈时) 传递到模板的值。您可引用模板的 Resources 和 Outputs 部分中的参数。这些参数会在执行Stack时候,生成界面,让用户输入。参数可以被 Stack 中其他元素通过名称引用。
Parameters:
InstanceType:
Description: WebServer EC2 instance type
Type: String
Default: t2.small //默认值
//包含参数允许值列表的阵列
AllowedValues:
- t2.micro
- t2.small
- t2.medium
//用于在违反约束时说明该约束的字符串。
ConstraintDescription: must be a valid EC2 instance type.
SSHLocation:
Description: The IP address range that can be used to SSH to the EC2 instances
Type: String
//一个整数值,确定要允许 String 类型使用的字符的最小数目。
MinLength: '9'
//一个整数值,确定要允许 String 类型使用的字符的最大数目
MaxLength: '18'
Default: 0.0.0.0/0
//一个正则表达式,表示要允许 String 类型使用的模式。
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.
DevopsGirlsUser:
Default: zhang.san
Description: Your firstname and lastname
Type: String
MinLength: '1'
MaxLength: '64'
ConstraintDescription: must begin with a letter and contain only alphanumeric
characters.
// 这里使用 S3 bucket
WordpressS3Bucket:
Default: devopsgirls-training-xian
Description: Bucket to get Wordpress from
Type: String
//EC2 的配置与CPU内存架构的映射关系.
Mappings:
AWSInstanceType2Arch:
t2.micro:
Arch: HVM64
t2.small:
Arch: HVM64
t2.medium:
Arch: HVM64
//AMI与CPU架构和AWS Zone的映射关系。
AWSRegionArch2AMI:
ap-southeast-1:
HVM64: ami-01da99628f381e50a
//AWS定义了一个资源清单,每个资源有一个Type,Type的值只能从已有的资源类型选择,不能随意指定。
Resources: //唯一必须的,一般有逻辑ID,资源类型, 资源属性组成。
//申请一个 ELB。这个ELB的逻辑名称为 ElasticLoadBalancer。
//每个资源有一个逻辑名称,在Stack中唯一;当资源创建出来之后,有一个全局唯一的物理ID(PhysicalID),由AWS分配。逻辑名称与PhysicalID对应。
ElasticLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
AvailabilityZones: !GetAZs ''
SecurityGroups:
- !GetAtt 'ElasticLoadBalancerSecurityGroup.GroupId'
CrossZone: 'true'
LBCookieStickinessPolicy:
- PolicyName: CookieBasedPolicy
CookieExpirationPeriod: '30'
Listeners:
- LoadBalancerPort: '80'
InstancePort: '80'
Protocol: HTTP
PolicyNames:
- CookieBasedPolicy
HealthCheck:
Target: TCP:80
HealthyThreshold: '2'
UnhealthyThreshold: '5'
Interval: '10'
Timeout: '5'
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable HTTP access via port 80 locked down to the load balancer
+ SSH access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
SourceSecurityGroupOwnerId: !GetAtt 'ElasticLoadBalancer.SourceSecurityGroup.OwnerAlias'
SourceSecurityGroupId: !GetAtt 'ElasticLoadBalancerSecurityGroup.GroupId'
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'SSHLocation' //使用 Ref 内部函数引用 SSHLocation 参数
ElasticLoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable HTTP access via port 80 locked down to the load balancer
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
WebServerGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones: !GetAZs ''
LaunchConfigurationName: !Ref 'LaunchConfig'
MinSize: '1'
MaxSize: '5'
DesiredCapacity: '2'
LoadBalancerNames:
- !Ref 'ElasticLoadBalancer' //Ref 函数将返回它指代的对象的值,也可以将某个资源的属性设置为另一个资源的属性值
CreationPolicy: //堆栈创建继续之前等待资源配置操作时,使用 CreationPolicy 属性
ResourceSignal: //AWS CloudFormation 创建关联的资源时,配置所需的成功信号数以及 AWS CloudFormation 等待这些信号的时间长度。
//AWS CloudFormation 在将资源状态设置为 CREATE_COMPLETE 之前必须收到的成功信号的数目。如果资源在超时期限过期之前收到失败信号或未收到指定数目的信号,则资源创建将失败并且 AWS CloudFormation 将回滚堆栈。
Count: 2 //默认为1
//AWS CloudFormation 等待 Count 属性中指定数目的信号的时长.该值必须采用以下形式的 ISO8601 持续时间格式:"PT#H#M#S",其中各个 # 分别表示小时数、分钟数和秒数。为获得最佳结果,请指定足够长的时间段,以便实例可以正常启动和运行。更短的超时可导致回滚。
Timeout: PT30M
UpdatePolicy:
//可以指定 AWS CloudFormation 是批量更新还是一次性全部更新 Auto Scaling 组中的实例。
AutoScalingRollingUpdate:
// 指定当 AWS CloudFormation 更新旧实例时,Auto Scaling 组中必须处于服务状态的实例的最小数目
MinInstancesInService: '1'
//指定 AWS CloudFormation 更新的实例的最大数目。
MaxBatchSize: '1'
// 在对一批实例进行更改以便为这些实例提供启动软件应用程序的时间后,AWS CloudFormation 暂停的时间量。例如,在扩展 Auto Scaling 组中的实例数时,您可能需要指定 PauseTime。
PauseTime: PT30M
//指定 Auto Scaling 组在更新期间是否等待来自新实例的信号。使用此属性可确保实例在 Auto Scaling 组继续更新之前已完成安装和配置应用程序。AWS CloudFormation 在新的 EC2 实例在 Auto Scaling 组中启动后暂停对该组的更新。在继续更新之前,AWS CloudFormation 必须在指定的 PauseTime 内收到来自每个新实例的信号
WaitOnResourceSignals: 'true'
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !FindInMap [AWSRegionArch2AMI, !Ref 'AWS::Region', !FindInMap [AWSInstanceType2Arch,
!Ref 'InstanceType', Arch]]
InstanceType: !Ref 'InstanceType'
SecurityGroups:
- !Ref 'WebServerSecurityGroup'
//用户自定义脚本
UserData: !Base64
Fn::Join:
- ''
- - "#!/bin/bash -xe \n"
- "yum update -y aws-cfn-bootstrap \n"
- "aws configure set default.s3.multipart_threshold 64MB \n"
- aws s3 cp s3://devopsgirls-training-xian/
- !Ref 'DevopsGirlsUser'
- "-wordpress.tgz /var/www/wordpress.tgz --no-sign-request \n"
- "yum install httpd php php-mysql -y \n"
- "mkdir -p /var/www/html \n"
- "tar xvfz /var/www/wordpress.tgz -C /var/www/html/ \n"
- "chown -R apache /var/www/html/ \n"
- "service httpd start \n"
- '/opt/aws/bin/cfn-signal -e $? '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerGroup '
- ' --region '
- !Ref 'AWS::Region'
- '
//用户自定义的输出。这个是 Stack 创建完成了之后,暴露给外部访问的入口。
//如这里的一个Output为Wordpress安装好了之后的访问地址。 '
Outputs:
WebsiteURL 是一个由一个 Join 函数调用返回的字符串,该字符串并置了 http://,资源 ElasticLoadBalancer 的 DNS 名
WebsiteURL:
Value: !Join ['', ['http://', !GetAtt 'ElasticLoadBalancer.DNSName', /]]
Description: WordPress Website
可以在 aws 界面将模板上传然后创建 stack,之后在底部的对话框中,单击事件。不停刷新它, 然后就能看到 Cloudformation 正在创建我们的环境。 等到堆栈状态变为 CREATE_COMPLETE,就代表创建成功,点击该堆栈的输出,找到并访问 WebsiteURL 的值,我们将会访问到刚才使用 Cloudformation 创建的 WordPress了。
或者通过 AWS CLI 创建堆栈
$ aws cloudformation create-stack --stack-name wordpress --template-body file:///path-to-your-yaml
帮助程序列表
cfn-init
cfn-init 帮助程序脚本读取来自 AWS::CloudFormation::Init key 的模板元数据并进行相应操作:
提取和解析来自 AWS CloudFormation 的元数据
安装软件包
将文件写入磁盘
启用/禁用以及启动/停止服务
注意:
如果使用 cfn-init 来更新现有文件,则它将在同一目录下为原始文件创建一个扩展名为 .bak 的备份副本。例如,如果更新 /*
path*/*
to*/*
file_name*
,则操作生成两个文件:/*
path*/*
to*/*
file_name*.bak
包含原始文件的内容,而 /*
path*/*
to*/*
file_name*
包含更新的内容。
cfn-init 无需提供凭证,因此不需要使用 --access-key
、--secret-key
、--role
或 --credential-file
选项。但是,如果不指定凭证,则 AWS CloudFormation 会检查堆栈成员并将调用范围限制为实例所属的堆栈。
语法
cfn-init --stack|-s stack.name.or.id \
--resource|-r logical.resource.id \
--region region
--access-key access.key \
--secret-key secret.key \
--role rolename\
--credential-file|-f credential.file \
--configsets|-c config.sets \
--url|-u service.url \
--http-proxy HTTP.proxy \
--https-proxy HTTPS.proxy \
--verbose|-v
选项
示例
下面的代码段演示 EC2 实例的 UserData 属性,该实例运行与 WebServerInstance 资源关联的 InstallAndRun 配置集。
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash -xe
- |
# Install the files and packages from the metadata
- '/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --configsets InstallAndRun '
- ' --region '
- !Ref 'AWS::Region'
- |+
cfn-signal
cfn-signal 帮助程序脚本向 AWS CloudFormation 发送信号来指示是否已成功创建或更新 Amazon EC2 实例。如果在实例上安装和配置软件应用程序,则可在这些软件应用程序准备就绪时向 AWS CloudFormation 发送信号。
将 cfn-signal 脚本与 CreationPolicy 结合使用或将 Auto Scaling 组与 WaitOnResourceSignals 更新策略结合使用。当 AWS CloudFormation 使用这些策略创建或更新资源时,它将暂停堆栈上的工作直至资源收到所需数量的信号或超出超时期限。对于 AWS CloudFormation 接收的每个有效信号,AWS CloudFormation 会将信号发送到堆栈事件以便您跟踪每个信号。
注意:
cfn-signal 不需要凭证,因此不需要使用 --access-key
、--secret-key
、--role
或 --credential-file
选项。但是,如果不指定凭证,则 AWS CloudFormation 会检查堆栈成员并将调用范围限制为实例所属的堆栈。
如果想向 AWS CloudFormation 资源发送信号,请使用以下语法。
cfn-signal --success|-s signal.to.send \ ##如为true,则信号“成功”,否则“失败”。
--access-key access.key \ ##(仅适用于向资源发送信号)
--credential-file|-f credential.file \ ##同时包含秘密访问密钥和访问密钥的文件。凭证文件参数取代 --role、--access-key 和 --secret-key 参数。
--exit-code|-e exit.code \ ##进程中出现错误代码,用于确定成功或失败。如果已经指定,则忽略 --success 选项。
--http-proxy HTTP.proxy \
--https-proxy HTTPS.proxy \
--id|-i unique.id \ ## 要发送的唯一 ID。
--region AWS.region \ ##(仅适用于向资源发送信号),要使用的 AWS CloudFormation 区域终端节点。
--resource resource.logical.ID \ ##仅适用于向资源发送信号,包含要向其发送信号的创建策略的资源的[逻辑 ID]
--role IAM.role.name \
--secret-key secret.key \ (仅适用于向资源发送信号)对应于指定的 AWS 访问密钥的 AWS 秘密访问密钥。
--stack stack.name.or.stack.ID \ ##(仅适用于向资源发送信号)包含要向其发送信号的资源的堆栈名称或堆栈 ID。
--url AWS CloudFormation.endpoint # 仅适用于向资源发送信号,要使用的 AWS CloudFormation 终端节点。
如果想向等待条件句柄发送信号,请使用以下语法。
cfn-signal --success|-s signal.to.send \
--reason|-r resource.status.reason \ ##仅适用于等待条件句柄,目前仅适用于 failure 的状态原因,如果 success = false ,默认为 'Configuration failed'
--data|-d data \ ##(仅适用于等待条件句柄)要通过 waitConditionHandle 发送回的数据。默认值待留空。
--id|-i unique.id \
--exit-code|-e exit.code \
waitconditionhandle.url ##(仅适用于等待条件句柄)可用于向关联的 WaitCondition 发送成功或失败信号的预签名 URL
可使用的选项取决于是向创建策略还是等待条件句柄发送信号。适用于创建策略的一些选项可能不适用于等待条件句柄。
常规使用模式将同时使用 cfn-init 和 cfn-signal。cfn-signal 调用利用了 cfn-init 调用返回状态(使用 $? shell 程序构造)。如果应用程序安装失败,则该实例将无法创建,并且堆栈将回滚。
示例:
AWSTemplateFormatVersion: 2010-09-09
Description: Simple EC2 instance
Resources:
MyInstance:
Type: 'AWS::EC2::Instance'
Metadata:
'AWS::CloudFormation::Init':
config:
files:
/tmp/test.txt:
content: Hello world!
mode: '000755'
owner: root
group: root
Properties:
ImageId: ami-a4c7edb2
InstanceType: t2.micro
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash -x
- |
# Install the files and packages from the metadata
- '/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource MyInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- |
# Signal the status from cfn-init
- '/opt/aws/bin/cfn-signal -e $? '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource MyInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
CreationPolicy:
ResourceSignal:
Timeout: PT5M
cfn-hup
cfn-hup 帮助程序作为一项后台程序,当检测出资源元数据中出现变更时,运行用户指定操作。通过此项操作,可以通过 UpdateStack API 操作对正在运行的 Amazon EC2 实例进行配置更新。
语法:
cfn-hup --config|-c config.dir --no-daemon --verbose|-v
配置参数说明:
cfn-hup.conf
cfn-hup.conf 文件存储了堆栈的名称和 cfn-hup 后台程序目标 AWS 凭证。
cfn-hup.conf 文件采用以下格式:
[main]
stack=<stack-name-or-id> ##堆栈名称或 ID。
credential-file=<credential-file> ##仅用户可用凭证文件,与用于命令行工具的格式相同。role 参数替代此参数。
role=<role> ##与实例关联的 IAM 角色的名称。
region=<region> ##包含堆栈的 AWS 区域名称。
umask=< umask> ##cfn-hup 守护程序使用的 umask。指定此值时可选择带或不带前导 0。在两种情况下,它都会被解释为八进制数 (与 Linux umask 命令非常相似)。此参数在 Windows 中无效。类型:介于 0 和 0777 之间的八进制整数。默认值:022,版本 1.4-22 及更高版本。022 的默认值覆盖组和全球写权限,因此 cfn-hup 守护程序创建的文件在默认情况下不支持组和全球写入。版本 1.4-21 及更低版本的默认值为 0,不覆盖任何值。
interval=<interval> ##用于检查资源元数据更改的时间间隔 (以分钟为单位)
verbose=< verbose> ##指定是否要使用详细日志记录。
hooks.conf 配置文件
cfn-hup 后台程序定期调用的用户操作已在 hooks.conf 配置文件中予以定义。hooks.conf 文件采用以下格式:
[hookname] ##此 hook 的唯一名称
triggers=post.add or post.update or post.remove ##待检测条件的逗号分隔列表。
path=Resources.<logicalResourceId> (.Metadata or .PhysicalResourceId)(.<optionalMetadatapath>)##元数据对象路径。支持元数据块中的随机深度路径。<LogicalResourceId>:监测资源的最新更新时间,触发资源的任何变更。<LogicalResourceId>.PhysicalResourceId:监测资源的物理 ID,仅当已关联资源标识变更时(例如,新的 EC2 实例)发生触发行为。<LogicalResourceId>.元数据(.可选路径):监测资源元数据的变更情况(可将元数据子路径指定为任一深度级别,以便监测特定数值)
action=<arbitrary shell command> ##按照既定运行的任意 shell 程序命令。
runas=<runas user> ##运行命令的用户。Cfn-hup 使用 su 命令切换至用户。
操作运行时,它将在当前环境(cfn-hup 处于其中)的副本中运行,此时 CFN_OLD_METADATA 设定为路径的先前数值,且 CFN_NEW_METADATA 设定为当前值。
hooks.conf仅可通过 cfn-hup 后台程序启动加载,因此需要后台程序才能重新启动新的hook。以前的元数据值的缓存存储在 /var/lib/cfn-hup/data/metadata_db 中,可以删除该缓存以强制 cfn-hup 再次运行所有 post.add 操作。
hooks.d 目录
要通过部署变更通知 hook 支持若干应用程序组合,cfn-hup 要支持位于 hook 配置目录中名为 hooks.d 的目录。可以将一个或多个附加 hook 配置文件置于 hooks.d 目录之中。附加 hook 文件必须使用与 hooks.conf 文件相同的版式。
cfn-hup 后台程序将解析并加载此目录中的所有文件。如果 hooks.d 中的任何 hook 与 hooks.conf 中的 hook 同名,则应将上述 hook 进行合并(表示 hooks.d 将重写 hooks.conf 针对上述两个文件指定的任何数值)。
示例:
在以下模板代码段中,当更改了与 LaunchConfig 资源关联的 AWS::CloudFormation::Init 资源时,AWS CloudFormation 会触发 cfn-auto-reloader.conf hook文件。
...
LaunchConfig:
Type: "AWS::AutoScaling::LaunchConfiguration"
Metadata:
QBVersion: !Ref paramQBVersion
AWS::CloudFormation::Init:
...
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
content: !Sub |
[cfn-auto-reloader-hook]
triggers=post.update
path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init
action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region}
runas=root
mode: "000400"
owner: "root"
group: "root"
...
cfn-get-metadata
cfn-get-metadata 帮助程序脚本从 AWS CloudFormation 中提取元数据块,并将其打印进行标准输出。如果指定了密钥,则还可以打印元数据块的子树。但是,仅支持具有最高级别的密钥。
注意
cfn-get-metadata 无需提供凭证,因此不需要使用 --access-key、--secret-key、--role 或 --credential-file 选项。但是,如果不指定凭证,则 AWS CloudFormation 会检查堆栈成员并将调用范围限制为实例所属的堆栈。
cfn-get-metadata --access-key access.key \
--secret-key secret.key \
--credential-file|f credential.file \
--key|k key \
--stack|-s stack.name.or.id \
--resource|-r logical.resource.id \
--role IAM.role.name \
--url|-u service.url \
--region region
https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/deploying.applications.html