Spring Boot App Running on Bluemix Kubernetes Using Kubernetes Secrets
In this post I’ll demonstrate how to:
-
Run a Java Spring Boot application on Bluemix Kubernetes that accesses a Bluemix MongoDB service
-
Securely configure the MongoDB service credentials using Kubernetes secrets
-
Use the Spring Cloud Kubernetes framework to access the secrets as standard Spring config properties.
This example builds on my previous post where I showed how to access a Bluemix MongoDB service from a Spring data app running locally. In that simple example the MongoDB credentials were either hard coded in the application or specified manually on the command line.
Prerequisites
To run this demo you’ll need to have:
-
A Bluemix account
-
Maven and Java installed on your computer. It is assumed that you can build and run a basic Spring Guide project.
Create a Kubernetes Cluster
Login to your Bluemix account and go to the Catalog. Under Containers select Kubernetes Cluster. On the Create Cluster page enter a cluster name and type. For this example we’ll use the name mycluster
and cluster type Lite. Select Create to create the cluster. It may take a few minutes to create and initialize the cluster so be patient.
After your cluster is initialized configure the CLI to run kubectl
commands against your cluster as described here.
Now that kubectl
is setup we can use the Kubernetes dashboard to view and manage the cluster. First start the Kubernetes proxy by issuing the following command:
You can now display the dashboard with the url http://localhost:8001/ui
. Initially the cluster should be empty as we haven’t deployed any apps to it yet:
Create a MongoDB Service
From the Bluemix Catalog, under Data & Analytics select the Compose for MongoDB service to create a new MongoDB instance. Select Create to create an instance of MongoDB – the default service name and credential name should be fine.
Create a Kubernetes Secret with the MongoDB Service Credentials
The MongoDB service has security credentials that are required by the application to access the service:
-
A connection string which contains a userid and password
-
An SSL certificate which is used to establish trust on the connection to the MongoDB service
The best practice for configuring a Kubernetes application with security credentials is to use Kubernetes Secrets, rather than hard coding them in the application or putting them in environment variables. We’ll create a secret that contains the following four pieces of data:
-
The MongoDB connection string
-
A Java trust store (a .jks file) containing the MongoDB service’s SSL certificate
-
The name of the trust store file
-
The password of the trust store
To get the service’s connection string and SSL certificate go to your Bluemix dashboard and select the MongoDB service – the connection string and certificate will be displayed:
We’ll use the kubectl create secret
command to create our secret from files, so we’ll need to create four files – one for each piece of data in the secret.
-
Create a file named
spring.data.mongodb.uri
and put the MongoDB connection string in it. -
Create a trust store containing the MongoDB service’s SSL certificate. First copy the certificate and save it in a file (
mongo-service.crt
in this example) and issue the following command: -
Create a file named
trust.file.name
that contains the name of the trust store – in this examplemongo-trust.jks
. -
Create a file named
trust.file.password
that contains the password of the trust store –keypass
.
Now create a Kubernetes secret named mongosecret
on your cluster from the four files just created by issueing the following command:
You can use the dashboard to verify that the secret was created:
Create the Application
We’ll use the Spring guide Accessing MongoDB Data with REST application for this example. Follow the instructions in the guide to download and build the complete project.
The project defaults to using a local MongoDB server installed on your computer. To use the Bluemix MongoDB service we’ll need to modify the app to access the MongoDB service using the credentials in the Kubernetes secret we created.
-
Create the file
src/main/resources/bootstrap.properties
with the following properties to tell Spring to set config properties from Kubernetes secrets located at/etc/mongo/config
: -
Modify
src/main/java/hello/Application.java
to add the following (highlighted) lines to tell Spring the host and port of the Kubernetes cluster service so that the Spring Cloud Kubernetes framework can communicate with the cluster: -
Add the following dependencies to the
pom.xml
file to add the Spring Cloud Kubernetes jars to the application. Note that thespring-data-rest-core
dependency is necessary becausespring-cloud-kubernetes-core
includes a down level REST, andokhttp
is necessary becausespring-cloud-kubernetes-core
does not includeokhttp
which is required. -
Add the following dependency management bom (Bill Of Materials) to the top level of the
pom.xml
file to ensure that various dependencies are at the right version: -
Create the following
src/main/java/hello/MyBeanPostProcessor.java
class to set the Java trust store and password system properties. The@Value
annotations get the property values from the Kubernetes secret and injects them into the variables.Note: System properties must be used because Spring config doesn’t currently support Java trust stores. ABeanPostProcessor
is needed in order to set the trust store before MongoDB initialization.
Finally, build the project with the following command:
Build the Docker Image and push it to the Bluemix Registry
To build the Docker image first create the following Dockerfile:
Then run the following commands where is your Bluemix container registry namespace:
Deploy the Application to the Bluemix Kubernetes Cluster
Create the following kube-pod.yaml
file. The highlighted lines mount mongosecret
at location /etc/mongo/config
. (This must be the same location specified in the Spring property spring.cloud.kubernetes.secrets.paths
in bootstrap.properties
.)
Then run the following command to deploy the app:
You can verify in the Kubernetes dashboard that the spring-mongo-rest-service
and it’s pod started successfully, and get it’s external port number – 30309 in this example:
Invoke the Application
Since this is a NodePort service the IP address of the service will be the IP Address of the node – 169.51.9.135 in this example – which you can get from the Kubernetes dashboard:
The app will be listening on 169.51.9.135:30309
for REST requests that it will forward to the remote Bluemix MongoDB service. You can now update and query the database using CURL commands to 169.51.9.135:30309
:
-
To add a person:
-
To query all people in the DB: