我正在使用 kubernetes ConfigMap,其中包含应用程序的数据库配置,并且有一个包含数据库密码的机密。 我需要在 ConfigMap 中使用此机密,因此当我尝试在 ConfigMap 中添加环境变量并从该机密指定 pod 部署中的值时,我无法使用密码连接到 mysql,因为 ConfigMap 中的值采用了变量的确切字符串。
apiVersion: v1
kind: ConfigMap
metadata:
name: config
data:
APP_CONFIG: |
port: 8080
databases:
default:
connector: mysql
host: "mysql"
port: "3306"
user: "root"
password: "$DB_PASSWORD"
和deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
labels:
app: backend
spec:
replicas: 1
template:
metadata:
labels:
app: backend
spec:
containers:
- name: app
image: simple-app-image
ports:
- name: "8080"
containerPort: 8080
env:
- name: APP_CONFIG
valueFrom:
configMapKeyRef:
name: config
key: APP_CONFIG
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: "mysql-secret"
key: "mysql-root-password"
注意:秘密存在,我可以获得“mysql-root-password”值并用于登录数据库
Kubernetes 无法为您进行这种替换,您应该在容器的入口点使用 shell 来完成此操作。
这是一个工作示例。我修改默认入口点以使用该替换创建一个新变量。在此命令之后,您应该添加所需的入口点。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
labels:
app: backend
spec:
replicas: 1
template:
metadata:
labels:
app: backend
spec:
containers:
- name: app
image: simple-app-image
command:
- /bin/bash
- -c
args:
- "NEW_APP_CONFIG=$(echo $APP_CONFIG | envsubst) && echo $NEW_APP_CONFIG && <INSERT IMAGE ENTRYPOINT HERE>"
ports:
- name: "app"
containerPort: 8080
env:
- name: APP_CONFIG
valueFrom:
configMapKeyRef:
name: config
key: APP_CONFIG
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: "mysql-secret"
key: "mysql-root-password"
您可以在 HELM 中执行类似的操作:
{{- define "getValueFromSecret" }}
{{- $len := (default 16 .Length) | int -}}
{{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}}
{{- if $obj }}
{{- index $obj .Key | b64dec -}}
{{- else -}}
{{- randAlphaNum $len -}}
{{- end -}}
{{- end }}
然后你可以在configmap中做这样的事情:
{{- include "getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" "<secret_name>" "Length" 10 "Key" "<key>") -}}
秘密在部署时应该已经存在;或者您可以使用 https://github.com/vmware-tanzu/carvel-kapp-controller
控制部署顺序对我来说,这样的方法有效(为了简单起见,仅共享相关示例片段):
示例配置映射
data:
example.yaml: |
user: ${USER}
示例秘密
data:
user: <some base64 encoded value>
示例部署
containers:
- name: example-container
image: example-image
env:
- name: USER
valueFrom:
secretKeyRef:
key: user
name: example-secret
volumeMounts:
- mountPath: /some/path/in/container
name: config
readOnly: true
volumes:
- name: config
configMap:
name: example-configmap
说明:
在上面的例子中,
我需要用秘密中
${USER}
密钥的解码值替换 configmap 中的 user:
。volumes.configMap
) 挂载到容器中的 volumeMounts
下,并且 env.valueFrom.secretKeyRef
)。结果: 配置映射中的
${USER}
将替换为密钥中 user:
密钥的解码值。原因: 这是因为 configmap 现在作为文件安装在容器内的
mountPath
处,因此可以访问容器内公开的任何 env 变量。
注意:deployment/pod、configmap和secret的命名空间应该相同。
可以选择使用外部秘密运算符并拉取您的 configMap,向其注入密码并从中创建一个秘密,最后安装它。
我会将整个
configMap
转换为 secret
并将数据库密码直接部署在那里。
然后,您可以将密钥作为文件安装到卷中,并像容器中的常规配置文件一样使用它。