OCP and SpringBoot
Background
I’ve helped about dozens of customers adopt Kubernetes and OpenShift in the past few years, and a recurring theme I keep hearing is how they believe rewriting their monolithic applications with spring-boot
is their modernization strategy. While I do agree that spring-boot
is a great tool, most of the architects and developers I worked with seem to care more about the boot
part than the spring
.
While the spring-boot
technology is newer, Spring
has been around for a long time. The spring-boot
project makes it easy for developers to adopt the Spring
Framework. They allow developers to quickly bootstrap applications, and do things the Spring
way via conventions over configurations.
These spring-boot
applications are easily deployed to OpenShift as regular Java applications, and this post today is more of a note-to-self on how to configure Java applications, including spring-boot
.
Deployments
All applications need to be declaratively deployed in Kubernetes somehow. It doesn’t matter if it’s a Deployment
, DeploymentConfig
, StatefulSet
, etc., this is just part of Kubernetes.
An application should externalize configurational settings so the image being built can be deployed into any environment, which allows environment-specific properties to be loaded at runtime. This follows the build once, deploy everywhere paradigm. This approach allows an application image to be fully tested in lower environments, with development-centric properties/configurations (logging levels, test databases, feature flags, etc.). Once an image is fully tested, it can be promoted to a higher environment with confidence that the code works. Any issue found will most likely be a misconfiguration, or due to dirty data based on the nature of working with real, production data.
Spring Boot Configurations
A spring-boot
application reads properties from src/main/resources/application.properties
by default. Some deployment strategies include creating environment specific application.properties
files every environment, and checking them all into the repository. Another strategy would be to create a ConfigMap
or Secret
, and project this file into the running container. We’re going to do the latter today as an example, as the former is pretty straightforward.
ConfigMap
Creating a ConfigMap
in Kubernetes is straight forward. If you have an existing properties file, you can use oc create cm propfile --from-file=<file/path>
. If not, you can just create a new ConfigMap and add the properties in yourself. Just make sure that the key is the name of the file, and use the |-
character to add values inline.
It should look something like this.
kind: ConfigMap
apiVersion: v1
metadata:
name: propfile
data:
application.properties: |-
server.port=8080
# more properties here
Once the ConfigMap
is available, project it into the Deployment as a volume. It can be anywhere, as long as it doesn’t override anything important. A safe place is /deployments/config
Environment Variables
When deploying a spring-boot
application onto OpenShift using the Red Hat OpenJDK base image, all there’s left to do is set the JAVA_ARGS
to point to the new location of where the application.properties
file is.
Note: JAVA_ARGS
gets appended to the entrypoint script when executing the java
command, so users can pass in any additional Java flags as needed.
Set the ENV variable JAVA_ARGS
value to --spring.config.location=file://deployments/config/application.properties
When the pod restarts, it will now be reading from the newly projected ConfigMap
!