Buy

Deploy to AWS!

So far, we've been deploying to a virtual machine. But... there's nothing stopping us from deploying to... the CLOUD! Let's try it - let's deploy to Amazon EC2. This is not an exhaustive tutorial about using EC2... but let's at least get our feet wet and see if we can get into some trouble!

Tip

Want to properly deploy with Ansible? Check out Ansistrano.

Manually Launching an EC2 Instance

I'm already on my EC2 dashboard. In a few minutes, we're going to use Ansible to actually launch a new instance. But for now, just hit "Launch Instance" to do it by hand. I'm looking for an image that's similar to what we're using with Vagrant: Ubuntu 14.04. Select that image, use the micro instance size, and just use the default settings on the next screens.

Tip

The instance id we used is ami-41d48e24 if you need to find it manually.

For the security group, I'm going to select a group I already created: "Web Access Testing." The important thing is to allow port 22 for SSH and ports 80 and 443 for web stuff. Hit "Review and Launch", then "Launch" that instance!

Bah! What a tease! No instance yet: we need to choose a key pair for SSH. I already created a pair for this tutorial called Ansible_AWS_tmp. When we launch the instance, instead of logging in with a username and password, we will SSH with a username and a private key. You'll need to create your own key pair. When you do that, you'll download its private key. In this case, the file is called Ansible_AWS_tmp.pem and I already downloaded it.

Ok, now launch the instance! Cool! Click to view its progress.

Configuring the new Host

While it's loading, let's get to work!

This new server represents a new host. In hosts.ini we have a local group with one server and a vb group with one server. Create a new group called aws:

13 lines ansible/hosts.ini
... lines 1 - 6
[aws]
... lines 8 - 13

Below, we need the IP to the server. Wait for it to boot.

When it's ready, copy its public IP address, go back to the hosts file, and paste! This time, set ansible_user to ubuntu: that's the user that's setup for this image. And instead of a password, use ansible_ssh_private_key_file= and put the path to your downloaded private key: ~/.ssh/Ansible_AWS_tmp.pem for me:

13 lines ansible/hosts.ini
... lines 1 - 6
[aws]
54.205.128.194 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/KnpU-Tutorial.pem
... lines 9 - 13

Host Group Children

Here's where things get cool! I want to run our playbook against the virtual machine and my EC2 instance. Because... it's totally valid to build two servers at once! That's where Ansible shines!

Right now, each lives under its own host group - vb and aws:

13 lines ansible/hosts.ini
... lines 1 - 3
[vb]
192.168.33.10 ansible_user=vagrant ansible_ssh_pass=vagrant
[aws]
54.205.128.194 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/KnpU-Tutorial.pem
... lines 9 - 13

Inside of our playbook, we've configured the play to only run against the vb group:

171 lines ansible/playbook.yml
---
- hosts: vb
... lines 3 - 171

How could we run that against the hosts in the vb group and in the aws group?

With a host group... group! Check it out: create a new group called webserver, but add a :children after. That special children syntax allows us to list other host groups below this: vb and aws:

13 lines ansible/hosts.ini
... lines 1 - 3
[vb]
192.168.33.10 ansible_user=vagrant ansible_ssh_pass=vagrant
[aws]
54.205.128.194 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/KnpU-Tutorial.pem
[webserver:children]
vb
aws

Yep, we now have a new group - webserver - that's a combination of these two.

Back in the playbook, change vb to webserver:

171 lines ansible/playbook.yml
---
- hosts: webserver
... lines 3 - 171

Running the Playbook

Deep breath. Run the playbook:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini --ask-vault-pass

Enter beefpass and deploy to the prod environment. You'll need to verify the authenticity of the new host this first time. And, by the way, you can disable this check in Ansible.

Now, watch the magic! You'll start to see it execute each task against both servers. The first time we do this, it'll take awhile: the new EC2 server is being setup from scratch. And, I was cheap - it's only a micro instance.

While we're waiting, let's go copy the IP address to the new server again. Temporarily open a new terminal tab and edit the /etc/hosts file:

sudo vim /etc/hosts

To test thing, update mootube.l to point to the IP address of the EC2 instance:

# /etc/hosts
# ...
#192.168.33.10 mootube.l
54.205.128.194 mootube.l

Then, save, quit and close the tab.

Even though Ansible is still working, if I go to http://mootube.l right now, I see the "Welcome to Nginx" page. Ha, cool! Ansible is already part way through the process!

Let's try to be patient... but also fast forward!

Done! And beautiful - it finished with no errors. That's kind of amazing: we launched a new cloud server from scratch... with no changes. Refresh the page. Got it! Welcome to MooTube, hosted on our fancy new EC2 instance. Notice that there's no data because we loaded in the prod environment: so the fixtures didn't run.

The only weird thing is that after changing my hosts file, I can't access MooTube on my VM anymore. But, we can solve that with host group vars.

Leave a comment!

  • 2017-10-30 Victor Bocharsky

    Hey Cesar,

    Good question! There's no particular reason doing so, except we just wanted to match the same Ubuntu release as we use in VirtualBox. However, keep in mind that if you use different versions for Vagrant and AWS - your playbook probably could fail without some extra work. I mean, if your playbook works well for Vagrant with Ubuntu 14.04 - it does not mean it'll 100% work for the different Ubuntu version (like 16.04) in AWS. Probably you'll need to install more packages, or some packages have different names, or you need to configure something in a different way. So I'd recommend you to use the same versions for Vagrant and AWS just due to simplicity.

    But there was a reason why we use 14.04 for Vagrant: https://knpuniversity.com/s... - in short, because it's a bit simpler to set up for Vagrant/Ansible. But in that screencast you'll find a big note how to set up 16.04 - the latest LTS (long-term support) release. However, Ubuntu 14.04 is an LTS release as well which means it's still supporting, see their roadmap: https://www.ubuntu.com/info... - so if you regularly update installed packages to the latest versions - I think you're safe with it.

    So, you can use whatever image you want or whatever you know best.

    Cheers!

  • 2017-10-29 Cesar

    Hi. When you deploy to AWS, you choose Ubuntu 14.04. I did the same and all the code runs perfectly. However, I would like to know why did you choose Ubuntu 14.04 instead of 16.04 or Amazon Linux? Is there any particular reason? I'm worry about possible security issues using and old version of Ubuntu. Maybe you can give more perspective about this.

  • 2017-10-16 Victor Bocharsky

    Hey Jian,

    Hm, good question! Actually, probably you want to secure your repository where the IP is shown, i.e. make your GitHub repo private or use other services like Bitbucket or GitLab which allow you to create private repositories for free. But I'd say no, it's not possible. The only workaround I see is use DNS name instead of public IP in ansible/hosts.ini file. Then the IP will be resolved automatically at runtime, but for programmers is not a difficult task to discover your public IP if they know DNS name. Or, you can invent any fake DNS name which you commit to the repo and in your local /etc/hosts point this fake DNS name to the real public IP address, so only you will know this IP even if someone else has access to your private repo.

    Also, I think you can specify a real IP address in command line, see -l option for ansible-playbook. So we use "-l aws", but you can use "-l 12.123.12.123", i.e. your real public IP, but this case you probably will need to tweak "hosts" value of your playbook to allow all hosts.

    Cheers!

  • 2017-10-15 jian su

    Hi Guys
    Is there a way to put aws IP address info to vars.yml and save it to vault. Exposing the IP and commit to github feel like security risk for me

  • 2017-06-20 Ahmed Bhs

    Oh Thnak you Victor Bocharsky for replying to me.
    I really appreciate your help, you made my day!

  • 2017-06-20 Victor Bocharsky

    Btw, if you're wondering about performance of your Symfony app - take a look at:
    http://symfony.com/doc/curr...

    Cheers!

  • 2017-06-20 Victor Bocharsky

    Hey Ahmed,

    Well done! You're a hero, my congratulations ;)

    Well, what about speed - it depends on your local machine: what kind of OS you use, what PHP version you have, what PHP extensions you have installed (btw, XDebug "eats" some time as well), your local php.ini configuration, etc. But yea, production websites always run faster in practice.

    1) Docker is just another way for virtualization, but it could be used in both development and production. But of course, like any virtualization tool, Docker will slows your performance. But how much slow exactly it will be is depend on the OS. Also Docker is a tool which allow you to scale ecosystem around your website, but of course it requires some good configuration and architectural design of your app. So it's more complex, need some solid understanding of how it works but have huge opportunities.

    2) Unfortunately, can't help you with this one, I have never use it before :/

    3) That's a good question! Doctrine allows you to cache its annotations in a separate cache system to increase reading speed. By defaults, Doctrine cache it in files, which is very slow in comparison with using cache engines. On KnpU we use APCu for storing Doctrine metadata cache.

    Cheers!

  • 2017-06-20 Victor Bocharsky

    Hey Ahmed,

    Ah, Apache service was not running, makes sense! What about writing hosts, ideally, you need to write both files on local and remove machines. But in practice, you need to write hosts file on your remove machine only when you want to get access to that host from inside of the remove machine, for example with Curl.

    Thanks for sharing it!

    Cheers!

  • 2017-06-20 Ahmed Bhs

    Hey, I just finished the course and my application run so fast, this amazing it's 5 time more fast than local.
    I don't know why my app seems so slow on the local.

    By the way, I have three questions wish you help me to get some answers :
    1) What is Docker and why Docker is so famous ? Does deploying with docker made my app fire so fast ? Or it's just it's a new virtualization tech for deployment.
    2) orm:
    auto_generate_proxy_classes: false

    + Does this configuration under orm désactive cache, by setting "auto_generate_proxy_classes" to "false", any explination about this config ?

    + Does caching made the app behaving more faster ?

    3)Same question about this configuration (any explanation !)

    doctrine:
    orm:
    metadata_cache_driver: apc

  • 2017-06-20 Ahmed Bhs

    I was facing two problems, the first that the Apache service was not running so just I typed: httpd service start
    the second problem like you already mentioned : I need to write the hosts file on your *local machine* (not in the AWS EC2 instance

  • 2017-06-16 Victor Bocharsky

    Hey Ahmed,

    Glad you got it solved! If it was not something I mentioned before - it would be nice of you to share this information with others users who has similar problem. But it's up to you ;)

    Cheers!

  • 2017-06-15 Ahmed Bhs

    Oh thank you for replay problém solved :)

  • 2017-06-15 Victor Bocharsky

    Hey Ahmed,

    Did you set "mootube.l your_public_ip_addr" in the "/etc/host" (notice the "/" in the beginning). Because "etc/hosts" will edit the etc/hosts file relative to the current directory you are in now. Please, double check that you write the hosts file on your *local machine* (not in the AWS EC2 instance). Also please, ensure this line is really present, you can check it with the next command: "$ cat /etc/hosts" - did you see the "mootube.l your_public_ip_addr" in the output? Are you sure you don't make a type in the domain address? Are you trying to open exactly the http://mootube.l/ domain?

    Btw, what OS are you on? Is it Windows? Because for Windows local machine the hosts file is located in a different folder.

    Cheers!

  • 2017-06-15 Ahmed Bhs

    After setting "mootube.l mypublic_ip_addr" under etc/hosts , i tried to acess to mootube.l via my brwoser but i get error "DNS not found" ?
    any explination !?