Mastering Ansible
Today I’d like to write a bit about a more technical topic, namely Ansible. Ansible is a ‘simple’ way to automate apps and IT infrastructure. It combines Application Deployment, Configuration Management and Continuous Delivery into one neat little package. I first started working with it at NN, during my time in the API NN Ext. Platform team. This was a very hectic time with a very high workload. This allowed me to work on many different subjects, but didn’t grant me any time to actually study any topic in-depth.
Now that’s changed. I’m no longer in that team or company and I have all the time to put a solid theoretical foundation under my existing Ansible knowledge. I want to do this by building my own Ansible swarm. The eventual plan will be to creare my own CI/CD pipeline on my Windows 10 PC via Gitlab CI and automate builds and build-information via AWS Alexa. Eventually, I want to copy this set-up on my Ubuntu Laptop for extra learning. Let’s get started.
The next couple of posts are based on “https://www.udemy.com/mastering-ansible/learn/v4”
Tools used:
- Atom
- Vagrant
- Ansible
- MySQl
- NGINX
- Apache2, Python
- Virtualbox
Vagrant is a very nice tool that helps you set up a virtual network. People call it a wrapper as its wrapped around Virtualbox and handles all tasks for you automatically. For each virtual environment I’m using the Ubuntu/Trusty64 image.
The idea is to create 5 instances:
- Control
- Loadbalancer
- Webserver 1
- Webserver 2
- Database
Control will be the main Ansible machine. The other four will work together to provide access to content on the Webserver.
The script for Vagrant is as follows:
# vi: set ft=ruby : # README # # Getting Started: # 1. vagrant plugin install vagrant-hostmanager # 2. vagrant up # 3. vagrant ssh # # This should put you at the control host # with access, by name, to other vms Vagrant.configure(2) do |config| config.hostmanager.enabled = true config.vm.box = "ubuntu/trusty64" config.vm.define "control", primary: true do |h| h.vm.network "private_network", ip: "192.168.135.10" h.vm.provision :shell, :inline => <<'EOF' if [ ! -f "/home/vagrant/.ssh/id_rsa" ]; then ssh-keygen -t rsa -N "" -f /home/vagrant/.ssh/id_rsa fi cp /home/vagrant/.ssh/id_rsa.pub /vagrant/control.pub cat << 'SSHEOF' > /home/vagrant/.ssh/config Host * StrictHostKeyChecking no UserKnownHostsFile=/dev/null SSHEOF chown -R vagrant:vagrant /home/vagrant/.ssh/ EOF end config.vm.define "lb01" do |h| h.vm.network "private_network", ip: "192.168.135.101" h.vm.provision :shell, inline: 'cat /vagrant/control.pub >> /home/vagrant/.ssh/authorized_keys' end config.vm.define "app01" do |h| h.vm.network "private_network", ip: "192.168.135.111" h.vm.provision :shell, inline: 'cat /vagrant/control.pub >> /home/vagrant/.ssh/authorized_keys' end config.vm.define "app02" do |h| h.vm.network "private_network", ip: "192.168.135.112" h.vm.provision :shell, inline: 'cat /vagrant/control.pub >> /home/vagrant/.ssh/authorized_keys' end config.vm.define "db01" do |h| h.vm.network "private_network", ip: "192.168.135.121" h.vm.provision :shell, inline: 'cat /vagrant/control.pub >> /home/vagrant/.ssh/authorized_keys' end end
The set-up is quite simple. By adding this in a ‘Vagrantfile’ (the one you get after doing ‘vagrant init’) you can establish the entire structure by running ‘vagrant up’. The next tier will contain a MySQL DB, Loadbalancer and two Webservers. A nice detail is that the control machine has a shared folder with my Windows 10 machine. This means I can run Atom on all Ansible .yml files and edit them in the GUI I’m used to. (I hate VIM or any other linux-based text editor)
You can log in the control machine by typing ‘vagrant ssh’. Once you’re in you have to install Ansible to deal with the config management of the lower tier (LB, DB and Webserver)
For the DB, Loadbalancer and Webservers, I have to add the following to each respective .yml file
DB Script:
--- - hosts: database become: true tasks: - name: install tools apt: name={{item}} state=present update_cache=yes with_items: - python-mysqldb - name: install mysql-server apt: name=mysql-server state=present update_cache=yes - name: ensure mysql started service: name=mysql state=started enabled=yes - name: ensure mysql listening on all ports lineinfile: dest=/etc/mysql/my.cnf regexp=^bind-address line="bind-address = 0.0.0.0" notify: restart mysql - name: create demo database mysql_db: name=demo state=present - name: create demo user mysql_user: name=demo password=demo priv=demo.*:ALL host='%' state=present handlers: - name: restart mysql service: name=mysql state=restarted
Webserver Script:
--- - hosts: webserver become: true tasks: - name: install items apt: name={{item}} state=present update_cache=yes with_items: - apache2 - libapache2-mod-wsgi - python-pip - python-virtualenv - python-mysqldb #Start Apache - name: ensure apache2 started service: name=apache2 state=started enabled=yes - name: ensure mod_wsgi enabled apache2_module: state=present name=wsgi notify: restart apache2 #Copy Demo Files - name: copy demo app source copy: src=demo/app/ dest=/var/www/demo mode=0755 notify: restart apache2 # Copy Config - name: copy apache virtual host config copy: src=demo/demo.conf dest=/etc/apache2/sites-available mode=0755 notify: restart apache2 # Initiate Python - name: setup python virtualenv pip: requirements=/var/www/demo/requirements.txt virtualenv=/var/www/demo/.venv notify: restart apache2 # Stop default site and start own site - name: deactivate default apache site file: path=/etc/apache2/sites-enabled/000-default.conf state=absent notify: restart apache2 - name: activate demo apache site file: src=/etc/apache2/sites-available/demo.conf dest=/etc/apache2/sites-enabled/demo.conf state=link notify: restart apache2 handlers: - name: restart apache2 service: name=apache2 state=restarted
LB Script:
--- - hosts: loadbalancer become: true tasks: - name: install tools apt: name={{item}} state=present update_cache=yes with_items: - python-httplib2 - name: install nginx apt: name=nginx state=present update_cache=yes - name: ensure nginx started service: name=nginx state=started enabled=yes - name: configure nginx site template: src=templates/nginx.conf.j2 dest=/etc/nginx/sites-available/demo mode=0644 notify: restart nginx - name: de-activate default nginx site file: path=/etc/nginx/sites-enabled/default state=absent notify: restart nginx - name: activate nginx site file: src=/etc/nginx/sites-available/demo dest=/etc/nginx/sites-enabled/demo state=link notify: restart nginx handlers: - name: restart nginx service: name=nginx state=restarted
By adding these scripts, some custom ‘app’ files in the Ansible folder and running the playbook, we now have a single Control station with Ansible, a Database running mySQL, a Loadbalancer with NGINX and two webservers with Apache2, ready to go. Following along with the lectures, I’ve also made two playbooks called “Stack_Status.yml” and “Stack_reset.yml” in order to check what’s going on and to reboot the entire stack.
I’ll be continuing to work on this going forward. I’ll be trying to recreate this same set-up again on Monday on my Ubuntu Laptop for training. There seems to be some bugs with my versions of 1.6 Ubuntu and 1.8 Vagrant but I’ll look into that later today. (Sad that I can’t take my desktop with me to work…)