Matt Warren

Deploying Flask With Ansible

Over the last couple weeks I have been getting acquainted with using Ansible to provision and deploy servers. One nice thing with using Ansible over a tool like fabric for deployment is that everything from provisioning, initializing, updating, management, and application deployment can be done with a minimal amount of code.

There are tips I learned as I got started with Ansible:

  1. install ansible with pip into a virtualenv.  This seemed to fix issues I ran into when having it installed globally on my computer.
  2. create a new directory to work with – it will have all the templates for nginx, supervisord, roles, playbooks, and server lists in it
  3. create an inventory file that lists all the servers you will manage
  4. split things into multiple playbooks – I have a webserver, database server and deploy playbook. having the deploy playbook separate keeps it simple and it will run quickly.
  5. the roles found on ansible-galaxy are almost never exactly what you want, even if they are you’ll likely have to read through the templates to find out what variables can be used to customize them.  In almost all cases it’s good to clone the role into your working directory’s roles subfolder so they are easily accessible and editable.
  6. the idempotent property of ansible playbooks make it easy to procedurally build up your playbook.
  7. it’s often easier to have an open ssh connection to manually see what’s changing on the server, make sure templates are rendering correctly etc.

my working directory looks like this for a simple single server Flask webapp.

digital_ocean

For my deploy playbook things couldn’t be simplier:

---
- hosts: webservers
  vars:
    app_name: awesomeapp
    repo_url: https://github.com/mfwarren/secretproject.git
    repo_remote: origin
    repo_version: master
    webapps_dir: /srv/webapps
    virtualenv_root: /srv/webapps/pyenv/versions/latest_v3
  tasks:
    - name: git pull project
      git: repo={{repo_url}} dest={{webapps_dir}}/{{app_name}} version=master
      notify:
        - restart app
    - pip: requirements={{webapps_dir}}/{{app_name}}/requirements.txt virtualenv=latest_v3 executable={{virtualenv_root}}/bin/pip3
    - shell: "{{virtualenv_root}}/bin/python3 manage.py deploy"
      args:
        chdir: "{{webapps_dir}}/{{app_name}}"
  handlers:
    - name: restart app
      supervisorctl: name={{app_name}} state=restarted

the tasks are very easy to follow, git pull the latest changes, install requirements that might have changed, run the ‘deploy’ command on the app which does DB migrations, and finally kick supervisord to restart the app.

On the command-line my process for executing this deploy looks like:

ansible-playbook deploy.yml -i ansible_hosts

Ansible is a tool for power users. It would be quite difficult to use without experience setting up the servers manually. Unlike Heroku or another PaaS, it will take several hours to learn and configure your first server through Ansible. However that onetime cost should pay for itself with the additional control you have, and server cost savings.

I certainly would love to see tools created to analyze your project and create a set of playbooks and templates which would create a production quality server setup, similar to how Heroku’s Buildpacks can figure out how to get a Django/Rails/Node.js app running.


Posted

in

by

Tags: