一 概述
AWS CloudFormation是一项AWS的托管服务,可用于以声明性模板的形式定义和配置AWS基础设施。它允许您以编程方式创建、更新和管理AWS资源,而无需手动操作。
利用AWS CloudFormation,您可以使用模板定义整个基础设施堆栈,包括计算资源(例如Amazon EC2实例)、存储资源(例如Amazon S3存储桶)和网络资源(例如Amazon VPC)。一旦定义了模板,您可以使用CloudFormation服务创建和管理基础设施堆栈,这样可以确保环境的一致性和可重复性。
以下是利用AWS CloudFormation进行基础设施管理的一般步骤:
二 目标
- 在 YAML 中构建 AwS cloudFormation 模板以定义基础设施资源。
- 创建CloudFormation 堆栈以预置基础架构并查看输出。
- 检测 AWS CloudFormation 堆栈中的偏差并生成偏差报告。
- 使用 AwS cloudFormation 更改集更新您的基础设施。
三 场景
在本实验中,您的任务是为开发团队创建一个简单的环境。开发团队要求打造一个可以通过 HTTP 和 SSH 访问的 Apache Web 服务器。根据提供给您的要求文档,您需要一个专用 VPC、单个子网,以及一个小型 Amazon Elastic Compute Cloud (Amazon EC2) 实例。您将使用 AwS cloud9 环境来修改现有 AwS cloudFormation 模板,以满足开发团队的要求,修改模板以使用 CloudFormation 的变更集和检测偏差功能。
首先,使用 Aws cloud9 修改 Aws cloudFormation 模板,以便构建简单的 Amazon Virtual Private cloud (Amazon vPc) 环境,并部署一个包含简单网页的 web 服务器。其次,验证网页是否正常渲染,然后手动修改 AWS Identity and Access Management (IAM)安全组,并使用 Detect drift 命令来检测更改。最后,创建一个更改集,以便将子网添加到环境中。
四 实战操作
登陆Cloud9:ap-south-1.console.aws.amazon.com/cloud9/ide/…
在本任务中,您将连接到 AWS Cloud9 集成开发环境 (IDE, Integrated Development Environment)。
Cloud9 开发环境预先打包了适用于 40 多种编程语言的 AWS CLI 和工具。在此任务中,您将验证是否已安装 AWS CLl。
查看aws cli版本
查看lab1.yaml内容
AWSTemplateFormatVersion: 2010-09-09
Description: >-
AWS CloudFormation Simple Infrastructure Template
VPC_Single_Instance_In_Subnet: This template will show how to create a VPC and
add an EC2 instance with an Elastic IP address and a security group.
Parameters:
VPCCIDR:
Description: CIDR Block for VPC
Type: String
Default: 10.199.0.0/16
AllowedValues:
- 10.199.0.0/16
PUBSUBNET1:
Description: Public Subnet 1
Type: String
Default: 10.199.10.0/24
AllowedValues:
- 10.199.10.0/24
## TASK 1.1 - BEGIN: Add the parameter definition for InstanceType
InstanceType:
Description: WebServer EC2 instance type
Type: String
Default: t2.nano
AllowedValues:
- t2.nano
- t2.micro
- t2.small
ConstraintDescription: must be a valid EC2 instance type.
## TASK 1.1 - END
LatestAmiId:
Description: Find the current AMI ID using System Manager Parameter Store
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: CF lab environment
Subnet:
Type: 'AWS::EC2::Subnet'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PUBSUBNET1
MapPublicIpOnLaunch: 'true'
AvailabilityZone: !Select
- '0'
- !GetAZs ''
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: Public Subnet
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
DependsOn: VPC
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
DependsOn: VPC
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
## Route resource
# TASK 1.2- BEGIN: Add the resource definition for ROUTE
Route:
Type: 'AWS::EC2::Route'
DependsOn:
- VPC
- AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
# TASK 1.2 - END
SubnetRouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
DependsOn:
- VPC
- InternetGateway
Properties:
SubnetId: !Ref Subnet
RouteTableId: !Ref RouteTable
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
DependsOn:
- VPC
- InternetGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '22'
To: '22'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
OutBoundHTTPSNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '443'
To: '443'
OutBoundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
DependsOn:
- VPC
- InternetGateway
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
SubnetNetworkAclAssociation:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet
NetworkAclId: !Ref NetworkAcl
IPAddress:
Type: 'AWS::EC2::EIP'
DependsOn: AttachGateway
Properties:
Domain: vpc
InstanceId: !Ref WebServerInstance
InstanceSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
VpcId: !Ref VPC
GroupDescription: Enable HTTP via port 80
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
# TASK 4.1 - BEGIN: Change IP Range to 0.0.0.0/0
CidrIp: 1.1.1.1/32
# TASK 4.1 - END
WebServerInstance:
Type: 'AWS::EC2::Instance'
DependsOn: AttachGateway
Metadata:
Comment: Install a simple application
'AWS::CloudFormation::Init':
config:
packages:
yum:
httpd: []
files:
/var/www/html/index.html:
content: !Join
- |+
- - >-
<h1>Congratulations, you have successfully deployed a simple
infrastructure using AWS CloudFormation.</h1>
mode: '000644'
owner: root
group: root
/etc/cfn/cfn-hup.conf:
content: !Join
- ''
- - |
[main]
- stack=
- !Ref 'AWS::StackId'
- |+
- region=
- !Ref 'AWS::Region'
- |+
mode: '000400'
owner: root
group: root
/etc/cfn/hooks.d/cfn-auto-reloader.conf:
content: !Join
- ''
- - |
[cfn-auto-reloader-hook]
- |
triggers=post.update
- >
path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
- 'action=/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- |
runas=root
mode: '000400'
owner: root
group: root
services:
sysvinit:
httpd:
enabled: 'true'
ensureRunning: 'true'
cfn-hup:
enabled: 'true'
ensureRunning: 'true'
files:
- /etc/cfn/cfn-hup.conf
- /etc/cfn/hooks.d/cfn-auto-reloader.conf
Properties:
InstanceType: !Ref InstanceType
ImageId: !Ref LatestAmiId
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
- Key: Name
Value: Lab Host
NetworkInterfaces:
- GroupSet:
- !Ref InstanceSecurityGroup
AssociatePublicIpAddress: 'true'
DeviceIndex: '0'
DeleteOnTermination: 'true'
SubnetId: !Ref Subnet
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash -xe
- |
yum update -y aws-cfn-bootstrap
- '/opt/aws/bin/cfn-init -v '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
- '/opt/aws/bin/cfn-signal -e $? '
- ' --stack '
- !Ref 'AWS::StackName'
- ' --resource WebServerInstance '
- ' --region '
- !Ref 'AWS::Region'
- |+
CreationPolicy:
ResourceSignal:
Timeout: PT15M
##Outputs
Outputs:
MySecurityGroup:
Description: Application instance's security group name
Value:
!GetAtt
- InstanceSecurityGroup
- GroupId
# TASK 1.3 - BEGIN: Add the output definition for URL
AppURL:
Description: Newly created application URL
Value: !Sub 'http://${WebServerInstance.PublicIp}'
# TASK 1.3 - END
- Description(描述):描述模板的文本字符串。
- Parameters(参数):创建或更新堆栈时在运行时传递给模板的值。
- Resources(资源):指定堆栈资源及其属性。
- Outputs(输出):堆栈运行成功完成后,作为堆栈属性返回的值。
AWS CloudFormation 可以提供一种通用语言,供您在云环境中对资源进行建模和预置。您可以使用 CloudFormation 模板语言(YAML或 JSON 格式)对基础设施进行编码。
YAML 和 JSON 都是数据序列化语言,但具有不同的功能。AwS cloudFormation 仅处理 JSON 格式的语言;启动堆栈创建时,YAML格式的模板会被转换为JSON 格式的模板。
- 构建
aws cloudformation create-stack --stack-name Lab1 --parameters ParameterKey=InstanceType,ParameterValue=t2.micro --template-body file://lab1.yaml
create-stack 命令可以调用指定的 AWS CloudFormation 模板并启动堆栈创建流程。参数 InstanceType 告知 CloudFormation 要部署的 Amazon EC2 实例的大小。
成功运行 create-stack 命令后,系统将在命令行中返回 Stackld。
- 验证stack状态
aws cloudformation describe-stacks --stack-name Lab1
注意:describe-stacks 命令会向终端返回大量信息。它会提供模板定义的每个资源的相关信息、构建流程中的当前状态以及您在运行 describe-stacks 命令时可用的资源的特定属性。AWS CloudFormation 控制面板会以更友好的格式提供这些信息。
CREATE_COMPLETE 状态代码表示堆栈创建过程已完成。
此时访问ip无法访问,因为安全中未正确放行端口
手动添加we端口放行
查看网页可以正常查看
由于手动通过web修改配置于基础设施代码发生不一致,通过web进行偏差检测。
查看偏差结果
通过偏差检测,您可以检测堆栈的实际配置是否与其预期配置不同。如果某个资源的任何实际属性值与预期的属性值不同,则认为该资源已发生偏差。这包括是否已删除属性或资源。在本实验中,您可以手动更改资源的值。解决这一偏差的最直接的方法是手动将资源修改回预期值。如果更改是因部署其他堆栈造成的,则回滚其他堆栈的更改。如果别无他法,可以删除堆栈,重新部署,但这种方法的破坏性最大。有关偏差的更多信息,请访问此链接:检测对堆栈和资源做出的非托管配置更改,通过CLI 验证 APPURL 是否正常运行。
aws cloudformation describe-stack-resource-drifts --stack-name Lab1 --stack-resource-drift-status-filters MODIFIED DELETED
- 使用更改集更新堆栈
- 创建更改集
aws cloudformation create-change-set --stack-name Lab1 --change-set-name Lab1ChangeSet --parameters ParameterKey=InstanceType,ParameterValue=t2.micro --template-body file://lab1-CS.yaml
预期输出:
五 总结
AWS CloudFormation是一种基础设施即代码(Infrastructure as Code)服务,它允许用户以声明性的方式定义和管理AWS基础设施资源。通过编写模板,用户可以描述他们想要创建的资源以及资源之间的关系和配置。然后,通过CloudFormation服务,用户可以创建、更新和删除这些资源的堆栈。
使用CloudFormation的好处之一是它的可扩展性。用户可以在模板中定义多个资源,包括虚拟私有云(VPC)、子网、负载均衡器、数据库实例等等。通过一次性部署整个堆栈,可以确保资源之间的正确关联和配置,减少了手动部署和配置的错误。
另一个优点是CloudFormation的自动化特性。一旦定义了模板,用户可以使用API、CLI或控制台工具自动创建和管理堆栈。这意味着可以轻松地进行重复部署、跨不同环境的迁移以及快速恢复操作。此外,CloudFormation还支持版本控制和回滚功能,使得管理和追踪基础设施变更变得更加容易和可控。