updating documentation

This commit is contained in:
2020-05-03 00:23:34 +01:00
parent bae738ad98
commit b16b747414
3 changed files with 146 additions and 162 deletions

View File

@@ -11,6 +11,7 @@
* [Fix Version Numbers](#FixVersionNumbers)
* [Strapi in git](#Strapiingit)
* [Cloudformation](#Cloudformation)
* [Output naming convention](#Outputnamingconvention)
* [Creating templates](#Creatingtemplates)
* [Adding resources](#Addingresources)
* [Using parameters](#Usingparameters)
@@ -225,6 +226,23 @@ You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run s
<https://adamtheautomator.com/aws-cli-cloudformation/> (example of deploying an S3 bucket with static site `index.html`.)
### <a name='Outputnamingconvention'></a>Output naming convention
You should follow a standard naming convention for your CF outputs.
For example:
```yaml
Outputs:
PublicVPCOutput:
Description: The VPC ID.
Value: !Ref PublicVPC
Export:
Name: !Sub "${AWS::StackName}-EBStrapiPublicVPC"
```
Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are).
### <a name='Creatingtemplates'></a>Creating templates
To create a cloudformation template you should create a `template.yaml`. This yaml file should have at the top:

View File

@@ -1,19 +1,35 @@
<!-- vscode-markdown-toc -->
- [Decoupling](#Decoupling)
- [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation)
- [Single instance (no load balancer)](#Singleinstancenoloadbalancer)
_ [EC2::VPC](#EC2::VPC)
_ [Enable DNS](#EnableDNS)
_ [EC2::Subnet](#EC2::Subnet)
_ [EC2::InternetGateway](#EC2::InternetGateway)
_ [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment)
_ [AWS::EC2::RouteTable](#AWS::EC2::RouteTable)
_ [AWS::EC2::Route](#AWS::EC2::Route)
_ [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation)
- [Running notes](#Runningnotes)
- [Reference an input parameter, or a resource ID from inside current template](#ReferenceaninputparameteroraresourceIDfrominsidecurrenttemplate) \* [Using `Fn::Sub`](#UsingFn::Sub)
- [Dynamically referencing resources from another stack.](#Dynamicallyreferencingresourcesfromanotherstack.)
* [Decoupling](#Decoupling)
* [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation)
* [Single instance (no load balancer)](#Singleinstancenoloadbalancer)
* [EC2::VPC](#EC2::VPC)
* [Enable DNS](#EnableDNS)
* [EC2::Subnet](#EC2::Subnet)
* [EC2::InternetGateway](#EC2::InternetGateway)
* [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment)
* [AWS::EC2::RouteTable](#AWS::EC2::RouteTable)
* [AWS::EC2::Route](#AWS::EC2::Route)
* [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation)
* [Running notes](#Runningnotes)
* [Database](#Database)
* [Work Commands](#WorkCommands)
* [tags](#tags)
* [deploy](#deploy)
* [delete](#delete)
* [describe-stack-resources](#describe-stack-resources)
* [Adding SSL to ELB](#AddingSSLtoELB)
* [With load balancer](#Withloadbalancer)
* [EB Templates/Resources](#EBTemplatesResources)
* [Configuring security groups](#Configuringsecuritygroups)
* [Elastic Load Balancer](#ElasticLoadBalancer)
* [Elastic Scaler](#ElasticScaler)
* [RDS](#RDS)
* [Security group to allow EC2 instances to talk to each other](#SecuritygrouptoallowEC2instancestotalktoeachother)
* [Custom VPC + Subnets in EB](#CustomVPCSubnetsinEB)
* [Using cloudformation functions in EB config files](#UsingcloudformationfunctionsinEBconfigfiles)
* [Creating a read replica RDS](#CreatingareadreplicaRDS)
* [Multiple security groups on the same resource](#Multiplesecuritygroupsonthesameresource)
* [Private subnets](#Privatesubnets)
<!-- vscode-markdown-toc-config
numbering=false
@@ -25,7 +41,7 @@
## <a name='Decoupling'></a>Decoupling
When creating an ELB instance with `--single` and `--database` the following is created as part of the ELB deployment:
When creating an EB instance with `--single` and `--database` the following is created as part of the EB deployment:
- security group
- EIP
@@ -41,15 +57,15 @@ Export these in the CF template with stackname (<https://docs.aws.amazon.com/AWS
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.
ELB will create a VPC for your EC2 instances.
EB will create a VPC for your EC2 instances.
You should use this VPC for you RDS instance.
Creating a VPC for ELB (with RDS) <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
Creating a VPC for EB (with RDS) <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
## <a name='Singleinstancenoloadbalancer'></a>Single instance (no load balancer)
Example cloudformation template that ELB uses: <https://raw.githubusercontent.com/awslabs/elastic-beanstalk-samples/master/cfn-templates/vpc-public.yaml>.
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.
@@ -125,7 +141,7 @@ 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
### <a name='Database'></a>Database
Needs:
@@ -143,19 +159,19 @@ Default ports:
| SQL Server | 1433 |
| DynamoDB | 8000 |
## Work Commands
## <a name='WorkCommands'></a>Work Commands
### tags
### <a name='tags'></a>tags
`--tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation`
`--tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation`
### deploy
### <a name='deploy'></a>deploy
`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --taws:elbv2:listener:defaultags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation`
`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-elb 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
### <a name='delete'></a>delete
`aws --profile admin cloudformation delete-stack --stack-name strapi-vpc`
@@ -165,7 +181,7 @@ Default ports:
List of all RDS Engines available under "Engine" header: <https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html>.
### describe-stack-resources
### <a name='describe-stack-resources'></a>describe-stack-resources
Will print a json list of all resources in the stack
@@ -175,13 +191,13 @@ Using `jq` for formatting:
`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'`
## Adding SSL to ELB
## <a name='AddingSSLtoELB'></a>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 name='Withloadbalancer'></a>With load balancer
A load balancer is not free! It costs ~£15 a month.
@@ -194,22 +210,28 @@ option_settings:
SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc
```
## <a name='EBTemplatesResources'></a>EB Templates/Resources
Good repo for examples: <https://github.com/awsdocs/elastic-beanstalk-samples>
Doc:
Add the ELB subnets to the VPC config
Creating a VPC for RDS in EB: <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
Create another custom security group for the EC2 instance - should be private
autoscaling should have current public security group
CF RDS EB template: <https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template>
Load balancer should have the current subnets
Decouple an exisitng RDS instance from ELB to RDS: <https://aws.amazon.com/premiumsupport/knowledge-center/decouple-rds-from-beanstalk/>
Loadbalancer security group should have inbound + outbound to 80+443 on 0.0.0.0/0
## <a name='Configuringsecuritygroups'></a>Configuring security groups
The option_settings: aws:elbv2:loadbalancer has two options for security groups
## <a name='ElasticLoadBalancer'></a>Elastic Load Balancer
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.
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.
@@ -219,11 +241,66 @@ It should also set the same for outbound as well
This security group should be set in `aws:elbv2:loadbalancer` under
`ManagedSecurityGroup` and `SecurityGroups`
Additional security groups (in addition to the default one created by ELB) for the EC2 instances are defined in `aws:autoscaling:launchconfiguration` under `SecurityGroups`
A security group will be created for you. You can ammend this (add 443 for https for example) by using `.config` file and creating a `AWS::EC2::SecurityGroupIngress` resource. (see 06-https.config)
### <a name='ElasticScaler'></a>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`.
### <a name='RDS'></a>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.
### <a name='SecuritygrouptoallowEC2instancestotalktoeachother'></a>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>.
LB SG: inbound/outbound 80/443 0.0.0.0/0
Scaling SG: inbound 80/443 from LBSG
DB SG: inbound 5432 from Scaling SG + home ip
## <a name='CustomVPCSubnetsinEB'></a>Custom VPC + Subnets in EB
In a `.config` file specify the subnets for each tier of your app:
```yaml
option_settings:
aws:ec2:vpc:
VPCId: "vpc-003597eb63a0a3efe"
Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
```
## <a name='UsingcloudformationfunctionsinEBconfigfiles'></a>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 ] ]`.
## <a name='CreatingareadreplicaRDS'></a>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>
## <a name='Multiplesecuritygroupsonthesameresource'></a>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>.
## <a name='Privatesubnets'></a>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.

125
todo.md
View File

@@ -1,130 +1,19 @@
# To Do
~~Finish S3 config for env vars~~
~~Deploy to AWS and ensure vars are working~~
## Immediate
~~Use cloudformation to deploy bucket instead of tieing it to the RDS instance.~~
Use <https://strapi.io/documentation/3.0.0-beta.x/deployment/amazon-aws.html#_2-create-the-bucket> for bucket options for the template.
Merge the CF templates into one, make sure all the importing and other snippets are documented.
~~Strapi documentation - build and host~~
- Create single instance deployment + https (document)
- Terraform it all up
## RDS Cloudformation
Use <http://blog.blackninjadojo.com/aws/elastic-beanstalk/2019/01/28/adding-a-database-to-your-rails-application-on-elastic-beanstalk-using-rds.html> to create an RDS for ELB.
- RDS cloudformation template
- Use the GUI to go through options and create cloudformation template
- Create an RDS db before deployment
- Configure Strapi to use this RDS db
- VPC + Security Group needs creating in template
Compare the `--database option` to without and make sure you create everything in the Cloudformation template.
Look at how to have multiple environments in the same elb app
Deploy strapi as load balanced rather than single instance
Deploy strapi with a custom domain with HTTPS as a single instance + load balanced.
Combine ELB Documentations (strapi, ELB etc)
## Long term
Use codebuild to update strapi
Use circle CI instead
Finish the backgrounds for the demo website
Cloudformation template to deploy an S3 bucket
## Links
## Documentation
Decouple an exisitng RDS instance from ELB to RDS: <https://aws.amazon.com/premiumsupport/knowledge-center/decouple-rds-from-beanstalk/>
Deploy the ELB environment referencing the VPC + Subnets created with Cloudformation. Use https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html as a reference.
This works! Create all the VPC + Subnet resources using Cloudformation and specify them in option settings:
```yaml
option_settings:
aws:ec2:vpc:
VPCId: "vpc-003597eb63a0a3efe"
Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
```
Recreate env with database, check the DB subnets - are they the same as the EC2 subnets? If so we can reference them in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc with ELBSubnets
Can we use cloudformation functions (imports) in .config files under option_settings? (reference a VPC that already exists?) (https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/) Yes?
Yes but only certain functions: <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.
Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ]
Updating 07 config to accept a parameter
For DB
Follow <https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template>
Create a subnet group (add each subnet to this group)
Create a security Group for DB
Create a SecurityGroupIngress
Use existing public VPC and subnet
What is the RDS hostname inside the container?
Follow a naming convention for likewise cloudformation templates
E.g.
```yaml
Outputs:
PublicVPCID:
Description: The VPC ID.
Value: !Ref PublicVPC
Export:
Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC"
```
Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are).
Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. - This is true. The RDS one is created in CF.
Does the db and the ec2 instances share the same VPC? - Yes. They have different security groups.
To Do
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.
CF RDS ELB template:
https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template
Read replica CF docs:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-sourcedbinstanceidentifier
Doc the CF changes for both
Combine them into a single CF stack
Deploy
Deploy strapi with LB + scaling
Enable HTTPS
Codebuild
Summarise the VPC creation - VPC is created, internet gateway is created (and route table) and is added to the VPC for internet access. Controlling what can and cannot go in/out to the internet is done with security groups.
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>.
Show how to create private + public subnets as in <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, but back in. How is this different to using security groups?
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/>). Advantage to NAT is all outgoing requests to the internet come from a single IP.
Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups.
Merge the CF templates into one, make sure all the importing and other s nippets are documented.
- Sort this page + documentation out
- Change ELB to EB
- Once documented and happy, create single CF Template
- Create single instance deployment + https (document)
- Terraform it all up
Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups. Document each individual resource needed bullet point and link to the git repo for the TF/CF templates.