Everything-as-code: DevOps und Continuous Delivery aus Sicht des Entwicklers.

Information about Everything-as-code: DevOps und Continuous Delivery aus Sicht des...

Published on November 15, 2017

Author: QAware

Source: slideshare.net

Content

1. #whoami Mario-Leander Reimer Cheftechnologe, QAware GmbH - Senior Developer && Architect - 20+ Jahre Erfahrung - #CloudNativeNerd - Open Source Enthusiast [email protected] http://github.com/lreimer http://speakerdeck.com/lreimer // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

2. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

3. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

4. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

5. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

6. Software Industrialization ist eine Schlüsselanforderung für erfolgreiches DevOps und Continuous Delivery. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

7. Ein Software-Fließband produziert und liefert die fertige Software an. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

8. Software Industrialisierung bedeutet ... • Hoher Automatisiersgrad von arbeitsintensiven und wiederkehrenden Arbeitsschritten • Bessere Software-Qualität durch eine abgestimmte Tool-Chain • Mehr Produktivität und Zufriedenheit der Teams • Kosten-Effizienz und Wettbewerbsfähigkeit // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

9. Die IDE ist unsere Werkbank.

10. val softwareIndustrialization = everythingAsCode() open fun everythingAsCode() = everythingIsMadeFromCode() && everythingIsMadeByCode() private fun everythingIsMadeFromCode() = true private fun everythingIsMadeByCode() = true // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

11. Auf die Domäne kommt es an! Eine beste Programmiersprache gibt es nicht. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

12. Die Queste nach dem idealen Polyglot Project Archetype • Welche Sprachen werden in unseren Projekten in welchen Domänen verwendet? • Welche Tools verwenden wir für Setup, Build, Code, Test, CI, Infrastructure, Documentation? • Was davon hat sich bewährt und was eher nicht? • Gibt es bereits Best Practices oder Anti-Patterns? + Wishful Greenfield Thinking! // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

13. Eine vielsprachige Reise beginnt ...

14. Lightweight Developer Provisioning mit Gradle • [ SEU ] -> Software Entwicklungs Umgebung • Nutzung von Gradle als Build-Tool für das Setup und die Aktualisierung unserer Entwicklungsumgebungen • Software-Pakete werden als Dependencies definiert • Gradle Tasks und Groovy Code statt Shell-Scripting • Versionskontrolle der SEU Definition und Skripte • Open Source. http://seu-as-code.io // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

15. plugins { id 'de.qaware.seu.as.code.base' version '2.4.0' } import static de.qaware.seu.as.code.plugins.base.Platform.isMac seuAsCode { seuHome = { if (isMac()) '/Volumes/Everything-as-code' else 'Y:' } projectName = 'Everything-as-code' } dependencies { // list of software dependencies ... software 'org.groovy-lang:groovy:2.4.7' software 'org.scala-lang:scala:2.11.8' software 'org.jruby:jruby:9.1.4.0' } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

16. # language: en Functionality: Authentication and Authorization Scenario Outline: Check proper login behaviour Given the username "<USERNAME>" And the password "<PASSWORD>" When the user logs into the system Then the login result is "<RESULT>" Examples: Login data | USERNAME | PASSWORD | RESULT | | mario-leander.reimer | invalidpwd | failure | | unknown | somepwd | failure | | mario-leander.reimer | correctpwd | success | // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

17. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

18. Maven ist gut. Gradle ist 100x schneller. • Sehr flexibel und vielseitig einsetzbar. • Einfache Unterstützung für polyglotte Projekte. • Build Skripte sind maximal kurz und prägnant. • Deutlich reduzierte Build-Zeiten durch inkrementelle Builds und Caching • Zahlreiche neue Features: Composite Builds, Kotlin- basierte Build-Skripte, Performance Verbesserungen, ... • Regelmäßige Releases. Stabil und ausgereift. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

19. apply plugin: 'application' apply plugin: 'war' apply plugin: 'kotlin' apply plugin: 'groovy' repositories { jcenter() } dependencies { providedCompile 'fish.payara.extras:payara-micro:4.1.1.164' // and many more ... } task everythingAsCode() << { println 'Everything-as-code using Gradle @ ContinuousLifecycle 2017.' } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

20. Java ist nach wie vor unsere primäre Implementierungssprache! Und das ist gut so! // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

21. Aber: Kotlin als Alternative zu Java ist einen Blick wert! // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

22. Warum Kotlin? Und nicht Scala, Clojure, ... • Für Java Entwickler sehr schnell zu erlernen. • Sehr ausgewogene Universalsprache. • Null Safety + Synatctic Sugar + jede Menge andere nützliche Features. • JDK6 kompatibel. Kleine Library-Größe. • Sehr guter IDE und Tool Support. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

23. @JsonIgnoreProperties(ignoreUnknown = true) data class Book(val title: String, val isbn: String, val author: String) @ApplicationScoped open class Bookshelf { private val books = listOf(Book("The Hitchhiker's Guide to the Galaxy", "0345391802")) open fun byIsbn(isbn: String): Book? = books.find { it.isbn == isbn } } @Path("books") @Produces(MediaType.APPLICATION_JSON) open class BookResource @Inject constructor(private val bookshelf: Bookshelf) { @GET @Path("/{isbn}") open fun byIsbn(@PathParam("isbn") isbn: String): Response { val book = bookshelf.byIsbn(isbn) return if (book != null) Response.ok(book).build() else Response.status(Status.NOT_FOUND).build() } } @ApplicationPath("api") class BookstoreAPI : Application() { override fun getClasses() = hashSetOf(JacksonFeature::class.java, BookResource::class.java) } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

24. Willkommen in der JavaScript Wunderwelt. • Ein Universum für sich! • Klarer Trend: Single Page Webapplikationen. • HTML5 + CSS3 + ? • ? = TypeScript oder • ? = ECMAScript2015 + Babel • Rückgrat des Builds: node + npm + webpack // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

25. Grovy + Spock eignen sich für Unit, Integration, Acceptance und UI-Tests class BookshelfSpec extends Specification { @Subject def bookshelf = new Bookshelf() @Unroll def "Find book #title by ISBN #isbn"() { when: 'we search a book by ISBN' def book = bookshelf.byIsbn(isbn) then: 'the title and author are correct' book?.title == title book?.author == author where: isbn || title | author "0345391802" || "The Hitchhiker's Guide to the Galaxy" | "Douglas Adams" "0345391829" || "Life, the Universe and Everything" | "Douglas Adams" } } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

26. Scala und Gatling für lesbare und performante Last-Tests class BooksPerformanceTest extends Simulation { val conf = http.baseURL("http://localhost:18080").acceptHeader("application/json") val feeder = csv("books.csv").random val scn = scenario("Book Search") .exec(http("Get all books").get("/api/books")) .during(30 seconds) { feed(feeder) .exec(http("Get book by title ${Title}").get("/api/books?title=${Title}")) .pause(1 second) .exec(http("Get book with ISBN ${ISBN}").get("/api/books/${ISBN}")) } setUp(scn.inject(atOnceUsers(10), rampUsers(50) over (30 seconds))) .assertions(global.responseTime.max.lessThan(5000)) .protocols(conf) } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

27. Definition einer Build-Pipeline per Jenkinsfile und Groovy #!/usr/bin/env groovy node { stage 'Checkout SCM' checkout scm stage 'Build/Analyse/Test' sh './gradlew clean build' archiveUnitTestResults() archiveDistributions() stage 'Dockerize' sh './gradlew buildDockerImage' stage 'Generate Documentation' sh './gradlew asciidoctor' } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

28. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

29. Architektur-Definition und Prüfung mit QAvalidator für wartbaren Code. architecture(name: "Mail Example", prefix: "tview", reflexMLversion: "1.0") { excludes "java.lang.*" api "JavaMail" : "javax.mail.*" component "Mail" { api "IMail" : "de.qaware.mail.*" impl ["de.qaware.mail.impl.*", "de.qaware.mail.impl2.*"] uses "JavaMail" component "MailSender" { api ["de.qaware.mail.sender.*", "javax.mail.*"] impl "de.qaware.mail.impl.javamail.JavaMailSender" uses "JavaMail" } } } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

30. Docker, Docker, Docker, ... FROM qaware-oss-docker-registry.bintray.io/base/alpine-k8s-openjdk8:8u121 MAINTAINER M.-Leander Reimer <[email protected]> RUN mkdir -p /app ADD build/distributions/everything-as-code-1.2.3.tar /app WORKDIR /app/everything-as-code-1.2.3 RUN chmod 755 bin/everything-as-code EXPOSE 18080 CMD ./bin/everything-as-code // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

31. Cluster Orchestration mit K8s et.al. --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: everything-as-code spec: replicas: 2 template: metadata: labels: tier: backend spec: containers: - name: everything-as-code image: "qaware-oss-docker-registry.bintray.io/lreimer/everything-as-code:1.2.3" ports: - containerPort: 18080 env: - name: PORT value: 18080 // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

32. Einfache Provisionierung mit Ansible. --- # file: jenkinsci.yml - hosts: jenkinsci remote_user: root tasks: - debug: msg="Creating a Jenkins pipeline job on {{ inventory_hostname }}" - jenkins_job: name: Everything-as-code Pipeline config: "{{ lookup('file', 'templates/pipeline-job.xml') }}" url: "http://{{ inventory_hostname }}" user: admin password: admin // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

33. Vagrant und Ruby zum Setup lokaler VMs. require 'yaml' $setup = <<SCRIPT sudo apt-add-repository ppa:ansible/ansible sudo apt-get update sudo apt-get install -y ansible sshpass SCRIPT Vagrant.configure("2") do |config| config.vm.box = "ubuntu/trusty32" settings = YAML.load_file 'src/vagrant/vagrant.yml' config.vm.provider "virtualbox" do |vb| vb.name = settings['vm']['name'] vb.gui = false vb.memory = "512" end config.vm.provision "shell", inline: $setup end // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

34. Ja, wir brauchen Dokumentation! • Und nein. Der Quellcode ist nicht genug! • Technische Dokumente mit Word sind ! " # • Dokumentation sollte neben dem Quellcode liegen: change code, change docs. • Schnell und einfach zu schreiben. • Unterstützung für Code, Bilder, Diagramme // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

35. // Beispiel Architektur-Dokumentation mit arc42 (https://arc42.github.io) :imagesdir: ./images = image:qaware-logo.png[QAware GmbH,2016] Everything-as-code :toc-title: Table of Contents :toc: [[section-introduction-and-goals]] == Introduction and Goals The introduction to the architecture documentation should list the driving forces that software architects must consider in their decisions. === Requirements Overview === Quality Goals === Stakeholders <<<< include::02_architecture_constraints.adoc[] // further includes for the remaining sections // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

36. Mit AsciidoctorJ und Gradle zum fertigen Dokument. plugins { id "org.asciidoctor.convert" version "1.5.3" } asciidoctorj { version = '1.5.4.1' } asciidoctor { sourceDir 'src/docs/architecture' resources { from('src/docs/architecture') { include 'images/**/*.png' include 'images/**/*.jpg' } } backends ['html5', 'pdf'] options doctype: 'article' attributes 'source-highlighter': 'coderay' } // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

37. Architectur-Dokumentation mit Structurizr def workspace = new Workspace("Everything-as-code", "The system context of Everything-as-code.") def model = workspace.model // create a model and the software system we want to describe def bookApp = model.addSoftwareSystem("Book Application", "The best source to get info on books.") // create the various types of people (roles) that use the software system def anonymousUser = model.addPerson("Anonymous User", "Anybody on the web.") anonymousUser.uses(bookApp, "Searches for books and views details.") def browser = bookApp.addContainer("Web Browser", "Allows users to view information about books", "Edge, Chrome, Firefox") anonymousUser.uses(browser, "Views information from and makes requests to") def webApp = bookApp.addContainer("Web Application", "Hosts the browser-based web application and services", "Payara Fish") browser.uses(webApp, "uses [JSON/HTTPS]") // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

38. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

39. These slides were written in Markdown. --- ## [fit] These slides were written in Markdown. - This is for real programmers! :smiley: - Several open source projects available - Use HTML and JavaScript alternatively. --- // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

40. Use the right tool for the job!

41. Alles mit Augenmaß! Der richtige Technologie-Stack hängt vom Team, dem Projekt-Kontext und unseren Kunden ab. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

42. Fork me on GitHub. https://github.com/lreimer/everything-as-code // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

43. // ContinuousLifecycle 2017 // Everything-as-code -> { created with ❤ and ☕ by @LeanderReimer @qaware }

#whoami presentations

Zer 0 no zer(0 day)   dragon jar
25. 09. 2020
0 views

Zer 0 no zer(0 day) dragon jar

Related presentations


Other presentations created by QAware

The Cloud Native Stack
02. 05. 2016
0 views

The Cloud Native Stack

Cloud Native Unleashed
14. 06. 2016
0 views

Cloud Native Unleashed

Cloud-native Java EE-volution
08. 11. 2017
0 views

Cloud-native Java EE-volution

QAware Big Data Landscape 2018
09. 01. 2018
0 views

QAware Big Data Landscape 2018

Clusterless mit AWS Fargate
14. 11. 2018
0 views

Clusterless mit AWS Fargate

Machine Learning made easy
22. 02. 2019
0 views

Machine Learning made easy

Big Data Landscape 2019
25. 02. 2019
0 views

Big Data Landscape 2019

K8s is not for App Developers
14. 06. 2019
0 views

K8s is not for App Developers

Building ML Pipelines with DCOS
10. 07. 2019
0 views

Building ML Pipelines with DCOS

Modeling Moods
23. 09. 2019
0 views

Modeling Moods

GitOps: Pain 'n Gain
31. 07. 2020
0 views

GitOps: Pain 'n Gain

Hack Me If You Can
01. 10. 2020
0 views

Hack Me If You Can