I have both Secret and ConfigMap. Everything is fine with ConfigMap but the issue is with Secret.
So first thing I did was adding the properties as environment variable:
containers:
- name: {{ include "helper.app-name" . }}
envFrom:
- configMapRef:
name: {{ include "helper.app-name" . }}-config
- secretRef:
name: {{ .Values.credentials.secretName }}
Properties named with dot such as my.property.name doesn't work even in ConfigMap which was surprising for me because a few years ago the same thing was working nicely. It only works if I change the name to MY_PROPERTY_NAME but this is not convenient because there can be 10 or 20 properties and converting them to that format is error prone.
So then I decided to add the properties as YAML file:
# configmaps
data:
application-configmap.yaml: |-
my.property.name: A Name
And mounted them as below:
spec:
volumes:
- name: config-volume
configMap:
name: {{ include "helper.app-name" . }}-config
items:
- key: "bootstrap.yaml"
path: "bootstrap.yaml"
- key: "application-configmap.yaml"
path: "application-configmap.yaml"
...
containers:
....
volumeMounts:
- name: config-volume
mountPath: "/config"
readOnly: true
- name: secret-volume
mountPath: "/secret"
readOnly: true
Now ConfigMap works but secret doesn't! Whether it's as environment variable or as a file, it just doesn't work. (Note: I have set active profiles to configmap already)
Then did some investigation and tried Spring Cloud:
implementation("org.springframework.cloud:spring-cloud-starter-kubernetes-fabric8-config:3.0.2")
With this in bootstrap.yaml defined in ConfigMap:
spring:
config.import: optional:configtree:/secret
cloud:
kubernetes:
reload:
enabled: true
secrets:
enabled: true
name: my-secret-config
and the secret:
# secret
metadata:
name: my-secret-config
stringData:
my.credentials.password: somepass
But no luck. I added spring.config.import property after seeing it somewhere but it just doesn't like Secret.
Please note that I have added Role and RoleBinding with read permission from configmaps and secrets to the ServiceAccount.
One more thing is that when I mount the secret, like below, later on when I check the yaml output of the deployed POD, strangely it's not there. It's like K8s ignores it:
volumeMounts:
- name: secret-volume
mountPath: "/secret"
readOnly: true
I dug in everywhere including StackOverflow and Spring Cloud docs and tried everything but nothing is working.
It sounds like you are trying to use Kubernetes Secrets to manage sensitive information in your Spring Boot application running in a Kubernetes cluster, but you are having trouble accessing the Secret data.
One thing to note is that Kubernetes Secrets are Base64-encoded, so you may need to decode the values before using them in your application.
Here are a few suggestions you can try:
- Use the Spring Cloud Kubernetes Secrets API
You mentioned that you tried using the Spring Cloud Kubernetes Fabric8 Config library, but it didn't work for Secrets. You may want to try using the Spring Cloud Kubernetes Secrets API instead. This API is specifically designed for accessing Secrets in a Kubernetes cluster from a Spring Boot application.
To use the API, add the following dependency to your project:
scssimplementation("org.springframework.cloud:spring-cloud-starter-kubernetes-secrets:3.0.2")
Then, in your application.properties file, set the following properties:
arduinospring.cloud.kubernetes.secrets.name=my-secret-config
spring.cloud.kubernetes.secrets.enabled=true
Replace "my-secret-config" with the name of your Secret. You can then inject the Secret values into your application using the @Value annotation, like this:
kotlin@Value("${my.credentials.password}")
private String password;
- Use the Kubernetes API directly
If the Spring Cloud Kubernetes Secrets API doesn't work for you, you can try using the Kubernetes API directly. Here's an example of how to do this:
scss@Autowired
private KubernetesClient kubernetesClient;
...
Secret secret = kubernetesClient.secrets().inNamespace("default").withName("my-secret-config").get();
byte[] passwordBytes = Base64.getDecoder().decode(secret.getData().get("my.credentials.password"));
String password = new String(passwordBytes);
Replace "default" with the namespace of your Secret.
- Check your ServiceAccount permissions
Make sure that the ServiceAccount your application is running under has read permissions for the Secret. You mentioned that you added Role and RoleBinding with read permission from configmaps and secrets to the ServiceAccount, but it's possible that there is still a permission issue.
You can check the permissions for your ServiceAccount by running the following command:
csharpkubectl auth can-i get secrets --as=system:serviceaccount:namespace:serviceaccountname
Replace "namespace" with the namespace of your Secret and "serviceaccountname" with the name of your ServiceAccount. This command will tell you whether the ServiceAccount has permission to access Secrets.
I hope these suggestions help you resolve your issue with accessing Kubernetes Secrets in your Spring Boot application.
Comments
Post a Comment