如何使用 Spring Boot 将来自 Google Secret Manager 的秘密作为环境变量注入 Kubernetes Pod?
How to inject secret from Google Secret Manager into Kubernetes Pod as environment variable with Spring Boot?
为了 Bryan 的生命,我该怎么做?
Terraform
用于在 GCP 中创建一个 SQL 服务器实例。
随机生成root密码和用户密码,然后放入Google Secret Manager。
数据库的 IP 通过私有 DNS 区域公开。
我现在如何获取用户名和密码以访问我的 K8s 集群中的数据库? 运行 Spring 在此处启动应用程序。
这是我想到的一个选项:
在我的部署中,我添加了一个 initContainer
:
- name: secrets
image: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- echo "DB_PASSWORD=$(gcloud secrets versions access latest --secret=\"$NAME_OF_SECRET\")" >> super_secret.env
好的,现在怎么办?我如何从这里将它放入我的应用程序容器?
还有像 bitnami/sealed-secrets
这样的选项,我不喜欢,因为设置已经在使用 Terraform
并将机密保存在 GCP 中。使用 sealed-secrets
时,我可以跳过使用机密管理器。与 Vault
IMO 相同。
How do I get it into my application container from here?
您可以使用 volume 来存储秘密并在初始容器和主容器中安装相同的卷,以便与来自初始容器的主容器共享秘密。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app
image: my-app:latest
volumeMounts:
- name: config-data
mountPath: /data
initContainers:
- name: secrets
image: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- echo "DB_PASSWORD=$(gcloud secrets versions access latest --secret=\"$NAME_OF_SECRET\")" >> super_secret.env
volumeMounts:
- name: config-data
mountPath: /data
volumes:
- name: config-data
emptyDir: {}
使用 emptyDir 的 volumes
和 medium: Memory
来保证秘密不会被持久化。
...
volumes:
- name: scratch
emptyDir:
medium: Memory
sizeLimit: "1Gi"
...
除了评论中的其他答案和建议之外,我还想推荐两个您可能会感兴趣的工具。
第一个是secret-init:
secrets-init
is a minimalistic init system designed to run as PID 1
inside container environments and it`s integrated with
multiple secrets manager services, e.x. Google Secret Manager
第二个是kube-secrets-init:
The kube-secrets-init
is a Kubernetes mutating admission webhook,
that mutates any K8s Pod that is using specially prefixed environment
variables, directly or from Kubernetes as Secret or ConfigMap.
它还支持与 Google Secret Manager 集成:
用户可以将 Google 秘密名称(前缀为 gcp:secretmanager:
)作为环境变量值。 secrets-init
将使用指定名称将任何环境值解析为引用的秘密值。
这里有一个很好的article关于它是如何工作的。
您可以使用 spring-cloud-gcp-starter-secretmanager
从 Spring 应用程序本身加载机密。
文档 - https://cloud.spring.io/spring-cloud-gcp/reference/html/#secret-manager
如果可以控制图像,可以更改入口点并使用 berglas
。
Docker 文件:
FROM adoptopenjdk/openjdk8:jdk8u242-b08-ubuntu # or whatever you need
# Install berglas, see https://github.com/GoogleCloudPlatform/berglas
RUN mkdir -p /usr/local/bin/
ADD https://storage.googleapis.com/berglas/main/linux_amd64/berglas /usr/local/bin/berglas
RUN chmod +x /usr/local/bin/berglas
ENTRYPOINT ["/usr/local/bin/berglas", "exec", "--"]
现在我们构建容器并测试它:
docker build -t image-with-berglas-and-your-app .
docker run \
-v /host/path/to/credentials_dir:/root/credentials \
--env GOOGLE_APPLICATION_CREDENTIALS=/root/credentials/your-service-account-that-can-access-the-secret.json \
--env SECRET_TO_RESOLVE=sm://your-google-project/your-secret \
-ti image-with-berglas-and-your-app env
这应该用 sm://
替换为实际的秘密值来打印环境变量。
在K8s中我们运行使用Workload Identity,所以调度pod所代表的K8s服务账号需要绑定一个Google有访问权限的服务账号秘密。
最后你的广告连播描述应该是这样的:
apiVersion: v1
kind: Pod
metadata:
name: your-app
spec:
containers:
- name: your-app
image: image-with-berglas-and-your-app
command: [start-sql-server]
env:
- name: AXIOMA_PASSWORD
value: sm://your-google-project/your-secret
为了 Bryan 的生命,我该怎么做?
Terraform
用于在 GCP 中创建一个 SQL 服务器实例。
随机生成root密码和用户密码,然后放入Google Secret Manager。
数据库的 IP 通过私有 DNS 区域公开。
我现在如何获取用户名和密码以访问我的 K8s 集群中的数据库? 运行 Spring 在此处启动应用程序。
这是我想到的一个选项:
在我的部署中,我添加了一个 initContainer
:
- name: secrets
image: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- echo "DB_PASSWORD=$(gcloud secrets versions access latest --secret=\"$NAME_OF_SECRET\")" >> super_secret.env
好的,现在怎么办?我如何从这里将它放入我的应用程序容器?
还有像 bitnami/sealed-secrets
这样的选项,我不喜欢,因为设置已经在使用 Terraform
并将机密保存在 GCP 中。使用 sealed-secrets
时,我可以跳过使用机密管理器。与 Vault
IMO 相同。
How do I get it into my application container from here?
您可以使用 volume 来存储秘密并在初始容器和主容器中安装相同的卷,以便与来自初始容器的主容器共享秘密。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app
image: my-app:latest
volumeMounts:
- name: config-data
mountPath: /data
initContainers:
- name: secrets
image: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- echo "DB_PASSWORD=$(gcloud secrets versions access latest --secret=\"$NAME_OF_SECRET\")" >> super_secret.env
volumeMounts:
- name: config-data
mountPath: /data
volumes:
- name: config-data
emptyDir: {}
使用 emptyDir 的 volumes
和 medium: Memory
来保证秘密不会被持久化。
...
volumes:
- name: scratch
emptyDir:
medium: Memory
sizeLimit: "1Gi"
...
除了评论中的其他答案和建议之外,我还想推荐两个您可能会感兴趣的工具。
第一个是secret-init:
secrets-init
is a minimalistic init system designed to run as PID 1 inside container environments and it`s integrated with multiple secrets manager services, e.x. Google Secret Manager
第二个是kube-secrets-init:
The
kube-secrets-init
is a Kubernetes mutating admission webhook, that mutates any K8s Pod that is using specially prefixed environment variables, directly or from Kubernetes as Secret or ConfigMap.
它还支持与 Google Secret Manager 集成:
用户可以将 Google 秘密名称(前缀为 gcp:secretmanager:
)作为环境变量值。 secrets-init
将使用指定名称将任何环境值解析为引用的秘密值。
这里有一个很好的article关于它是如何工作的。
您可以使用 spring-cloud-gcp-starter-secretmanager
从 Spring 应用程序本身加载机密。
文档 - https://cloud.spring.io/spring-cloud-gcp/reference/html/#secret-manager
如果可以控制图像,可以更改入口点并使用 berglas
。
Docker 文件:
FROM adoptopenjdk/openjdk8:jdk8u242-b08-ubuntu # or whatever you need
# Install berglas, see https://github.com/GoogleCloudPlatform/berglas
RUN mkdir -p /usr/local/bin/
ADD https://storage.googleapis.com/berglas/main/linux_amd64/berglas /usr/local/bin/berglas
RUN chmod +x /usr/local/bin/berglas
ENTRYPOINT ["/usr/local/bin/berglas", "exec", "--"]
现在我们构建容器并测试它:
docker build -t image-with-berglas-and-your-app .
docker run \
-v /host/path/to/credentials_dir:/root/credentials \
--env GOOGLE_APPLICATION_CREDENTIALS=/root/credentials/your-service-account-that-can-access-the-secret.json \
--env SECRET_TO_RESOLVE=sm://your-google-project/your-secret \
-ti image-with-berglas-and-your-app env
这应该用 sm://
替换为实际的秘密值来打印环境变量。
在K8s中我们运行使用Workload Identity,所以调度pod所代表的K8s服务账号需要绑定一个Google有访问权限的服务账号秘密。
最后你的广告连播描述应该是这样的:
apiVersion: v1
kind: Pod
metadata:
name: your-app
spec:
containers:
- name: your-app
image: image-with-berglas-and-your-app
command: [start-sql-server]
env:
- name: AXIOMA_PASSWORD
value: sm://your-google-project/your-secret