Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

A CI-CD Alternative to Push and Pray for OpenStack

A CI-CD Alternative to Push and Pray for OpenStack

How do you validate OpenStack code and config changes before you push them to production? Rather than push and pray, we developed a CI/CD toolchain which allows us to review, test, and validate config and code changes before they land in production. Our process takes “infrastructure as code” fully to heart with integrated unit testing and tools that make it easier to spot errors earlier in the release process. In this talk we’ll follow a code change as it begins in a virtual OpenStack environment and proceeds through code review, puppet catalog testing, and the full release train.

Avatar for Matt Fischer

Matt Fischer

May 20, 2015
Tweet

More Decks by Matt Fischer

Other Decks in Programming

Transcript

  1. Introduction Clayton O’Neill –  [email protected] –  IRC: clayton (Twitter: @clayton_oneill)

    Matt Fischer –  [email protected] –  IRC: mfisch (Twitter: @openmfisch) Eric Peterson –  [email protected] –  IRC: ducttape_
  2. Background •  New team started in Nov 2013 •  OpenStack

    in production July 2014 •  CI/CD infrastructure started after production
  3. Our CI/CD Stats •  Over 4300 Reviews in our gerrit

    instance •  Over 300k nodepool slaves spun-up •  Hundreds of deploys •  Thousands of lines of Puppet, Ansible, and Python •  16.5k lines of upstream changes
  4. Development to Production Dev OpenStack on Prod Team Member DEV01

    DEV02 Team Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  5. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  6. Dev OpenStack on Prod Dev OpenStack on Prod Team Member

    DEV01 DEV02 Team Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  7. Virtualized Dev Environments •  Vagrant based –  ggiamarchi/vagrant-openstack-provider •  All

    environments built with the same tools •  Team members can have multiple environments •  Can be any or all node types •  Sharable for troubleshooting
  8. Code Review Dev OpenStack on Prod Team Member DEV01 DEV02

    Team Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  9. Jenkins Dev OpenStack on Prod Team Member DEV01 DEV02 Team

    Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  10. Single Use Jenkins Slaves •  Clean state on every job

    run •  Nodepool –  Builds Jenkins slaves as needed –  Builds Glance images once a day –  Supports multi-node slaves •  Single Use Slave Jenkins Plugin –  Ensures slaves are are offlined after job
  11. Jenkins Job Builder •  Jenkins job management doesn’t scale • 

    Using JJB for all jobs –  Jobs defined as YAML –  Code/config reuse via macros and templates –  Deploy and version jobs like everything else –  JJB is authoritative.
  12. Automated Testing Dev OpenStack on Prod Team Member DEV01 DEV02

    Team Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  13. Pre-Merge Testing •  Puppet lint •  Syntax tests •  Unit

    tests •  Tox •  Puppet catalog compiles & diffs
  14. Puppet Catalog Compiles? •  Puppet builds a catalog for each

    node •  Inputs are code + config + facts •  Jenkins builds before and after view for one of each node type in every environment •  Jenkins posts comment on review with changed nodes + link to diffs •  Diffs are built with ripienaar/puppet-catalog-diff module
  15. Catalog Diff Pro/Con •  Validate config in all environments • 

    More detail than unit tests •  Faster than integration testing (<5 min) •  Doesn’t report on –  Ruby code changes –  Service restarts, package upgrades, etc
  16. Automated Integration Testing •  Hourly testing of core node types

    •  Using Nodepool multi-node slaves •  Node builds are parallelized •  Test runs in ~45 minutes •  Catches breaking changes post-commit •  Future focus area
  17. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  18. Puppet Configuration •  Single Puppet master per environment •  Not

    using dynamic environments •  Minimal PuppetDB usage •  Hiera for environment specific changes •  Use hiera-eyaml for secret data •  Use r10k for module versioning & deployment
  19. Normal Puppetfile mod "mysql", :git => 'https://github.com/puppetlabs/puppetlabs-mysql.git', :tag => '3.3.0'

    # Forked until this PR is accepted # https://github.com/michaeltchapman/puppet-galera/pull/27 mod 'galera', :git => 'https://github.com/twc-openstack/puppet-galera', :commit => 'c3e37c8e61b367e64263f80f89642ce12dfecdb7' mod 'haproxy', :git => 'https://github.com/puppetlabs/puppetlabs-haproxy.git', :tag => '0.5.0'
  20. Top of Puppetfile # This loads the YAML file that

    Jenkins maintains of the latest commits # approved through Gerrit. PUPPET_DIR = ENV['PUPPET_DIR'] || '/etc/puppet' PUPPETFILE_YAML = File.join(PUPPET_DIR, 'Puppetfile.yaml') if File.readable?(PUPPETFILE_YAML) require 'yaml' data = YAML.load_file(PUPPETFILE_YAML) data['modules'].each_pair do |modulename, moduledata| mod modulename, :git => moduledata['git'], :commit => moduledata['ref'] end end
  21. Puppetfile.yaml entry modules: cirrus: author_date: "2015-05-04 15:20:04 +0000" author_email: "[email protected]"

    author_name: "Clayton O'Neill" changeid: I686e85f61cd7526d4faa56727351206ea9789dfa gerrit_url: "https://bfd-gerrit.os.cloud.twc.net/#q,I686e85f61cd7526d4faa56727..." git: ssh://deploy-host/puppet-cirrus issue: CIRRUS-2103 ref: 2b7d32df9f2c741425e8396414ecf2927f8b510d subject: "Add designate sink support
  22. Deploying OpenStack Code •  Using Ubuntu (UCA) packages for most

    services •  Shared dependencies make upgrades harder •  Only one version can be installed at a time •  Problems with service management
  23. Deploying Keystone from Master •  Keystone was first service we

    packaged •  Built using a pbuilder driven by jenkins-debian-glue •  Automated tox tests •  Issues: –  Packaging tools are a pain –  Dependencies are a rat hole
  24. Deploying Virtualenvs - Horizon •  Horizon deployed with virtualenvs • 

    Initial apache install & config via Puppet •  Ansible handles everything else: –  Deploys a given tag into a virtualenv –  Installs pre-reqs into a new unique folder –  Moves a symlink and touches the wsgi file to reload Horizon
  25. Deploying Virtualenvs - Designate •  Designate deployed with virtualenvs, except

    using Puppet –  Largely based upon upstream OpenStack Puppet work –  Drove us to create more tooling and infrastructure –  We’re holding a patch for this Puppet work
  26. Deployment Dev OpenStack on Prod Team Member DEV01 DEV02 Team

    Member Dev02 DEV02 Dev01 DEV01 Team Member DEV01 Shared Dev BFD02 DEV01 DEV02 Staging STG02 STG01 DEV01 DEV02 Production PRD02 PRD01 Infra Gerrit Jenkins
  27. Deployment in Detail •  Jenkins drives Ansible •  Ansible orchestrates

    deploy across nodes –  Puppet repo updates –  Puppet module updates –  Node ordering –  Pre & Post Health checks
  28. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  29. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  30. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  31. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  32. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  33. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  34. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  35. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  36. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  37. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  38. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  39. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  40. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  41. Region 2 Region 1 Control Control MySQL Cluster Compute Node

    Node Node RabbitMQ Cluster Keystone/Horizon Node Node Node Node Node Nodes Keystone/Horizon Node Node Node HAProxy Node Node MySQL Cluster Node Node Node RabbitMQ Cluster MySQL Cluster Ceph Node Node Nodes Compute Node Node Nodes Ceph Node Node Nodes HAProxy Node Node Build Server Puppet Cobbler Build Server Puppet Cobbler
  42. Deployment options •  Can limit deploy to specific nodes • 

    Can force Galera restart, Rabbit restart, etc •  Can trigger managed reboots
  43. Deployment Improvements •  More and better pre/post checks ◦  Rabbit

    cluster ◦  Ceph health ◦  Swift health •  More parallelization •  More targeted deploys •  Better release note generation