This repository contains sample code and instructions that would help you get started with Spring Boot based application integration with the following K8s features:
- Readiness and liveness probes
- Config Maps
- Service Discovery - See branch
Service Discovery
These samples use Fabric8 Maven Plugin and Spring Cloud Kubernetes to make this happen. It is not necessary for you to use the Fabric8
plugin, however it just makes deploying a Spring Boot app to K8s much easier. Some of the cool features of the plugin is:
- Consistent and easy K8s deployment descriptor generation for Java/Spring Boot apps
- Spring Boot Actuator based Readiness and Liveness probes K8s Probes
- Enabling Spring Boot features based on the presence of the dependency withing the
pom
file
- A local or remote K8s cluster
- If using MiniKube make sure to execute
eval $(minikube docker-env)
so that the built image available as part of the MiniKube Docker daemon - If not using MiniKube, make sure your image is available on DockerHub or an internal private docker registry
The most common approach to configure your spring boot application is to edit the application.yaml
file. Often the user may override properties by specifying system properties or env variables.
This feature works somewhat like Spring Cloud Config server, but without a Git or Vault based backend configuration store.
Kubernetes has the notion of ConfigMap for passing configuration to the application.
The ConfigMap
PropertySource
when enabled will lookup Kubernetes for a ConfigMap
named after the application (see spring.application.name
). If the map is found it will read its data and do the following:
- apply individual configuration properties.
- apply as yaml the content of any property named
application.yaml
- apply as properties file the content of any property named
application.properties
Example:
kind: ConfigMap
apiVersion: v1
metadata:
name: spring-boot-k8s-recipes
data:
application.yml: |-
greeting:
message: From default Spring profile
---
spring:
profiles: development
greeting:
message: From development Spring profile
---
spring:
profiles: kubernetes
greeting:
message: From kubernetes Spring profile
Kubernetes has the notion of Secrets for storing sensitive data such as password, OAuth tokens, etc.
The Secrets
PropertySource
when enabled will lookup Kubernetes for Secrets
from the following sources:
- reading recursively from secrets mounts
- named after the application (see
spring.application.name
) - matching some labels
Please note that by default, consuming Secrets via API (points 2 and 3 above) is not enabled.
If the secrets are found theirs data is made available to the application.
Example:
apiVersion: v1
kind: Secret
metadata:
name: activemq-secrets
labels:
broker: activemq
type: Opaque
data:
amq.username: bXl1c2VyCg==
amq.password: MWYyZDFlMmU2N2Rm
You can select the Secrets to consume in a number of ways:
-
By listing the directories were secrets are mapped:
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/activemq,etc/secrets/postgres
If you have all the secrets mapped to a common root, you can set them like:
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
-
By setting a named secret:
-Dspring.cloud.kubernetes.secrets.name=postgres-secrets
-
By defining a list of labels:
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq -Dspring.cloud.kubernetes.secrets.labels.db=postgres
Properties:
Name | Type | Default | Description |
---|---|---|---|
spring.cloud.kubernetes.secrets.enabled | Boolean | true | Enable Secrets PropertySource |
spring.cloud.kubernetes.secrets.name | String | ${spring.application.name} | Sets the name of the secret to lookup |
spring.cloud.kubernetes.secrets.labels | Map | null | Sets the labels used to lookup secrets |
spring.cloud.kubernetes.secrets.paths | List | null | Sets the paths were secrets are mounted /example 1) |
spring.cloud.kubernetes.secrets.enableApi | Boolean | false | Enable/Disable consuming secrets via APIs (examples 2 and 3) |
Notes:
- The property spring.cloud.kubernetes.secrets.labels behave as defined by Map-based binding.
- The property spring.cloud.kubernetes.secrets.paths behave as defined by Collection-based binding.
- Access to secrets via API may be restricted for security reasons, the preferred way is to mount secret to the POD.
Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration. The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related ConfigMap or Secret change.
This feature is disabled by default and can be enabled using the configuration property spring.cloud.kubernetes.reload.enabled=true
(eg. in the bootstrap.properties file).
The following levels of reload are supported (property spring.cloud.kubernetes.reload.strategy
):
- refresh (default): only configuration beans annotated with
@ConfigurationProperties
or@RefreshScope
are reloaded. This reload level leverages the refresh feature of Spring Cloud Context. - restart_context: the whole Spring ApplicationContext is gracefully restarted. Beans are recreated with the new configuration.
- shutdown: the Spring ApplicationContext is shut down to activate a restart of the container. When using this level, make sure that the lifecycle of all non-daemon threads is bound to the ApplicationContext and that a replication controller or replica set is configured to restart the pod.
The reload feature supports two operating modes:
- event (default): watches for changes in config maps or secrets using the Kubernetes API (web socket).
Any event will produce a re-check on the configuration and a reload in case of changes.
The
view
role on the service account is required in order to listen for config map changes. A higher level role (eg.edit
) is required for secrets (secrets are not monitored by default). - polling: re-creates the configuration periodically from config maps and secrets to see if it has changed.
The polling period can be configured using the property
spring.cloud.kubernetes.reload.period
and defaults to 15 seconds. It requires the same role as the monitored property source. This means, for example, that using polling on file mounted secret sources does not require particular privileges.
Properties:
Name | Type | Default | Description |
---|---|---|---|
spring.cloud.kubernetes.reload.enabled | Boolean | false | Enables monitoring of property sources and configuration reload |
spring.cloud.kubernetes.reload.monitoring-config-maps | Boolean | true | Allow monitoring changes in config maps |
spring.cloud.kubernetes.reload.monitoring-secrets | Boolean | false | Allow monitoring changes in secrets |
spring.cloud.kubernetes.reload.strategy | Enum | refresh | The strategy to use when firing a reload (refresh, restart_context, shutdown) |
spring.cloud.kubernetes.reload.mode | Enum | event | Specifies how to listen for changes in property sources (event, polling) |
spring.cloud.kubernetes.reload.period | Long | 15000 | The period in milliseconds for verifying changes when using the polling strategy |
Notes:
- Properties under spring.cloud.kubernetes.reload.* should not be used in config maps or secrets: changing such properties at runtime may lead to unexpected results;
- Deleting a property or the whole config map does not restore the original state of the beans when using the refresh level.
Spring Boot uses HealthIndicator to expose info about the health of an application. That makes it really useful for exposing health related information to the user and are also a good fit for use as readiness probes.
The Kubernetes health indicator which is part of the core modules exposes the following info:
- pod name
- visible services
- flag that indicates if app is internal or external to Kubernetes
When the application is run inside Kubernetes a profile named kubernetes
will automatically get activated.
This allows the user to customize the configuration that will be applied in and out of kubernetes (e.g. different dev and prod configuration).
- Clone this repo
mvn clean install -Pintegration
mvn fabric8:deploy
mvn fabric8:log
The required K8s RBAC configuration is stored in src/main/k8s
. This will be picked by the fabric8
plugin and will be applied as part of the deploy
task. That is, a new ServiceAccount
with the required permissions would be created.
If you already have a provisioned ServiceAccount
, just update the deployment.yml
located in src/main/fabric8
to reflect the name of the service account and delete sa.yml
and rb.yml
For further reference, please consider the following sections: