This guide details the deployment of our microservices (Order-Service, Inventory-Service, and Billing-Service) on Kubernetes using Minikube. The deployment includes:
- Three Spring Boot microservices
- MySQL database
- Apache Kafka
- Kubernetes Deployments, Services and ConfigMaps
-
Minikube: installed and running
-
kubectl CLI tool installed (installed with minikube installation)
-
Docker installed (for minikube)
- Start minikube with minikube start and verify the status.
minikube start
minikube status
eval $(minikube docker-env)
This command configures your terminal to use Minikube's Docker daemon.
Build the Docker images for each service within Minikube's environment:
-
Navigate to each service
order-service
,inventory-service
andbilling-service
where DockerFile is located. -
Build docker images for all services one by one.
Docker image for zookeeper, kafka and mysql is pulled by kubectl through deployment.
# Build Order Service
cd order-service
docker build -t order-service:latest .
# Build Inventory Service
cd ../inventory-service
docker build -t inventory-service:latest .
# Build Billing Service
cd ../billing-service
docker build -t billing-service:latest .
To deploy MySQL with the provided YAML files, the resources need to be created in a specific order to ensure all dependencies are resolved properly. Here's the recommended order:
-
Create the Secret File:
mysql-secret.yaml
The MySQL deployment requires the root password from the secret. This must exist before the deployment starts.kubectl apply -f mysql-secret.yaml
-
Create the ConfigMap File:
mysql-configmap.yaml
The ConfigMap contains the initialization script for the database. This must be mounted as a volume when the MySQL container starts.kubectl apply -f mysql-configmap.yaml
-
Create the PersistentVolumeClaim (PVC) File:
mysql-pvc.yaml
The PVC provides persistent storage for MySQL's data. The deployment will mount this PVC, so it must be created first.kubectl apply -f mysql-pvc.yaml
-
Deploy MySQL Service File:
mysql-service.yaml
The service allows other pods in the Kubernetes cluster to communicate with the MySQL database by abstracting the pod IPs. Exposes MySQL on port 3306 (the default port for MySQL).kubectl apply -f mysql-service.yaml
-
Deploy MySQL File:
mysql-deployment.yaml
The deployment will reference the Secret, ConfigMap, and PVC. Ensure these resources are created beforehand.kubectl apply -f mysql-deployment.yaml
Run the commands in the following order:
kubectl apply -f mysql-secret.yaml
kubectl apply -f mysql-configmap.yaml
kubectl apply -f mysql-pvc.yaml
kubectl apply -f mysql-service.yaml
kubectl apply -f mysql-deployment.yaml
After applying these resources, you can verify the deployment:
# Check the pods
kubectl get pods
# Check the Persistent Volume and Persistent Volume Claim
kubectl get pv
kubectl get pvc
# Check the ConfigMap and Secret
kubectl get configmap
kubectl get secret
kubectl get deployments
kubectl get service
Navigate to infrastructure directory and run the following command. The following commands create necessary config, deployment,services for zookeeper, kafka, order-service, inventory-service and billing-service.
kubectl apply -f apply-all-kube-config.yaml
- kubectl pull the images for mysql, zookeeper, kafka.
Verify with following
```bash
docker images
```
```bash
docker ps
```
![kube11.png](screenshots%2Fkubernetes%2Fkube11.png)
Verify the deployment,pods,service with following command
```bash
kubectl get all
```
- Kafka topics is created.
- All tables are created in mysql
- Service is able to produce message to topic.
- Service is able to consume the message.
- Verify the tables are updated
Execute the kafka pod with following command
kubectl exec -it <your-pod-name> -- /bin/bash
kubectl exec -it kafka-8cf75665c-57wt2 -- /bin/bash
Navigate to kafka directory.
cd /opt/kafka
Get the list of kafka-topics with following command:
./bin/kafka-topics.sh --bootstrap-server localhost:9092 --list
Get the list of consumer group id.
./bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
billing-group-id
and inventory-group-id
are created and ready to consume the messages
Execute the mysql pod with following command
kubectl exec -it <your-pod-name> -- /bin/bash
kubectl exec -it mysql-55d56f565d-fckkb -- /bin/bash
Login to mysql server
mysql -u root -p
Enter password on prompt.
Verify the database with following
show databases;
use product_database;
show tables;
All tables are created.
The order-service
app is used for producing message to the topic.
It provides POST endpoint to produce message.
The endpoint can be executed within and outside the cluster.
-
Within cluster
To execute the endpoint with curl, execute order-service pod and use curl to hit the endpoint.
- Use following command to execute order-service pod
kubectl exec -it <your-pod-name> -- /bin/bash
kubectl exec -it order-service-deployment-7797579499-f4hxv -- /bin/bash
- Once executed inside pod, use curl command to hit endpoint
curl -X POST http://localhost:8080/orders/place-order -H "Content-Type: application/json" -d '{"productName":"Samsung Galaxy S23","quantity":1,"price":999.99}'
- Verify the application logs
kubectl logs -f <pod_name>
kubectl logs -f order-service-deployment-7797579499-f4hxv kubectl logs -f billing-service-deployment-5bcd779767-pbskn kubectl logs -f inventory-service-deployment-75bbbfcb9f-f8rfr
- Execute the kafka pod with following command
kubectl exec -it <your-pod-name> -- /bin/bash
kubectl exec -it kafka-8cf75665c-57wt2 -- /bin/bash
- Check the messages consumed in order-topic
- Navigate to kafka directory
cd /opt/kafka
- Enter the following command
./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic order-topic --from-beginning
Execute the mysql pod with following command
kubectl exec -it <your-pod-name> -- /bin/bash
kubectl exec -it mysql-55d56f565d-fckkb -- /bin/bash
Login to mysql server
mysql -u root -p
Enter password on prompt.
Verify the database with following.
show databases;
use product_database;
select * from inventory;
select * from orders;
select * from billing;
All tables are updated. Services are able to communicate with each other with kafka messaging.
HorizontalPodAutoscaler is the configuration for a horizontal pod autoscaler, which automatically manages the replica count of any resource implementing the scale subresource based on the metrics specified.
Find autoscaling.yaml file in infrastructure/autoscaling
kubectl apply -f autoscaling.yaml
kubectl get hpa
kubectl describe hpa <hpa-name>
-
Cluster is missing the Metrics Server, which HPA needs to collect resource metrics.
You might see the following error when you describe the hpa.
Warning FailedGetResourceMetric 12s (x3 over 42s) horizontal-pod-autoscaler failed to get cpu utilization: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io) Warning FailedGetResourceMetric 12s (x3 over 42s) horizontal-pod-autoscaler failed to get memory utilization: unable to get metrics for resource memory: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io)
Install metrics server with following command
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Enable in minikube with:
minikube addons enable metrics-server
The high memory usage you're seeing is likely due to Java's default heap space allocation in Spring Boot applications. The JVM allocates a percentage of the container's memory limit (512Mi) at startup, even if the application isn't actively using it.
To optimize this, add these JVM arguments to your container specs:
env:
- name: JAVA_OPTS
value: "-Xms128m -Xmx256m -XX:+UseG1GC"
- name: SPRING_HEAP_MEMORY
value: "-XX:MaxRAMPercentage=50.0"
This will:
- Set initial heap size to 128MB
- Limit max heap to 256MB
- Use G1 garbage collector
- Limit JVM memory to 50% of container memory
Monitor your deployment using:
# Get pod status
kubectl get pods
# Get pod logs
kubectl logs -f <pod-name>
# Get resource usage
kubectl top pods
<screenshot: Show monitoring dashboard or CLI output>
To remove all deployed resources:
# Delete all deployments from default namespace
kubectl delete all --all -n default
# Stop Minikube
minikube stop
- All services are configured to use internal Kubernetes DNS for service discovery
- Persistent volumes are used for MySQL data storage
- Services are exposed through Kubernetes Services
- ConfigMaps are used for environment-specific configurations
- Secrets are used for sensitive data like passwords
For any issues or improvements, please create an issue in the repository.