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
代码json{ "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
-
代码
json"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
上-
代码
json"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
上-
代码
json"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
-
代码
json"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
-
代码
json"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
-
代码
json"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"}] } },
-
-