Externalize Configuration to ConfigMap
We will use the Spring Cloud Kubernetes project’s PropertySource
implementations to help read external configuration. We’ll need to add some dependencies to our project as well as some additional JKube resource fragments, but we won’t need to make any changes to the application’s source code.
Open the project’s pom.xml
file again. We first need to add the Spring Cloud Bill of Materials to the project:
- In the
<properties>
section, add<spring-cloud.version>2022.0.0</spring-cloud.version>
- Note:
2022.0.0
was the latest version as of the writing of this article. You can look on Maven Central for the latest version.
- Note:
- After the
<properties>
section, add a new section:<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
- In the
<dependencies>
, add thekubernetes-client-config
starter:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-client-config</artifactId> </dependency>
NOTE: The completed
pom.xml
file containing these changes can be found on the solution branch of the repo.
As a sanity check, you could run./mvnw verify
on Linux/macOS or mvnw.cmd verify
on Windows to make sure everything still works.
Spring Cloud Kubernetes library needs the view
role on the service account running the application in order to read other objects in the namespace. We can instruct JKube to do this for us when we deploy the application.
Add a new file, src/main/jkube/rolebinding.yml
, with the following contents:
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: default
Additionally, we need to deploy a ConfigMap
containing the configuration into the same namespace as our application. By default, the Spring Cloud Kubernetes Config library will look for a ConfigMap in the same namespace with the same name as the application, although its configuration can be altered if needed. We can instruct JKube to do this for us as well.
Add a new file, src/main/jkube/configmap.yml
, with the following contents:
data:
hello.greeting: Hello (from Kubernetes ConfigMap)
Redeploy to minikube
In the same terminal as before, run ./mvnw k8s:deploy -Pk8s
on Linux/macOS or mvnw.cmd k8s:deploy -Pk8s
on Windows. This will redeploy the application.
Once it finishes, run the command minikube service list
. You should see something like this:
|------------------------------|------------------------------|--------------|----------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|------------------------------|------------------------------|--------------|----------------------------|
| default | kubernetes | No node port |
| kube-system | kube-dns | No node port |
| spring-jkube-external-config | spring-jkube-external-config | http/8080 | http://192.168.205.5:30526 |
|------------------------------|------------------------------|--------------|----------------------------|
NOTE: Your ip address in the URL will most likely be different than what is shown here.
The URL
column should contain a URL for your application that you can now interact with.
Interact with the endpoints again, either by opening a browser window or using the curl
command from another terminal. The following table shows what the values of some of the endpoints should look like. The values for podIp
, hostIp
, and podName
will most likely be different for you.
- http://<your-ip>:30526/hello
Hello (from Kubernetes ConfigMap) World
- http://<your-ip>:30526/hello/Yoda
Hello (from Kubernetes ConfigMap) Yoda
- http://<your-ip>:30526/actuator/info
{ "kubernetes": { "nodeName": "minikube", "podIp": "172.17.0.3", "hostIp": "192.168.205.5", "namespace": "spring-jkube-external-config", "podName": "spring-jkube-external-config-85f8488d6d-5kqrp", "serviceAccount": "default", "inside": true } }
- http://<your-ip>:30526/actuator/env/hello.greeting
{ "property": { "source": "composite-configmap:configmap.spring-jkube-external-config.spring-jkube-external-config", "value": "Hello (from Kubernetes ConfigMap)" } }
NOTE: There is most likely more data in the http://<your-ip>:30526/actuator/env/hello.greeting response. The output is trimmed for brevity.
As you can see, the value of the hello.greeting
property is now being read from the ConfigMap
named spring-jkube-external-config
in the spring-jkube-external-config
namespace. Additionally, you see that the /actuator/info
endpoint now returns information about the Kubernetes environment the application is running in. The Spring Cloud Kubernetes library adds to the info actuator endpoint.