因公司小项目多,账户多,每次构建aws初始化环境均很麻烦,且每个人操作的时候,想法都不一样,规则不统一,导致环境信息无法通用.
所以准备使用 cf 来构建一个通用模板,保持环境一致性.
之前一直没有使用,是因为 cf 本身编写不是太方便,然而我低估了 aws 的牛逼,仔细看了文档才知道, 有个 cf 本身有个堆栈,可以直接复刻当前环境.
这个工具就是
cloudformer
那么步骤来了~
-
先通过 web 控制台生成一个适合本地化的通用环境,比如 vpc,子网,安全组,数据库子网组,参数组,s3以及相应的s3生命周期规则等等
-
构建 cloudformer 堆栈,并通过 cloudformer 服务生成当前环境模板
-
将当前环境模板的一些非通用内容,换成变量,并构建成 cf 参数或者脚本
-
最后通过执行脚本,并输入变量值,来生成新模板
-
在新环境里调用新模板来初始化环境
下面是我贴出的一个基础环境生成脚本
-
vpc: x.x.0.0/16
-
prod: x.x.128.0/17
- prod 子网默认有四个, 分别是 EC2 两个可用区, Database 两个可用区
-
qa: x.x.0.0/19
- qa 子网默认有四个, 分别是 EC2 两个可用区, Database 两个可用区
-
prod 和 qa 通过安全组来分割
-
prod 规则示例如下(qa一样):
-
Prod-EC2-common:
规则名 协议 开放端口 源ip或者其它安全组ID 所有流量 全部 全部 10.130.128.0/17
| SSH | TCP | 22 | ${src_allow_ssh_ip} | |
-
Prod-Database-common:
规则名 协议 开放端口 源ip或者其它安全组ID 自定义 TCP 规则 TCP 1025 - 65535 ${src_allow_rds_ip} 自定义 TCP 规则 TCP 1025 - 65535 Prod-EC2-common-Group-ID
-
-
SNS 默认预警主题
-
mysql 子网组
-
redis 子网组
-
s3以及初始化生命周期规则
-
vpc 路由表不会添加默认路由, 还请自行添加(Internet 网关会自动生成)
#!/bin/bash
# 本脚本用来生成一份基础环境的 cf 模板
# 网络A和B段,例如 10.10 那么 vpc 就是 10.10.0.0/16
VpcCidrBlockAB=
# 大区区域, 例如 新加坡 那么区域就写 ap-southeast-1
Region=
# 项目名,用于区分资源以及添加 Team 标签 (只能是字母数字组合)
TagTeamValue=
# 允许访问EC2的22号端口的ip (指的是非vpc内网),通常应该是堡垒机或者公司外网
src_allow_ssh_ip=
# 允许访问数据库端口的ip (指的是非vpc内网),通常应该是堡垒机或者公司外网
src_allow_rds_ip=
# 默认 SNS 服务主体名 SNSThemeName
SNSThemeName=${TagTeamValue}
# 默认 SNS 服务信息接收用户邮箱, cf 模板执行完后,需要用户邮箱读取邮件自行确认消息
SNSEmail=
# 设置 vpc 任意两个可用区 字母标识, 比如 a b
AvailabilityZoneOne=a
AvailabilityZoneTwo=b
######## 本模板, 不会添加 vpc 默认路由, 请自行加 #########
cat > cf-common.yml << EOF
AWSTemplateFormatVersion: 2010-09-09
Resources:
vpc12345:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: ${VpcCidrBlockAB}.0.0/16
InstanceTenancy: default
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Name
Value: ${TagTeamValue}
Metadata:
'AWS::CloudFormation::Designer':
id: 84f85642-9390-4126-b347-95ca2ebf1c15
subnet0qa0database0${AvailabilityZoneOne}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.3.0/24
AvailabilityZone: ${Region}${AvailabilityZoneOne}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-qa-database-${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 864ecf93-1ce6-4b4d-9b29-c3d89f07141b
subnet0prod0database0${AvailabilityZoneOne}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.131.0/24
AvailabilityZone: ${Region}${AvailabilityZoneOne}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-prod-database-${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 7ef6daea-3bcd-4913-ab55-ba4f7bced319
subnet0qa0ec20${AvailabilityZoneTwo}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.2.0/24
AvailabilityZone: ${Region}${AvailabilityZoneTwo}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-qa-ec2-${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: bc2b5a08-f7b8-4699-a7ba-5c9c6c021bd8
subnet0qa0database0${AvailabilityZoneTwo}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.4.0/24
AvailabilityZone: ${Region}${AvailabilityZoneTwo}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-qa-database-${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: b4738f0a-11a6-4d75-b9f0-a24072e53228
subnet0prod0ec20${AvailabilityZoneTwo}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.129.0/24
AvailabilityZone: ${Region}${AvailabilityZoneTwo}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-prod-ec2-${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 2ffb24f6-49fd-4d3a-bdfe-69e90e228517
subnet0prod0ec20${AvailabilityZoneOne}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.128.0/24
AvailabilityZone: ${Region}${AvailabilityZoneOne}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-prod-ec2-${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 9a2789fc-b7d2-4532-811b-be3455ab7d7d
subnet0qa0ec20${AvailabilityZoneOne}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.1.0/24
AvailabilityZone: ${Region}${AvailabilityZoneOne}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-qa-ec2-${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 5c6c2638-a7b5-4185-a7a3-08d5901c252a
subnet0prod0database0${AvailabilityZoneTwo}:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock: ${VpcCidrBlockAB}.132.0/24
AvailabilityZone: ${Region}${AvailabilityZoneTwo}
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: ${TagTeamValue}-prod-database-${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 00a78a8b-fd72-4613-bf09-8319b876ba2b
igw088b65cb430bc5ca0:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Name
Value: ${TagTeamValue}-internet-gw
Metadata:
'AWS::CloudFormation::Designer':
id: e60ac13b-274d-46db-ac2a-5afaf975e1eb
dopt8128ece5:
Type: 'AWS::EC2::DHCPOptions'
Properties:
DomainName: ${Region}.compute.internal
DomainNameServers:
- AmazonProvidedDNS
Metadata:
'AWS::CloudFormation::Designer':
id: 909e6481-ccca-40fe-a1b1-4abe15a2ba18
acl03e81a4f65756520d:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref vpc12345
Metadata:
'AWS::CloudFormation::Designer':
id: 93e06538-fe9e-49a7-8549-e2efb97dfab7
dbsubnet${TagTeamValue}prod:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
DBSubnetGroupDescription: ${TagTeamValue}-prod
SubnetIds:
- !Ref subnet0prod0database0${AvailabilityZoneTwo}
- !Ref subnet0prod0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 16096ba6-c5de-4a73-a083-07b2c0573362
dbsubnet${TagTeamValue}qa:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
DBSubnetGroupDescription: ${TagTeamValue}-qa
SubnetIds:
- !Ref subnet0qa0database0${AvailabilityZoneTwo}
- !Ref subnet0qa0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 186893f8-59ef-4d56-880f-d62294d25780
dbpg${TagTeamValue}prod:
Type: 'AWS::RDS::DBParameterGroup'
Properties:
Description: ${TagTeamValue}-prod-mysql5.6
Family: mysql8.0
Parameters:
binlog_cache_size: '32768'
binlog_format: MIXED
character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_filesystem: utf8mb4
character_set_results: utf8mb4
character_set_server: utf8mb4
collation_connection: utf8mb4_general_ci
explicit_defaults_for_timestamp: '1'
innodb_buffer_pool_size: '{DBInstanceClassMemory*3/4}'
innodb_file_per_table: '1'
innodb_flush_method: O_DIRECT
Metadata:
'AWS::CloudFormation::Designer':
id: 87a954ed-d1b2-4626-87fe-f2515f4479b4
dbpg${TagTeamValue}qa:
Type: 'AWS::RDS::DBParameterGroup'
Properties:
Description: ${TagTeamValue}-qa-mysql5.6
Family: mysql8.0
Parameters:
binlog_cache_size: '32768'
binlog_format: MIXED
character_set_client: utf8
character_set_connection: utf8
character_set_database: utf8
character_set_filesystem: utf8
character_set_results: utf8
character_set_server: utf8
collation_connection: utf8_general_ci
explicit_defaults_for_timestamp: '1'
innodb_buffer_pool_size: '{DBInstanceClassMemory*3/4}'
innodb_file_per_table: '1'
innodb_flush_method: O_DIRECT
Metadata:
'AWS::CloudFormation::Designer':
id: 6c4c2e1e-ec99-4e7f-b254-0f09145a0d87
cachesubnet${TagTeamValue}databaseprod:
Type: 'AWS::ElastiCache::SubnetGroup'
Properties:
Description: '${TagTeamValue}_prod'
SubnetIds:
- !Ref subnet0prod0database0${AvailabilityZoneTwo}
- !Ref subnet0prod0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: bdfb3d49-78d8-40df-84b6-63bf65616f5c
cachesubnet${TagTeamValue}databaseqa:
Type: 'AWS::ElastiCache::SubnetGroup'
Properties:
Description: '${TagTeamValue}_qa'
SubnetIds:
- !Ref subnet0qa0database0${AvailabilityZoneOne}
- !Ref subnet0qa0database0${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 70367616-0a11-4bc9-9373-a23be1690a59
topicIT:
Type: 'AWS::SNS::Topic'
Properties:
DisplayName: ${SNSThemeName}
Subscription:
- Endpoint: ${SNSEmail}
Protocol: email
Metadata:
'AWS::CloudFormation::Designer':
id: 343cc3f4-4380-47e5-850e-cc3fb560f22a
${TagTeamValue}qacommon:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: ${TagTeamValue}-qa-common
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: QA-EC2-common,Don't modify me
Metadata:
'AWS::CloudFormation::Designer':
id: d31db020-e702-41e5-8ccc-d71a5a26f565
${TagTeamValue}prodcommon:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: ${TagTeamValue}-prod-common
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: Prod-EC2-common,Don't modify me
Metadata:
'AWS::CloudFormation::Designer':
id: f54456ef-e984-4b00-b04d-64b16a2057ea
ITLinshi:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: IT-Linshi
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: I'm god
Metadata:
'AWS::CloudFormation::Designer':
id: 182b7e60-f895-4519-8845-4d32a8591340
${TagTeamValue}proddatabase:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: ${TagTeamValue}-prod-database
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: Prod-database-common,Don't modify me
Metadata:
'AWS::CloudFormation::Designer':
id: 44f0485a-2575-4eab-82b3-bc7507cd5820
${TagTeamValue}qadatabase:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: ${TagTeamValue}-qa-database
VpcId: !Ref vpc12345
Tags:
- Key: Name
Value: QA-database-common,Don't modify me
Metadata:
'AWS::CloudFormation::Designer':
id: f903102a-c394-4301-a08d-5625293ac23f
snspolicyIT:
Type: 'AWS::SNS::TopicPolicy'
Properties:
Topics:
- !Ref topicIT
PolicyDocument:
Version: 2008-10-17
Id: __default_policy_ID
Statement:
- Sid: __default_statement_ID
Effect: Allow
Principal:
AWS: '*'
Action:
- 'SNS:GetTopicAttributes'
- 'SNS:SetTopicAttributes'
- 'SNS:AddPermission'
- 'SNS:RemovePermission'
- 'SNS:DeleteTopic'
- 'SNS:Subscribe'
- 'SNS:ListSubscriptionsByTopic'
- 'SNS:Publish'
- 'SNS:Receive'
Resource: !Ref topicIT
Condition:
StringEquals:
'AWS:SourceOwner': '705452591009'
Metadata:
'AWS::CloudFormation::Designer':
id: 66a45d1a-3c99-4ef8-9c4e-db9ba717e17e
acl1:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
CidrBlock: 0.0.0.0/0
Egress: 'true'
Protocol: '-1'
RuleAction: allow
RuleNumber: '100'
NetworkAclId: !Ref acl03e81a4f65756520d
Metadata:
'AWS::CloudFormation::Designer':
id: de76822e-cddc-40d9-ba6f-4de20d1188ec
acl2:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
CidrBlock: 0.0.0.0/0
Protocol: '-1'
RuleAction: allow
RuleNumber: '100'
NetworkAclId: !Ref acl03e81a4f65756520d
Metadata:
'AWS::CloudFormation::Designer':
id: eb6e0bf9-3c84-4991-a037-64e2a368650b
subnetacl1:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0prod0ec20${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 2801f8a7-901b-43b6-b4d9-9275d5639b86
subnetacl2:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0qa0ec20${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 67641cac-39f6-4ee1-8410-60eaba963c27
subnetacl3:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0qa0ec20${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 4b480f9d-e7b8-4034-b253-1c254fd83758
subnetacl4:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0qa0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 1792de63-b1da-4c31-bab9-9925de98de6c
subnetacl5:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0prod0database0${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: e62f3e81-63f0-4f5e-b3e0-aa733ba6f323
subnetacl6:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0prod0ec20${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: 28228fcf-5649-4e5e-bf03-d636ca28bffe
subnetacl8:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0qa0database0${AvailabilityZoneTwo}
Metadata:
'AWS::CloudFormation::Designer':
id: 00ab0d37-3e37-427e-ac06-e94663719fcf
subnetacl9:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0qa0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: ee93485d-3df4-416d-ab61-4f77c46441f1
subnetacl10:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref acl03e81a4f65756520d
SubnetId: !Ref subnet0prod0database0${AvailabilityZoneOne}
Metadata:
'AWS::CloudFormation::Designer':
id: a4208016-e7cf-4acf-a718-104a25fef4c3
gw1:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref vpc12345
InternetGatewayId: !Ref igw088b65cb430bc5ca0
Metadata:
'AWS::CloudFormation::Designer':
id: 3071b8a9-f4ab-4d61-83d8-d2792481e135
dchpassoc1:
Type: 'AWS::EC2::VPCDHCPOptionsAssociation'
Properties:
VpcId: !Ref vpc12345
DhcpOptionsId: !Ref dopt8128ece5
Metadata:
'AWS::CloudFormation::Designer':
id: 69a63971-39fa-45c9-8a17-cc730730083d
ingress1:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}qacommon
IpProtocol: '-1'
CidrIp: ${VpcCidrBlockAB}.0.0/19
ingress2:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}prodcommon
IpProtocol: '-1'
CidrIp: ${VpcCidrBlockAB}.128.0/17
ingress3:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}proddatabase
IpProtocol: tcp
FromPort: '1025'
ToPort: '65535'
SourceSecurityGroupId: !Ref ${TagTeamValue}prodcommon
SourceSecurityGroupOwnerId: '705452591009'
Metadata:
'AWS::CloudFormation::Designer':
id: 8972689f-9301-4538-b493-bd1956559ecd
ingress4:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}qadatabase
IpProtocol: tcp
FromPort: '1025'
ToPort: '65535'
SourceSecurityGroupId: !Ref ${TagTeamValue}qacommon
SourceSecurityGroupOwnerId: '705452591009'
Metadata:
'AWS::CloudFormation::Designer':
id: 236a8060-da9c-4be7-af29-fb6758a764a9
ingress5:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ITLinshi
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
ingress6:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}qacommon
IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: ${src_allow_ssh_ip}
ingress8:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}prodcommon
IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: ${src_allow_ssh_ip}
ingress11:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}proddatabase
IpProtocol: tcp
FromPort: '1025'
ToPort: '65535'
CidrIp: ${src_allow_rds_ip}
ingress14:
Type: 'AWS::EC2::SecurityGroupIngress'
Properties:
GroupId: !Ref ${TagTeamValue}qadatabase
IpProtocol: tcp
FromPort: '1025'
ToPort: '65535'
CidrIp: ${src_allow_rds_ip}
egress1:
Type: 'AWS::EC2::SecurityGroupEgress'
Properties:
GroupId: !Ref ${TagTeamValue}qacommon
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
egress2:
Type: 'AWS::EC2::SecurityGroupEgress'
Properties:
GroupId: !Ref ${TagTeamValue}prodcommon
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
egress3:
Type: 'AWS::EC2::SecurityGroupEgress'
Properties:
GroupId: !Ref ITLinshi
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
egress4:
Type: 'AWS::EC2::SecurityGroupEgress'
Properties:
GroupId: !Ref ${TagTeamValue}proddatabase
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
egress5:
Type: 'AWS::EC2::SecurityGroupEgress'
Properties:
GroupId: !Ref ${TagTeamValue}qadatabase
IpProtocol: '-1'
CidrIp: 0.0.0.0/0
Description: ''
EOF