How-tos

Centralized Configuration for Spring Apps on Bluemix Kubernetes

Share this post:

In this tutorial, we’ll adapt the Centralized Configuration guide from the Spring website to be deployed to Bluemix Kubernetes.  We’ll host our configuration files in a Github repository.  Before getting started, you should follow the guide or download the complete version.

Prerequisites

Before you begin, you’ll need to have the following installed and configured on your PATH:

I will also assume that you are logged into the Bluemix CLI and the Bluemix Container Registry CLI.  You should also have a Kubernetes cluster created in Bluemix and configured with the Kubernetes CLI.

Creating a Config Repository

Your configuration files can be stored in any Git repository you choose.  For simplicity, I will use a public Github repository.  However, in practice you will probably want to use something safer from prying eyes.

Once you have created a repository, we’ll add our first configuration file.  Create an application.properties file with the following contents:

[code title=”repository_dir/application.properties”]
message = Hello world!
[/code]

Commit this file to your repository.  Next we’re going to connect the configuration server to this repository.

Note: Spring provides support for encrypted configuration files.  There are several additional steps required to set this up, so we won’t cover it here.  If you are interested in encrypting your files, see the Spring Cloud Config docs for guidance.

Adjusting Spring Project for Kubernetes

Before we can deploy our applications to Kubernetes, we need to make a couple adjustments.  If you downloaded the complete version from the Centralized Configuration guide I mentioned above, you’ll want to work with the projects in the complete directory.

First, open the application.properties file from the “configuration-service” project. We’re going to add the URI for our Git repository here.

[code title=”configuration-service/main/resources/application.properties”]
server.port=8888

spring.cloud.config.server.git.uri=https://github.com/<username>/spring-cloud-config
[/code]

I mentioned previously that you could use a private Git repository.  If you chose to use a private repository, you’ll need to include a couple more properties:

[code gutter=”false”]
spring.cloud.config.server.git.username
spring.cloud.config.server.git.password
[/code]

The username should be an account that can read from the configuration repository. The password can be the account’s password, but you should consider generating a personal API token if you are using Github, or a similar revokable token.

That’s all we need to change to run the Spring Configuration Server on Bluemix Kubernetes! Now let’s create a Docker image with this application. Create a Dockerfile file with the following contents:

[code title=”configuration-service/Dockerfile”]
FROM java:8
COPY /target/configuration-service-0.0.1-SNAPSHOT.jar /configuration-service-0.0.1-SNAPSHOT.jar
EXPOSE 8888
ENTRYPOINT java -jar /configuration-service-0.0.1-SNAPSHOT.jar
[/code]

Then run the following commands in the same directory as your Dockerfile:

[code language=”bash” gutter=”false”]
$ mvn package

$ docker build . -t registry.ng.bluemix.net/<namespace>/config-service:latest

$ docker push registry.ng.bluemix.net/<namespace>/config-service:latest

[/code]

Note: Be sure to replace with your own private Bluemix namespace.  For help on creating a Bluemix namespace, see the Bluemix instructions.

Next we’ll switch over to the “configuration-client” project and make some changes there. Open the bootstrap.properties file and change the config URI:

[code title=”configuration-client/main/resources/bootstrap.properties”]
spring.application.name=a-bootiful-client
# N.B. this is the default:
spring.cloud.config.uri=http://config-service:8888
management.security.enabled=false
[/code]

Then create another Dockerfile for this application, with the following contents:

[code title=”configuration-client/Dockerfile”]
FROM java:8
COPY /target/configuration-client-0.0.1-SNAPSHOT.jar /configuration-client-0.0.1-SNAPSHOT.jar
EXPOSE 8080
ENTRYPOINT java -jar /configuration-client-0.0.1-SNAPSHOT.jar
[/code]

Then run the following commands in the same directory as your Dockerfile:

[code language=”bash” gutter=”false”]
$ mvn package

$ docker build . -t registry.ng.bluemix.net/<namespace>/config-client:latest

$ docker push registry.ng.bluemix.net/<namespace>/config-client:latest

[/code]

That’s it, now we’re ready to deploy to Kubernetes and give the test out the configuration server.

Deploying to Bluemix Kubernetes

We’ll need a few files in order to deploy to Kubernetes.  First create service-pod.yaml and client-pod.yaml files with the following contents:

[code title=”service-pod.yaml”]
apiVersion: v1
kind: Pod
metadata:
name: config-service
labels:
name: config-service
spec:
containers:
– name: config-service
image: registry.ng.bluemix.net/<namespace>/config-service:latest
ports:
– containerPort: 8888
[/code]

[code title=”client-pod.yaml”]
apiVersion: v1
kind: Pod
metadata:
name: config-client
labels:
name: config-client
spec:
containers:
– name: config-client
image: registry.ng.bluemix.net/<namespace>/config-client:latest
ports:
– containerPort: 8080
[/code]

These are simple pod deployment files, using the images we created earlier. Next create a services.yaml file with the following contents:

[code title=”services.yaml”]
apiVersion: v1
kind: Service
metadata:
name: client-service
namespace: default
spec:
type: NodePort
ports:
– port: 8080
selector:
name: config-client

apiVersion: v1
kind: Service
metadata:
name: config-service
namespace: default
spec:
ports:
– port: 8888
selector:
name: config-service
[/code]

In this file, we define two services. The first will create a NodePort allowing us to access our “configuration-client” REST endpoints. The second is the service where our client will look to find it’s configuration.

Now we are ready to run our Spring applications on our Bluemix Kubernetes cluster! Create a proxy connection to your cluster with the following command:

[code language=”bash” gutter=”false”]
$ kubectl proxy
[/code]

Then navigate to the Kubernetes dashboard at: 127.0.0.1:8001/ui.

From the dashboard, click CREATE in the top-right corner, then select the Upload a YAML or JSON file option, and choose your services.yaml file.  Upload this file with the UPLOAD button.  Then follow the same procedure with your service-pod.yaml file.

Allow the “configuration-service” application to start before continuing. You can check its progress through the pod logs. After it has started, go ahead and deploy your client-pod.yaml file as well.

Next you will need to find where the service is being exposed. To find the public node IP, click Nodes on the left sidebar and use the name of the node that your pod is running on (there should only be one node if you are using a Lite cluster plan). To find the service NodePorts, click Services on the left sidebar and find the port number (in the range 30000-32767) associated with the “client-service” service.

In a terminal, use the following command to make a request to the client service. The URL will be formed by the public node IP and “client-service” NodePort.

[code language=”bash” gutter=”false”]
$ curl http://168.1.140.71:31936/message
Hello world
[/code]

You should get a response of “Hello world” if everything went as expected. If you received “Hello default” instead, you likely didn’t wait long enough before starting the client pod. But that is okay, you can still continue on and we will see how to refresh the client configuration.

Return to your Git repository and create an a-bootfiul-client.properties file with the following contents:

[code title=”repository_dir/a-bootiful-client.properties”]
message = New message
[/code]

Then push this file to your repository so it will be accessible by the Spring configuration server application. In order to see this new configuration file in action, you’ll need to refresh your client application. You can do this by sending an empty POST request to the /refresh endpoint:

[code language=”bash” gutter=”false”]
curl -X POST http://168.1.140.71:31936/refresh
[/code]

Now if you visit the /message endpoint again, you should see your new message!

[code language=”bash” gutter=”false”]
$ curl http://168.1.140.71:31936/message
New message
[/code]

Conclusion

In this tutorial, we adapted the “Centralized Configuration” guide from the Spring website to run on Bluemix Kubernetes.  The Spring configuration server allows your applications to pull their config from a central location at start, as well as have their configuration refreshed while running (through Spring Actuator).

More How-tos stories
October 19, 2018

Part 1: Build Messaging Solutions with Apache Kafka or Event Streams for IBM Cloud

As part of the iterative approach described in the main introduction blog of this series, the first step is to building messaging solutions is to identify the use case requirements and quantify these requirements as much as possible in terms of Apache Kafka and Event Streams.

Continue reading

October 18, 2018

Mount iSCSI Block Storage on VMware ESXi 6.5U2

It seems like pretty much everyone is using VMware ESXi virtualization nowadays. In this article, I'll cover how to mount IBM Cloud Block Storages onto this popular hypervisor using the iSCSI protocol.

Continue reading

October 18, 2018

Journey to Cloud – Moving On-Premise Mobile Foundation Apps to IBM Cloud

IBM MobileFirst Platform Foundation powers many on-premise customers in more than 50 countries, delivering the best-of-the-best apps and serving a large number of users. IBM Cloud Mobile Foundation Service offers all the same capabilities available in on-premise MobileFirst Foundation, with the additional benefits of fully managed service with instant deployment and scale-out option.

Continue reading