CloudFormation
关于CloudFormation Template
Template就是一个text文本文件,文件内容的格式是json或yaml
Template里声明了要在Amazone创建或配置的resource,这些resource相互关联,组成了stack
Template声明顶层对象包括以下:
-
AWSTemplateFormatVersion:可选
-
Description:可选
-
Parameters:可选
-
Mappings:可选
-
Resources:必须,Template至少要声明一个resource
-
Outputs:可选
AWSTemplateFormatVersion对象
用于指定Template的版本,如果不指定,则CloudFormation会使用最新的版本
Description对象
用于对Template添加描述信息,可以是任何json或yaml格式的文本
Parameters对象
用于声明向Template传递的参数
通过参数,可以避免将敏感信息嵌入到template里
Parameters对象可以包含多个parameter对象,每个parameter对象又可以有多个attribute,其中type attribute是必须项
Default attribute表示默认值,Default attribute如果没有指定,则必须通过参数传递过来,否则创建stack时会报错
NoEcho
通过指定NoEcho attribute为true,可以将返回的参数信息做Data Masking处理(****)
NoEcho不会对以下attribute做Data Masking处理
-
Metadata Section,CloudFormation不会对metadata里的任何信息做转换,修改或编辑处理
-
Outputs Section
-
Resouce Section的metadata attribute
注:强烈建议不要直接在CloudFormation Template里嵌入敏感信息(密码,验证信息等),可将敏感信息存储在Template之外(比如Amazon Systems Manager Parameter Store 或者Amazon Secrets Manager),再将敏感信息以动态传参的方式传入Template
参数的类型为以下:
-
String
-
Number
-
Amazon的特定类型
通过以下两种方式验证参数的有效性:
-
声明约束(constraints)
参数若是String类型,可以使用以下Attribute用于约束
-
MinLength
-
MaxLength
-
Default
-
AllowedValues
-
AllowedPattern
参数若是Number类型,数字可以是整型或浮点型,可以使用以下Attribute用于约束
- MinValue
- MaxValue
- Default
- AllowedValues
-
-
为parameter的type attribute 指定Amazon的特定类型
参数若是Amazon的特定类型,CloudFormation在创建stack资源之前,会根据用户帐户和要创建的stack的区域中的现有值验证参数值
Resources对象
Resources对象至少要包含一个reosurce对象
每一个resource对象都有对应的attribute,其中type attribute是必须的
每个attribute都是resource的子对象,它们都是自描述的
type attribute的格式是:
AWS::ProductIdentifier::ResourceType
比如Amazon S3 bucket的resource type是
AWS::S3::Bucket
不同type的resource会有不同的attribute,它们有的是必须的,有的是可选的,要根据实际情况而定,当没有显式的指定时,会使用默认值
比如创建bucket时,如果没有指定其他的attribute,则CloudFormation会使用默认值的设置这些attribute
Resources:
HelloBucket:
Type: AWS::S3::Bucket
在resource的声明里,可以使用Properties attribute来指定创建resource时需要的一些信息
不同type的resource可以有不同的property
每个resource的Properties可以有多个子项,每个子项的值都是string,比如:
Resources:
HelloBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
CloudFormation Template可以创建多个resource,这些resource可以相互配合工作从而搭建起一个应用或解决方案
resource声明里的名称是逻辑名称,当CloudFormation创建这些resource时,会将逻辑名,stack名和unique id拼接起来作为这些资源的物理名
以下attribute是可以在任何resource里作为可选attribute
-
DependsOn:用于指定该resource依赖于哪个resource
-
DeletionPolicy : 用于指定CloudFormation如何执行删除resource操作
-
Metadata:用于指定使用resource构建的结构化数据
Mappings对象
类似java里的switch分支语句,可以根据需要,通过不同的输入值返回不同的结果
需要使用FindInMa函数
Mappings:
RegionMap:
us-east-1:
AMI: ami-76f0061f
us-west-1:
AMI: ami-655a0a20
eu-west-1:
AMI: ami-7fd4e10b
ap-southeast-1:
AMI: ami-72621c20
ap-northeast-1:
AMI: ami-8e08a38f
Resources:
Ec2Instance:
Type: 'AWS::EC2::Instance'
Properties:
KeyName: !Ref KeyName
ImageId: !FindInMap
- RegionMap
- !Ref 'AWS::Region'
- AMI
UserData: !Base64 '80'
伪参数
AWS::Region
用于获取创建stack所在的region
AWS::CloudFormation::Stack
将其他stack作为一个resource嵌入到template中
函数
!Ref函数
用于指定某一个resource
Parameters:
KeyName:
Description: The EC2 Key Pair to allow SSH access to the instance
Type: 'AWS::EC2::KeyPair::KeyName'
Resources:
Ec2Instance:
Type: 'AWS::EC2::Instance'
Properties:
SecurityGroups:
- !Ref InstanceSecurityGroup
- MyExistingSecurityGroup
KeyName: !Ref KeyName
ImageId: ami-7a11e213
InstanceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Enable SSH access via port 22
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
!GetAZs函数
用于获取一个region下所有可用的zones列表
!GetAtt函数
用于获取resource的指定attribute
有两个参数,第一个参数是要获取attribute所在的resource,第二个参数是想要获取的resource的attribute
Resources:
myBucket:
Type: 'AWS::S3::Bucket'
myDistribution:
Type: 'AWS::CloudFront::Distribution'
Properties:
DistributionConfig:
Origins:
- DomainName: !GetAtt
- myBucket
- DomainName
Id: myS3Origin
S3OriginConfig: {}
Enabled: 'true'
DefaultCacheBehavior:
TargetOriginId: myS3Origin
ForwardedValues:
QueryString: 'false'
ViewerProtocolPolicy: allow-all
!FindInMap函数
用于匹配mapping的值
!Join函数
用于拼接值
有两个参数,第一个参数是拼接符,第二个参数是一个数组
返回结果是用第一个参数表示的拼接符,按照第二个参数表示的数组中元素的顺序将各个元素拼接起来
例:
HealthCheck:
Target: !Join
- '-'
- - 123
- 456
- 789
结果:Target的值是123-456-789
!ImportValue函数
引用其他stack导出的resource
更新Template
Template中的resource是可以更新的
基本操作就是在本地将Template更新好后,通过console上传,CloudFormation会查看并更新stack
CloudFormation只会对更新部分做更新,未更新部分仍会保持原样
当更新Template时,需要考虑以下几点:
- 当需要更新resource时,是否会对resource本身后者其他关联的resource有影响,比如更新instance type时,需要先停止instance然后再启动,这样可能就会对业务有影响
- 确定更新是可变还是不可变的,一些resource的property的更新是不被底层的服务支持的;如果property支持更新,则底层服务使用modify或update类型的api;如果property不支持更新,则会用更新的属性创建新的resource,并链接到stack中,最后删除就的resource;在stack重新配置期间,应用将无法完全运行,比如请求和后台访问等
Security
Cloud Security是Amazone最高的层级的Security
技巧
模块化组织stack
最好不要将所有的resource都放到一个stack中,最好按照不同的目的将resource分类,不同的类别放到放到不同的stack中
组织stack的方式有以下两种:
-
多层架构
就是将所有stack组织划分成各个层级,每个层级都各自依赖于其他层级,每个层级又可以有多个stack
-
面向服务架构(SOA)
根据业务逻辑,将不同的业务划分为不同的service,然后根据需求将不同的service整合到同一个stack中,这些stack之间相互协同
使用跨stack引用导出共享resource
如果一个stack中需要使用另外一个stack里的resource,可以通过hard code或参数的方式实现,但是这样会使Template的维护变得困难
如果通过跨stack引用的方式,将一个stack中的resource导出,这样其他stack就可以引用导出的resource了
使用ImportValue函数可以其他stack导出的resource
验证所有类型reource的配额
在启动stack之前,需要确保所创建的所有resource不要超过账户对应的resource上限
比如,默认一个账号在一个region可创建最多200个stack,但如果该账号创建的stack数超过了200,则CloudFormation在创建这些stack时会失败,直到把账号的200个stack上限提高
多环境下复用Template
Template在dev环境开发好后,还要在tst环境测试,并最终发布到prd环境
但是不同的环境下,设置可能会有不同,比如dev环境所需要的配置可能会低于prd或tst环境,但环境配置外的部分应该都是不变的
因此,将配置部分通过参数,mapping等方式做自定义化,这样同一个Template可以在三个环境同时使用了
使用模块复用resource配置
随着使用资源不断增长,可以将一些共通的组件整合到一起,使用Modules是一个很好的方式
使用Amazon特定的参数类型
如果Template要求既存的Amazon特定值作为参数,则使用Amazone特定的参数类型,这样CloudFormation可以很快的通过验证
使用参数约束
通过使用参数约束,CloudFormation可以捕捉到不合法的参数
使用AWS::CloudFormation::Init来发布软件应用到EC2实例
使用最新版本的helper scripts
使用Template前先验证
使用Template创建stack之前,请先通过CloudFormation验证下Template是否有错误,包括语法错误,依赖关联等
CloudFormation 首先先验证Template是否是合格的json格式,如果不是则验证是否是合格的yaml格式,若都不是,则会返回验证错误
验证Template是否符合公司的安全要求
通过CloudFormation来管理所有stack资源
不要通过CloudFormation之外更新调整resource,这样会使用=resource和Template的描述不一致,从而导致通过Template更新resource时会报错
在更新stack前创建change set
更新stack之前创建change set,即可通过检查change set确定本次更新是否符合预期及评估影响
使用stack policy
使用stack policy可以防止一些重要的resource不被更新,因为有些重要的resource更新时会影响业务
比如数据库实例,更新是会停止运行
stack policy就是一个json文档,用于描述在哪些resource上会执行哪些操作
在stack更新过程中,必须显式的指定哪些被保护的resource是要被更新的,否则这些被保护的resource是不会被更新的
通过代码review及版本控制管理Template
像管理代码源文件一样,管理Template
review Template可确保质量,同时确保历史各个时期版本的完整,保证出问题时可以追根朔源
定期更新EC2 linux实例
对于所有EC2 linux实例以及通过CloudFormation创建的EC2 linux实例,要定期通过yum update命令更新,确保获得最新的版本