seanmayer / spring-microservices-refresher

Java, Docker, Kubernetes, client side load balancing, dynamic scaling, fault tolerance, etc
3 stars 0 forks source link
docker docker-compose eureka kubernetes microservice microservices resillence4j spring-boot spring-cloud zipkin

Spring Microservices Refresher (SMR)

Introduction

Microservices Overview

Screenshot

Naming Server

In a microservice architecture, a naming server serves as a registry for service discovery. Each microservice in the system has a unique name and runs on its own address, and the naming server maintains a mapping between the service names and their addresses. When a client wants to access a certain microservice, it can query the naming server to find the address of the service it needs. This eliminates the need for hard-coded addresses and allows for dynamic reconfiguration of the system as services come and go. The naming server plays a crucial role in the seamless functioning of a microservice-based system.

Screenshot

In this example we use Eureka naming server.

Screenshot

Load Balancing

In a microservice architecture, a load balancer is an important component that sits between the client and the microservices. Its primary function is to distribute incoming requests to multiple instances of a microservice, improving system reliability and scalability.

When a client makes a request, the load balancer routes it to one of the available instances of the target microservice. This helps to evenly distribute the incoming request load, avoid overloading any single instance, and prevent a single point of failure. In case an instance of the microservice fails, the load balancer can detect this and redirect requests to other healthy instances.

By using a load balancer, microservice-based systems can dynamically scale up or down the number of instances of a service based on the incoming request volume, ensuring that the system remains responsive and resilient even under high load.

Screenshot

API Gateway (Spring Cloud Gateway)

An API gateway is a single entry point for all requests from clients to the backend services in a microservice architecture. It sits between the client and the microservices and routes requests to the appropriate microservice. It also provides a single place to apply common cross-cutting concerns such as security, monitoring, and resiliency.

Obeservability and OpenTelemetry

Distributed Tracing (Zipkin)

Distributed tracing is a technique that helps to monitor and troubleshoot complex distributed systems. It allows developers to trace the flow of a request as it is processed by multiple microservices. This helps to identify performance bottlenecks and errors in the system.

Screenshot

In this example we use Zipkin distributed tracing.

  1. docker run -d -p 9411:9411 openzipkin/zipkin
  2. http://localhost:9411/zipkin/

Spring Boot Actuator

Micrometer (Spring Boot Actuator)

OpenTelemetry (Spring Boot Actuator)

Docker

Screenshot

Docker Architecture

Screenshot

Docker example commands

Creating a container image with Maven

Running images with Docker manually

Running images with Docker Compose

Spring Cloud Gateway

Screenshot

Circuit Breaker (Resilience4j)

Screenshot

Testing endpoint with multiple requests using Apache Bench

Container Orchestration

Screenshot

Kubernetes

Screenshot

Kubernetes Architecture

Screenshot

Kuberenetes uses single responsibility (pods, services, deployments, etc) to manage containers

Kubernetes Master Node

Api Server

Distributed Database (etcd)

Scheduler

Controller Manager

Screenshot

Kubernetes Worker Node

Kubelet

Kube Proxy

Container Runtime

Screenshot

Kubernetes Pods!

Screenshot

How to get a pod's IP address?

How to get a pod's logs?

How to get a pod's shell?

How to describe a pod?

Kubernetes ReplicaSets

How to get a ReplicaSets

Kubernetes Deployments

Screenshot

How to scale a deployment?

How to set a deployment's image? (Rolling update) - zero downtime deployment (blue/green deployment)

How to get a deployment's history?

How to rollback a deployment?

Kubernetes Services

Kubernetes Responsibilities

Example kubectl commands

Edit deployment.extensions/hello-world

Check events

Check pods

Check replicasets

Check deployments

Check services

Example file contents:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  creationTimestamp: "2020-10-03T20:47:39Z"
  generation: 1
  labels:
    app: hello-world
  name: hello-world
  namespace: default
  resourceVersion: "1000"
  selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/hello-world
  uid: 3b5b5b5b-5b5b-5b5b-5b5b-5b5b5b5b5b5b
spec:
  progressDeadlineSeconds: 600
  replicas: 3
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: hello-world
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: hello-world
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: Always
        name: hello-world
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

Cloud Orchestration Options

Google Cloud Engine (GKE)

Install Google Cloud SDK

Quickstart with K8s/Docker/Maven

  1. Create Maven project images (/kubernetes/)

    • mvn clean package
    • Run docker daemon
    • mvn spring-boot:build-image -DskipTests
  2. Add to docker registry

    • docker push seanmayerz/smr-currency-exchange-service-kubernetes:0.0.1-SNAPSHOT
    • docker push seanmayerz/smr-currency-conversion-service-kubernetes:0.0.1-SNAPSHOT
    • Check docker registry https://hub.docker.com/u/seanmayerz
  3. Create Kubernetes cluster in GKE

    • Login to https://cloud.google.com/ (using free trial credits)
    • Create new project
    • Enable Kubernetes Engine API
    • Create cluster Screenshot
    • Cluster configuration Screenshot
    • Cluster network configuration Screenshot
  4. Create/Connect to GKE Cluster

    • Install Google Cloud SDK
    • https://cloud.google.com/sdk/docs/install
    • gcloud init
    • gcloud auth login
    • Create cluster (not autopilot)
    • gcloud container clusters create smr-cluster --zone europe-west2-a --num-nodes 1
    • Connect to GKE cluster using cloud shell (you can also use your local machine) Screenshot
  5. Prepare to deploy microservices to Kubernetes

    • kubectl version
    • kubectl create deployment currency-exchange-kubernetes --image=seanmayerz/smr-currency-exchange-service-kubernetes:0.0.1-SNAPSHOT
    • kubectl create deployment currency-conversion-kubernetes --image=seanmayerz/smr-currency-conversion-service-kubernetes:0.0.1-SNAPSHOT
    • kubectl expose deployment currency-exchange-kubernetes --type=LoadBalancer --port=8000
    • kubectl expose deployment currency-conversion-kubernetes --type=LoadBalancer --port=8100
    • kubectl get svc or kubectl get services
    • kubectl get pods
    • kubectl get rs or kubectl get replicasets
    • kubectl get all
    • set env deployment/currency-conversion-kubernetes CURRENCY_EXCHANGE_SERVICE_HOST={{EXTERNAL-IP}} - get external ip from kubectl get svc command
    • kubectl describe deployment currency-conversion-kubernetes - check environment variables
  6. Open GKE Kuberenetes GKE cloud shell

    • curl http://{{EXTERNAL-IP}}:8000/currency-exchange/from/USD/to/INR - get external ip from kubectl get svc command
    • curl http://{{EXTERNAL-IP}}:8100/currency-conversion-feign/from/USD/to/INR/quantity/10 - get external ip from kubectl get svc command
  7. Create declaritive configuration yaml for currency-exchange-service

  1. Create declaritive configuration yaml for currency-conversion-service

    • kubectl get deployments
    • cd into /kubernetes/currency-conversion-service
    • kubectl get deployment currency-conversion-kubernetes -o yaml > deployment.yaml - save yaml for existing deployment
    • kubectl get service currency-conversion-kubernetes -o yaml > service.yaml - save yaml for existing service (copy the service yaml from the file to the deployment yaml, then delete the service yaml)
  2. Deploy declaritive configuration yaml for currency-exchange-service

    • kubectl diff -f deployment.yaml - check diff
    • kubectl apply -f deployment.yaml - apply changes You could update the replicas here and then use watch curl http://{{EXTERNAL-IP}}:8000/currency-exchange/from/USD/to/INR to see load balancing in action
  3. Deploy declaritive configuration yaml for currency-conversion-service

    • kubectl diff -f deployment.yaml - check diff
    • kubectl apply -f deployment.yaml - apply changes You could update the replicas here and then use watch curl http://{{EXTERNAL-IP}}:8100/currency-conversion-feign/from/USD/to/INR/quantity/10 to see load balancing in action
  4. Enable Logging and Tracing in Google Cloud

    • In Google Cloud search API & Services
    • Enable API & Services Screenshot
    • Search Cloud Logging
    • Enable Cloud Logging Screenshot
    • Also search Stackdrivers
    • Enable all of these: Screenshot
  5. Deploying Microservice using YAML deployment

    • First delete the existing deployment and service
    • kubectl delete all -l app=currency-exchange-kubernetes
    • kubectl delete all -l app=currency-conversion-kubernetes
    • kubectl get all (should only see cluster-ip service)
    • Go to /kubernetes/currency-exchange-service and /kubernetes/currency-conversion-service and run kubectl apply -f deployment.yaml
    • kubectl get all (should see deployment, replicaset, pod, service)
    • kubectl get pods (should see 2 pods)
    • kubectl get rs (should see 2 replicasets)
    • kubectl get svc --watch (wait eventually should see 2 services)
    • curl http://{{EXTERNAL-IP}}:8000/currency-exchange/from/USD/to/INR - get external ip from kubectl get svc command
  6. Deploying Microservice using YAML deployment with ConfigMap

    • kubectl create configmap currency-conversion-kubernetes --from-literal=CURRENCY_EXCHANGE_SERVICE_URI=http://currency-exchange-kubernetes
    • kubectl get configmap
    • kubectl get configmap currency-conversion-kubernetes
    • kubectl get configmap currency-conversion-kubernetes -o yaml
    • kubectl get configmap currency-conversion-kubernetes -o yaml > configmap.yaml
    • copy the configmap yaml to the deployment yaml
    • kubectl apply -f deployment.yaml
  7. Monitoring centralised logging in GKE

    • Go to https://console.cloud.google.com/kubernetes/list/overview
    • Click on the cluster
    • Click on View Logs
    • Click on View GKE Dashboard
    • Click on Workloads
    • Click on currency-conversion-kubernetes
    • Click on currency-conversion-kubernetes-xxxxx
    • Click on View Logs
    • Click on Workloads
    • Click on currency-exchange-kubernetes
    • Click on currency-exchange-kubernetes-xxxxx
  8. Deployments and Rollbacks

  1. Deploying Microservice using YAML deployment with Secrets
  1. Configuring Readiness and Liveness Probes

Kuberentes will check the health of the pod and if it's not healthy, it will restart the pod, and if it's still not healthy, it will restart the pod again and again. This is called Liveness Probe.

Kubernetes will check if the pod is ready to serve the request. If it's not ready, it will not send the request to the pod. This is called Readiness Probe.

Spring Boot Actuator provides /actuator/health endpoint which can be used for readiness and liveness probes.

We have this configured in application.properties file.

management.endpoint.health.probes.enabled=true
management.health.livenessState.enabled=true
management.health.readinessState.enabled=true

How to test this?

  readinessProbe:
    httpGet:
      path: /actuator/health/readiness
      port: 8000
  livenessProbe:
    httpGet:
      path: /actuator/health/liveness
      port: 8000
  1. Scaling pods manually
  1. Scaling pods automatically
  1. Checking resources
  1. Deleting autoscaler
  1. Deleting Cluster in GKE

Screenshot

Bonus

Deleting pods

Issues

Running multiple springboot microservice projects in VSCode (Without Docker)

Current workaround is reload VS Code window, or F1 ->Clean the java language server workspace.

Reference: https://stackoverflow.com/questions/57857855/could-not-find-or-load-main-class-vs-code