Scaling Laravel Using AWS Elastic Beanstalk Part 2: Setting up VPC, RDS and ElastiCache

db-setuplaravel-part2

In my last article we decoupled Laravel and got it ready for deployment to the Elastic Beanstalk architecture. However, before we race ahead to actually deploying our code to Elastic Beanstalk we need to do some preparation first. Specifically we need to set up some other AWS services that will be used by our Laravel app. These include:

With these “supporting” services up and running we can finally move on to deploying our Laravel app to Elastic Beanstalk.

Creating a VPC

The first thing we need to do is create a VPC for our infrastructure. By creating a VPC we can control every aspect of our network including which servers are available to the public internet and which servers should remain private. All of our EC2 servers (controlled by Elastic Beanstalk) should be on a private subnet (not accessible on the public internet) and all public traffic should be routed through either our load balancer (controlled by Elastic Beanstalk) for inbound traffic or our NAT for outbound traffic.

As a side note, we are going to be creating these services using the AWS Console and not the AWS CLI as it’s easier to visualize what we are doing. However these tasks can just as easily be completed (and automated) using the AWS CLI.

So let’s get started by heading over to the VPC console and clicking Start VPC Wizard:

  • Step 1: Select VPC with Public and Private Subnets.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-00-40-am

  • Step 2: Give your VPC a name. You can leave most of these settings as the default, however you can change the IP CIDR block if you want. As we want to use a NAT gateway (instead of creating our own instance) we will need to create an Elastic IP first. You can do this by going to the EC2 console and under “Network & Security > Elastic IPs” click Allocate New Address. Back in the VPC wizard select your new Elastic IP and when you are ready click Create VPC.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-15-55-am

Congratulations! We now have a VPC that we can use when creating the rest of our AWS services. There is one extra step we need to take here before we can create our RDS database below. RDS production databases require at least two availability zones, so we’re going to need to create a second public subnet for our VPC in a different availability zone (when we set up our RDS database we’re going to make it publically accessible so we need an extra public subnet).

In the VPC console, under “Subnets” click Create Subnet. Fill in the details making sure you are creating it in the correct VPC, the availability zone is different from the availability zone of the public subnet created by the wizard and the CIDR block in unique. When you’re ready click Yes, Create.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-45-31-am

To make this subnet a public subnet you need to update the route table to use the public one created by the wizard. With the subnet selected, in the “Route Table” tab click Edit and change the route table to the one used by your other public subnet.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-12-26-56-pm

Setting up RDS

The next thing we want to do is to set up an RDS instance to host our MySQL database. If you read the AWS docs Deploying a Laravel Application to Elastic Beanstalk you will have noticed that they encourage you to set up the RDS database as part of the Elastic Beanstalk environment. While at first glance this might look like the obvious route, you should be aware that if you ever delete the Elastic Beanstalk environment the RDS database will also be deleted. So we’re going to mitigate that mistake-waiting-to-happen by setting up our own RDS instance separate from Elastic Beanstalk.

So let’s head on over to the RDS console and click Launch a DB Instance:

  • Step 1: Select the database engine you would like to use. Amazon Aurora is probably overkill for small applications so let’s just select MySQL and continue.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-26-26-am

  • Step 2: Assuming this is a production app select “MySQL” under “Production” and continue to the Next Step.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-27-45-am

  • Step 3: Again most of these settings are sensible defaults and can be left as is. Depending on the size of your application you can select a smaller/larger DB Instance Class to suit your needs. Fill in your database details under “Settings” and when you are ready continue to the Next Step.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-31-49-am

  • Step 4: The “Network & Security” settings here are important. First we want to select the VPC we created above. If you want to be able to access your database from outside the VPC (using an app like Sequel Pro) you will want to set Publicly Accessible to “Yes”. If you choose “No” only your EC2 instances from inside the VPC private subnet will be able to access the database, which is more secure but harder to manage. While you can let RDS create a new security group specifically for the database, I think it’s fine to simply select “default (VPC)” for VPC Security Group(s). Fill in the Database Name and when you are ready click Launch DB Instance.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-11-39-00-am

Great, our MySQL database is up and running on an RDS instance! Now to be able to connect to our database we’re going to have to do a bit of fiddling to allow your IP address to access the database instance. If you enter the database details into an app like Sequel Pro you’ll notice that you get a timeout error. That’s because the security group being used by the RDS instance is blocking your connection.

sequel-pro-screen-shot-5-dec-2016-11-55-19-am

To resolve this expand your database instance in the RDS console. In the “Details” tab you will see the security group being used by the instance. Click it and it should take you to the EC2 console Security Groups page.

sequel-pro-screen-shot-5-dec-2016-11-58-52-am

With the security group selected click the “Inbound” tab. This table shows the rules describing what traffic is allowed to access instances managed by this security group. Currently only traffic from this security group can access our instances (basically any servers in our VPC).

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-12-01-25-pm

Click Edit and add a rule with a “MySQL/Aurora” type. If you select “My IP” under Source it will autofill your current IP address. Click Save. If you try to connect again now you should be able to connect successfully and see the database created by RDS. Remember if your IP address changes you will need to repeat this process to add the new IP.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-12-03-33-pm

Setting up ElastiCache

In the last article we configured Laravel to use a Redis cache. If you remember this is because we decoupled Laravel so that distinct pieces of the infrastructure can be scaled out. Due to Elastic Beanstalk’s autoscaling you could have many servers being created and destroyed at different times based on the traffic load. However, all of these instances need to be able to read/write from the same cache (similar to the database). So we need to set up a Redis cache cluster that can be accessed by our Elastic Beanstalk autoscaling group.

To get started, head over to the ElastiCache console and under “Create Cluster” click Create:

Make sure “Redis” is selected as our cluster engine. As above, most of the default settings will be fine here. For bigger applications you may want to enable Cluster Mode and tweak the size of the Node type and Number of replicas you want.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-12-33-12-pm

Under “Advanced Redis Settings” we will need to create a new subnet group for our cache cluster. Give the subnet group a name and description, select our VPC, select the private subnets from our VPC (unless you want the ElastiCache instance to be publically accessible, in which case select our public subnets) and leave the rest of the settings as default. When you are ready click Create.

google-chrome-console-aws-amazon-com-screen-shot-5-dec-2016-12-38-55-pm

Getting There

So we now have Laravel fully decoupled with all of our “supporting” services in place and ready to go. In the next article we’ll finally get round to setting up our Laravel app in Elastic Beanstalk which will include configuring our load balancer and auto scaling groups, and setting up our ebextensions files for automatically provisioning our EC2 servers.

Have you ever used a VPC in AWS? Have any experience with RDS or Elasticache with some helpful tips you want to share? Let us know in the comments.

About the Author

Gilbert Pellegrom

Gilbert loves to build software. From jQuery scripts to WordPress plugins to full blown SaaS apps, Gilbert has been creating elegant software his whole career. Probably most famous for creating the Nivo Slider.

  • Adam Breen

    Hey folks, as you get more sophisticated with your AWS usage, I highly recommend investigating Amazon OpsWorks. It’s a nice web-based GUI with a Chef backend (you don’t need to write any Chef code to use it).

    OpsWorks really makes it easy to define an entire application at each layer, and auto-deploy. It’s definitely the way to go if you want to get more sophisticated with your elastic scaling strategy (ie. instead of Elastic Beanstalk) 😀

    • Hi Adam. Thanks for your recommendation. I’ll definitely check out OpsWorks.

  • mike

    I would highly recommend putting everything into private subnets – this includes the EB EC2 servers, the ElasticCache cluster, RDS, etc.

    Only things to put on the public subnet are the ELB and a bastion host. Then tunnel everything through that bastion host (Sequel Pro and other things natively have SSH tunnel support, otherwise you can always use your own SSH forwarding)

    It adds a little more complexity, but it also will achieve best practices, and you won’t have to be concerned if a security group winds up being opened “too much” – it’s a much stricter safeguard in place.

    • Hi Mike. Those sound like good suggestions. I’m not a devops guy and so am feeling my way through this. Thanks for pointing me in the right direction.

  • Игорь Иванов

    Thx! Great job!
    I look forward to continuing.

  • Raphael

    Can’t wait to see that next article for installing Laravel on Beanstalk, multiple instances !

  • Gustavo Woltmann

    A very informative post. Thanks for sharing.

    – Gustavo Woltmann

  • Jack Barham

    Thank you so much for these articles. They’ve been very helpful. When is the next article up? I’m looking it deploy in the next few weeks 🙂

  • kenny423565@mail.ru

    Phenomena and amazing info, Scaling Laravel using apps so important for elastic-beanstalk why not it has hugely day by day in a reputed organization in the tech media world where has used more like as VPC and RDS elasticache. Thanks for exceptional articles.