AWS CloudFormation 系列--(1)快速入门
AWS CloudFormation 系列–(1)快速入门
B站视频链接:https://www.bilibili.com/video/BV1Wd4y1i7PE/?spm_id_from=333.999.0.0
微信公众号:自刘地
文章目录
最近打算系统性的整理和分享AWS相关知识,而AWS CloudFormation这服务非常能提高你学习AWS的效率。所以先从这个服务开始介绍,后续我也会经常用到这个服务。
首先提醒一下,AWS CloudFormation需要你具有一定的AWS相关知识,比如在AWS Console上创建过VPC和EC2等资源,因为AWS CloudFormation这个服务,就是用代码的方式来创建资源,如果你不会通过图形化的方式创建,那么很难通过代码的方式来理解。
一、为什么需要AWS CloudFormation服务
利用AWS CloudFormation服务,可以让你通过代码的方式来创建AWS资源,这是AWS的基础架构即代码服务(IaC)。
为什么不在AWS Console界面来创建、删除资源,而是通过代码的方式来操作资源,主要有下面几个优势:
- 容易分享AWS环境给他人。通过代码的方式分享你的AWS环境,可以确保每次部署都是完全相同的,不用担心一些误操作引起的环境差异。当你需要学习一个新的服务时,经常会看到别人已经搭建好了所有的测试环境,并且分享了CloudFormation的代码,学会看这些代码能帮你提高学习效率。例如学习GWLB时看到这篇文档[参考链接1],节约了很多部署环境的时间。
- 可以「批量」操作AWS资源。在AWS CloudFormation代码里面,定义的VPC和EC2等这些资源,形成了一个堆栈(stack),创建或者删除一堆栈,就会自动创建或删除堆栈里面定义的所有资源。这个特点太方便学习做实验了,需要时,一键创建所有实验环境,做完后,一键打扫战场。避免漏删资源而扣费。
- 可以做版本控制。因为AWS CloudFormation都是代码文件,所以可以使用Git来进行版本控制。
二、AWS CloudFormation 模板格式
CloudFormation 模板就是你需要写的代码文件,模板是JSON
或YAML
格式的文本文件,你可以指定任何的扩展名称,例如.txt,后缀名并不会影响内容的读取。
下面是在模板里面定义创建一个VPC,分别用JSON和YAML格式来展现。JSON和YAML格式是可以相互转换的,但是YAML支持注释功能,所以我更习惯使用YAML格式来写模板,之后的CloudFormation模板的代码我都会使用YAML格式来写。
通过JSON
格式来创建一个VPC的代码,不用关心代码里面的字段,后面会讲解。
"MyTestVpc" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : "10.0.0.0/16",
"EnableDnsSupport" : "true",
"EnableDnsHostnames" : "true",
"Tags" : [
{"Key" : "Name", "Value" : "MyTestVpc"}
]
}
}
通过YAML
格式来创建一个VPC的代码。YAML格式写起来更加简单,你可以写单引号、双引号、不写引号,都是一样的。我一般不写引号,除非字符较多,会通过引号来分隔字符。YAML和Python语法一样,不同的层级,通过缩进来区分。
# 创建VPC
MyTestVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: MyTestVpc
三、AWS CloudFormation 模板字段
下面是CloudFormation模板的所有字段,这是快速入门,只介绍最重要的一个字段,其他参考大家可以自己看文档模板格式[参考链接2],以后在其他文章中会陆续介绍这些参数。
Resources
:这是唯一的必选字段,定义模板要创建哪些资源,例如创建VPC、EC2等,模板的主要作用就是定义资源,模板里面其他字段都可以省略,但是必须定义资源字段。
---
AWSTemplateFormatVersion: "version date"
Description:
String
Metadata:
template metadata
Parameters:
set of parameters
Rules:
set of rules
Mappings:
set of mappings
Conditions:
set of conditions
Transform:
set of transforms
Resources:
set of resources
Outputs:
set of outputs
四、AWS CloudFormation 资源字段属性
4.1、实战案例
首先来看最重要的Resources
字段,这个字段下面会有很多属性,而且不同的服务类型,属性参数并不一样。这些属性不需要你刻意去记忆, 主要还是明确需求之后,去查看文档资源和属性类型参考[参考链接3]。
这里通过一个实际的需求来看如何写CloudFormation的模板:创建一个VPC,内部创建一个EC2实例并关联安全组,实例通过IGW访问互联网。
4.2、创建VPC
创建一个VPC,查询VPC这个资源有哪些属性字段,AWS::EC2::VPC[参考链接4]
MyTestVpc
是我起的一个名字,称为逻辑ID,注意命名不能有中横线和下划线。
AWS::EC2::VPC
表示创建的资源类型。资源类型标识符采用这个格式:service-provider::service-name::data-type-name
。
10.0.0.0/16
是为VPC分配的CIDR地址段,这是一个必选属性。创建一个资源时,脑海里面可以回顾AWS Console的操作,一般控制台界面必选的参数,在CloudFormation模板里面也会是必选。如果你需要修改某些特殊属性,但是不知道属性名称,那就需要查看文档了。
Tags
标签参数应该不会陌生,因为可以添加多个标签,-
表示列表,可以添加多个标签。
# 创建一个VPC
MyTestVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Name
Value: MyTestVpc
4.3、创建IGW并关联到VPC
创建IGW并且关联到VPC:AWS::EC2::InternetGateway[参考链接5]
这里创建了一个IGW并且关联到了上面创建的VPC。将IGW关联到VPC时,用到了Ref
这个函数。Ref内部函数[参考链接6]可以返回指定的参数或资源的值。例如你需要查看AWS::EC2::VPC[参考链接4]就可以知道,它返回的是VpcId
信息。
这里使用了Ref函数的短格式写法,可以写在一行!Ref logicalName
,第二部分会专门介绍各种函数的用法。
# 创建IGW
MyTestIgw:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: my-test-igw
# IGW 关联VPC
MyTestAttachIgw:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
VpcId: !Ref MyTestVpc
InternetGatewayId: !Ref MyTestIgw
4.4、创建子网
在VPC里面创建子网:AWS::EC2::Subnet[参考链接7]
这里子网需要指定VpcId
,可以使用Ref内部函数来获取这个信息。
# 在VPC内创建子网
MyTestVpcSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyTestVpc
CidrBlock: 10.0.0.0/24
AvailabilityZone: cn-northwest-1a
Tags:
- Key: Name
Value: my-test-vpc-public-subnet
4.5、路由表操作
在VPC内创建路由表并关联到子网,路由表设置默认路由指向IGW:AWS::EC2::RouteTable、AWS::EC2::Route、AWS::EC2::SubnetRouteTableAssociation
# VPC内创建路由表
MyTestPublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref IpsecTsVpc
Tags:
- Key: Name
Value: my-test-public-route-table
# 路由表关联子网
MyTestRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref MyTestPublicRouteTable
SubnetId: !Ref MyTestVpcSubnet
# 路由表设置默认路由指向IGW
MyTestInternetRoute:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref MyTestPublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyTestIgw
4.6、创建安全组
在VPC内创建一个安全组:AWS::EC2::SecurityGroup
安全组里面数字-1
表示允许所有。
# 在VPC内创建一个安全组
MyTestVpcSg:
Type: AWS::EC2::SecurityGroup
DependsOn: MyTestVpc
Properties:
GroupDescription: SG to test ping
VpcId: !Ref MyTestVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 8443
ToPort: 8443
CidrIp: 0.0.0.0/0
4.7、创建EC2实例
创建一个EC2实例:AWS::EC2::Instance
指定了EC2的AMI ID,可以通过控制台查询AMI ID。需要确认账号下存在MyCN-CloudFormation-Test-Key
这个密钥对信息。设置实例类型为t3.small
。另外接口设置自动获取公网IP地址、因为是第一个主接口,所以编号为0
、接口关联之前创建的安全组、接口放置之前创建的子网内。
# 创建一个EC2实例
MyTestEc2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-003a3de8892ecbc45
KeyName: MyCN-CloudFormation-Test-Key
InstanceType: t3.small
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- Ref: MyTestVpcSg
SubnetId: !Ref MyTestVpcSubnet
五、AWS 控制台创建堆栈(stack)
要将模板的代码实例化,就需要创建堆栈,可以通过AWS控制台、AWS CLI、API,来创建创建、更新、删除堆栈。模板里面所有的资源可以作为一个堆栈进行管理。
前面的内容单独解释每个资源如何创建,现在将这些资源都写到一个模板里面。这个模板中创建了一个VPC,VPC内部创建一个IGW,创建子网并将默认路由指向IGW。最后创建了一个EC2放置在公有子网里面,允许获取公网IP地址。
Resources:
# 创建一个VPC
MyTestVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Name
Value: MyTestVpc
# 创建IGW
MyTestIgw:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: my-test-igw
# IGW 关联VPC
MyTestAttachIgw:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
VpcId: !Ref MyTestVpc
InternetGatewayId: !Ref MyTestIgw
# 在VPC内创建子网
MyTestVpcSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyTestVpc
CidrBlock: 10.0.0.0/24
AvailabilityZone: cn-northwest-1a
Tags:
- Key: Name
Value: my-test-vpc-public-subnet
# VPC内创建路由表
MyTestPublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref MyTestVpc
Tags:
- Key: Name
Value: my-test-public-route-table
# 路由表关联子网
MyTestRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref MyTestPublicRouteTable
SubnetId: !Ref MyTestVpcSubnet
# 路由表设置默认路由指向IGW
MyTestInternetRoute:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref MyTestPublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyTestIgw
# 在VPC内创建一个安全组
MyTestVpcSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SG to test ping
VpcId: !Ref MyTestVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 8443
ToPort: 8443
CidrIp: 0.0.0.0/0
# 创建一个EC2实例
MyTestEc2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-003a3de8892ecbc45
KeyName: MyCN-CloudFormation-Test-Key
InstanceType: t3.small
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- Ref: MyTestVpcSg
SubnetId: !Ref MyTestVpcSubnet
进入AWS CloudFormation控制台,点击创建堆栈,选择使用新资源创建。
选择模板已就绪,上传准备的yaml文件,文件最大支持1MB,AWS会自动创建一个S3桶来存储模板文件。你也可以将模板文件上传到上s3,然后指定s3的路径来调用模板。
通过Designer你可以以图形化的方式来创建、查看和修改模板。我觉得这个Designer做的并不是很直观,仅供参考一下吧。
最后设置堆栈的名称,注意堆栈名称不能有下划线,可以有中横线。
通过【事件】可以查看堆栈创建的进度,如果堆栈创建失败,通过事件输出信息,可以非常容易的定位错误原因。
例如这里我故意将子网的AZ信息写成cn-northwest-1
,少写了一个a
。可以通过【事件】来查看报错信息,状态原因非常明确的说明了错误原因,你可以快速的根据“逻辑ID”来定位是哪个资源有错误,因为逻辑ID就是模板内的资源名称。
另外,当堆栈创建失败的时候,堆栈会自动回滚,将前面所有创建的资源都会删除,全都删除完成后,堆栈状态为ROLLBACK_COMPLETE
,此时可以删除堆栈重新在创建一次。
将AZ信息修改正确后重新部署成功。
查看创建的VPC
查看创建的EC2和安全组
目前已经了解了AWS CloudFormation是如何工作的,有了一个快速了解,后续会继续介绍CloudFormation的内部函数。
六、参考文档
-
**[1] aws-gateway-load-balancer-code-samples:**https://github.com/aws-samples/aws-gateway-load-balancer-code-samples/tree/main/aws-cloudformation/centralized_architecture
-
**[2] AWS 模板格式:**https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/template-anatomy.html
-
**[3] AWS 资源和属性类型参考:**https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
-
[4] AWS CloudFormation AWS::EC2::VPC:https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
-
**[5] AWS CloudFormation AWS::EC2::InternetGateway:**https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html
-
**[6] AWS Ref 内部函数:**https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html
-
**[7] AWS CloudFormation AWS::EC2::Subnet:**https://docs.aws.amazon.com/zh_cn/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html