Development on Kubernetes with Okteto and Spring Boot
Okteto Platform seems to be an interesting alternative to the other more popular tools that simplify development on Kubernetes. In comparison to the tools like Skaffold or Draft, the idea around Okteto is to move development entirely to Kubernetes. What does it mean in practice? Let’s check it out.
Okteto decouples development from deployment. It means that we can deploy our application using kubectl, Helm, or even Skaffold, and then use Okteto for implementing and testing application components. Of course, we may do the whole process just using Okteto commands available within CLI. This simple idea – “code locally, run and debug directly on Okteto Cloud” – accelerate your local development, reduces local setup, and eliminates integration issues.
In this article, I’m going to show you how to use Okteto for the development of a Spring Boot application that connects to a MongoDB database running on Kubernetes. The sample application will be built using Maven, which is supported on Okteto. There is a small catch in this solution – it is payable. However, you may take advantage of the developer free plan, which includes 2 CPUs and 4GB RAM, and sleeps after 24h. Developer PRO plan with 4 CPUs and 8GB RAM is available for 14 days free trial.
I have already described another useful tool for deploying applications on Kubernetes – Skaffold. If you are interested in more details you may refer to the following article Local Java Development on Kubernetes.
Example
The source code of the sample Spring Boot application that connects to MongoDB is as usual available in my GitHub repository: https://github.com/piomin/sample-spring-boot-on-kubernetes.git.
Getting started with Okteto
You should start from downloading Okteto CLI. The same as other similar solutions it is available as a single executable file that needs to be placed in your PATH. After that you should execute command okteto login
that downloads and adds your Okteto’s account credentials to kubeconfig file, and sets it as a current context. Now you can use kubectl
to interact with your new remote Kubernetes cluster.
Okteto configuration
In fact, to start development with Okteto you just need to add file okteto.yml
with required configuration to the root directory of your application. You have pretty configuration options, but you should add the name of your application and an image used for development. What is very important here – it is not the Docker image just with your application. When Okteto development mode is initialized for your application, it replaces your application container with a development container that contains development tools (e.g. maven and jdk, or npm, python, go compiler, debuggers, etc). In that case we are using a special Docker image dedicated for maven okteto/maven
. We are also setting Maven command for starting our Spring Boot application, some environment variables with MongoDB credentials and database name, and port forwarding option.
name: employee-service
image: okteto/maven
command: ["mvn", "spring-boot:run" ]
workdir: /app
environment:
- MONGO_USERNAME=okteto
- MONGO_DATABASE=okteto
- MONGO_PASSWORD=okteto
forward:
- 8080:8080
Now, all you need to do is to execute command okteto up
in the root directory of your application. Okteto is able to automatically create Deployment
, perform Maven build and deploy your Spring Boot application on a remote Kubernetes cluster.
Spring Boot development
Spring Boot application has been started on Okteto Cloud by executing Maven goal spring-boot:run
. Before that it runs the full Maven build. Okteto is listening for changes in the code and synchronizes it to your remote development environment. Of course such change should not trigger Maven build once again – like for example in Skaffold. To enable that feature the only thing we need to do is to add Spring Boot Devtools to the project dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
Applications that use spring-boot-devtools
will automatically restart whenever files on the classpath change. With Okteto the change in the local file system will trigger the restart of the application running on your remote development environment. It is also important to enable the automatic rebuilding of an application on file change in your local development IDE. If you are using IntelliJ IDEA you should enable the option Build project automatically inside Compiler section and also enable some additional registry keys. Here’s the article with a detailed description of all required steps:
https://mkyong.com/spring-boot/intellij-idea-spring-boot-template-reload-is-not-working/.
Implementation of Spring Boot for Okteto
We are building a simple application that uses Mongo as a backend store and exposes REST endpoints outside. Here’s the list of required Maven dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
We are using Spring Data Repository pattern for integration with Mongo. We are adding some custom find methods to the inherited list of methods defined for CrudRepository
in Spring Data Mongo.
public interface PersonRepository extends CrudRepository<Person, String> {
Set<Person> findByFirstNameAndLastName(String firstName, String lastName);
Set<Person> findByAge(int age);
Set<Person> findByAgeGreaterThan(int age);
}
Database connection settings are configured in application.yml
. We are using environment variables injected to the container and set in okteto.yml
configuration file.
spring:
application:
name: sample-spring-boot-on-kubernetes
data:
mongodb:
uri: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@mongodb/${MONGO_DATABASE}
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
We are injecting the repository into the controller and implementing simple CRUD methods exposed as HTTP endpoints.
@RestController
@RequestMapping("/persons")
public class PersonController {
private PersonRepository repository;
PersonController(PersonRepository repository) {
this.repository = repository;
}
@PostMapping
public Person add(@RequestBody Person person) {
return repository.save(person);
}
@PutMapping
public Person update(@RequestBody Person person) {
return repository.save(person);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") String id) {
repository.deleteById(id);
}
@GetMapping
public Iterable<Person> findAll() {
return repository.findAll();
}
@GetMapping("/{id}")
public Optional<Person> findById(@PathVariable("id") String id) {
return repository.findById(id);
}
@GetMapping("/first-name/{firstName}/last-name/{lastName}")
public Set<Person> findByFirstNameAndLastName(@PathVariable("firstName") String firstName,
@PathVariable("lastName") String lastName) {
return repository.findByFirstNameAndLastName(firstName, lastName);
}
@GetMapping("/age-greater-than/{age}")
public Set<Person> findByAgeGreaterThan(@PathVariable("age") int age) {
return repository.findByAgeGreaterThan(age);
}
@GetMapping("/age/{age}")
public Set<Person> findByAge(@PathVariable("age") int age) {
return repository.findByAge(age);
}
}
Deploy Spring Boot on Okteto
Before deploying our example application on Okteto we will initialize MongoDB there. Okteto provides a web-based management console. Besides managing currently developed applications, we may easily deploy some predefined software, like databases or message brokers. As you may easily run MongoDB in a single click.
Of course, in the background Okteto is creating Deployment and required Secrets.
Now, we can finally initialize our remote development environment on Okteto Cloud. The command code>okteto up
is able to create new Deployment
if it does not exist. Then it is enabling port forwarding on localhost:8080 and starting Maven build as shown below.
After running command okteto up
we have two the Deployment
object and two running pods.
We can verify the status of the environment using Okteto Web UI.
Our application is exposing some Actuator and /persons
endpoints outside. We can easily access them at the address https://sample-spring-boot-on-kubernetes-piomin.cloud.okteto.net. Since we have already enabled port forwarding, we can also just call it using a localhost address.
Now, we are ready to send some test requests. Let’s add two persons using POST /persons
endpoint.
Finally let’s call GET /persons
method to verify if two Persons
has been succesfully saved in Mongo.
Conclusion
With Okteto you don’t have Docker or Kubernetes installed on your machine. You can focus just on development in your favorite programming IDE, the same as you would do without using any cloud platform. By defining a single Okteto configuration file and then by running a single command using Okteto CLI you are able to prepare your remote development environment. In fact, you don’t have to know much about Kubernetes to start your development with Okteto, but in case you need it you may still take advantage of all Kubernetes features and special resources.
4 COMMENTS