Today we're going to talk about an amazing tool that somebody introduced me to a little while ago last year, some time. It's called Ansible. And Ansible allows us to administer machines, provision them, and perform tasks over SSH. And it's a really, really incredible tool that works really, really simply right out of the box.
I've worked with some other tools out there that make this kind of task very difficult and tricky to get set up. And to get working, and to debug, and a bunch of other nightmarish kinds of problems that you end up having with them. But with Ansible, I really got up and running very quickly. So I found it to be very well built and very useful.
And let me tell you first what Ansible is. It'll give you a sense of it. So far in our deployment classes, we've been doing everything by hand. We've been SSHing into either a Vagrant machine or an Amazon EC2 instance. And then setting up that machine with software that we need to run our programs, and whatever other provisioning tasks we needed to do to get it ready to go.
Well, what if we had more than one server? What if we had, say, eight servers, or two, or three? You can see where SSHing into all of them independently or individually would be quite a nightmare over time. And the other issue is, you have to remember all of the various steps that need to be performed each time. And so you end up kind of tinkering with the system until you get it just right.
Wouldn't it be nice if we could just script that out, so that we don't have to remember how to do it each time? And then also have be able to run these scripts simultaneously on multiple machines over SSH? And that's what Ansible allows us to do.
Here's a quick diagram in the best handwriting that I can muster that shows a bunch of different roles that we might have in our environment. We have two app servers, a database server, and two load balancers. And you can see already that having to SSH into each one of these independently or individually and set them up would be cumbersome.
So we can use Ansible to SSH into all of them automatically and run whatever provisioning scripts we want to have run. And one of the nice things about Ansible, versus just writing regular scripts that we would run like at a Bash terminal, is that Ansible is smart enough to be able to tell whether the machine is already in the state that we want it to be in. And so if something it has already been done, it won't do it again. And so it's smart enough to just do the things that are required to bring the machine to a state that we want it to be in.
Let me show you around an example Ansible project. An Ansible project has a host file for a given environment that you're in, like production, or staging, or local. And in that file, we define a bunch of roles using this INI type of syntax. So we've got load balancer, app, worker, database. We might have a bunch of different types of roles. And then underneath that, the actual machines-- the addresses of the machines that are in that role.
So for example, this one will define load balancer 1 and 2 dot prod. And this is actually defined in my ssh config file as a host, so that I don't have to remember the IP addresses. And so this is a host file that shows you how we can map different machines onto specific roles. And we might have a situation where one machine is in more than one role. So we might, for example, say that our database machine is also the app server and is also the CAS server.
In the simplest example, Ansible allows us to run commands remotely. In this case, I'm using the Ansible command line tool on all the hosts in my environment. And the module that I'm going to use is the ping module. So I'm going to set a ping to all the different hosts in my environment. And I want to run that on the production inventory.
So this is going to be the actual Evented Mind system that's in production. And when I press Enter, automatically, it SSHs into each of these machines and runs the ping command. And I get back a response for each of the hosts in my environment. When things start to get more complex, you can put a series of these commands into something called a playbook. And so these YAML configuration files define a sequence of steps for a set of hosts for different things like deployment, or setting up an environment, or showing a maintenance page, hiding a maintenance page-- all different types of things you can imagine we might want to do with our deployment environment.
In this class, I'm going to show you around some of the features of Ansible so that you get a sense of how to use it. Because we're going to be using it a lot to provision different machines down the road for web, when we set up machines for deploying a Meteor application, or Rails application, or Node.js application-- all of those things. We're just going to be using Ansible to set up a machine that has certain software running on it in order to deploy whatever application framework we might be using.
So once you clone this project, you're going to, inside the project directory, have a Vagrant file. To make things simple, we're going to work with virtual machines so you don't have to get an Amazon account or a Digital Ocean account to do this. You can just run it locally on your laptop and follow along.
So in the Vagrant file-- let's just take a look at that. Unlike some previous classes, where the Vagrant file just defines one host, so we just have one virtual machine. In this case, we're going to have a bunch of hosts.
So notice this array here. What this is doing is saying that there's going to be one load balancer, two apps, and one database server. So it's sort of mimicking a slightly more complex environment than what we've been used to. And then down here, this script here is going to loop through those and go ahead and provision all those machines. And it will bring up the machine with a particular IP address.
In the project directory, I can type vagrant up to bring up the virtual machines for the first time. Or if you've shut them down after shutting down your laptop or something, you can type vagrant up. That'll bring them up. This will take a couple of minutes to complete.
And then since I've been enabling public networking for these machines, it's going to ask me which interface I want to connect to. And you can just pick display ethernet or the Wi-Fi one. So I'm going to type 1 here. I'd just pick one that works.
Once that process completes, we can type vagrant status. And unlike previous times, you're going to see a bunch of machines now-- all the ones that were provisioned. lb1 is load balancer 1. app1, app2, and db1. They're all running.
And just like previously, if we want to SSH into one of them, I can use the vagrant ssh command and then just type the host name. So lb1-- oops-- lb1.local, for example. And that will SSH me into that machine.
But we want to do a little trick here, which is that I want to be able to SSH into it directly just by typing ssh lb1.local. And since I don't have lb1.local in my SHH config, in my home directory, I'm going to have to tell SSH how to connect to this. What the address is, which identity file to use, and all of that.
So what I can do is create an SSH config that's specific to this project. So if I type vagrant ssh config, it's going to spit out an SSH configuration file. And what I want to do is to take that and put it into a dot ssh folder. So I'll just create that folder if it doesn't exist. And then I'll say vagrant shh config, and pop that into dot ssh in a file called config.
Now we can provide that configuration file to the SSH command like this. I can say SSH into, I don't know, let's pick db1.local. And use a configuration file. So that's the capital-F option that comes from dot ssh config. And now we can SSH into it, just like we could a regular machine.
Now, this is useful, because this will work with Ansible as well. So we'll tell Ansible to go ahead and use this local configuration file to run any SSH commands in our local environment. And if we were in a production environment, we could have a different configuration file for the production environment. So that's all you need to know with Vagrant. Again, I'll link to the Vagrant video on that, if you're not familiar with how to use Vagrant in the prerequisite section.
Here's an example of the prerequisites down here in the body, along with any notes and corrections, if there happen to be any. And as always, over in the Materials section is where you can find the source code and the transcripts. And if you enjoy this class, or you enjoy any of the videos in it, please go ahead and share it with your friends on one of these social mediums. I'd really appreciate that.