如何在Spring Boot的application.yaml中引用并解密KMS加密的Kubernetes Secret?
Kubernetes Secret在Spring Boot中的引用与解密
一、在application.yaml中引用Kubernetes Secret
要在Spring Boot里引用Kubernetes Secret,需先把Secret内容传递到Pod内部,常用两种方式:环境变量注入或卷挂载,再在application.yaml中读取对应值。
1. 环境变量注入方式
先在Deployment配置里,将Secret的key映射为Pod的环境变量:
apiVersion: apps/v1 kind: Deployment metadata: name: my-spring-boot-deploy spec: replicas: 1 selector: matchLabels: app: my-spring-boot-app template: metadata: labels: app: my-spring-boot-app spec: containers: - name: my-spring-boot-app image: your-app-image:latest env: # 映射Secret中的USER_NAME到环境变量DB_USER - name: DB_USER valueFrom: secretKeyRef: name: mysecret key: USER_NAME # 映射Secret中的PASSWORD到环境变量DB_PASS - name: DB_PASS valueFrom: secretKeyRef: name: mysecret key: PASSWORD
随后在Spring Boot的application.yaml中直接引用这些环境变量:
spring: datasource: username: ${DB_USER} password: ${DB_PASS}
2. 卷挂载方式
也可将Secret挂载为Pod内的文件,再读取文件内容:
在Deployment中配置卷和挂载路径:
apiVersion: apps/v1 kind: Deployment metadata: name: my-spring-boot-deploy spec: replicas: 1 selector: matchLabels: app: my-spring-boot-app template: metadata: labels: app: my-spring-boot-app spec: volumes: - name: secret-volume secret: secretName: mysecret containers: - name: my-spring-boot-app image: your-app-image:latest volumeMounts: - name: secret-volume mountPath: /etc/app-secrets readOnly: true
此时Secret的每个key会变成/etc/app-secrets目录下的文件,文件内容即为对应值。在application.yaml中通过file:前缀读取:
spring: datasource: username: ${file:/etc/app-secrets/USER_NAME} password: ${file:/etc/app-secrets/PASSWORD}
注意:Spring Boot 2.4+需确保引入spring-boot-starter或相关依赖,以支持file:类型的属性源。
二、解密KMS加密的内容
针对你提到的Pod内Secret为KMS加密状态的场景,分两种情况处理:
1. Kubernetes etcd静态加密场景
如果是集群开启了etcd静态加密(用KMS provider加密etcd中的Secret数据),当Secret挂载到Pod时,Kubelet会自动完成解密,Pod内的环境变量或文件内容已是明文,Spring Boot无需额外处理,直接使用即可。
2. Secret值本身是KMS加密密文场景
如果Secret的data字段存储的是KMS加密后的密文(而非base64编码的明文),需在Spring Boot中调用KMS服务解密:
- 先确保Pod对应的Kubernetes ServiceAccount拥有调用KMS服务的权限(比如AWS IAM角色绑定、GCP服务账号权限等,根据使用的KMS提供商配置)。
- 编写解密工具类调用KMS解密API,以AWS KMS为例:
import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.DecryptRequest; import java.nio.ByteBuffer; import java.util.Base64; import org.springframework.stereotype.Component; @Component public class KmsDecryptUtil { public String decrypt(String encryptedBase64Str) { AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient(); byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64Str); DecryptRequest request = new DecryptRequest() .withCiphertextBlob(ByteBuffer.wrap(encryptedBytes)); ByteBuffer plaintextBuffer = kmsClient.decrypt(request).getPlaintext(); byte[] plaintextBytes = new byte[plaintextBuffer.remaining()]; plaintextBuffer.get(plaintextBytes); return new String(plaintextBytes); } }
- 通过配置类绑定并解密属性:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @ConfigurationProperties(prefix = "spring.datasource") @Component public class DatasourceProperties { private String username; private String password; @Autowired private KmsDecryptUtil decryptUtil; public String getUsername() { return decryptUtil.decrypt(username); } public void setUsername(String username) { this.username = username; } public String getPassword() { return decryptUtil.decrypt(password); } public void setPassword(String password) { this.password = password; } }
这样application.yaml中可直接使用从Secret拿到的加密值,会自动解密为明文。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

