In this article I want to show the best way to configure any Spring Cloud bootstrap properties in your application, making it the a most flexible and future-proof way.
Jump to the code here!
Microservices stack
Following or switching into more microservice architecture, most modern Spring boot applications start using one day something from Spring Cloud stack additionally due to its features and compatibility with Spring Boot stack it already has, i.e. you take the whole ecosystem.
I describe an example in this article of how neat you it is possible to integrate Spring and Spring Boot by using starters.
Along side with Spring Cloud stack, most applications start using Kubernetes as microservices orchestration service, and for this we have the growing Spring Cloud Kubernetes project.
On purpose to externalise application's properties there are two most commons ways to implement this:
- k8s configmap
- Spring Cloud Config server
Considering pros and cons both of these are worth to use and none is really better than another.
Definitely, stack and complexity grows with this and following the hello world approaches online developers rather implement configuration in a way that still brings problems and/or kept unclear for other developers.
One of the crucial and the most important things is enabling/disabling of configuration, as it brings the most influence to your runtime, activating or disabling beans. This is partially confirmed by Stackoverflow questions, querying:
- spring configuration doesn't start: 973
- spring configuration disable: 2748
- and all the other questions on bean duplication / missing problems
In order to make the best out of your configuration, I'd like to show some best practices on an example with Spring Cloud Kubernetes config.
Before jumping to the example it's better to know the basis about the Spring application properties order of precedence:
- application properties https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config
- bootstrap properties https://cloud.spring.io/spring-cloud-commons/multi/multi__spring_cloud_context_application_context_services.html
How to configure bootstrap properties
What are the requirements to the best configuration?
- It always starts in each k8s environment
- It doesn't start in tests
- It start's for a local application run easily when you need it
What do we know?
-
bootstrap
properties start beforeapplication
one - application in k8s cluster container fetchs data from k8s configmap only if it's enabled beforehand
- application must know where to take the properties from before the load
-
spring.cloud.kubernetes.enabled
enables all the sub-configurations -
spring.cloud.kubernetes.config.enabled
enables fetching configmap -
kubernetes
profile exists out of box and will be activated always when the application runs as a pod inside Kubernetes
Then we need:
-
bootstrap.yaml
in resources directory containing:
spring:
cloud:
kubernetes:
config:
enabled: false
enabled: false
-
bootstrap-kubernetes.yaml
containing:
spring:
cloud:
kubernetes:
config:
enabled: true
enabled: true
-
application.yaml
orapplication-kubernetes.yaml
containing:
spring:
cloud:
kubernetes:
config:
name: your-configmap-name
namespace: ${KUBERNETES_NAMESPACE}
Env variable KUBERNETES_NAMESPACE
can't be determined on bootstrap configuration loading as the k8s configmap won't be fetched yet. Hence, we put it into application
properties.
- k8s
service.yaml
containing:
spec:
containers:
env:
- name: "KUBERNETES_NAMESPACE"
valueFrom:
fieldRef:
fieldPath: "metadata.namespace"
- [OPTIONAL] To make it more transparent to developers and let everyone know that
kubernetes
profile will be enabled I'd advice to put this profile explicitly,service.yaml
. Another argument here, that if you already useSPRING_PROFILES_ACTIVE
than it definitely will be clearer if you put additionally thekubernetes
profile, defining all the profiles list at the same place:
spec:
containers:
env:
- name: SPRING_PROFILES_ACTIVE
value: "your-profile,kubernetes"
Conclusions
With this configuration you can easily enable k8s by activating kubernetes
profile and it will disabled on any other run.
Hints
- Staring common
@SpringBootApplication
main class withkubernetes
profile we aware that- You might need env variable
KUBERNETES_NAMESPACE
- It uses k8s context and namespace from the one that is used in your configuration (kubectl) now
- You might need env variable
Top comments (0)