Slide 1

Slide 1 text

Kubernetes & Co, beyond the hype 10 tips for designers who want to create cloud native apps

Slide 2

Slide 2 text

Alexandre Touret Architect / Developer #Java #API #CI #Cloud #Software_Craftsmanship 2 @touret_alex https://blog.touret.info

Slide 3

Slide 3 text

Some context... 1.

Slide 4

Slide 4 text

4

Slide 5

Slide 5 text

Used technologies 5

Slide 6

Slide 6 text

Do you REALLY need it?

Slide 7

Slide 7 text

Small business application Controlled scope Automatized deployments already implemented 7

Slide 8

Slide 8 text

What are the NFRs? Do you have constraining SLOs? (eg. >99% SLA availability) Does your system need to be dynamically scaled? 8

Slide 9

Slide 9 text

Providing « on demand » environments 9 Do you need to deliver environments on demand (and really fast)?

Slide 10

Slide 10 text

Docker & Cie basics

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

You will have to know… 12

Slide 13

Slide 13 text

13

Slide 14

Slide 14 text

Organization

Slide 15

Slide 15 text

«Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.» — M. Conway 15

Slide 16

Slide 16 text

What’s the associated RACI ? Is your organisation compatible? 16 RACI & Responsabilies

Slide 17

Slide 17 text

The stateless apps and the others…

Slide 18

Slide 18 text

18 Codebase One codebase tracked in revision control, many deploys Dependencies Explicitly declare and isolate dependencies Config Store config in the environment Backing Services Treat backing services as attached resources Build, release, run Strictly separate build and run stages Backing Services Treat backing services as attached resources Processes Execute the app as one or more stateless processes Port Binding Export services via port binding Disposability Maximize robustness with fast startup and graceful shutdown Dev/prod parity Keep development, staging, and production as similar as possible Logs Treat logs as event streams Admin processes Run admin/management tasks as one-off processes Source: https://12factors.net

Slide 19

Slide 19 text

19 For an API

Slide 20

Slide 20 text

(Fast) application startup

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

Choose wisely your frameworks and target runtime platforms

Slide 23

Slide 23 text

23

Slide 24

Slide 24 text

24 Items to check ✓ Fast startup ✓ Shutdown handling ✓ Ability to be integrated into Docker and K8S ✓ Observability ✓ Memory and CPU consumption ✓ Dependency and patch management

Slide 25

Slide 25 text

TOMCAT vs FAT JARS → Production – Development teams trade-off 25

Slide 26

Slide 26 text

Observability

Slide 27

Slide 27 text

Address this point from design phase Don’t wait for the production deployment Expose your system status through endpoints Be careful to the used FRAMEWORKS 27

Slide 28

Slide 28 text

liveness & readiness probes livenessProbe: failureThreshold: 3 httpGet: path: /actuator/health/liveness port: http scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 28 readinessProbe: failureThreshold: 3 httpGet: path: /actuator/health/readiness port: http scheme: HTTP initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 1

Slide 29

Slide 29 text

Spring Actuator management.health.probes.enabled=true management.endpoints.enabled-by-default=true management.health.livenessstate.enabled=true management.health.readinessstate.enabled=true management.endpoint.health.show-details=always management.endpoint.health.probes.enabled=true management.endpoint.health.enabled=true LivenessStateHealthIndicator & ReadinessStateHealthIndicator 29

Slide 30

Slide 30 text

30 @Component public class MongoDBActuatorHealthIndicator implements HealthIndicator { [...] @Override public Health health() { // ping database } @Override public Health getHealth(boolean includeDetails) { if (!includeDetails) { return health(); } else { var statuses = mongoDBHealthService.findStatusForAllConfigurations(); return Health.status(checkStatus(statuses)).withDetails(statuses).build(); } } [...] }

Slide 31

Slide 31 text

Monitoring ▪ Micrometer ▪ Prometheus ▪ Grafana 31

Slide 32

Slide 32 text

32 management: endpoints: enabled-by-default: true web: exposure: include: '*' jmx: exposure: include: '*' endpoint: health: show-details: always enabled: true probes: enabled: true shutdown: enabled: true prometheus: enabled: true metrics: enabled: true health: livenessstate: enabled: true readinessstate: enabled: true datasource: enabled: true metrics: web: client: request: autotime: enabled: true Actuator configuration Metrics configuration

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Steps to integrate in your CI/CD pipeline ✓ Unit and integration tests ✓ Docker image creation ✓ Created docker image “Smoke tests” ✓ Continuous deployment of your develop branch ✓ HELM charts deployment ✓ Release deployment ✓ ... 34

Slide 35

Slide 35 text

Example Spring Boot, Tomcat, JDK Migration Tested locally → Dev → Staging ⇒ In one day 35

Slide 36

Slide 36 text

Configuration

Slide 37

Slide 37 text

37 ▪ Environment variables ▪ Config Maps ▪ Secrets

Slide 38

Slide 38 text

Environment variables spec: containers: - env: - name: JAVA_OPTS value: >- -XX:+UseContainerSupport -XX:MaxRAMPercentage=70.0 -Dfile.encoding=UTF-8 - Djava.security.egd=file:/dev/./urandom 38

Slide 39

Slide 39 text

Config maps apiVersion: v1 kind: ConfigMap metadata: creationTimestamp: 2021-03-11T18:38:34Z name: my-config-map [...] data: JAVA_OPTS: >- -XX:+UseContainerSupport -XX:MaxRAMPercentage=70.0 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom 39

Slide 40

Slide 40 text

What about configuration files? We can specify them as variables in config maps We can also externalize them 40

Slide 41

Slide 41 text

Files in config maps volumeMounts: - mountPath: /config name: configuration-volume readOnly: true [...] volumes: - configMap: defaultMode: 420 name: configuration name: configuration-volume 41 apiVersion: v1 kind: ConfigMap [...] data: my.conf: {{- (.Files.Glob "conf/*").AsConfig | nindent 2 }}

Slide 42

Slide 42 text

Externalize values apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: labels: [...] spec: maxReplicas: {{ .Values.myapp.maxReplicaCount }} minReplicas: {{ .Values.myapp.minReplicaCount }} [...] targetCPUUtilizationPercentage: {{ .Values.myapp.replicationThreesold }} 42

Slide 43

Slide 43 text

Values.yml myapp: minReplicaCount: "2" maxReplicaCount: "6" replicationThreesold: 80 43

Slide 44

Slide 44 text

File templates apiVersion: v1 kind: ConfigMap metadata: name: configuration labels: [...] data: application.properties: |- {{ tpl (.Files.Get "conf/application.properties") . | nindent 4}} 44

Slide 45

Slide 45 text

Templates application.properties file logging.level.org.hibernate.stat={{ .Values.configmap.application.org_hib ernate_stat }} logging.level.org.springframework.sec urity={{ .Values.configmap.application.org_spr ingframework_security }} 45 values.yml file configmap: application: org_hibernate_stat: ERROR org_springframework_security: ERROR

Slide 46

Slide 46 text

Binary files apiVersion: v1 # Definition of secrets kind: Secret [...] type: Opaque # Inclusion of binary configuration files data: my_keystore.jks: {{ .Files.Get "secrets/my_keystore.jks" | b64enc }} 46

Slide 47

Slide 47 text

Efficiently logging

Slide 48

Slide 48 text

Log management In the console: kubectl logs --tail Logs aggregator (ex. ELK) 48

Slide 49

Slide 49 text

Docker containers output stream stdout & stderr It’s useless to setup a file output stream 49

Slide 50

Slide 50 text

Best practices Indicate in your LOGS: Container informations (image name, container ID,…) Kubernetes related informations (POD @IP, POD ID, namespace,...) Log4j Docker Support – Log4j Kubernetes Support 50

Slide 51

Slide 51 text

To go further You can identify the related informations of the APIs calls: Caller ID, Correlation ID, request data,… zalando/logbook: An extensible Java library for HTTP request and response logging 51

Slide 52

Slide 52 text

Distributed tracing You can identify and correlate your API calls on your microservices based architecture by implement Opentracing 52

Slide 53

Slide 53 text

53

Slide 54

Slide 54 text

Thanks! Any question? 54