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

A Practical Guide to Cloud-Native Java Apps & Continuous Delivery

A Practical Guide to Cloud-Native Java Apps & Continuous Delivery

I've presented this deck at JavaOne 2016, where I showed how to get started with getting a simple Java app to run on Kubernetes in minutes, make changes on your workstation, and deploying it onto a Kubernetes cluster instantly. I then introduced concepts of continuous delivery, focusing on monitoring the app with Prometheus. Having shown a simple app, the presentation follows up with a complete microservices demo app, a sock shop that uses Spring as well as non-Java services (including Node.js and Go).

121dcfb4f05ed316247772545e2cd590?s=128

Ilya Dmitrichenko

October 02, 2017
Tweet

Transcript

  1. @errordeveloper A Practical Guide to Cloud-Native Java Apps & Continuous

    Delivery
  2. Microservices BoF Oct 2, 6:30 pm, room 2002 with Chris

    Richardson, Josh Long, & Ilya Dmitrichenko Kubernetes BoF Oct 2, 7:30 pm, room 2002 with Ilya Dmitrichenko & Tamao Nakahara
  3. outline: – our story – technical intro – gitops theory

    – tutorial
  4. outline: – our story – technical intro – gitops theory

    – tutorial
  5. – our story what do we do?

  6. – our story what we offer?

  7. – our story how I benefit?

  8. Kubernetes: what is it?

  9. Kubernetes: how it works?

  10. Kubernetes: say more?

  11. apiVersion: v1 kind: Pod metadata: name: java-demo labels:{ app: java-demo

    } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  12. apiVersion: v1 kind: Pod metadata: name: java-demo labels:{ app: java-demo

    } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  13. apiVersion: v1 kind: Pod metadata: name: java-demo labels:{ app: java-demo

    } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  14. apiVersion: v1 kind: Pod metadata: name: java-demo labels:{ app: java-demo

    } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  15. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: <ReplicaCount> selector:{ matchLabels: <PodLabels> } template: <PodSpec>
  16. ReplicaCount = 3 PodLabels = { app: java-demo } PodSpec

    = { metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }] }
  17. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: <ReplicaCount> selector:{ matchLabels: <PodLabels> } template: <PodSpec>
  18. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels: <PodLabels> } template: <PodSpec>
  19. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: <PodSpec>
  20. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  21. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  22. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  23. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  24. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  25. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  26. apiVersion: apps/v1beta2 kind: Deployment metadata: name: java-demo labels:{ app: java-demo

    } spec: replicas: 3 selector:{ matchLabels:{ app: java-demo } } template: metadata: { labels:{ app: java-demo } } spec: containers: - name: server image: java-demo:v0.0.1 ports: [{ containerPort: 8080 }]
  27. kubectl apply -f deployment.yaml

  28. > kubectl get deployment java-demo NAME DESIRED CURRENT UP-TO-DATE AVAILABLE

    AGE java-demo 3 3 3 3 1m > kubectl get pods -l app=java-demo NAME READY STATUS RESTARTS AGE java-demo-307071-c93l1 1/1 Running 0 1m java-demo-307071-f6nfc 1/1 Running 0 1m java-demo-307071-x4rr8 1/1 Running 0 1m
  29. apiVersion: v1 kind: Service metadata: name: java-demo labels:{ app: java-demo

    } spec: type: LoadBalancer selector:{ app: java-demo } ports: - name: http protocol: TCP port: 80 targetPort: 8080
  30. apiVersion: v1 kind: Service metadata: name: java-demo labels:{ app: java-demo

    } spec: type: LoadBalancer selector:{ app: java-demo } ports: - name: http protocol: TCP port: 80 targetPort: 8080
  31. apiVersion: v1 kind: Service metadata: name: java-demo labels:{ app: java-demo

    } spec: type: LoadBalancer selector:{ app: java-demo } ports: - name: http protocol: TCP port: 80 targetPort: 8080
  32. kubectl apply -f service.yaml

  33. > kubectl describe service java-demo Name: java-demo Labels: app=java-demo Selector:

    app=java-demo Type: LoadBalancer IP: 10.39.245.50 LoadBalancer Ingress: 35.197.214.121 Port: http 80/TCP Endpoints: 10.36.1.79:8080,10.36.1.80:8080,10.36.1.81:8080 ... > curl http://35.197.214.121/ Hello, JavaOne '17!
  34. > kubectl get pods -l app=java-demo -o wide NAME READY

    STATUS IP ... java-demo-307071-c93l1 1/1 Running 10.36.1.80 java-demo-307071-f6nfc 1/1 Running 10.36.1.79 java-demo-307071-x4rr8 1/1 Running 10.36.1.81
  35. Prometheus: what is it?

  36. Prometheus: how it works?

  37. Prometheus: say more?

  38. > curl http://35.197.214.121/prometheus ... # HELP process_starttime_seconds The starttime of

    the Java virtual machine # TYPE process_starttime_seconds gauge process_starttime_seconds 1.506735317456E9 # HELP process_uptime_seconds The uptime of the Java virtual machine # TYPE process_uptime_seconds gauge process_uptime_seconds 145236.015
  39. > curl http://35.197.214.121/prometheus ... # HELP http_requests_duration_seconds Timer of servlet

    request # TYPE http_requests_duration_seconds summary http_requests_duration_seconds_count{method="GET",status=" 200",uri="/"} 2.0 http_requests_duration_seconds_sum{method="GET",status="20 0",uri="/"} 0.05230485
  40. process_uptime_seconds

  41. process_uptime_seconds{job=“default/java-demo”}

  42. http_requests_duration_seconds_count

  43. http_requests_duration_seconds_count{ job=“default/java-demo”, method=“GET”, uri=“/”, }

  44. sum( http_requests_duration_seconds_count{ job=“default/java-demo”, method=“GET”, uri=“/”, } )

  45. sum( rate( http_requests_duration_seconds_count{ job=“default/java-demo”, method=“GET”, uri=“/”, }[1m] ) )

  46. – gitops theory

  47. – gitops theory • any developer can use git •

    anyone can join team and ship a new app or make changes easily • all changes can be stored, audited and validated in git and we didn’t have to do anything very new or clever =)
  48. – gitops theory • config is code • code (&

    config!) must be version controlled • CD tools that do not record changes in git are harmful
  49. – gitops theory Continuous Delivery/Deployment Image Repo Orchestrator Deploy Synchronizer

    Config change Manual deployment Git Code change Git Update Hint Continuous Integration Deploy Automator CI Pipeline
  50. – kube pitfalls

  51. I just go and kubectl all the things; great!

  52. Maybe, I should get my CI to do kubectl!

  53. – more gitops

  54. – more gitops •everything is checked in git •easy to

    deploy the entire stack locally •easy to fork a cluster •easy to detect ad-hoc changes, alert/undo
  55. – more gitops •git is the source of truth •review

    process is the same as for code •infra changes go through review process •you are free to use whatever tools
  56. tutorial part 1: deploying Spring Boot app to Kubernetes, step-by-step

    http://github.com/errordeveloper/prom-java-demo
  57. tutorial part 2: deploying Socks Shop to Kubernetes, the gitops

    way
  58. cloud.weave.works

  59. ilya@weave.works slack.weave.works

  60. Microservices BoF Oct 2, 6:30 pm, room 2002 with Chris

    Richardson, Josh Long, & Ilya Dmitrichenko Kubernetes BoF Oct 2, 7:30 pm, room 2002 with Ilya Dmitrichenko & Tamao Nakahara