1. 概述
在 Kubernetes 中,ConfigMap 和 Secret 是两种用于将应用配置和敏感信息从代码中解耦的核心资源类型。它们各自有不同的用途和行为特点。
本文将重点介绍 ConfigMap 与 Secret 在使用场景、创建方式、数据编码、挂载方式等方面的区别,并通过示例代码展示其典型用法,帮助你更好地理解两者之间的差异和适用场景。
2. 创建与数据编码
ConfigMap 的创建
ConfigMap 用于存储非敏感的配置信息,支持多种格式的键值对。以下是一个典型的 ConfigMap 定义:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
string-value: "Hello, world!"
number-value: "42"
boolean-value: "true"
multiline-value: |
This is a multiline value
that spans multiple lines
list-value: |
- item1
- item2
- item3
object-value: |
key1: value1
key2: value2
json-value: |-
{
"key": "value",
"array": [1, 2, 3],
"nested": {
"innerKey": "innerValue"
}
}
yaml-value: |-
key: value
array:
- 1
- 2
- 3
nested:
innerKey: innerValue
✅ 所有值都以明文形式存储在 data
字段下。
创建该 ConfigMap:
kubectl apply -f my-config.yaml
查看某个键值:
kubectl get configmap my-configmap -o jsonpath='{.data.string-value}'
输出:
Hello, world!
Secret 的创建
Secret 用于存储敏感信息,例如密码、密钥等。它支持 Base64 编码的 data
字段和明文的 stringData
字段。
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
string-value: SGVsbG8sIHdvcmxkIQ==
number-value: NDI=
boolean-value: dHJ1ZQ==
multiline-value: |
VGhpcyBpcyBhIG1pbmxpbmUgdmFsdWUgZXZlcnkgdGhhdCBzcGFuIG11bHRpcGxlIGxpbmVzCg==
json-value: eyAiY29tcGxleCI6ICIxMjM0NSIsICJzdHJpbmciOiAiSGVsbG8sIHdvcmxkISIsICJuZXN0ZWQiOiB7ICJpbnN0YW5jZSI6IDEsICJzdHJpbmciOiAxLCAibmVzdGVkIjogeyAiaW5uZXJLZXkiOiAiSW5uZXJWYWx1ZSJ9fX0=
binary-value: YmFzZTY0IHN0cmluZwo=
stringData:
list-value: |
item1
item2
item3
object-value: |
key1: value1
key2: value2
key3: value3
yaml-value: |
key: value
string: Hello, world!
nested:
innerKey: innerValue
⚠️ 注意:stringData
是明文,Kubernetes 会自动将其转换为 Base64 并存入 data
字段。
创建 Secret:
kubectl apply -f my-secret.yaml
获取并解码 Secret:
kubectl get secret my-secret -o jsonpath='{.data.string-value}' | base64 -d
输出:
Hello, world!
3. 作为环境变量注入容器
ConfigMap 和 Secret 都可以作为环境变量注入容器中。
以下是一个 Pod 定义文件,将 Secret 和 ConfigMap 的值分别注入为环境变量:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: ubuntu-container
image: ubuntu
command: ["sleep", "infinity"]
env:
- name: SECRET_VALUE
valueFrom:
secretKeyRef:
name: my-secret
key: string-value
- name: CONFIG_VALUE
valueFrom:
configMapKeyRef:
name: my-configmap
key: number-value
创建 Pod:
kubectl apply -f pod.yaml
查看环境变量:
kubectl exec my-pod -- env | grep -i VALUE
输出:
CONFIG_VALUE=42
SECRET_VALUE=Hello, world!
✅ Secret 的值即使是以 Base64 编码存储,注入容器时也会自动解码。
4. 内置类型与用途
4.1 Opaque Secret
Opaque Secret 是最通用的 Secret 类型,适合存储任意敏感信息。
例如,存储 MySQL 的用户名和密码:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
username: bXktcHJvdG9jb2xvcmVk
password: bXktcGFzc3dvcmQ=
root-password: bXktcm9vdC1wYXNzd29yZA==
然后在 Pod 中引用这些值:
env:
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: username
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: root-password
创建资源并验证:
kubectl apply -f mysql-secret.yaml -f mysql-pod.yaml
kubectl exec -it mysql-pod -- mysql -uroot -pmy-root-password -e "SELECT VERSION();"
输出:
+-----------+
| VERSION() |
+-----------+
| 8.0.33 |
+-----------+
✅ 成功使用 Secret 注入数据库凭证。
4.2 TLS Secret
TLS Secret 用于存储 TLS 证书和私钥。可以使用 kubectl create secret tls
命令创建:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt
kubectl create secret tls my-tls-secret --cert=tls.crt --key=tls.key
在 Pod 中挂载该 Secret:
volumes:
- name: tls-volume
secret:
secretName: my-tls-secret
volumeMounts:
- name: tls-volume
mountPath: /etc/tls
readOnly: true
验证挂载结果:
kubectl exec tls-pod -- ls /etc/tls/
输出:
tls.crt
tls.key
✅ 成功挂载 TLS Secret。
5. 自动挂载
只有特定类型的 Secret(如 service-account-token
)支持自动挂载功能。
定义一个 ServiceAccount 并启用自动挂载:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
---
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-pod
spec:
serviceAccountName: my-service-account
containers:
- name: ubuntu-container
image: ubuntu
command: ["sleep", "infinity"]
automountServiceAccountToken: true
创建资源:
kubectl apply -f sa-ubuntu.yaml
验证自动挂载的 Token:
kubectl exec ubuntu-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
✅ Token 成功被自动挂载。
6. 功能对比总结
对比维度 | ConfigMap | Secret |
---|---|---|
数据分类 | 存储非敏感信息 | 存储敏感信息 |
数据编码 | 明文 | Base64 编码 |
类型与用途 | 无特定类型,用于配置 | 支持多种类型(如 Opaque、TLS) |
API 支持 | 支持通用操作 | 支持更丰富的类型操作 |
挂载方式 | 只能显式挂载 | 支持 service-account-token 自动挂载 |
7. 总结
本文通过多个示例详细对比了 Kubernetes 中 ConfigMap 与 Secret 的差异,包括:
- 创建方式与数据编码方式的不同
- 环境变量注入时的行为差异
- 挂载方式及自动挂载的支持情况
- 各自的内置类型与典型使用场景
✅ 总结:ConfigMap 更适合用于存储非敏感的配置数据,而 Secret 更适合用于处理敏感信息,尤其在安全性要求较高的场景中具有不可替代的优势。在实际项目中,应根据需求选择合适的资源类型。