Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Build Immutable Servers with Packer & Ansible @ Microsoft OS Camp PT

Build Immutable Servers with Packer & Ansible @ Microsoft OS Camp PT

Slides of my talk about "Build Immutable Servers with Packer & Ansible" at Microsoft Open-Source Camp in Lisbon, Portugal.

The code samples can be found here: https://github.com/dcsg/build-immutable-servers-packer-ansible

Daniel Gomes

April 05, 2017

More Decks by Daniel Gomes

Other Decks in Programming


  1. About me • Senior Software Engineer at Talkdesk • Co-founder

    of phplx • DevOps Enthusiast • @_dcsg • dcsg.me
  2. Configuration Drift • Manual ad-hoc changes and updates to servers

    that are not recorded • Servers in your infrastructure became more and more different from each others @_dcsg #MSOSCAMP
  3. Snowflake Server • Long running servers • Difficult to reproduce

    • No consistency between servers • Lack of confidence in your systems • Hard to spin up another instance in the same state @_dcsg https://martinfowler.com/bliki/SnowflakeServer.html
  4. The cluster state after a few weeks State A @_dcsg

    #MSOSCAMP State C State B State B
  5. Configuration Management The process of systematically handling changes to a

    system in a way that it maintains integrity over time. @_dcsg #MSOSCAMP
  6. Configuration Management Spin up Base Image Run Config Management Server

    in desire state Changes Edit config file Upgrade/install package … Running Server
  7. Applying to the cluster state State A @_dcsg #MSOSCAMP State

    C State B State B Config Management Apply State D
  8. How Ansible works? • Agent-less by operating over SSH •

    Ad-hoc commands execution • Playbooks @_dcsg #MSOSCAMP
  9. Ansible “components” • Inventory of hosts - your raw materials

    (servers) • Modules - your tools (apt, yum, etc) • Playbooks - your instructions manual (executes tasks) @_dcsg #MSOSCAMP
  10. Ansible Inventory - Hosts & Groups # /my_project/hosts mail.example.com [webservers]

    foo.example.com bar.example.com [dbservers] one.example.com two.example.com
  11. Ansible Modules - — name: Install vim
 apt: pkg=vim state=latest

    - — name: reboot the server
 command: /sbin/reboot -t now
  12. Ansible Playbook “components” • Hosts • Variables, Conditions, Loops •

    Templating (Jinja2) • Tasks • Handlers • Roles @_dcsg http://docs.ansible.com/ansible/playbooks.html
  13. --- - hosts: webservers vars: http_port: 80 remote_user: root tasks:

    - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf notify: - restart apache - name: ensure apache is running (and enable it at boot) service: name=httpd state=started enabled=yes handlers: - name: restart apache service: name=httpd state=restarted Ansible Variables, Tasks, Handlers
  14. Ansible Conditions & Loops - name: add several users user:

    name: "{{ item.name }}" state: present groups: "{{ item.groups }}" with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' } when: - ansible_distribution == "CentOS"
  15. Ansible Roles Example # Folder structure roles/ common/ files/ templates/

    tasks/ main.yml handlers/ vars/ defaults/ meta/ # roles/common/tasks/main.yml - name: install common packages yum: name: "{{ item }}" state: present with_items: - htop - vim
  16. Recap • Configuration Drift • Problems of the Snowflake Servers

    • Configuration Management • Ansible @_dcsg #MSOSCAMP
  17. “A server should be like a phoenix, regularly rising from

    the ashes.” - Martin Fowler in PhoenixServer @_dcsg #MSOSCAMP
  18. Phoenix Servers • Avoid configuration drifts • Disposable servers •

    Servers can be built from scratch @_dcsg #MSOSCAMP
  19. The cluster Re-launch an instance State D @_dcsg #MSOSCAMP State

    D State D State D Terminate 
 Instance Config Management Apply State D State D
  20. Built Process Spin up Base Image Run Config Management Server

    in desire state Install packages Create folders Create user Upload app etc Run Config Management Repositories unavailable Package not locked to specific version
  21. “An Immutable Server is a server, that once deployed, is

    never modified, merely replaced with a new updated instance.” - Kief Morris in ImmutableServer @_dcsg #MSOSCAMP
  22. Immutable Servers • Final state image with everything baked in.

    • No changes after it’s built. • Include scripts to start the application at boot. • Easy to scale out, deploy and rollback • Trustable and testable • Easy to adopt A/B testing, Canary releases or Blue/Green deployments @_dcsg #MSOSCAMP
  23. Immutable Server Build Process Run Config Management (puppet, chef, ansible)

    Bake In the App App Final Image Server in desire state configure application
 environment Spin up Base Image
  24. Build Image Stages Flow Example Base Image OS Hardening Common

 (vim, htop, etc) etc Application Base Image Install necessary software to run the App Create user/folders Application Final Image Upload App Script to run App at boot System upgrades & Security updates Application security, package, configuration updates
  25. • SnowFlake Servers • Inconsistent states between machine (Config Drifts)

    • Phoenix Serves • Avoids Config Drifts using CM Automation Tools • Can be built from scratch • Immutable Serves • Final image with everything baked in • After built cannot be modified • Can only be replaced with an updated instance Recap
  26. “Packer is an open source tool for creating identical machine

    images for multiple platforms from a single source configuration.” What’s Packer? @_dcsg #MSOSCAMP
  27. User Variables Can be defined from: • The command line

    • Environment Variables • From a file @_dcsg https://www.packer.io/docs/templates/user-variables.html
  28. User Variables { "variables": { "client_id": "{{env `CLIENT_ID`}}", "my_var": ""

    }, "builders": [ { "type": "azure-arm", "client_id": "{{ user `client_id` }}", "…": "…" } ] }
  29. Building using variables and Env vars > packer build -var-file=vars.json

    base-image.json # vars.json { “client_id": "foo", "my_var": "bar" }
  30. "builders": [ { "type": "docker", "image": "ansible/ubuntu14.04-ansible", "export_path": "out/base-image.tar" },

    { "type": "virtualbox-ovf", "source_path": "vagrant-base-box/box.ovf", "ssh_username": "vagrant", "ssh_password": "vagrant" } ] Builders
  31. Run packer using only docker Builder > packer build -only=docker

    base-image.json > packer build -parallel=true base-image.json Run packer using both Builders in Parallel
  32. Provisioners "provisioners": [ { "type": “shell-local“, "command": “tar -zcvf ./toupload/app.tar.gz

    ../app” }, { "type": “file", "source": “./toupload", "destination": "/tmp/" }, { "type": "ansible", "playbook_file": "ansible/site.yml" } ]
  33. "post-processors": [ { "type": "vagrant", "output": "out/my-app.box", "only": ["virtualbox-ovf"] },

    [ { "type": "docker-import", "repository": "dcsg/my-app", "tag": "0.1", "only": ["docker"] }, { "type": "docker-push", "login": true, "login_username": "{{user `docker_hub_user`}}", "login_password": "{{user `docker_hub_password`}}", "only": ["docker"] } ] ]