== what Kubernetes actually mounts == $ find /tmp/demo-configmap /tmp/demo-secret -type f | sort /demo.datasource-url /demo.greeting /demo.pool-size /demo/nested/value /demo.api-key $ cat /demo.greeting; echo from-configmap-volume Each file holds a bare value with no trailing newline and no key. There is no properties syntax to parse -- the filename is the key. == importing it == $ java -jar target/profiles-and-config-1.0.0.jar \ --spring.config.import=configtree:/tmp/demo-configmap/,configtree:/tmp/demo-secret/ active profiles : (none) effective value : from-configmap-volume 1. from-configmap-volume <- ConfigTreePropertySource {name='Config tree '/tmp/demo-configmap''} 2. from-application-yaml <- 'file application.yaml' via location 'optional:classpath:/''} holders that lost: 1 demo.pool-size = 25 demo.nested.value = from-nested-directory demo.api-key = sk_live_not_a_real_key A directory under the mount becomes a nested property: demo/nested/value is demo.nested.value. That is how a ConfigMap with slashes in its keys arrives. == the part that surprises people == An imported config tree outranks application.yaml, but it is still config data, so it still loses to an environment variable: active profiles : (none) effective value : from-environment-variable 1. from-environment-variable <- OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'} 2. from-configmap-volume <- ConfigTreePropertySource {name='Config tree '/tmp/demo-configmap''} 3. from-application-yaml <- 'file application.yaml' via location 'optional:classpath:/''} holders that lost: 2 There is also no such thing as a profile-specific config tree. There is no -prod directory convention; a per-environment ConfigMap is a different mount chosen by the deployment, not by spring.profiles.active.