Search code examples
spring-bootkubernetesspring-cloudspring-cloud-kubernetesspring-boot-3

Spring boot 3 does not load configMap


I have a minimalist app with spring boot 3.1.1 and spring cloud 2022.0.4, on EKS with kubernetes 1.27, but unfortunately the config is never loaded from the ConfigMap ...

The app is made of a single file without any configuration or application.yaml to serve content from static resources:

package ch.brw.hive.frontend

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class App

fun main(args: Array<String>) {
    runApplication<App>(*args)
}

My gradle project name is spring-boot-frontend and the build.gradle.kts is:

...
springBoot {
  buildInfo()
}
...
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-client")
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-client-config")
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-client-all")
...

My deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: "spring-boot-frontend"
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: "frontend"
    spec:
      containers:
        - name: "spring-boot-frontend"
          image: "{{ .Values.frontend.image.registry }}/{{ .Values.frontend.image.name }}:{{ .Values.frontend.image.tag }}"
          imagePullPolicy: {{ .Values.frontend.image.pullPolicy | quote }}
          ports:
            - name: http
              containerPort: 8080
          resources:
            {{- toYaml .Values.frontend.resources | nindent 12 }}
      restartPolicy: Always
  selector:
    matchLabels:
      app: "frontend"

My configMap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: "spring-boot-frontend"
data:
  application.yaml: |-
    server:
      port: 8181

My role.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: {{ .Values.fullyQualifiedName }}
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]

My roleBinding.yaml (I use the default service account):

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ .Values.fullyQualifiedName }}
subjects:
  - kind: ServiceAccount
    name: default
    namespace: {{ .Release.Namespace }}
roleRef:
  kind: Role
  name: {{ .Values.fullyQualifiedName }}
  apiGroup: ""

The log does not show any error:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.1.1)

2023-08-31T19:54:27.718Z  INFO 1 --- [           main] ch.brw.hive.frontend.AppKt               : Starting AppKt using Java 17.0.8 with PID 1 (/app/classes started by root in /)
2023-08-31T19:54:27.720Z  INFO 1 --- [           main] ch.brw.hive.frontend.AppKt               : The following 1 profile is active: "kubernetes"
2023-08-31T19:54:29.061Z  INFO 1 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=3d87bae4-72a0-3c9a-ad7b-c5d752a70bf4
2023-08-31T19:54:29.381Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-08-31T19:54:29.391Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-08-31T19:54:29.392Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.10]
2023-08-31T19:54:29.476Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-08-31T19:54:29.479Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1674 ms
2023-08-31T19:54:30.075Z  INFO 1 --- [           main] o.s.c.k.client.KubernetesClientUtils     : Created API client in the cluster.
2023-08-31T19:54:30.308Z  INFO 1 --- [ler-V1Endpoints] i.k.client.informer.cache.Controller     : informer#Controller: ready to run resync & reflector runnable
2023-08-31T19:54:30.308Z  INFO 1 --- [ler-V1Endpoints] i.k.client.informer.cache.Controller     : informer#Controller: resync skipped due to 0 full resync period
2023-08-31T19:54:30.310Z  INFO 1 --- [s.V1Endpoints-1] i.k.c.informer.cache.ReflectorRunnable   : class io.kubernetes.client.openapi.models.V1Endpoints#Start listing and watching...
2023-08-31T19:54:30.342Z  INFO 1 --- [els.V1Service-1] i.k.c.informer.cache.ReflectorRunnable   : class io.kubernetes.client.openapi.models.V1Service#Start listing and watching...
2023-08-31T19:54:31.308Z  INFO 1 --- [pool-9-thread-1] s.c.k.c.d.KubernetesDiscoveryClientUtils : Waiting for the cache of informers to be fully loaded..
2023-08-31T19:54:31.309Z  INFO 1 --- [           main] s.c.k.c.d.KubernetesDiscoveryClientUtils : Cache fully loaded (total 3 services), discovery client is now available
2023-08-31T19:54:31.464Z  INFO 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint(s) beneath base path '/actuator'
2023-08-31T19:54:31.539Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-08-31T19:54:31.564Z  INFO 1 --- [           main] ch.brw.hive.frontend.AppKt               : Started AppKt in 4.674 seconds (process running for 5.105)

As you can see the port is never changed to 8181, which should be the case the the application.yaml was loaded properly.

I was reading the doc again and again:

https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/index.html#configmap-propertysource

Does anyone have any ideas about what I am missing ?


Solution

  • I managed to make it work by adding in my deployment.yaml:

    args: [
      "--spring.cloud.bootstrap.enabled=true"
      "--spring.cloud.kubernetes.config.name=spring-boot-frontend",
      "--spring.cloud.kubernetes.config.namespace={{ .Release.Namespace }}"
    ]
    

    This was poorly documented ...