TODOS-API is a sample Spring Boot microservice that uses spring-boot-starter-web to implement a REST API for TODO(s).
The service fits into a larger TODO application, which includes a WebUI, an edge service, as well as caching and database services.
The service can be accessed from a Web UI or directly at the endpoints it exposes.
The Domain Model is a TODO object which has an id, a title, a category, the deadline and the status.
ex.:
{
"category": "personal",
"complete": false,
"deadline": "2020/10/01",
"id": "4d0918be-36fa-4dcd-b7b8-14200ef31d4c",
"title": "todo3"
}
todos-api
exposes multiple endpoints, by default running at port 8082
:
/
- [GET] returns all TODO items/{id}
- [GET] returns a TODO items for the specified id/
- [POST] creates a new TODO item/{id}
- [POST] creates a new TODO item with a specified id, in lieu of an auto-generated id/{id}
- [PATCH] updates an existing TODO item/
- [DELETE] - deletes all TODOs in the database and evicts the cache/{id}
- [DELETE] - deletes a TODO for the specified id
todos-api
exposes additionally a separate set of endpoints for introspection, out-of-the-box and customized
/actuator
- [GET] returns all actuators enabled in the application; by default almost all available actuators have been enabled, for educational purposes/actuator/health
- [GET] returns the OOB health info + customized health info collected from the service/actuator/custom
- [GET] implements a custom actuator/actuator/info
- [GET] collects customized info from the application
Building and running the application assumes that you have installed a number of pre-requisites:
- Java 8 - configured to run the application by default. You can decided to build and run the app also with Java 11 or 14
- Maven - compiling the application and running tests
- Helm v3 - for installing the caching and database solutions. Helm installation link.
- Skaffold - for building, pushing, deploying and debugging the application. Skaffold installation link.
- Kustomize - for using a template-free way to customize application configuration that simplifies the use of off-the-shelf applications. Kustomize installation link.
- HTTPie - highly recommended as a cUrl replacement for a user-friendly command-line HTTP client for the API era. It comes with JSON support, syntax highlighting, persistent sessions, wget-like downloads, plugins, etc. HTTPie installation link.
- Kubectl - the Kubernetes CLI, allows you to run commands against Kubernetes clusters. Kubectl installation link.
This repo contains 4 scripts for setting up, respectively cleaning up pre-requisite tolls and Spring Boot microservices for usage with the TODOS-API application.
# Setup - please run in order
./setup/install-tools.sh -- Helm chart based installer for caching and database
cd setup
./setup-app.sh -- kubectl-based deployment for 4 services for the TODO app
# installation can be validated by checking all running services in K8s
kubectl get services
# Ex.:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 93d
todo-mysql-instance-mariadb ClusterIP 10.0.12.243 <none> 3306/TCP 3d22h
todo-mysql-instance-mariadb-slave ClusterIP 10.0.1.47 <none> 3306/TCP 3d22h
todo-redis-instance-headless ClusterIP None <none> 6379/TCP 3d22h
todo-redis-instance-master ClusterIP 10.0.0.20 <none> 6379/TCP 3d22h
todo-redis-instance-slave ClusterIP 10.0.3.76 <none> 6379/TCP 3d22h
todos-mysql LoadBalancer 10.0.1.43 35.223.204.37 9090:30207/TCP 47h
todos-redis LoadBalancer 10.0.14.98 104.154.253.234 8888:31530/TCP 47h
todos-service LoadBalancer 10.0.11.54 35.225.226.171 9999:30011/TCP 47h
todos-webui LoadBalancer 10.0.14.60 104.197.8.27 8080:30908/TCP 47h
# Cleanup - please run in order
./setup/cleanup-tools.sh -- Helm chart based installer for caching and database
./setup/remove-app.sh -- kubectl-based removal for 4 services for the TODO app
The application is configured by default with Java 8 in the Maven pom.xml file. You can update it to Java 11 or Java 14 if you choose to do so.
Local development
The app can be built and started locally from the command-line or from withing an IDE
./mvnw clean package
Images
To build and run Docker images, start clean by checking that no todos-api images exist on your machine by executing
docker images | grep todos-api | awk '{print $3}' | xargs docker rmi -f
To compile the code and build an image for todos-api
, this repo illustrates 3 methods.
A pre-built image has already been provisioned in Docker Hub at this todos-api link and can be retrieved by executing docker pull triathlonguy/todos-api:latest
1. Maven and Docker
./mvnw clean package
docker build -t triathlonguy/todos-api .
# validate image creation
docker images | grep todos-api
2. Spring Boot image builder - as of Spring 2.3.x, uses Paketo buildpacks
mvn clean spring-boot:build-image
# validate image creation
docker images | grep todos-api
3. Skaffold
# builds the image only
skaffold build
# validate image creation
docker images | grep todos-api
The app can be built and started locally from the command-line or from withing an IDE
./mvnw clean package
java -jar target/todos-api-1.0.0-SNAPSHOT.jar
# requests can be sent to localhost:8082
# /src/main/resources/application.yaml needs to be updated with the endpoints of the cache, respectively database
The app can be deployed and started in any Kubernetes environment using kubectl
kubectl apply -f kubernetes/app
Removing the todos-api
deployment can be done by executing
kubectl delete -f kubernetes/app
Skaffold is a command line tool that facilitates continuous development for Kubernetes applications. It simplifies the development process by combining multiple steps into one easy command and provides the building blocks for a CI/CD process.
Developers can use Skaffold to manage the development lifecycle of the todos-api by executing
skaffold dev -f skaffold-dev.yaml
Skaffold builds the application, deploys it and monitors for any changes. If any file is changed, from an IDE or text editor, Skaffold will trigger a fresh build and deploy process.
To end the working session, just press CTRL-C in the terminal window from where the Skaffold command has been executed. Skaffold will clean up all deployed artifacts.
Skaffold allows developers to have remote debugging sessions in Kubernetes, by executing
skaffold debug --port-forward -f skaffold-dev.yaml
Skaffold will forward port 5005, where a remote debugging session can be setup in IntelliJ/Eclipse/VSCode.
Please set up a remote session in your favorite IDE at port 5005, set up breakpoints and send HTTP requests to the API at the configured for this app (8082 is the default).
IDEs indicate when the remote connection has been established:
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Deploying, Developing & Debugging in Kubernetes with Externalized Configurations using Skaffold & Kustomize
- One of the 12 factors for cloud native apps is to externalize configuration
- Kubernetes provides support for externalizing configuration via config maps and secrets
- A config map or secret can easily be created using kubectl
- Kustomize offers a much improved way of generating config maps and secrets as part of our customizations to different environments, which can be versioned and managed in Source Control
Kustomize features
- Allows easier deployments to different environments/providers
- Allows you to keep all the common properties in one place
- Generate configuration for specific environments
- No templates, no placeholder spaghetti, no environment variable overload
For example, if we wish to deploy the app to a QA environment, we wish to customize some of the configuration.
This repo has an example of a QA environment which scales the todos-api to 2 replicas, as per the update-replicas.yaml
customization file made available in /kubernetes/overlays/qa
Deploy the todos-api
using Skaffolf + Kustomize for the imaginary QA environment by executing
skaffold dev -p qa
# note that the skaffold.yaml file is not specified, as Skaffold looks by default for a file called skaffold.yaml, which is availalble in this repo
# observe that 2 replicas of the todos-api have been created
pod/todos-api-7f795466ff-7gp5w 1/1 Running 0 9s
pod/todos-api-7f795466ff-k9jkx 1/1 Running 0 10s
Once the app is deployed in Kubernetes, please retrieve the endpoint at which todos-api
is exposed
kubectl get svc
# example
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
todos-api LoadBalancer 10.0.13.177 35.193.98.123 8082:31783/TCP 15m
To add a new TODO item
, say todo0
execute:
http <external_svc_ip>:8082 completed=false title=todo0 category=personal deadline=2020/10/01
http 35.193.98.123:8082 completed=false title=todo0 category=personal deadline=2020/10/01
{
"category": "personal",
"complete": false,
"deadline": "2020/10/01",
"id": "0d892025-8425-4af4-bf72-979a02b3d4bc",
"title": "todo0"
}
To retrieve all TODO items
execute:
http <external_svc_ip>:8082
http 35.193.98.123:8082
# or
curl 35.193.98.123:8082
[
{
"category": "personal",
"complete": false,
"deadline": "2020/10/01",
"id": "0d892025-8425-4af4-bf72-979a02b3d4bc",
"title": "todo0"
},
{
"category": "Default group",
"complete": false,
"deadline": "2020/09/14",
"id": "cc56f488-57df-447d-a161-e59ed21bb230",
"title": "todo1"
}
]
To retrieve a TODO item by {id}
execute:
http <external_svc_ip>:8082/{id}
http 35.193.98.123:8082/0d892025-8425-4af4-bf72-979a02b3d4bc
# or
curl 35.193.98.123:8082/0d892025-8425-4af4-bf72-979a02b3d4bc
{
"category": "personal",
"complete": false,
"deadline": "2020/10/01",
"id": "0d892025-8425-4af4-bf72-979a02b3d4bc",
"title": "todo0"
}
To retrieve the customized Info Actuator
data execute
http <external_svc_ip>:8082/actuator/info
http 35.193.98.123:8082/actuator/info
# or
curl 35.193.98.123:8082/actuator/info
{
"app": {
"description": "TODOs - API - business logic w/ DB and cache access",
"name": "todos-api - Spring Boot Application"
}
}
To retrieve the customized Health Actuator
data execute
http <external_svc_ip>:8082/actuator/health
http 35.193.98.123:8082/actuator/health
# or
curl 35.193.98.123:8082/actuator/health
{
"components": {
"customHealthCheck": {
"details": {
"Custom Health Check Status": "passed"
},
"status": "UP"
},
"diskSpace": {
"details": {
"exists": true,
"free": 80728559616,
"threshold": 10485760,
"total": 101241290752
},
"status": "UP"
},
"livenessState": {
"status": "UP"
},
"ping": {
"status": "UP"
},
"readinessState": {
"status": "UP"
}
},
"groups": [
"liveness",
"readiness"
],
"status": "UP"
}
To access a Custom Actuator
introduced for educational purposes execute
http <external_svc_ip>:8082/actuator/custom
http 35.193.98.123:8082/actuator/custom
# or
curl 35.193.98.123:8082/actuator/custom
{
"CustomEndpoint": "Everything looks good at the custom endpoint"
}