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.

Infrastructure automation with Gradle and Puppet for GR8Conf EU 2015

1,712 views

Published on

Infrastructure-as-code is becoming a mandatory part of any successful project. During this presentation we will show how to use Gradle plugins and Puppet manifests to provision and maintain consistent infrastructure configuration. We will also touch tools like Jenkins, Vagrant, Packer, VirtualBox and AWS.

Published in: Technology
  • Be the first to comment

Infrastructure automation with Gradle and Puppet for GR8Conf EU 2015

  1. 1. 01
  2. 2. About me 02
  3. 3. Andrey Adamovich Bio: Developer, coach, speaker, author Company: Aestas/IT (http://aestasit.com) E­mail: andrey@aestasit.com Linkedin: http://www.linkedin.com/in/andreyadamovich Lanyrd: http://lanyrd.com/profile/andrey­adamovich GitHub: https://github.com/aadamovich SO: http://stackoverflow.com/users/162792/andrey­adamovich Twitter: @codingandrey, @aestasit • • • • • • • • 03
  4. 4. Workshop structure Preparations and installation Introduction, background, path, reasoning Demo and try­out of (biased) integration of Gradle + Puppet • • • 04
  5. 5. WARNING! 05
  6. 6. Preparation 06
  7. 7. Install tools Gradle 2.+ VirtualBox 4.3.+ Vagrant 1.7.+ • • • 07
  8. 8. Vagrant box Download Vagrant box file: http://bit.ly/1M5shfd Register box in Vagrant: vagrant box add puphpet/ubuntu1404‐x64 ub...x.box ‐‐force • • 01. 08
  9. 9. Project source Source: http://bit.ly/1LYylpk Slides: http://bit.ly/1BFXuzD • • 09
  10. 10. Project setup (step 1) Download Tomcat 8 from apache­tomcat­8.0.18.tar.gz and put it into the  repository  directory. Build the  petclinic  application ( gradle clean build ) in the application/spring‐petclinic  directory and place the application/spring‐petclinic/build/libs/petclinic‐0.1‐ SNAPSHOT.war  archive into the  repository  directory. • • 10
  11. 11. Project setup (step 2) Run  vagrant up  to start all the virtual machines. Run  gradle initNode  to initialize software needed for provisioning (Puppet) to work. Run  gradle puppetapply  to apply Puppet configuration to virtual servers. • • • 11
  12. 12. Timing Download tomcat ~ 4 minutes spring­petclinic/ gradle clean build  ~ 3 minutes (+ library download) vagrant up  ~ 15 minutes (­ vagrant box) gradle initNode  ~ 4 minutes gradle puppetApply  ~ 8 minutes • • • • • 12
  13. 13. Background 13
  14. 14. Background Big projects built by Ant, Maven, and eventually Gradle Teams composed mostly of Java developers Complex (sometimes, over­engineered) architectures Many environments (DEV, TEST, QA, SIT, UAT, PRE­PROD, PROD) to support • • • • 14
  15. 15. Problems I Infrastructure is influenced by (relatively) frequent architecture changes (components, versions, layers) We want our environments to be the same (or at least quite similar) to avoid any side effects during development, testing and production We don't want to spend hours/days/weeks on configuring each and every new server and keeping them in­sync • • • 15
  16. 16. Problems II Operations guys are not always available (e.g. busy supporting production systems or just not skilled enough) Development infrastructure (Jenkins, Sonar, Version Control, Load Testing etc.) also needs maintenance We want to reuse experience available in our team and avoid throwing in too many various trendy technologies that will fail our expectations • • • 16
  17. 17. Automation is the key! 17
  18. 18. Questions How do I connect (ssh) to my server to perform actions required for deployment? How do I store my configuration for various servers? How do I store secrets? How do I ensure that remote server has everything on it to run my application? How do I verify that my automation works (prefferably without breaking anything important)? • • • • 18
  19. 19. Changing architecture 19
  20. 20. Local development 20
  21. 21. Splitting layers 21
  22. 22. Scaling out 22
  23. 23. Fail­over 23
  24. 24. Performance tuning 24
  25. 25. Maintaining system 25
  26. 26. What if? 26
  27. 27. Or even? 27
  28. 28. Splitting layers 28
  29. 29. Scaling out 29
  30. 30. Maintaining system 30
  31. 31. Late alignment issues 31
  32. 32. Similarity levels DEV << QA <<< PROD DEV < QA < PROD DEV ~ QA ~ PROD DEV = QA = PROD 1. 2. 3. 4. 32
  33. 33. Infrastructure as code 33
  34. 34. Keep it in version control 34
  35. 35. Connectivity 35
  36. 36. How do I connect to my server?36
  37. 37. First Blood 37
  38. 38. Ant + Gradle ant.taskdef(   name: 'scp',    classname: 'o.a.t.a.t.o.ssh.Scp',    classpath: configurations.secureShell.asPath)  ant.taskdef(   name: 'sshexec',    classname: 'o.a.t.a.t.o.ssh.SSHExec',    classpath: configurations.secureShell.asPath)  01. 02. 03. 04. 05.06. 07. 08. 09. 38
  39. 39. Simple call ant.sshexec(   host: host,    username: user,    password: password,    command: command,    trust: 'true',    failonerror: failOnError) 01. 02. 03. 04. 05. 06. 07. 39
  40. 40. Next step: wrapper function def ssh(String command,          Properties props,          boolean failOnError = false,          String suCommandQuoteChar = "'",          String outputProperty = null) {   ...  } 01. 02. 03. 04. 05. 06. 07. 40
  41. 41. Next step: wrapper function def scp(String file,          String remoteDir,          Properties props) {   ... } 01. 02. 03. 04. 05. 41
  42. 42. Task example I task installFonts << {   forAllServers { props ‐>     ssh('yes | yum install *font*', props)   } } 01. 02. 03. 04. 05. 42
  43. 43. Task example II task uninstallNginx  << {   forAllServers { props ‐>     ssh('/etc/init.d/nginx stop', props)     ssh('yes | yum remove nginx', props, true)     ssh('rm ‐rf /etc/yum.repos.d/nginx.repo', props)     ssh('rm ‐rf /var/log/nginx', props)     ssh('rm ‐rf /etc/nginx /var/nginx', props)   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 43
  44. 44. Drawbacks New connection each time Excplicit repeating parameters Complex scripts are hard to maintain Tasks are not idempotent • • • • 44
  45. 45. Libraries jsch sshj overthere sshoogr • • • • 45
  46. 46. Sshoogr 46
  47. 47. Sshoogr features Groovy­based SSH DSL for: Remote command execution File uploading/downloading Tunneling • • • 47
  48. 48. Sshoogr usage (import) @Grab(   group='com.aestasit.infrastructure.sshoogr',   module='sshoogr',   version='0.9.16') import static com.aestasit.ssh.DefaultSsh.* 01. 02. 03. 04. 05. 48
  49. 49. Sshoogr usage (defaults) defaultUser    = 'root' defaultKeyFile = new File('secret.pem') execOptions {   verbose      = true   showCommand  = true } 01. 02. 03. 04. 05. 06. 49
  50. 50. Sshoogr usage (connection) remoteSession {   url = 'user2:654321@localhost:2222'   exec 'rm ‐rf /tmp/*'   exec 'touch /var/lock/my.pid'   remoteFile('/var/my.conf').text = "enabled=true" } 01. 02. 03. 04. 05. 06. 50
  51. 51. Sshoogr usage (multi­line content) remoteFile('/etc/yum.repos.d/puppet.repo').text = '''   [puppet]   name=Puppet Labs Packages   baseurl=http://yum.puppetlabs.com/el/   enabled=0   gpgcheck=0 ''' 01. 02. 03. 04. 05. 06. 07. 51
  52. 52. Sshoogr usage (file copying) remoteSession {   scp {     from { localDir "$buildDir/application" }     into { remoteDir '/var/bea/domain/application' }   } } 01. 02. 03. 04. 05. 06. 52
  53. 53. Sshoogr usage (command result) def result = exec(command: '/usr/bin/mycmd',   failOnError: false, showOutput: false) if (result.exitStatus == 1) {   result.output.eachLine { line ‐>     if (line.contains('WARNING')) {       throw new RuntimeException("Execution failed with: ${line}")     }   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 53
  54. 54. Sshoogr usage (shortcuts) if (ok('/usr/bin/mycmd')) {   ... } if (fail('/usr/bin/othercmd')) {   ... } 01. 02. 03. 04. 05. 06. 54
  55. 55. Sshoogr usage (tunnels) tunnel('1.2.3.4', 8080) { int localPort ‐>   def url = "http://localhost:${localPort}/flushCache"   def result = new URL(url).text   if (result == 'OK') {     println "Cache is flushed!"   } else {     throw new RuntimeException(result)   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 55
  56. 56. Sshoogr usage (prefix/suffix) prefix('sudo ') {   exec 'rm ‐rf /var/log/abc.log'   exec 'service abc restart' } suffix(' >> output.log') {   exec 'yum ‐y install nginx'   exec 'yum ‐y install mc'   exec 'yum ‐y install links' } 01. 02. 03. 04. 05. 06. 07. 08. 09. 56
  57. 57. From scripts to declarations57
  58. 58. Puppet 58
  59. 59. Puppet example 59
  60. 60. Puppet provisioning 60
  61. 61. Puppet provisioning 61
  62. 62. Puppet provisioning 62
  63. 63. Puppet provisioning 63
  64. 64. Puppet state management 64
  65. 65. Puppet state management 65
  66. 66. Puppet state management 66
  67. 67. Puppet modules 67
  68. 68. Puppet modules 68
  69. 69. Puppet modules 69
  70. 70. Deployment vs. Infrastructure management70
  71. 71. Push vs. Pull 71
  72. 72. Pull 72
  73. 73. Push 73
  74. 74. Push imple­ mentation 74
  75. 75. Sshoogr + Gradle + Puppet75
  76. 76. Upload modules task uploadModules << {   remoteSession {     exec 'rm ‐rf /tmp/repo.zip'     scp {       from { localFile "${buildDir}/repo.zip" }       into { remoteDir "/root" }     }     ... 01. 02. 03. 04. 05. 06. 07. 08. 76
  77. 77. Upload modules     ...     exec 'rm ‐rf /etc/puppet/modules'     exec 'unzip /tmp/repo.zip ‐d /etc/puppet/modules'   } } 01. 02. 03. 04. 05. 77
  78. 78. Apply manifests task puppetApply(dependsOn: uploadModules) << {   remoteSession {     scp {       from { localFile "${buildDir}/setup.pp" }       into { remoteDir "/tmp" }     }     exec 'puppet apply /tmp/setup.pp'   } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 78
  79. 79. What we solved? Separated infrastructure state description and operations tasks Scripts became more maintainable and idempotent • • 79
  80. 80. Declaration reuse 80
  81. 81. How do I store my configuration?81
  82. 82. Maven profiles 82
  83. 83. *.properties files 83
  84. 84. ConfigSlurper 84
  85. 85. Topology What to do if environment has more than 1 server? 85
  86. 86. Server roles 86
  87. 87. Hiera 87
  88. 88. External dependencies 88
  89. 89. Puppet module tool... 89
  90. 90. is not that good! 90
  91. 91. Puppet module repositories Puppet forge Pulp GitHub Maven as a repository • • • • 91
  92. 92. Dependencies managers Puppet module tool Puppet librarian r10k Puppet Module Installer • • • • 92
  93. 93. Demo / Playground 93
  94. 94. Summary 94
  95. 95. Configuration code coverage 95
  96. 96. Images, manifests, tasks 96
  97. 97. Questions? 97
  98. 98. Thank you! 98
  99. 99. Happy infrastructure management!99

×