我的k8s命名空间包含一个在部署时(由svcat
创建)Secret
,因此事先不知道这些值。
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: my-database-credentials
data:
hostname: ...
port: ...
database: ...
username: ...
password: ...
Deployment
需要以略有不同的格式注入这些值:
...
containers:
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: my-database-credentials
key: jdbc:postgresql:<hostname>:<port>/<database> // ??
- name: DATABASE_USERNAME
valueFrom:
secretKeyRef:
name: my-database-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-database-credentials
key: password
DATABASE_URL
需要由先前定义的密钥的hostname
、port
、"数据库"组成。
有没有办法做这个构图?
Kubernetes 允许您使用先前定义的环境变量作为配置中其他地方的后续环境变量的一部分。来自 Kubernetes API 参考文档:
变量引用 $(VAR_NAME) 使用容器中先前定义的环境变量和任何服务环境变量进行扩展。
此$(...)
语法定义容器的相互依赖的环境变量。
因此,您可以先将所需的机密值提取到环境变量中,然后使用这些变量组成DATABASE_URL
。
...
containers:
env:
- name: DB_URL_HOSTNAME // part 1
valueFrom:
secretKeyRef:
name: my-database-credentials
key: hostname
- name: DB_URL_PORT // part 2
valueFrom:
secretKeyRef:
name: my-database-credentials
key: port
- name: DB_URL_DBNAME // part 3
valueFrom:
secretKeyRef:
name: my-database-credentials
key: database
- name: DATABASE_URL // combine
value: jdbc:postgresql:$(DB_URL_HOSTNAME):$(DB_URL_PORT)/$(DB_URL_DBNAME)
...
你可以做几件我能想到的事情:
- 使用机密卷
并创建一个启动脚本,该脚本从卷中读取机密,然后使用
DATABASE_URL
环境变量启动应用程序。apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: your_db_container command: [ "yourscript.sh" ] volumeMounts: - name: mycreds mountPath: "/etc/credentials" volumes: - name: mycreds secret: secretName: my-database-credentials defaultMode: 256
在容器规范的
command
键中传递 env 变量:apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: your_db_container command: [ "/bin/sh", "-c", "DATABASE_URL=jdbc:postgresql:<hostname>:<port>/<database>/$(DATABASE_USERNAME):$(DATABASE_PASSWORD) /start/yourdb" ] env: - name: DATABASE_USERNAME valueFrom: secretKeyRef: name: my-database-credentials key: username - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: my-database-credentials key: password
如果所有前变量都定义为 env 变量:
- { name: DATABASE_URL, value: '{{ printf "jdbc:postgresql:$(DATABASE_HOST):$(DATABASE_PORT)/$(DB_URL_DBNAME)" }}'}
使用此语句,您还可以从 values.yaml 文件中引入 vlaues:
例如:
如果可能在值文件中定义了DB_URL_DBNAME:
- { name: DATABASE_URL, value: '{{ printf "jdbc:postgresql:$(DATABASE_HOST):$(DATABASE_PORT)/%s" .Values.database.DB_URL_DBNAME }}'}
有几种方法可以走(按复杂性递增顺序):
-
在将参数放入密钥之前对其进行修改(扩展用于在其中插入信息的任何内容)。
将 脚本添加到 Pod/容器中,以将传入参数(环境变量或命令参数)修改为所需的参数。如果不能或不想拥有自己的容器映像,可以将额外的脚本作为卷添加到容器中,并将容器的
command
字段设置为覆盖容器映像启动命令。
向 Kubernetes 添加一个工具以在"幕后"执行自动管理:您可以添加一个动态准入控制器来执行重整,或者您可以创建一个 Kubernetes 运算符并添加自定义资源定义(CRD 会告诉操作员要监视哪些秘密更改,操作员将读取值并生成您想要的任何其他条目)。