aws_0">aws(学习笔记第十二课)
- 使用AWS的
RDS
学习内容:
- AWS的
RDS
-MySQL
1. 使用AWS的RDS
-
什么是
RDS
RDS
就是Relation Database Service
的缩写,是AWS
提供的托管关系型数据库系统。让用户能够在 AWS Cloud 云中更轻松地设置、操作和扩展关系数据库。- 数据库和
web server
服务器下的架构
- 数据库和
-
使用
Cloudformation
构建RDS
以及AutoScaling
注意mail
地址的时候,要指定postgresql@163.com的形式,要用@加上domain
的形式,否则,下面的wordpress
的install
会报错,导致该cloudformation
创建失败Cloudformation
代码{"AWSTemplateFormatVersion": "2010-09-09","Description": "AWS in Action: chapter 9","Parameters": {"KeyName": {"Description": "Key Pair name","Type": "AWS::EC2::KeyPair::KeyName","Default": "my-cli-key"},"BlogTitle": {"Description": "The title of the blog.","Type": "String","Default": "Amazon Web Services in Action - Example"},"AdminUsername": {"Description": "A username for admin.","Type": "String","Default": "admin"},"AdminPassword": {"Description": "A password for admin","Type": "String","NoEcho": "true"},"AdminEMail": {"Description": "The email address of the administrator.","Type": "String"}},"Mappings": {"EC2RegionMap": {"ap-northeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-cbf90ecb"},"ap-southeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-68d8e93a"},"ap-southeast-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-fd9cecc7"},"eu-central-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a8221fb5"},"eu-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a10897d6"},"sa-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-b52890a8"},"us-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-1ecae776"},"us-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-d114f295"},"us-west-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-e7527ed7"}}},"Resources": {"VPC": {"Type": "AWS::EC2::VPC","Properties": {"CidrBlock": "172.31.0.0/16","EnableDnsHostnames": "true"}},"InternetGateway": {"Type": "AWS::EC2::InternetGateway","Properties": {}},"VPCGatewayAttachment": {"Type": "AWS::EC2::VPCGatewayAttachment","Properties": {"VpcId": {"Ref": "VPC"},"InternetGatewayId": {"Ref": "InternetGateway"}}},"SubnetA": {"Type": "AWS::EC2::Subnet","Properties": {"AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]},"CidrBlock": "172.31.38.0/24","VpcId": {"Ref": "VPC"}}},"SubnetB": {"Type": "AWS::EC2::Subnet","Properties": {"AvailabilityZone": {"Fn::Select": ["1", {"Fn::GetAZs": ""}]},"CidrBlock": "172.31.37.0/24","VpcId": {"Ref": "VPC"}}},"RouteTable": {"Type": "AWS::EC2::RouteTable","Properties": {"VpcId": {"Ref": "VPC"}}},"RouteTableAssociationA": {"Type": "AWS::EC2::SubnetRouteTableAssociation","Properties": {"SubnetId": {"Ref": "SubnetA"},"RouteTableId": {"Ref": "RouteTable"}}},"RouteTableAssociationB": {"Type": "AWS::EC2::SubnetRouteTableAssociation","Properties": {"SubnetId": {"Ref": "SubnetB"},"RouteTableId": {"Ref": "RouteTable"}}},"RoutePublicNATToInternet": {"Type": "AWS::EC2::Route","Properties": {"RouteTableId": {"Ref": "RouteTable"},"DestinationCidrBlock": "0.0.0.0/0","GatewayId": {"Ref": "InternetGateway"}},"DependsOn": "VPCGatewayAttachment"},"NetworkAcl": {"Type": "AWS::EC2::NetworkAcl","Properties": {"VpcId": {"Ref": "VPC"}}},"SubnetNetworkAclAssociationA": {"Type": "AWS::EC2::SubnetNetworkAclAssociation","Properties": {"SubnetId": {"Ref": "SubnetA"},"NetworkAclId": {"Ref": "NetworkAcl"}}},"SubnetNetworkAclAssociationB": {"Type": "AWS::EC2::SubnetNetworkAclAssociation","Properties": {"SubnetId": {"Ref": "SubnetB"},"NetworkAclId": {"Ref": "NetworkAcl"}}},"NetworkAclEntryIngress": {"Type": "AWS::EC2::NetworkAclEntry","Properties": {"NetworkAclId": {"Ref": "NetworkAcl"},"RuleNumber": "100","Protocol": "-1","RuleAction": "allow","Egress": "false","CidrBlock": "0.0.0.0/0"}},"NetworkAclEntryEgress": {"Type": "AWS::EC2::NetworkAclEntry","Properties": {"NetworkAclId": {"Ref": "NetworkAcl"},"RuleNumber": "100","Protocol": "-1","RuleAction": "allow","Egress": "true","CidrBlock": "0.0.0.0/0"}},"LoadBalancer": {"Type": "AWS::ElasticLoadBalancing::LoadBalancer","Properties": {"Subnets": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}],"LoadBalancerName": "awsinaction-elb","Listeners": [{"InstancePort": "80","InstanceProtocol": "HTTP","LoadBalancerPort": "80","Protocol": "HTTP"}],"HealthCheck": {"HealthyThreshold": "2","Interval": "5","Target": "TCP:80","Timeout": "3","UnhealthyThreshold": "2"},"SecurityGroups": [{"Ref": "LoadBalancerSecurityGroup"}],"Scheme": "internet-facing"},"DependsOn": "VPCGatewayAttachment"},"LoadBalancerSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-elb-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"CidrIp": "0.0.0.0/0","FromPort": 80,"IpProtocol": "tcp","ToPort": 80}]}},"WebServerSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"CidrIp": "0.0.0.0/0","FromPort": 22,"IpProtocol": "tcp","ToPort": 22}, {"FromPort": 80,"IpProtocol": "tcp","SourceSecurityGroupId": {"Ref": "LoadBalancerSecurityGroup"},"ToPort": 80}]}},"DatabaseSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-db-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"IpProtocol": "tcp","FromPort": "3306","ToPort": "3306","SourceSecurityGroupId": {"Ref": "WebServerSecurityGroup"}}]}},"Database": {"Type": "AWS::RDS::DBInstance","DeletionPolicy": "Delete","Properties": {"AllocatedStorage": "25","DBInstanceClass": "db.t3.medium","DBInstanceIdentifier": "awsinaction-db","DBName": "wordpress","Engine": "MySQL","EngineVersion": "5.7","MasterUsername": "wordpress","MasterUserPassword": "wordpress","VPCSecurityGroups": [{"Fn::GetAtt": ["DatabaseSecurityGroup", "GroupId"]}],"DBSubnetGroupName": {"Ref": "DBSubnetGroup"}},"DependsOn": "VPCGatewayAttachment"},"DBSubnetGroup" : {"Type" : "AWS::RDS::DBSubnetGroup","Properties" : {"DBSubnetGroupDescription" : "DB subnet group","SubnetIds": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}]}},"LaunchTemplate": {"Type": "AWS::EC2::LaunchTemplate","Metadata": {"AWS::CloudFormation::Init": {"config": {"packages": {"yum": {"php": [],"php-mysql": [],"mysql": [],"httpd": []}},"sources": {"/var/www/html": "https://wordpress.org/wordpress-4.2.4.tar.gz"},"files": {"/tmp/config": {"content": {"Fn::Join": ["", ["#!/bin/bash -ex\n","cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php\n","sed -i \"s/'database_name_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'username_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'password_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'localhost'/'", {"Fn::GetAtt": ["Database", "Endpoint.Address"]}, "'/g\" wp-config.php\n","chmod -R 777 wp-content/ \n","curl -O https://raw.githubusercontent.com/AWSinAction/builds/gh-pages/phar/wp-cli.phar \n","php wp-cli.phar core install --url=\"", {"Fn::GetAtt": ["LoadBalancer", "DNSName"]}, "/wordpress\" --title=\"", {"Ref": "BlogTitle"}, "\" --admin_user=\"", {"Ref": "AdminUsername"}, "\" --admin_password=\"", {"Ref": "AdminPassword"}, "\" --admin_email=\"", {"Ref": "AdminEMail"}, "\" \n" ]]},"mode": "000500","owner": "root","group": "root"}},"commands": {"01_config": {"command": "/tmp/config","cwd": "/var/www/html/wordpress"}},"services": {"sysvinit": {"httpd": {"enabled": "true","ensureRunning": "true"}}}}}},"Properties": {"LaunchTemplateName": "LaunchTemplate","LaunchTemplateData":{"EbsOptimized": false,"ImageId": {"Fn::FindInMap": ["EC2RegionMap", {"Ref": "AWS::Region"}, "AmazonLinuxAMIHVMEBSBacked64bit"]},"InstanceType": "t2.micro","NetworkInterfaces":[{"DeviceIndex":0,"AssociatePublicIpAddress":true,"Groups":[{"Ref": "WebServerSecurityGroup"}],"DeleteOnTermination":true}],"KeyName": {"Ref": "KeyName"},"UserData": {"Fn::Base64": {"Fn::Join": ["", ["#!/bin/bash -ex\n","yum update -y aws-cfn-bootstrap\n","/opt/aws/bin/cfn-init -v --stack ", {"Ref": "AWS::StackName"}, " --resource LaunchTemplate --region ", {"Ref": "AWS::Region"}, "\n","/opt/aws/bin/cfn-signal -e $? --stack ", {"Ref": "AWS::StackName"}, " --resource AutoScalingGroup --region ", {"Ref": "AWS::Region"}, "\n"]]}}}}},"AutoScalingGroup": {"Type": "AWS::AutoScaling::AutoScalingGroup","Properties": {"LoadBalancerNames": [{"Ref": "LoadBalancer"}],"LaunchTemplate" : {"LaunchTemplateId" : {"Ref" : "LaunchTemplate"},"Version" : {"Fn::GetAtt" : ["LaunchTemplate","LatestVersionNumber"]}},"MinSize": "2","MaxSize": "2","DesiredCapacity": "2","VPCZoneIdentifier": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}]},"CreationPolicy": {"ResourceSignal": {"Timeout": "PT10M"}},"DependsOn": "VPCGatewayAttachment"}},"Outputs": {"URL": {"Value": {"Fn::Join": ["", ["http://", {"Fn::GetAtt": ["LoadBalancer", "DNSName"]}, "/wordpress"]]},"Description": "Wordpress URL"}} }
-
逐步解析整个
Cloudformation
-
定义
VPC
以及两个subnet
- 代码
"VPC": {"Type": "AWS::EC2::VPC","Properties": {"CidrBlock": "172.31.0.0/16","EnableDnsHostnames": "true"}},"InternetGateway": {"Type": "AWS::EC2::InternetGateway","Properties": {}},"VPCGatewayAttachment": {"Type": "AWS::EC2::VPCGatewayAttachment","Properties": {"VpcId": {"Ref": "VPC"},"InternetGatewayId": {"Ref": "InternetGateway"}}},"SubnetA": {"Type": "AWS::EC2::Subnet","Properties": {"AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]},"CidrBlock": "172.31.38.0/24","VpcId": {"Ref": "VPC"}}},"SubnetB": {"Type": "AWS::EC2::Subnet","Properties": {"AvailabilityZone": {"Fn::Select": ["1", {"Fn::GetAZs": ""}]},"CidrBlock": "172.31.37.0/24","VpcId": {"Ref": "VPC"}}},
- 系统构成
- 代码解析
- 定义了一个
VPC
- 定义了一个
InternetGateway
,并将其attach
到VPC
上。 - 定义了两个
subnet
,其中每个subnet
都在一个AvailabilityZone
(AZ
)里面。
- 定义了一个
- 代码
-
定义
Router
和RouteTable
,并附加在两个subnet
上- 代码
"RouteTable": {"Type": "AWS::EC2::RouteTable","Properties": {"VpcId": {"Ref": "VPC"}}},"RouteTableAssociationA": {"Type": "AWS::EC2::SubnetRouteTableAssociation","Properties": {"SubnetId": {"Ref": "SubnetA"},"RouteTableId": {"Ref": "RouteTable"}}},"RouteTableAssociationB": {"Type": "AWS::EC2::SubnetRouteTableAssociation","Properties": {"SubnetId": {"Ref": "SubnetB"},"RouteTableId": {"Ref": "RouteTable"}}},"RoutePublicNATToInternet": {"Type": "AWS::EC2::Route","Properties": {"RouteTableId": {"Ref": "RouteTable"},"DestinationCidrBlock": "0.0.0.0/0","GatewayId": {"Ref": "InternetGateway"}},"DependsOn": "VPCGatewayAttachment"},
- 对应的系统构成
注意,"DependsOn": "VPCGatewayAttachment"
,因为需要0.0.0.0
路由到InternetGateway
的时候,需要VPC
attach到InternetGateway
作为先行条件,所以加上DependsOn
。 - 代码解析
- 定义一个
RouteTable
,指定VPC
- 将这个
RouteTable
附加到subnet A
上 - 将这个
RouteTable
附加到subnet B
上 - 给路由表
RouteTable
加上路由Route
,EC2
如果想要访问Internet
网络,那么经由InternetGateway
- 定义一个
- 对应的系统构成
- 代码
-
定义
Router
和RouteTable
,并附加在两个subnet
上-
代码
"NetworkAcl": {"Type": "AWS::EC2::NetworkAcl","Properties": {"VpcId": {"Ref": "VPC"}}},"SubnetNetworkAclAssociationA": {"Type": "AWS::EC2::SubnetNetworkAclAssociation","Properties": {"SubnetId": {"Ref": "SubnetA"},"NetworkAclId": {"Ref": "NetworkAcl"}}},"SubnetNetworkAclAssociationB": {"Type": "AWS::EC2::SubnetNetworkAclAssociation","Properties": {"SubnetId": {"Ref": "SubnetB"},"NetworkAclId": {"Ref": "NetworkAcl"}}},"NetworkAclEntryIngress": {"Type": "AWS::EC2::NetworkAclEntry","Properties": {"NetworkAclId": {"Ref": "NetworkAcl"},"RuleNumber": "100","Protocol": "-1","RuleAction": "allow","Egress": "false","CidrBlock": "0.0.0.0/0"}},"NetworkAclEntryEgress": {"Type": "AWS::EC2::NetworkAclEntry","Properties": {"NetworkAclId": {"Ref": "NetworkAcl"},"RuleNumber": "100","Protocol": "-1","RuleAction": "allow","Egress": "true","CidrBlock": "0.0.0.0/0"}},
-
系统构成
-
代码解析
- 定义一个
NetworkAcl
- 定义两个
SubnetNetworkAclAssociation
,一个是从0.0.0.0
入站(egress = true
)的网络都开放,另一个是从subnet
出站(egress = true
)到0.0.0.0
的都开放
- 定义一个
-
-
定义一个
LoadBalancer
以及security group
- 代码
"LoadBalancer": {"Type": "AWS::ElasticLoadBalancing::LoadBalancer","Properties": {"Subnets": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}],"LoadBalancerName": "awsinaction-elb","Listeners": [{"InstancePort": "80","InstanceProtocol": "HTTP","LoadBalancerPort": "80","Protocol": "HTTP"}],"HealthCheck": {"HealthyThreshold": "2","Interval": "5","Target": "TCP:80","Timeout": "3","UnhealthyThreshold": "2"},"SecurityGroups": [{"Ref": "LoadBalancerSecurityGroup"}],"Scheme": "internet-facing"},"DependsOn": "VPCGatewayAttachment"},"LoadBalancerSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-elb-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"CidrIp": "0.0.0.0/0","FromPort": 80,"IpProtocol": "tcp","ToPort": 80}]}},
- 系统构成
- 代码解析
- 定义一个
LoadBalancer
- 定义一个
LoadBalancerSecurityGroup
,开放internet
到LoadBalancer
的80
端口访问
- 定义一个
- 代码
-
定义
WebServerSecurityGroup
- 代码
"WebServerSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"CidrIp": "0.0.0.0/0","FromPort": 22,"IpProtocol": "tcp","ToPort": 22}, {"FromPort": 80,"IpProtocol": "tcp","SourceSecurityGroupId": {"Ref": "LoadBalancerSecurityGroup"},"ToPort": 80}]}},
- 系统构成
- 代码解析
- 定义一个
WebServerSecurityGroup
- 允许
internet
访问22
端口 - 只允许
LoadBalancerSecurityGroup
所属的主机访问80
端口
- 定义一个
- 代码解析
- 代码
-
定义数据库和数据所在的
security group
- 代码
"DatabaseSecurityGroup": {"Type": "AWS::EC2::SecurityGroup","Properties": {"GroupDescription": "awsinaction-db-sg","VpcId": {"Ref": "VPC"},"SecurityGroupIngress": [{"IpProtocol": "tcp","FromPort": "3306","ToPort": "3306","SourceSecurityGroupId": {"Ref": "WebServerSecurityGroup"}}]}},"Database": {"Type": "AWS::RDS::DBInstance","DeletionPolicy": "Delete","Properties": {"AllocatedStorage": "25","DBInstanceClass": "db.t3.medium","DBInstanceIdentifier": "awsinaction-db","DBName": "wordpress","Engine": "MySQL","EngineVersion": "5.7","MasterUsername": "wordpress","MasterUserPassword": "wordpress","VPCSecurityGroups": [{"Fn::GetAtt": ["DatabaseSecurityGroup", "GroupId"]}],"DBSubnetGroupName": {"Ref": "DBSubnetGroup"}},"DependsOn": "VPCGatewayAttachment"},"DBSubnetGroup" : {"Type" : "AWS::RDS::DBSubnetGroup","Properties" : {"DBSubnetGroupDescription" : "DB subnet group","SubnetIds": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}]}},
- 系统构成
- 代码解析
- 定义一个
RDS(mysql)
- 定义一个
DatabaseSecurityGroup
,在这里单单允许从属于WebServerSecurityGroup
的虚拟机能访问3306
端口
- 定义一个
- 代码
-
定义
LaunchTemplate
为AutoScaling
提供模版- 代码
"LaunchTemplate": {"Type": "AWS::EC2::LaunchTemplate","Metadata": {"AWS::CloudFormation::Init": {"config": {"packages": {"yum": {"php": [],"php-mysql": [],"mysql": [],"httpd": []}},"sources": {"/var/www/html": "https://wordpress.org/wordpress-4.2.4.tar.gz"},"files": {"/tmp/config": {"content": {"Fn::Join": ["", ["#!/bin/bash -ex\n","cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php\n","sed -i \"s/'database_name_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'username_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'password_here'/'wordpress'/g\" wp-config.php\n","sed -i \"s/'localhost'/'", {"Fn::GetAtt": ["Database", "Endpoint.Address"]}, "'/g\" wp-config.php\n","chmod -R 777 wp-content/ \n","curl -O https://raw.githubusercontent.com/AWSinAction/builds/gh-pages/phar/wp-cli.phar \n","php wp-cli.phar core install --url=\"", {"Fn::GetAtt": ["LoadBalancer", "DNSName"]}, "/wordpress\" --title=\"", {"Ref": "BlogTitle"}, "\" --admin_user=\"", {"Ref": "AdminUsername"}, "\" --admin_password=\"", {"Ref": "AdminPassword"}, "\" --admin_email=\"", {"Ref": "AdminEMail"}, "\" \n" ]]},"mode": "000500","owner": "root","group": "root"}},"commands": {"01_config": {"command": "/tmp/config","cwd": "/var/www/html/wordpress"}},"services": {"sysvinit": {"httpd": {"enabled": "true","ensureRunning": "true"}}}}}},"Properties": {"LaunchTemplateName": "LaunchTemplate","LaunchTemplateData":{"EbsOptimized": false,"ImageId": {"Fn::FindInMap": ["EC2RegionMap", {"Ref": "AWS::Region"}, "AmazonLinuxAMIHVMEBSBacked64bit"]},"InstanceType": "t2.micro","NetworkInterfaces":[{"DeviceIndex":0,"AssociatePublicIpAddress":true,"Groups":[{"Ref": "WebServerSecurityGroup"}],"DeleteOnTermination":true}],"KeyName": {"Ref": "KeyName"},"UserData": {"Fn::Base64": {"Fn::Join": ["", ["#!/bin/bash -ex\n","yum update -y aws-cfn-bootstrap\n","/opt/aws/bin/cfn-init -v --stack ", {"Ref": "AWS::StackName"}, " --resource LaunchTemplate --region ", {"Ref": "AWS::Region"}, "\n","/opt/aws/bin/cfn-signal -e $? --stack ", {"Ref": "AWS::StackName"}, " --resource AutoScalingGroup --region ", {"Ref": "AWS::Region"}, "\n"]]}}}}},
- 系统架构
- 代码解析
- 定义一个
LaunchTemplate
,这里使用了cfn-init
,这里就会回调父节点的"AWS::CloudFormation::Init"
,能够对使用模版创建的EC2
实例进行初期化。类似于使用puppet
或者chef
来对EC2
进行详细的配置。 - 完成了
cfn-init
之后调用cfn-signal -e
来通知Cloudformation
,AutoScalingGroup
已经创建完毕。
- 定义一个
- 代码
-
定义
AutoScalingGroup
- 代码
"AutoScalingGroup": {"Type": "AWS::AutoScaling::AutoScalingGroup","Properties": {"LoadBalancerNames": [{"Ref": "LoadBalancer"}],"LaunchTemplate" : {"LaunchTemplateId" : {"Ref" : "LaunchTemplate"},"Version" : {"Fn::GetAtt" : ["LaunchTemplate","LatestVersionNumber"]}},"MinSize": "2","MaxSize": "2","DesiredCapacity": "2","VPCZoneIdentifier": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}]},"CreationPolicy": {"ResourceSignal": {"Timeout": "PT10M"}},"DependsOn": "VPCGatewayAttachment"}
- 系统架构
- 代码解析
- 定义一个
AutoScalingGroup
,这里使用LaunchTemplate
,注意LaunchTemplate
定义的时候,使用cfn-init
,在初期化的时候,使用DB
设定,指向设定的RDS(mysql)
properties
的maxsize
和minsize
都是2,保证至少有两个EC2
来服务wordpress
- 定义一个
- 系统架构
- 代码
-