Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zero Downtime Deployment with Ansible

354 views

Published on

My talk from DevOpsCon Berlin 2016.

Ansible is a radically simple and lightweight provisioning framework which makes your servers and applications easier to provision and deploy. By orchestrating your application deployments you gain benefits such as documentation as code, testability, continuous integration, version control, refactoring, automation and autonomy of your deployment routines, server and application configuration. Ansible uses a language that approaches plain English, uses SSH and has no agents to install on remote systems. It is the simplest way to automate and orchestrate application deployment, configuration management and continuous delivery.

In this tutorial you will be given an introduction to Ansible and learn how to provision Linux servers with a web-proxy, a database and some other packages. Furthermore we will automate zero downtime deployment of a Java application to a load balanced environment.

  • Be the first to comment

Zero Downtime Deployment with Ansible

  1. 1. Zero Downtime Deployment with Ansible DevOpsCon Berlin 2016 @steinim stein.inge.morisbak@BEKK.no OPEN
  2. 2. Slides http://steinim.github.io/slides/devopscon/zero-downtime-ansible Source code git@github.com:steinim/zero-downtime-ansible.git Full tutorial http://steinim.github.io/slides/devopscon/zero-downtime- ansible/tutorial.html
  3. 3. What's a provisioning framework? Automated setup of servers Configuration as code Not immutable (in itself)
  4. 4. Examples Create users Install software Generate and manipulate config files Start/stop/restart processes Set up dependencies between operations
  5. 5. Describe what to do (imperative) #!/bin/bash if$(command-vvim>/dev/null2>&1);then echo"vimisalreadyinstalled." else apt-getinstallvim fi if$(grep-Fxq"filetypeindentoff"/etc/vim/vimrc);then echo"setfiletypeindentoffisalreadyin/etc/vim/vimrc." else echo"filetypeindentoff">>/etc/vim/vimrc #TODO:Donotcontinueifthisfails. fi #TODO:Rollbackifsomethingfails.
  6. 6. Describe state (declarative) -name:ensureinstalledvim apt:pkg=vimstate=installed -name:setfiletypeindentoffforvim lineinfile: dest=/etc/vim/vimrc line='filetypeindentoff' state=present
  7. 7. Pros In source control. Self documenting (it's code!). Refactoring. Less differences between environments. Deterministic. Prevents manual steps. Fast and easy to configure up a new environment. Easier to test server setup.
  8. 8. Ansible SSH-based Client only (no server) YAML configuration Push (and pull) Supports more than setup and provisioning: Application deployment Remote command execution
  9. 9. Bring up the boxes vagrantup
  10. 10. Layout (convention over configuration) ├──ansible.cfg ├──hosts ├──site.yml ├──group_vars │  └──<groupname> ├──host_vars │  └──<hostname> ├──roles │  ├──<role> │  │  ├──files │  │   └──<file> │  │  └──templates │  │   └──<template>.j2 │  │  ├──handlers │  │  │  └──main.yml │  │  ├──tasks │  │  │  └──main.yml │  │  ├──vars │  │  │  └──main.yml
  11. 11. Play! ansible-playbooksite.yml
  12. 12. Facts Ansible by default gathers “facts” about the machines under management. These facts can be accessed in Playbooks and in templates. ansible-msetupapp1.local
  13. 13. The task An app user 'devops', with: Home directory: /home/devops ssh-key A PostgresSQL database. Nginx as a reverse proxy. An init script installed as a service. Deploy an application that uses the provisioned infrastructure.
  14. 14. Help! http://docs.ansible.com/list_of_all_modules.html
  15. 15. Task1: Install and configure software Modify roles/common/tasks/apt.yml. Install Vim. Insert the line 'filetype indent off' in /etc/vim/vimrc Help: http://docs.ansible.com/apt_module.html http://docs.ansible.com/lineinfile_module.html
  16. 16. Task1: Solution -name:Ensureinstalledvim apt: pkg=vim state=present update_cache=no tags: -vim -name:Setfiletypeindentoff lineinfile: dest=/etc/vim/vimrc line='filetypeindentoff' state=present tags: -vim
  17. 17. Run it! ansible-playbooksite.yml--tagsvim ProTip:Use'--tags','--skip-tags','--limit' and/or'gather_facts:False' toreduceexecutiontime.
  18. 18. Progress Installed software Manipulated files
  19. 19. Variables Use variables! → Infrastructure as data. Where should variables be defined? Ansible has very many options. Inventory (./hosts) group_vars and host_vars Playbook (site.yml) Facts (local or server) Command line (as arguments) Access variables from playbooks: "{{ variable }}" http://docs.ansible.com/playbooks_variables.html
  20. 20. Task2: Create an application user Create roles/users/tasks/main.yml Home directory: /home/devops ssh-key Use variables! (group_vars) Help: (createadirectory) (.ssh/authorized_keys) http://docs.ansible.com/group_module.html http://docs.ansible.com/user_module.html http://docs.ansible.com/file_module.html http://docs.ansible.com/lineinfile_module.html http://docs.ansible.com/playbooks_best_practices.html#group-and-host-variables
  21. 21. Define some variables #group_vars/appservers user:devops group:devops user_name:"Devopsappuser"
  22. 22. Task2: Solution #roles/users/tasks/main.yml -name:Creategroup group:name={{group}}state=present tags: -users -name:Createuser user: name={{user}} comment="{{user_name}}" group={{group}} createhome=yes home=/home/{{user}} shell=/bin/bash state=present tags: -users -name:Ensuresshdirectoryexistsforuser
  23. 23. Run it! ansible-playbooksite.yml--limitappservers--skip-tagsapt,vim,java Try it! sshdevops@app1.local
  24. 24. Progress Installed software Manipulated files Created a user and set up a ssh-key
  25. 25. Task3: Install and configure PostgreSQL roles/postgresql ├──files │  └──postgresql.conf ├──handlers │  └──main.yml ├──tasks │  ├──main.yml │  └──... └──templates └──pg_hba.conf.j2 Usevariables(group_vars/dbservers). Template:roles/postgresql/templates/pg_hba.conf.j2 Usehandlertorestartpostgresqluponnotification Help: (pg_hba.conf.j2)http://docs.ansible.com/template_module.html http://docs.ansible.com/postgresql_user_module.html http://docs.ansible.com/postgresql_db_module.html http://docs.ansible.com/playbooks_intro.html#handlers-running-operations-on-change
  26. 26. Define some variables #group_vars/dbservers postgresql: version:9.4 repo:'debhttp://apt.postgresql.org/pub/repos/apt/precise-pgdgmain' user:postgres group:postgres data_dir:/var/lib/pgsql/data address:192.168.101.0/24 db: name:devops user:devops password:devops123
  27. 27. Create a template #roles/postgresql/templates/pg_hba.conf.j2 #TYPE DATABASE USER ADDRESS METHOD local all all trust host {{db.name}} {{db.user}} {{postgresql.address}} md5
  28. 28. Create a handler #roles/postgresql/handlers/main.yml -name:Restartpostgresql service:name=postgresqlstate=restarted
  29. 29. Task3: Solution #roles/postgresql/tasks/postgresql.yml -name:InstallPostgresqlanddependencies apt:pkg={{item}}state=installedupdate_cache=yes with_items: -postgresql-{{postgresql.version}} -python-psycopg2 tags: -pg_install -name:Installpostgresql.conf copy:src=postgresql.conf dest=/etc/postgresql/{{postgresql.version}}/main/postgresql.conf owner={{postgresql.user}} group={{postgresql.group}} notify: -Restartpostgresql tags: -pg_install
  30. 30. Run it! ansible-playbooksite.yml--limitdbservers--tagspg_install Try it! $vagrantsshdb vagrant@db:~$psql-ddevops-Udevops-W devops=>q
  31. 31. Progress Installed software Manipulated files Created a user and set up a ssh-key Installed and configured a database and a db user
  32. 32. Task4: Deploy! roles/app ├──files │  └──init.sh ├──tasks │  └──main.yml └──templates └──config.properties.j2 NB!Usevariables(./hosts). Set'serial:1'forappserversintheplaybook(site.yml). Help: http://docs.ansible.com/service_module.html
  33. 33. Browse to Run it! ansible-playbooksite.yml--limitappservers--tagsdeploy Try it! http://app1.local:1234/
  34. 34. What just happened? /home/devops ├──config.properties ├──current->/home/devops/devops_1416228023.jar ├──previous->/home/devops/devops_1416221573.jar ├──devops_1416221573.jar ├──devops_1416228023.jar └──logs ├──stderr.log └──stdout.log /etc/init.d └──devops
  35. 35. Progress Installed software Manipulated files Created a user and set up a ssh-key Installed and configured a database and a db user Deployed an application to two appservers and enabled it as a service
  36. 36. Task5: Deploy database roles/db ├──files │  └──migrate_db.sql └──tasks └──main.yml Help: http://docs.ansible.com/command_module.html
  37. 37. Task5: Solution -name:Copydbmigrationscript copy:src=migrate_db.sqldest=/tmp/migrate_db.sql become_user:postgres tags: -deploy -name:Rundbmigrationscript command:psql-d{{db.name}}-q-f/tmp/migrate_db.sql become_user:postgres tags: -deploy
  38. 38. Browse to Run it! ansible-playbooksite.yml--limitdbservers--tagsdeploy Try it! $vagrantsshdb vagrant@db:~$psql-ddevops-Udevops-W devops=>dt devops=>select*fromhello; devops=>q http://app1.local:1234/
  39. 39. Progress Installed software Manipulated files Created a user and set up a ssh-key Installed and configured a database and a db user Deployed an application to two appservers and enabled it as a service Migrated the database schema and fetched data from it through the application
  40. 40. Task6: Set up proxy roles/nginx ├──handlers │  └──main.yml ├──tasks │  ├──config_nginx.yml │  ├──install_nginx.yml │  └──main.yml └──templates └──devops.conf.j2 Help: http://wsgiarea.pocoo.org/jinja/docs/loops.html
  41. 41. Task6: Solution upstreambackend { {%forappserveringroups.appservers%} server{{appserver}}:{{app_port}}fail_timeout=1s; {%endfor%} } server{ listen80; server_name_; access_log/var/log/nginx/devops-access.log; location/{ proxy_pass http://backend; proxy_redirect off; proxy_next_upstream errortimeoutinvalid_headerhttp_500http_502; proxy_connect_timeout 2; } }
  42. 42. Browse to # refresh me many times Run it! ansible-playbooksite.yml--limitproxies--tagsnginx Try it! http://proxy.local/
  43. 43. Progress Installed software Manipulated files Created a user and set up a ssh-key Installed and configured a database and a db user Deployed an application to two appservers and enabled it as a service Migrated the database schema and fetched data from it through the application Set up a reverse proxy for automatic failover between the two appservers
  44. 44. The Expand/Contract pattern Expand Contract Add tables Add columns Tweak indexes Remove tables Remove columns Remove/add constraints
  45. 45. Play time :-) Suggestions: Change database table name from HELLO to MESSAGES and deploy a new version without downtime. Implement automated rollback.
  46. 46. September 5th and 6th 2016
  47. 47. Thank you! @steinim stein.inge.morisbak@BEKK.no

×