Electronic Engineer
Universidad del Valle
cristian@swapps.co
Python developer
Does not hate Javascript that much
Rustacean from time to time
Boss: Hey Joe, you got to install Redis on every server we use because we heard it was a cool thing to do.
Joe:
- SSH to server 1
- $ sudo apt-get update
- $ sudo apt-get install redis-server
100 servers and a couple hours later:
Joe: Mission accomplished.
Boss: Hey Carl, you got to install Redis on every server we use because we heard it was a cool thing to do.
Carl: ./my_pretty_script_for_installing_random_things.sh
100 servers and a couple minutes later:
Carl: Mission accomplished.
#!/bin/bash
# Taken from: http://stackoverflow.com/questions/13928116/write-a-shell-script-to-ssh-to-a-remote-machine-and-execute-commands
USERNAME=someUser
HOSTS="host1 host2 host3..host100"
SCRIPT="sudo apt-get update; sudo apt-get install -y redis-server"
for HOSTNAME in ${HOSTS} ; do
ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
done
WE CAN DO BETTER
Boss: Hey Andres, you got to install Redis on every server we use because we heard it was a cool thing to do.
Andres: Inventory file
Andres:
[my-servers]
some.com
some-other.com
123.123.123.123
ansible my-servers -i my-inv -m apt -a "update-cache=yes name=redis-server state=present" -b
We have a lot of tools to choose from. There are a lot of alternatives to ansible, with chef, puppet and salt being the most used ones. With other choices why should we pick Ansible?
This is just about what i have learnt from using Ansible for a couple months now.
If you use alternatives that is OK. The point is to automate as much as possible to improve the quality and speed of your releases.
Boss: Hey Mr. DevOpsRockStar, do you remember that time you installed Redis really fast? Now we want to do the same for all of our most used packages.
Mr. DevOpsRockStar: Too easy.
---
- hosts: my-servers
pre_tasks:
- name: Update apt cache if needed
become: yes
apt: update_cache=yes cache_valid_time=86400
tasks:
- name: Install system packages.
- become: yes
- apt: name={{ item }} state=present
- with_items:
- redis-server
- build-essential
- python-dev
Mr. DevOpsRockStar: And now I run my playbook
ansible-playbook playbook.yml -i my-inv
Ansible defines everything on units called plays, group those plays on playbooks and run the playbooks on hosts.
The playbooks define a general state of the system.
I.E. This package should be present, these packages should be absent, these directories should be present with permissions for this user, etc.
Ansible uses Jinja2, which allows you to define variables for ansible to use inside of your playbooks. That gives you a lot of flexibility.
# playbook.yml
---
- hosts: all
tasks:
- name: Copy nginx config file
become: yes
template:
src: my_nginx_config
dest: /etc/nginx/sites-available/{{ app_name }}
# my_nginx_config
server {
server_name {{ server_name }};
listen 80;
access_log /var/log/nginx/{{ app_name }}.access.log;
error_log /var/log/nginx/{{ app_name }}.error.log;
location / {
uwsgi_pass unix:///tmp/{{ app_name }}.sock;
include uwsgi_params;
}
}
ansible-playbook playbook.yml -i my-inv --extra-vars "app_name=my_app server_name=myapp.com"
Ansible needs to be installed. You can do that with:
pip install ansible
You need to be able to log in to to our hosts via SSH. If you cannot use your default key, you must specify the key to use. Once you can connect, Ansible will take care of the rest.
With other automation tools you need to install agents on every hosts before being able to perform any tasks. This increases the surface for attackers, from a security viewpoint. From a lazy developer point of view, you have to make sure that an agent is installed and running on every host, which is not good because if something fails you have to work more.
Ansible only needs to be able to connect via SSH. You can create a new DigitalOcean or AWS EC2 instance and run exactly the same playbook with the same outcome.
Ansible has over 200 core modules, where apt is just one of them.
You can do anything from making sure that a package is installed to creating a new EC2 instance on the fly.
Other examples are:
At Swapps we use Codeship for Continuous Integration. It runs the tests for our projects and notifies our "ops" server on success if the code checked belongs to one of our main branches.
The ops server then takes the commit id and deploy it to our servers automatically. Normally we use develop for our staging instances and master for production.
In short, we deploy with a git push.
There are other tools that you may use for the integrations and the setup of a continuous delivery pipeline. As that is a topic for another day, i will leave just a list for now if you are interested on digging deeper:
Swapps is hiring! You can find information on https://www.swapps.io/jobs/