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

Infrastructure testing with Jenkins, Puppet and...

Infrastructure testing with Jenkins, Puppet and Vagrant

Extend Continuous Integration to automatically test your infrastructure.

Continuous Integration can be extended to test deployments and production environments, in a Continuous Delivery cycle, using infrastructure-as-code tools like Puppet, allowing to manage multiple servers and their configurations, and test the infrastructure the same way continuous integration tools do with developers’ code.

Puppet is an infrastructure-as-code tool that allows easy and automated provisioning of servers, defining the packages, configuration, services, … in code. Enabling DevOps culture, tools like Puppet help drive Agile development all the way to operations and systems administration, and along with continuous integration tools like Jenkins, it is a key piece to accomplish repeatability and continuous delivery, automating the operations side during development, QA or production, and enabling testing of systems configuration.

Using Vagrant, a command line automation layer for VirtualBox, we can easily spin off virtual machines with the same configuration as production servers, run our test suite, and tear them down afterwards.

We will show how to set up automated testing of an application and associated infrastructure and configurations, creating on demand virtual machines for testing, as part of your continuous integration process.

Avatar for Carlos Sanchez

Carlos Sanchez

October 29, 2013
Tweet

More Decks by Carlos Sanchez

Other Decks in Technology

Transcript

  1. Fear of change Risky deployments It works on my machine!

    Siloisation Dev Change vs. Ops stability
  2. manifests ruby-like ERB templates exec { "maven-untar": command => "tar

    xf /tmp/x.tgz", cwd => "/opt", creates => "/opt/apache-maven-${version}", path => ["/bin"], } -> file { "/usr/bin/mvn": ensure => link, target => "/opt/apache-maven-${version}/bin/mvn", } file { "/usr/local/bin/mvn": ensure => absent, require => Exec["maven-untar"], } file { "$home/.mavenrc": mode => "0600", owner => $user, content => template("maven/mavenrc.erb"), require => User[$user], }
  3. Vagrant Virtual and cloud automation VirtualBox VMWare Fusion AWS Rackspace

    Easy Puppet and Chef provisioning Keep VM configuration for different projects Share boxes and configuration files across teams base box + configuration files
  4. using Vagrant $ gem install vagrant $ vagrant box add

    centos-6.0-x86_64 \ http://dl.dropbox.com/u/1627760/centos-6.0-x86_64.box $ vagrant init myproject $ vagrant up $ vagrant ssh $ vagrant suspend $ vagrant resume $ vagrant destroy
  5. Vagrant.configure("2") do |config| # Every Vagrant virtual environment requires a

    box to build off of. config.vm.box = "CentOS-6.4-x86_64-minimal" config.vm.box_url = "https://.../CentOS-6.4-x86_64-minimal.box" # web server config.vm.define :www do |config| config.vm.hostname = "www.acme.local" config.vm.network "forwarded_port", guest: 80, host: 10080 config.vm.network "private_network", ip: "192.168.33.12" end config.vm.provision :puppet do |puppet| puppet.module_path = "modules" puppet.manifest_file = "site.pp" end end Vagrant
  6. What am I doing to automate deployment Ant tasks plugin

    ssh commands Assembly plugin Cargo Capistrano
  7. What can I do to automate deployment Handle full deployment

    including infrastructure not just webapp deployment Help Ops with clear, automated manifests Ability to reproduce production environments in local box using Vagrant / VirtualBox / VMWare Use the right tool for the right job
  8. Installing Maven $repo1 = { id => "myrepo", username =>

    "myuser", password => "mypassword", url => "http://repo.acme.com", } # Install Maven class { "maven::maven": version => "2.2.1", } -> # Create a settings.xml with the repo credentials class { "maven::settings" : servers => [$repo1], }
  9. New Maven type maven { "/tmp/maven-core-2.2.1.jar": id => "org.apache.maven:maven-core:jar:2.2.1", repos

    => ["http://repo1.maven.apache.org/maven2", "http://mirrors.ibiblio.org/pub/mirrors/maven2"], }
  10. New Maven type maven { "/tmp/maven-core-2.2.1.jar": groupId => "org.apache.maven", artifactId

    => "maven-core", version => "2.2.1", packaging => "jar", repos => ["http://repo1.maven.apache.org/maven2", "http://mirrors.ibiblio.org/pub/mirrors/maven2"], }
  11. Continuous Delivery developer commit git repo jenkins binary repository QA

    vm db tomcat* www post commit hook build integration testing production
  12. Puppet Modules required $ bundle install && librarian-puppet install forge

    'http://forge.puppetlabs.com' mod 'puppetlabs/java', '>=1.0.0' mod 'puppetlabs/apache', '>=0.9.0' mod 'puppetlabs/postgresql', '>=3.0.0' mod 'puppetlabs/firewall' mod 'camptocamp/tomcat', :git => 'https://github.com/carlossg/puppet-tomcat.git', :ref => 'setclasspath' mod 'maestrodev/maven', '>=1.0.0' mod 'stahnma/epel', '>=0.0.2' mod 'maestrodev/avahi', '>=1.0.0' mod 'acme', :path => 'mymodules/acme'
  13. mymodules/acme/manifests/db_node.pp class 'acme::db_node' { class { 'postgresql::server': ip_mask_allow_all_users => '192.168.0.0/0',

    listen_addresses => '*', postgres_password => 'postgres', } -> postgresql::server::db { 'appfuse': user => 'appfuse', password => 'appfuse', grant => 'all', } firewall { '100 allow postgres': proto => 'tcp', port => '5432', action => 'accept', } }
  14. mymodules/acme/manifests/tomcat_node.pp I class acme::tomcat_node( $db_host = 'db.local', $repo = 'http://carlos-mbook-pro.local:8000/repository/all/',

    $appfuse_version = '2.2.2-SNAPSHOT', $service = 'tomcat-appfuse', $app_name = 'appfuse', $tomcat_root = '/srv/tomcat') { # install java class { 'java': } # install tomcat class { 'tomcat': } -> # create a tomcat server instance for appfuse # It allows having multiple independent tomcat servers in different ports tomcat::instance { 'appfuse': ensure => present, http_port => 8080, } # where the war needs to be installed $webapp = "${tomcat_root}/${app_name}/webapps/ROOT"
  15. mymodules/acme/manifests/tomcat_node.pp II # install maven and download appfuse war file

    from our archiva instance class { 'wget': } -> class { 'maven::maven' : version => '3.0.4', } -> # clean up to deploy the next snapshot exec { "rm -rf ${webapp}*": } -> maven { "${webapp}.war": id => "org.appfuse:appfuse-spring:${appfuse_version}:war", repos => [$repo], require => File["${tomcat_root}/${app_name}/webapps"], notify => Service[$service], } -> firewall { '100 allow tomcat': proto => 'tcp', port => '8080', action => 'accept', } }
  16. mymodules/acme/manifests/www_node.pp class acme::www_node($tomcat_host = 'tomcat1.local') { class { 'apache': }

    class { 'apache::mod::proxy_http': } # create a virtualhost that will proxy the tomcat server apache::vhost { "${::hostname}.local": port => 80, docroot => '/var/www', proxy_dest => "http://${tomcat_host}:8080", } firewall { '100 allow apache': proto => 'tcp', port => '80', action => 'accept', } }
  17. manifests/nodes/tomcat.pp # tomcat1.acme.com, tomcat2.acme.com,... node /tomcat\d\..*/ inherits ‘parent’ { file

    {'/etc/motd': content => ”tomcat server: ${::hostname}\n”, } class {'acme::tomcat_node'} }
  18. manifests/nodes/qa.pp node /qa\..*/ inherits ‘parent’ { class {'acme::db_node': } class

    {'acme::tomcat_node': db_host => 'localhost', } class {'acme::www_node': tomcat_host => 'localhost', } }
  19. spec/hosts/db_spec.pp require 'rspec-puppet' describe 'db.acme.com' do let(:facts) { { :osfamily

    => 'RedHat', :operatingsystem => 'CentOS', :operatingsystemrelease => ‘6.3’} } it { should contain_class('postgresql::server') } end
  20. spec/hosts/www_spec.pp require 'rspec-puppet' describe 'www.acme.com' do let(:facts) { { :osfamily

    => 'RedHat', :operatingsystem => 'CentOS', :operatingsystemrelease => ‘6.3’} } it { should contain_package('httpd') } end
  21. Photo Credits Brick wall - Luis Argerich http://www.flickr.com/photos/lrargerich/4353397797/ Agile vs.

    Iterative flow - Christopher Little http://en.wikipedia.org/wiki/File:Agile-vs-iterative-flow.jpg DevOps - Rajiv.Pant http://en.wikipedia.org/wiki/File:Devops.png Pimientos de Padron - Howard Walfish http://www.flickr.com/photos/h-bomb/4868400647/ Compiling - XKCD http://xkcd.com/303/ Printer in 1568 - Meggs, Philip B http://en.wikipedia.org/wiki/File:Printer_in_1568-ce.png Relativity - M. C. Escher http://en.wikipedia.org/wiki/File:Escher%27s_Relativity.jpg Teacher and class - Herald Post http://www.flickr.com/photos/heraldpost/5169295832/