14 KiB
- Decoupling
- Creating Database + VPC + Subnets in Cloudformation
- Single instance (no load balancer)
- Running notes
- Work Commands
- Adding SSL to ELB
- EB Templates/Resources
- Configuring security groups
- Elastic Load Balancer
- Custom VPC + Subnets in EB
- Using cloudformation functions in EB config files
- Creating a read replica RDS
- Multiple security groups on the same resource
- Private subnets
Temp Notes
Decoupling
When creating an EB instance with --single and --database the following is created as part of the EB deployment:
- security group
- EIP
- RDS database
Is the security group created without a databse? (probably yes...)
Creating Database + VPC + Subnets in Cloudformation
Template from AWS showing cross-stack referencing and creating and referencing a VPC: https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleNetworkCrossStack.template.
Export these in the CF template with stackname (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html)
A security group is a resource that defines what IPs/Ports are allowed on inbound/outbound for an AWS resource. You can have one for EC2 instance, or RDS among others.
EB will create a VPC for your EC2 instances.
You should use this VPC for you RDS instance.
Creating a VPC for EB (with RDS) https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html
Single instance (no load balancer)
Example cloudformation template that EB uses: https://raw.githubusercontent.com/awslabs/elastic-beanstalk-samples/master/cfn-templates/vpc-public.yaml.
Create a VPC - this is an object that spans all availability zones in a region. You assign a VPC a CIDR block. This is a set of IP addresses that this VPC has access to.
You should create public subnets inside this VPC - these subnets should cover all availablility zones in your region. The CIDR block you specified in the VPC defines all the ips, you should create N subnets that equally contain these IP addresses for your region.
For example a VPC in eu-west-1 has a CIDR block of 172.31.0.0/16.
There are 3 availablity zones in eu-west-1: eu-west-1a, eu-west-1b and eu-west-1c.
To find other availablity zones you should go to the EC2 Dashboard for the region you want to work in, and scroll down to the Service health header. Here, a list of all availability zones will be shown.
You should create subnets with the following:
| Availability Zone | Subnet CIDR | Real IP Range |
|---|---|---|
eu-west-1a |
172.31.0.0/20 | 172.31.0.0 - 172.31.15.255 |
eu-west-1b |
172.31.16.0/20 | 172.31.16.0 - 172.31.31.255 |
eu-west-1c |
172.31.32.0/20 | 172.31.32.0 - 172.31.47.255 |
This covers all IP addresses across all availability zones in the VPC.
To make these subnets actually public, you should associate them with an internet gateway.
An internet gateway is an object that allows communication to the internet. In Cloudformation you should create an internet gateway and a VPC Gateway attachment. This attachment should reference the VPC you have created and reference the internet gateway object you create as well. Then, in your subnets (which are public) you can use MapPublicIpOnLaunch: true in the Properties block for each subnet.
You should then create a public route table and associate it with the VPC you have created.
You should then create a public route. You can then attach the internet gateway attachment to this route and specify a list of IPs that will go out to the internet. To allow all trafic to the internet set a DestinationCidrBlock of 0.0.0.0/0.
EC2::VPC
Enable DNS
Enable EnableDnsHostnames + EnableDnsSupport - this allows resources in the VPC to use DNS in AWS.
EC2::Subnet
Go to the EC2 dashboard to find all availability zones. Create a subnet for each zone.
AvailabilityZoneVpcIdCidrBlockMapPublicIpOnLaunch
EC2::InternetGateway
EC2::VPCGatewayAttachment
VpcIdInternetGatewayId
AWS::EC2::RouteTable
VpcId
AWS::EC2::Route
RouteTableIdDestinationCidrBlockGatewayId
AWS::EC2::SubnetRouteTableAssociation
SubnetIdRouteTableId
Running notes
If we specify the VPC + Subnets from Cloudformation in a config file, will it create the security groups automatically for the EC2 instances? - Yes
Database can use existing subnets. Database needs a security group creating EC2 security groups automatically created and associated with the VPC. Use aws:ec2:vpc (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc)
Database
Needs:
AWS::RDS::DBSubnetGroupAWS::EC2::SecurityGroupIngressAWS::RDS::DBInstance
Default ports:
| Database Engine | Default Port |
|---|---|
| Aurora/MySQL/MariaDB | 3306 |
| PostgreSQL | 5432 |
| Oracle | 1521 |
| SQL Server | 1433 |
| DynamoDB | 8000 |
Work Commands
tags
--tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation
deploy
aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation
aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc --tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation
delete
aws --profile admin cloudformation delete-stack --stack-name strapi-vpc
aws --profile admin cloudformation delete-stack --stack-name strapi-rds
aws --profile admin cloudformation delete-stack --stack-name temp
List of all RDS Engines available under "Engine" header: https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html.
describe-stack-resources
Will print a json list of all resources in the stack
aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc
Using jq for formatting:
aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'
Adding SSL to ELB
You should generate an SSL Certificate in Certificate Manager for your domain. To do this you will need to create a CNAME record to verify you have access to the DNS settings.
At the same time you should create a CNAME record that maps your subdomain (<strapi.panaetius.co.uk>) to the DNS name AWS has given your load balancer (<awseb-AWSEB-68CXGV0UTROU-1492520139.eu-west-1.elb.amazonaws.com>).
With load balancer
A load balancer is not free! It costs ~£15 a month.
- Configure the load balancer listener in a EB
.configfile:
option_settings:
aws:elbv2:listener:443:
Protocol: HTTPS
SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc
EB Templates/Resources
Good repo for examples: https://github.com/awsdocs/elastic-beanstalk-samples
Creating a VPC for RDS in EB: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html
CF RDS EB template: https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template
Decouple an exisitng RDS instance from ELB to RDS: https://aws.amazon.com/premiumsupport/knowledge-center/decouple-rds-from-beanstalk/
Configuring security groups
Elastic Load Balancer
Should set: inbound/outbound 80/443 on 0.0.0.0/0
The option_settings: aws:elbv2:loadbalancer has two options for security groups.
| Option | Description |
|---|---|
| ManagedSecurityGroup | Defines the security group that is used for the load balancer itself. |
| SecurityGroups | Is a list of additional security groups you want to attach. |
If you define a ManagedSecurityGroup you should set SecurityGroups as well to the same one.
Load balancer needs a security group that allows incoming 80 + 443 from anywhere It should also set the same for outbound as well
This security group should be set in aws:elbv2:loadbalancer under
ManagedSecurityGroup and SecurityGroups
Elastic Scaler
Should set inbound 80/443 from LBSG.
EB will create a security group for the EC2 instances. In addition to this, you can create a new security group that will be applied to EC2 instances the elastic scaler creates.
This is set under aws:autoscaling:launchconfiguration.
RDS
Should set: inbound 5432 from Scaling SG + home ip (change port and home ip).
The database should have a security group creating that allows incoming connections from the EC2 instances only.
Security group to allow EC2 instances to talk to each other
Security group rule to allow instances in the same security group to talk to one another: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html#sg-rules-other-instances.
Custom VPC + Subnets in EB
In a .config file specify the subnets for each tier of your app:
option_settings:
aws:ec2:vpc:
VPCId: "vpc-003597eb63a0a3efe"
Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
Using cloudformation functions in EB config files
Only certain CF functions can be used in EB config files. For anything more advanced you should use Terraform to deploy additional resources alongside an EB template.
Reddit discussion on the topic: https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/.
EB documentaion on what functions are supported: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions-functions.html#ebextensions-functions-getatt.
You cannot use FN::ImportValue to reference a resource in another Cloudformation stack.
You can use join for resources that EB creates itself: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ].
Creating a read replica RDS
To have a replica database you should create a new DB instance with same AllocatedStorage size and DBInstanceClass. You should set the SourceDBInstanceIdentifier to be a !Ref of your primary DB. You should also set the SourceRegion.
Read replica CF docs: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-sourcedbinstanceidentifier
Multiple security groups on the same resource
Multiple security groups get squashed to determine what is and isn't allowed: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html.
Private subnets
You can create private subnets that do not have an internet gateway attached to them. An example of CF template is https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/cfn-templates/vpc-privatepublic.yaml.
You need a nat gateway to allow private subnets to go out to the internet.
If you use private subnets, the nat gateway is not cheap - £30 a month.
You dont need the nat gateway, you can achieve the same thing with security groups (block all incoming) (explained https://www.reddit.com/r/aws/comments/75bjei/private_subnets_nats_vs_simply_only_allowing/).
An advantage to NAT is all outgoing requests to the internet come from a single IP.