Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/vertx-howtos/k8s-client-side-lb-howto
Client side load balancing on Kubernetes
https://github.com/vertx-howtos/k8s-client-side-lb-howto
howto kubernetes load-balancer vertx
Last synced: about 3 hours ago
JSON representation
Client side load balancing on Kubernetes
- Host: GitHub
- URL: https://github.com/vertx-howtos/k8s-client-side-lb-howto
- Owner: vertx-howtos
- Created: 2024-11-27T12:51:51.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2024-12-02T17:40:36.000Z (2 months ago)
- Last Synced: 2024-12-07T00:39:54.039Z (about 2 months ago)
- Topics: howto, kubernetes, load-balancer, vertx
- Language: Java
- Homepage:
- Size: 62.5 KB
- Stars: 0
- Watchers: 5
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.adoc
Awesome Lists containing this project
README
= Client side load balancing on Kubernetes
:page-permalink: /
:page-github: vertx-howtos/k8s-client-side-lb-howtoThis document will show you how to perform client side load balancing on Kubernetes with a microservice.
== What you will build
You will build a Vert.x microservice which:
* listens to HTTP requests for the `/` URI
* makes an HTTP request to a back-end service using a load balancer
* sends the back-end service HTTP response contentIt consists of a single part named _microservice_ communicating with another pod deployed in Kubernetes.
== What you need
* A text editor or IDE
* Java 11 higher
* Maven or Gradle
* https://kubernetes.io/docs/tasks/tools/install-minikube/[Minikube] or any Kubernetes cluster
* `kubectl` command-line tool== Create the project
The code of the _microservice_ project contains Maven and Gradle build files that are functionally equivalent.
=== Dependencies
The project depends on:
* https://vertx.io/docs/vertx-core/java[`Vert.x Core`]
* https://vertx.io/docs/5.0.0.CR2/vertx-service-resolver/java/[`Vert.x Service Resolver`]The Service Resolver library is a plugin that lets Vert.x clients call services using logical service names instead of network addresses.
The service resolver is also capable of performing client side load balancing with the usual strategies.=== Containerization
To create containers we will use https://github.com/GoogleContainerTools/jib[Jib] because:
- it creates images with distinct layers for dependencies, resources and classes, thus saving build time and deployment time
- it supports both Maven and Gradle
- it requires neither Docker nor Podman=== Using Maven
Here is the content of the `pom.xml` file you should be using for the _microservice_:
ifdef::env-github[]
link:pom.xml[_Microservice_ Maven POM file]
endif::env-github[]
ifndef::env-github[]
[source,xml,role="collapsed"]
._Microservice_ Maven `pom.xml`
----
include::pom.xml[]
----
endif::env-github[]=== Using Gradle
Assuming you use Gradle with the Kotlin DSL, here is what your `build.gradle.kts` file should look like for the _microservice_:
ifdef::env-github[]
link:build.gradle.kts[_Microservice_ Gradle build file]
endif::env-github[]
ifndef::env-github[]
[source,kotlin,role="collapsed"]
._Microservice_ Gradle `build.gradle.kts`
----
include::build.gradle.kts[]
----
endif::env-github[]== Implement the service
Let's implement the _microservice_ and then test it on the development machine.
The _frontend_ service is encapsulated in a `MicroServiceVerticle` class.
The service will request another pod of the Kubernetes cluster with a service address.
The _microservice_ Verticle creates an `HttpClient` configured with a _load-balancer_ and a _resolver_.ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=client]
----
endif::env-github[]For this matter we create an address resolver that takes logical `ServiceAddress` as input and returns a list of addresses the HTTP client can use in practice.
The `KubeResolver` is the resolver to go when deploying in Kubernetes.
Notice that the resolver is created with `new KubeResolverOptions()`, configured from the pod env variables set by the Kubernetes.ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=resolver]
----
endif::env-github[]The load-balancer part is very straightforward with a round-robin strategy.
ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=load-balancer]
----
endif::env-github[]There are other available strategies.
We also need to create and bind a web server for our service, this is very much straightforward:
ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=server]
----
endif::env-github[]Finally let's have a look at service request handling.
First we create an HTTP server request to the back-end server.
Instead of passing the back-end server socket address, we use instead the logical service address, which is the name of the service in Kubernetes (`hello-node`).ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=request]
----
endif::env-github[]Then we implement the back-end server response handling.
We send back the original response as part of our response, decorated with the response socket address so we can determine which server the service interacted with.ifdef::env-github[]
link:src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[MicroServiceVerticle]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.Java `src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java`
----
include::src/main/java/io/vertx/howtos/clientsidelb/MicroServiceVerticle.java[tag=response]
----
endif::env-github[]== Deploy to Kubernetes
First, make sure Minikube has started with `minikube status`.
NOTE: If you don't use Minikube, verify that `kubectl` is connected to your cluster.
=== Push container image
There are https://minikube.sigs.k8s.io/docs/handbook/pushing/[different ways] to push container images to Minikube.
In this document, we will push directly to the in-cluster Docker daemon.
To do so, we must point our shell to Minikube's docker-daemon:
----
eval $(minikube -p minikube docker-env)
----Then, within the same shell, we can build the images with Jib:
* with Maven: `mvn compile jib:dockerBuild`, or
* with Gradle: `./gradlew jibDockerBuild` (Linux, macOS) or `gradlew jibDockerBuild` (Windows).NOTE: Jib will not use the Docker daemon to build the image but only to push it.
NOTE: If you don't use Minikube, please refer to the https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#configuration[Jib Maven] or https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#configuration[Jib Gradle] plugin documentation for details about how to configure them when pushing to a registry.
=== Back-end service deployment
For the sake of simplicity, we will reuse the HTTP server from the Minikube https://kubernetes.io/docs/tutorials/hello-minikube/[tutorial].
We simply need to create a deployment with 3 pods for the purpose of this how-to.
----
kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080
----Verify the pods have started successfully:
----
kubectl get pods --selector=app=hello-node
----You should see something like:
----
NAME READY STATUS RESTARTS AGE
hello-node-66d457cb86-vndgc 1/1 Running 0 45s
----Let's increase the number of replicas to 3 for the purpose of this how-to.
----
kubectl scale deployment hello-node --replicas=3
----And verify the new pods have started successfully:
----
NAME READY STATUS RESTARTS AGE
hello-node-66d457cb86-m9nsr 1/1 Running 0 11s
hello-node-66d457cb86-vndgc 1/1 Running 0 2m51s
hello-node-66d457cb86-z6x26 1/1 Running 0 11s
----Finally, we need to expose the pods as a service
----
kubectl expose deployment hello-node --type=LoadBalancer --port=8080
----Again, verify the service has been successfully created:
----
kubectl get services hello-node
----You should see something like:
----
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.101.56.23 8080:32159/TCP 2m31s
----=== Microservice deployment
Now we can deploy our microservice in Kubernetes.
ifdef::env-github[]
link:deployment.yml[Microservice Deployment]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.YML `deployment.yml`
----
include::deployment.yml[]
----
endif::env-github[]Apply this configuration:
----
kubectl apply -f deployment.yml
----Verify the pods have started successfully:
----
kubectl get pods --selector=app=microservice
----You should see something like:
----
NAME READY STATUS RESTARTS AGE
microservice-deployment-69dfcbc79c-kk85f 1/1 Running 0 117s
----We also need a service to load-balance the HTTP traffic.
Pods will be selected by the label `app:microservice` that was defined in the deployment:
ifdef::env-github[]
link:service.yml[Microservice]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.YML `service.yml`
----
include::service.yml[]
----
endif::env-github[]Apply this configuration:
----
kubectl apply -f service.yml
----Verify the service has been created successfully:
----
kubectl get services microservice
----You should see something like:
----
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
microservice LoadBalancer 10.109.6.50 80:30336/TCP 2m3s
----Finally, we need to configure the _default_ service account to grant permission to observe the endpoints to the Vert.x service resolver.
ifdef::env-github[]
link:roles.yml[Endpoints]
endif::env-github[]
ifndef::env-github[]
[source,java,role="collapsed"]
.YML `roles.yml`
----
include::roles.yml[]
----
endif::env-github[]Apply this configuration
----
kubectl apply -f roles.yml
----=== Test the microservice
Now it is time to test our microservice and observe client side load balancing in action.
If you use Minikube, open another terminal window and run:
----
minikube service microservice
----This opens a web browser and show our microservice in action, you should see something like
----
Hello from: 10.244.0.48:8080 with: NOW: 2024-11-27 17:18:37.179191424 +0000 UTC m=+1267.971197286
----You can refresh the page to show that the IP address of the back-end service our microservice interacted with has
changed.== Follow-up activities
You can go beyond and implement the following features
* Use different load-balancing https://vertx.io/docs/5.0.0.CR2/vertx-core/java/#_client_side_load_balancing[strategies]
* Come up with your own https://vertx.io/docs/5.0.0.CR2/apidocs/io/vertx/core/net/endpoint/LoadBalancer.html[load-balancer] implementation
* The microservice could interact with a https://vertx.io/docs/5.0.0.CR2/vertx-grpc/java/#_client_side_load_balancing[gRPC service] instead of a generic HTTP server== Summary
This document covered:
* dependencies required to deploy a microservice load balancing between Kubernetes pods
* containerization of Vert.x services with Jib== See also
* https://github.com/GoogleContainerTools/jib/[`Containerization with Jib`]
* https://vertx.io/docs/5.0.0.CR2/vertx-core/java/#_client_side_load_balancing[Client side load balancing with Vert.x HTTP client]
* https://vertx.io/docs/vertx-service-resolver/java/#_configuring_for_kubernetes[Vert.x service resolver for Kubernetes]