11. configMap 与 Secret
ConfigMap
在 Kubernetes(简称 K8s)里,我们经常需要给应用设置一些“可变配置”,比如数据库地址、服务端口、API 密钥之类的。为了方便管理这些配置信息,K8s 提供了一个叫 ConfigMap 的资源对象。
ConfigMap 的作用就是——把这些非机密的数据(比如配置参数)保存成“键值对”的形式,然后让容器在运行时可以读取到它们。
这些配置信息可以通过几种方式使用:
- 当作 环境变量 提供给应用;
- 当作 命令行参数 传给程序;
- 或者直接 挂载成配置文件 存在容器里。
这样一来,我们就能把“程序逻辑”和“配置内容”分开(也就是“解耦”)。想改配置的时候,不用重新改代码、重新打镜像,只要更新 ConfigMap 就行,非常方便。
不过要注意,ConfigMap 不会对数据加密或保密。
如果你要保存密码、Token 等敏感信息,那就应该用 Secret 资源或者其他安全工具,而不是 ConfigMap。
举个例子:
有个应用需要连接 Redis 数据库。我们当然不想把 Redis 地址写死在代码里,因为如果 Redis 换了位置,每次都得改代码、重新打包镜像。
这时候,用 ConfigMap 就很合适。我们可以:
- 把 Redis 地址单独存在 ConfigMap 里;
- 或者直接把整个 Redis 的配置文件放进去;
然后让容器在启动时去读取。
从结构上看,ConfigMap 也是一种 K8s 资源对象,但它不像 Deployment、Pod 那样有个 spec 字段。
它主要用 data 和 binaryData 这两个字段来保存内容:
data用来放普通的文本(UTF-8 格式);binaryData用来放二进制内容(比如图片、压缩包等),会以 Base64 形式存储。
每个字段下面的“键名”(key)只能用字母、数字、-、_ 或 .,并且同一个键不能同时出现在 data 和 binaryData 里。
另外,从 Kubernetes v1.19 版本开始,还可以给 ConfigMap 加上一个 immutable(不可变)字段,这样创建之后就不能再被修改,防止误操作。
创建
yaml 创建
ConfigMap 资源对象使用 key-value 形式的键值对来配置数据,这些数据可以在 Pod 里面使用,如下所示的资源清单:
# cm-demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-demo
namespace: default
data:
data.1: hello
data.2: world
config: |
property.1=value-1
property.2=value-2
property.3=value-3
---
# pod-cm-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-demo-pod
namespace: default
spec:
containers:
- name: demo
image: busybox
command: ["/bin/sh", "-c", "env; cat /etc/config/config; sleep 3600"]
envFrom:
- configMapRef:
name: cm-demo
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo
验证:
# 创建
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f ./cm-demo.yaml
configmap/cm-demo created
pod/cm-demo-pod created
# 查看ConfigMap 详情
ubuntu@ubuntu:~/example/config_map$ kubectl get configmap cm-demo -n default -o yaml
apiVersion: v1
data:
config: |
property.1=value-1
property.2=value-2
property.3=value-3
data.1: hello
data.2: world
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"config":"property.1=value-1\nproperty.2=value-2\nproperty.3=value-3\n","data.1":"hello","data.2":"world"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"cm-demo","namespace":"default"}}
creationTimestamp: "2025-11-12T06:33:47Z"
name: cm-demo
namespace: default
resourceVersion: "408495"
uid: 589410b7-60a3-427d-a2cb-da4153a77c7a
# 查看 Pod 状态
ubuntu@ubuntu:~/example/config_map$ kubectl get pod cm-demo-pod -n default
NAME READY STATUS RESTARTS AGE
cm-demo-pod 1/1 Running 0 27s
# 查看日志
ubuntu@ubuntu:~/example/config_map$ kubectl logs --tail 2000 cm-demo-pod -n default
data.2=world
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=cm-demo-pod
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
config=property.1=value-1
property.2=value-2
property.3=value-3
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
data.1=hello
property.1=value-1
property.2=value-2
property.3=value-3
# 或者进入容器查看
ubuntu@ubuntu:~/example/config_map$ kubectl exec -it cm-demo-pod -n default -- sh
/ # cd /etc/config/
/etc/config # ls
config data.1 data.2
/etc/config # cat /etc/config/config
property.1=value-1
property.2=value-2
property.3=value-3
/etc/config #
ConfigMap 中每个 key 可以同时用于:
- 环境变量(envFrom / env)
- 挂载卷文件(volumeMounts / volumes)
目录创建
ubuntu@ubuntu:~/example/config_map$ cd ./cm-test-dir/
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ ls
mysql.conf redis.conf
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ cat ./redis.conf
host=127.0.0.1
prot=6379
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ cat ./mysql.conf
host=127.0.0.1
prot=3306
# 使用 from-file 关键字来创建包含这个目录下面所以配置文件的 ConfigMap
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ kubectl create configmap cm-demo1 --from-file=/home/ubuntu/example/config_map/cm-test-dir
# 查看配置
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ kubectl describe configmap cm-demo1
Name: cm-demo1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
mysql.conf:
----
host=127.0.0.1\r
prot=3306
redis.conf:
----
host=127.0.0.1\r
prot=6379
BinaryData
====
Events: <none>
# 查看json格式的
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ kubectl get configmap cm-demo1 -n default -o json
{
"apiVersion": "v1",
"data": {
"mysql.conf": "host=127.0.0.1\r\nprot=3306",
"redis.conf": "host=127.0.0.1\r\nprot=6379"
},
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2025-11-12T07:03:23Z",
"name": "cm-demo1",
"namespace": "default",
"resourceVersion": "414963",
"uid": "128f4aec-bd35-4721-ac1c-40513d46e600"
}
}
# 删除
# ubuntu@ubuntu:~/example/config_map$ kubectl delete cm cm-demo1
# configmap "cm-demo1" deleted
文件创建
除了通过文件目录进行创建,我们也可以使用指定的文件进行创建 ConfigMap
ubuntu@ubuntu:~/example/config_map/cm-test-dir$ kubectl create configmap cm-demo2 --from-file=/home/ubuntu/example/config_map/cm-test-dir/redis.conf
# 查看配置
ubuntu@ubuntu:~/example/config_map$ kubectl describe configmap cm-demo2
Name: cm-demo2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis.conf:
----
host=127.0.0.1\r
prot=6379
BinaryData
====
Events: <none>
# 查看json格式的
ubuntu@ubuntu:~/example/config_map$ kubectl get configmap cm-demo2 -n default -o json
{
"apiVersion": "v1",
"data": {
"redis.conf": "host=127.0.0.1\r\nprot=6379"
},
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2025-11-12T10:33:28Z",
"name": "cm-demo2",
"namespace": "default",
"resourceVersion": "458987",
"uid": "071efc03-82ed-4a40-9f92-905b42c3040f"
}
}
直接命令传递
# 创建
ubuntu@ubuntu:~/example/config_map$ kubectl create configmap cm-demo3 --from-literal=db.host=localhost --from-literal=db.port=3307
configmap/cm-demo3 created
# 查看
ubuntu@ubuntu:~/example/config_map$ kubectl get configmap cm-demo3 -n default -o json
{
"apiVersion": "v1",
"data": {
"db.host": "localhost",
"db.port": "3307"
},
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2025-11-13T06:44:07Z",
"name": "cm-demo3",
"namespace": "default",
"resourceVersion": "528382",
"uid": "dad923f5-9500-469f-93c7-31a65376e379"
}
}
使用
ConfigMap 创建成功了,那么我们应该怎么在 Pod 中来使用呢?我们可以使用四种方式来使用 ConfigMap 配置 Pod中的容器:
- 在容器命令和参数内
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
这些不同的方法适用于不同的数据使用方式,对前三个方法,kubelet 会使用 ConfigMap 中的数据在 Pod 中启动容器。第四种方法需要编写代码才能读取 ConfigMap 数据。
环境变量
# testcm1-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: testcm1-pod
namespace: default
spec:
containers:
- name: demo
image: busybox
command: ["/bin/sh", "-c", "env; sleep 3600"]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.port
envFrom:
- configMapRef:
name: cm-demo1
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl logs testcm1-pod
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=testcm1-pod
DB_PORT=3307
SHLVL=1
HOME=/root
mysql.conf=host=127.0.0.1
prot=3306
redis.conf=host=127.0.0.1
prot=6379
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
DB_HOST=localhost
ubuntu@ubuntu:~/example/config_map$
数据卷
# testcm3-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: testcm3-pod
namespace: default
spec:
containers:
- name: demo
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/redis.conf; sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo2
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl logs testcm3-pod
host=127.0.0.1
当然我们也可以在 ConfigMap 值被映射的数据卷里去控制路径,如下 Pod 定义:
# testcm4-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
namespace: default
spec:
containers:
- name: demo
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/path/to/mysql.conf; sleep 3600"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo1
items:
- key: mysql.conf
path: path/to/mysql.conf
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl logs testcm4-pod
host=127.0.0.1
另外需要注意的是,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新。kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。这时可以增加一些监测配置文件变更的脚本,然后重加载对应服务就可以实现应用的热更新。以环境变量方式使用的ConfigMap 数据不会被自动更新,更新这些数据需要重新启动 Pod。
subPath
上面我们介绍了可以将 ConfigMap 以数据卷的形式挂载到容器中去,但是如果原本容器目录下已经有一些文件或者数据,将数据挂载进去后便会覆盖容器目录下的数据,这个时候我们可以指定 volumeMounts.subPath 属性来指定卷内的子路径,而不是其根路径。
subPath 用于指定在挂载卷(volume)中的一个子路径,只将该子路径的内容挂载到容器内。
ConfigMap 定义(nginx-config.yaml)
# nginx-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
错误示例(直接挂载整个目录)
# nginx-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: web
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: /etc/nginx
subPath: nginx.conf
volumes:
- name: config
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf
正确使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: web
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: /etc/nginx/nginx.conf # ✅ 挂载单个文件
subPath: nginx.conf # ✅ 使用 subPath 避免目录覆盖
volumes:
- name: config
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf
验证:
# 创建
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f ./nginx-config.yaml
configmap/nginx-config created
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f ./nginx-test.yaml
deployment.apps/nginx created
# 查看信息
ubuntu@ubuntu:~/example/config_map$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-646b4b5d75-2wqvv 0/1 CrashLoopBackOff 10 (2m42s ago) 29m
# 发现覆盖了
ubuntu@ubuntu:~/example/config_map$ kubectl logs -f nginx-646b4b5d75-2wqvv
2025/11/13 09:05:22 [emerg] 1#0: open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:11
nginx: [emerg] open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:11
# 修改yaml 加上 subPath: nginx.conf
ubuntu@ubuntu:~/example/config_map$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-6447696fc6-q82hm 1/1 Running 0 4s
ubuntu@ubuntu:~/example/config_map$
除此之外我们还可以使用带有扩展环境变量的 subPath,通过使用subPathExpr 字段可以基于 downward API 环境变量来构造 subPath 目录名,不过需要注意 subPath 和 subPathExpr 属性是互斥的。
使用 subPathExpr 动态创建目录保存日志
在 Kubernetes 中,我们经常希望在宿主机上为每个 Pod 创建独立的日志目录,以便管理和查看。可以通过 subPathExpr 配合 Downward API 实现这一功能。
核心思路
- 使用 Downward API 获取 Pod 名称。
- 将宿主机目录(hostPath)挂载到容器内的日志目录,同时通过
subPathExpr动态生成子目录。 - 容器日志最终保存在宿主机的子目录中。
# sub_path_expr.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
image: busybox
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
command:
- sh
- -c
- while true; do echo 'Hello' >> /logs/hello.txt; sleep 1; done
volumeMounts:
- name: log
mountPath: /logs
subPathExpr: $(POD_NAME) # 使用 Downward API 环境变量创建子目录
restartPolicy: Never
volumes:
- name: log
hostPath:
path: /var/log
工作流程
- 创建 Pod 后,Kubernetes 通过 Downward API 获取 Pod 名称
pod1,并设置环境变量POD_NAME=pod1。 subPathExpr: $(POD_NAME)会在宿主机/var/log下创建一个名为pod1的目录。- 容器
/logs目录挂载到宿主机/var/log/pod1。 - 容器内写入
/logs/hello.txt的日志文件最终保存在宿主机/var/log/pod1/hello.txt。
注意:
subPathExpr使用的是小括号$(),而不是大括号${}。
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1 1/1 Running 0 79s 10.244.1.142 node2 <none> <none>
# 去宿主机查看日志
ubuntu@ubuntu:~$ tail -f /var/log/pod1/hello.txt
Hello
不可变更的 ConfigMap
Kubernetes 自 v1.21 起将 Immutable Secrets 和 ConfigMaps 作为稳定特性提供。
通过在 ConfigMap 或 Secret 中设置:
immutable: true
即可将其标记为不可变更(immutable)。
示例 immu-cm.yaml
# immu-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: immu-cm
data:
mysql.conf: |-
host=127.0.0.1
port=3306
immutable: true
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f immu-cm.yaml
configmap/immu-cm created
# 修改文件后重新应用
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f immu-cm.yaml
The ConfigMap "immu-cm" is invalid: data: Forbidden: field is immutable when `immutable` is set
Secret
Secret 的作用
Secret 是 Kubernetes 中用于存储敏感信息的资源对象。与 ConfigMap(明文配置) 不同,Secret 专门用于存储保密数据,例如:
- 密码
- OAuth Token
- SSH Key
- 私有仓库认证信息
相比把敏感数据直接写进 Pod、YAML 或镜像里,使用 Secret 更安全、更灵活。
Secret 类型(内置类型一览)
| Secret 类型 | 说明 |
|---|---|
| Opaque | 默认类型,数据为 Base64 编码(可轻易 decode,安全性较弱) |
| kubernetes.io/dockercfg | ~/.dockercfg 的序列化形式 |
| kubernetes.io/dockerconfigjson | 私有 Docker Registry 的认证信息 (~/.docker/config.json) |
| kubernetes.io/service-account-token | ServiceAccount 自动挂载到 /run/secrets/... |
| kubernetes.io/ssh-auth | SSH 身份认证密钥 |
| kubernetes.io/basic-auth | HTTP Basic Auth 凭据 |
| bootstrap.kubernetes.io/token | 用于集群引导的 token |
自定义 Secret 类型
你也可以给 type 字段设置任意非空字符串,K8s 不限制命名规则。
如果 type 为空,则自动视为 Opaque。
安全性
默认情况下 Secret 是未加密存储在 etcd 中的。
这意味着:
-
任何能访问 API Server 的用户可能查看或修改 Secret
-
任何能访问 etcd 的用户可直接读取明文 Secret
-
任何在命名空间具有 创建 Pod 权限 的用户,都能通过挂载 Pod 获取该命名空间所有 Secret
因此,默认 Secret 并不绝对安全,需要额外措施增强安全性。
Opaque Secret
Secret 资源包含 2 个键值对: data 和 stringData,data 字段用来存储 base64 编码的任意数据,提供stringData 字段是为了方便,它允许 Secret 使用未编码的字符串。data 和 stringData 的键必须由字母、数字、-,_ 或 . 组成。
比如我们来创建一个用户名为 admin,密码为 admin321 的 Secret 对象
# secret-demo.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: YWRtaW4zMjE=
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f secret-demo.yaml
secret/mysecret created
ubuntu@ubuntu:~/example/config_map$ kubectl get secret
NAME TYPE DATA AGE
mysecret Opaque 2 6s
ubuntu@ubuntu:~/example/config_map$ kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 8 bytes
username: 5 bytes
# 查看明文
ubuntu@ubuntu:~/example/config_map$ kubectl get secret mysecret -o yaml
apiVersion: v1
data:
password: YWRtaW4zMjE=
username: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"password":"YWRtaW4zMjE=","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"type":"Opaque"}
creationTimestamp: "2025-11-17T03:55:59Z"
name: mysecret
namespace: default
resourceVersion: "661149"
uid: b1a4fbf4-7914-42c6-ab7e-c56976f59423
type: Opaque
ubuntu@ubuntu:~/example/config_map$
对于某些场景,你可能希望使用 stringData 字段,这字段可以将一个非 base64 编码的字符串直接放入 Secret中, 当创建或更新该 Secret 时,此字段将被编码。
比如当我们部署应用时,使用 Secret 存储配置文件, 你希望在部署过程中,填入部分内容到该配置文件。例如,如果你的应用程序使用以下配置文件:
apiUrl: "https://my.api.com/api/v1"
username: "<user>"
password: "<password>"
那么我们就可以使用以下定义将其存储在 Secret 中:
# mysecret2.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret2
type: Opaque
stringData:
config.yaml: |
apiUrl: "https://my.api.com/api/v1"
username: admin
password: admin@123
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f mysecret2.yaml
secret/mysecret2 created
ubuntu@ubuntu:~/example/config_map$ kubectl get secret mysecret2 -o yaml
apiVersion: v1
data:
config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IGFkbWluCnBhc3N3b3JkOiBhZG1pbkAxMjMK
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"mysecret2","namespace":"default"},"stringData":{"config.yaml":"apiUrl: \"https://my.api.com/api/v1\"\nusername: admin\npassword: admin@123\n"},"type":"Opaque"}
creationTimestamp: "2025-11-17T06:08:31Z"
name: mysecret2
namespace: default
resourceVersion: "689609"
uid: 73e80db4-4238-4da2-8d44-1cb3f7c6f8fc
type: Opaque
创建好 Secret 对象后,有两种方式来使用它:
- 以环境变量的形式
- 以 Volume 的形式挂载
环境变量
首先我们来测试下环境变量的方式,同样的,我们来使用一个简单的 busybox 镜像来测试下:
# secret1-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret1-pod
spec:
containers:
- name: secret1
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f secret1-pod.yaml
pod/secret1-pod created
# 查看日志
ubuntu@ubuntu:~/example/config_map$ kubectl logs secret1-pod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=secret1-pod
SHLVL=1
HOME=/root
USERNAME=admin
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
PASSWORD=admin321
Volume 挂载
# secret2-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret2-pod
spec:
containers:
- name: secret2
image: busybox
command: ["/bin/sh", "-c", "ls /etc/secrets"]
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: mysecret
# optional: defaultMode: 0440 # 若需修改文件权限取消注释并设置
# optional: true # 若 Secret 可能不存在且希望 Pod 仍能启动,可设置 optional: true
验证:
ubuntu@ubuntu:~/example/config_map$ kubectl apply -f ./secret2-pod.yaml
pod/secret2-pod created
ubuntu@ubuntu:~/example/config_map$ kubectl logs secret2-pod
password
username
Secret vs ConfigMap
Secret 和 ConfigMap这两种资源对象的异同点:
相同点
- key/value 的形式
- 属于某个特定的命名空间
- 可以导出到环境变量
- 可以通过目录/文件形式挂载
- 通过 volume 挂载的配置信息均可热更新
不同点
- Secret 可以被 ServerAccount 关联
- Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
- Secret 支持 Base64 加密
- Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque等多种类型,而 Configmap 不区分类型
同样 Secret 文件大小限制为 1MB(ETCD 的要求);Secret 虽然采用 Base64 编码,但是我们还是可以很方便解码获取到原始信息,所以对于非常重要的数据还是需要慎重考虑,可以考虑使用 Vault 来进行加密管理。

浙公网安备 33010602011771号