K8S configmap & secret
K8s ConfigMap与Secret 完整进阶笔记
一、K8s配置资源核心概述
K8s提供ConfigMap和Secret两大核心配置资源,核心作用是解耦应用配置与容器镜像,实现配置与代码分离。无需重新打包镜像、重建Pod即可更新业务配置,彻底解决配置硬编码问题,适配集群多Pod统一配置管理场景。
两者核心定位区分:ConfigMap用于存储非敏感明文配置,Secret用于存储敏感加密类配置,是K8s集群核心的配置中心组件。
二、ConfigMap 普通配置资源详解
2.1 ConfigMap核心概念与使用限制
ConfigMap是K8s托管的普通配置资源,可将各类业务配置文件、键值对配置统一存储,通过挂载卷、环境变量的方式注入Pod,实现多Pod共享同一套配置,统一管理、批量更新。
核心使用限制(硬性规则):
1、Pod使用限制:仅通过Kubernetes API创建的Pod可使用ConfigMap,静态Pod无法绑定、无法使用;
2、资源大小限制:受ETCD存储机制约束,单个ConfigMap最大存储容量为1MB;
3、数据安全限制:仅存储明文普通配置,无加密能力,严禁存储密码、密钥、证书等敏感数据。
2.2 ConfigMap核心作用
集群多Pod业务场景中,若数十上百个Pod需要复用相同配置文件,无需逐个修改Pod配置。只需创建一份ConfigMap并关联所有目标Pod,即可实现全局统一配置下发。
ConfigMap支持配置动态更新,资源配置修改后,关联Pod的文件系统配置会自动同步,但Pod内运行的业务进程不会自动重启、重载配置,该特性后续会详细说明。
2.3 YAML多行文本特殊符号详解
ConfigMap的data字段支持多行文本配置,依靠YAML特殊符号控制文本换行、折叠格式,所有规则均配套实际案例与解析结果,是编写复杂配置的核心语法。
1、竖线符 |:保留文本原始内部换行,去除每行末尾空白与行尾空行,保留文本内部缩进
lines: |
我是第一行
我是第二行
我是Egon
我是第四行
我是第五行
解析结果:{"lines": "我是第一行\n我是第二行\n 我是Egon\n 我是第四行\n我是第五行\n"}
2、|- 符号:保留文本内部换行,删除文本末尾所有换行符
value: |-
hello
world
解析结果:{"value": "hello\nworld"}
3、|+ 符号:完整保留文本所有换行,包括末尾空行,有多少回车即保留多少换行符
value: |+
hello
world
解析结果:{"value": "hello\nworld\n\n"}
4、大于号 >:折叠换行,文本内普通换行转换为空格,仅空白行保留换行,文本末尾换行默认保留
lines: >
我是第一行
我也是第一行
我仍是第一行
我依旧是第一行
我是第二行
这么巧我也是第二行
解析结果:{"lines": "我是第一行 我也是第一行 我仍是第一行 我依旧是第一行\n我是第二行 这么巧我也是第二行\n"}
2.4 ConfigMap两种创建方式
2.4.1 YAML清单文件创建(精准自定义配置)
通过YAML文件自定义各类键值对、多行配置,支持普通键值与多行文本混合配置,是生产环境精准配置的常用方式。
apiVersion: v1
data:
xxx: "111"
yyy: "222"
data.1: hello
data.2: world
config1: |
property.1=value-1
property.2=value-2
property.3=value-3
config2: |-
hello
world
config3: |+
hello
world
config4: >
我是第一行
我也是第一行
我仍是第一行
我依旧是第一行
我是第二行
这么巧我也是第二行
kind: ConfigMap
metadata:
name: test1-config
namespace: default
创建并查看格式化配置命令:
kubectl apply -f test1-config.yaml
kubectl get cm test1-config -o json
2.4.2 命令行快速创建(快速批量配置)
无需编写YAML文件,通过kubectl命令快速创建,支持目录、单个文件、字面量键值对三种创建模式,适配快速测试、批量配置场景。
1、指定目录创建:读取目录下所有配置文件,文件名为key、文件内容为value
# 准备配置目录与配置文件
mkdir /myconf && cd /myconf
cat > redis.conf << EOF
host=127.0.0.1
port=6379
EOF
cat > mysql.conf << EOF
host=127.0.0.1
port=3306
EOF
# 根据目录创建ConfigMap
kubectl create configmap test2-config --from-file=/myconf
# 查看配置
kubectl get cm test2-config -o yaml
2、指定单个文件创建:精准绑定单个配置文件,可多次叠加--from-file参数绑定多文件
kubectl create configmap test3-config --from-file=/myconf/mysql.conf
kubectl get cm test3-config -o yaml
3、字面量键值对创建:直接通过命令行传入键值对,无需本地配置文件
kubectl create configmap test4-config --from-literal=db.host=localhost --from-literal=db.port=3306
kubectl get cm test4-config -o yaml
2.5 ConfigMap三种Pod关联使用方式
2.5.1 环境变量注入方式
将ConfigMap的键值对注入为容器环境变量,支持单个键精准注入、整个ConfigMap批量注入,适合简单键值对配置。
apiVersion: v1
kind: Pod
metadata:
name: testcm1-pod
spec:
containers:
- name: testcm1
image: busybox
command: [ "/bin/sh", "-c", "tail -f /dev/null" ]
env:
# 精准注入单个键值对
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: test4-config
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: test4-config
key: db.port
# 批量注入整个ConfigMap
envFrom:
- configMapRef:
name: test2-config
查看容器环境变量配置:
kubectl logs -f testcm1-pod
2.5.2 容器命令变量引用方式
将注入的环境变量直接用于容器启动命令,实现配置动态调用,适配启动参数依赖配置的场景。
apiVersion: v1
kind: Pod
metadata:
name: testcm2-pod
spec:
containers:
- name: testcm2
image: busybox
command: [ "/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)" ]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: test4-config
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: test4-config
key: db.port
执行查看变量输出结果:
kubectl logs -f testcm2-pod
2.5.3 数据卷挂载方式(生产最常用)
将ConfigMap以数据卷形式挂载到容器指定目录,支持完整挂载、子路径自定义挂载,是唯一支持配置热更新的使用方式。
1、完整挂载示例:将整个ConfigMap配置挂载到指定目录
apiVersion: v1
kind: Pod
metadata:
name: testcm3-pod
spec:
volumes:
- name: my-volume
configMap:
name: test3-config
containers:
- name: testcm3
image: busybox
command: [ "/bin/sh", "-c", "cat /etc/config/mysql.conf" ]
volumeMounts:
- name: my-volume
mountPath: /etc/config
2、子路径自定义挂载示例:按需挂载指定配置文件,自定义容器内文件路径
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
spec:
volumes:
- name: my-volume
configMap:
name: test2-config
items:
- key: mysql.conf
path: path1/to/msyql.conf
- key: redis.conf
path: path2/to/redis.conf
containers:
- name: testcm4
image: busybox
command: [ "/bin/sh","-c","cat /etc/config/path1/to/msyql.conf ;sleep 10 ;cat /etc/config/path2/to/redis.conf" ]
volumeMounts:
- name: my-volume
mountPath: /etc/config
2.6 ConfigMap热更新机制详解
2.6.1 原生热更新特性与缺陷
原生热更新机制:当ConfigMap以数据卷挂载方式关联Pod时,通过kubectl edit、apply等方式更新ConfigMap配置后,无需重启Pod,集群会自动同步更新Pod容器内的配置文件内容,实现文件层级的热更新。
核心致命缺陷:集群仅更新Pod文件系统中的配置文件,不会主动通知、重启业务进程。绝大多数应用仅在启动时读取一次配置,运行过程中不会主动监听、重载配置文件,因此单纯更新ConfigMap无法让业务生效,必须手动重启Pod或重载应用配置。
原生解决方案:手动删除重建Pod、编写监控脚本监听文件变更并重载服务,操作繁琐、无法自动化。
2.6.2 全自动热更新方案(Reloader组件)
通过部署Stakater Reloader组件,实现ConfigMap/Secret变更→自动滚动重启Deployment→应用加载新配置的全自动化流程,是生产标准热更新方案。
1、完整部署流程
# 下载Reloader部署清单
wget --no-check-certificate https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
# 适配集群环境并部署
sed -i 's#RELEASE-NAME#config#g' reloader.yaml
kubectl apply -f reloader.yaml
2、Reloader完整资源清单(权限+部署,无删减)
# ServiceAccount 账号配置
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
meta.helm.sh/release-namespace: "default"
meta.helm.sh/release-name: "reloader"
labels:
app: reloader-reloader
chart: "reloader-1.0.97"
release: "reloader"
heritage: "Helm"
app.kubernetes.io/managed-by: "Helm"
name: reloader-reloader
namespace: default
---
# ClusterRole 集群权限配置
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
meta.helm.sh/release-namespace: "default"
meta.helm.sh/release-name: "reloader"
labels:
app: reloader-reloader
chart: "reloader-1.0.97"
release: "reloader"
heritage: "Helm"
app.kubernetes.io/managed-by: "Helm"
name: reloader-reloader-role
rules:
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["list", "get", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "daemonsets", "statefulsets"]
verbs: ["list", "get", "update", "patch"]
- apiGroups: ["extensions"]
resources: ["deployments", "daemonsets"]
verbs: ["list", "get", "update", "patch"]
- apiGroups: ["batch"]
resources: ["cronjobs"]
verbs: ["list", "get"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
---
# ClusterRoleBinding 权限绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
meta.helm.sh/release-namespace: "default"
meta.helm.sh/release-name: "reloader"
labels:
app: reloader-reloader
chart: "reloader-1.0.97"
release: "reloader"
heritage: "Helm"
app.kubernetes.io/managed-by: "Helm"
name: reloader-reloader-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-reloader-role
subjects:
- kind: ServiceAccount
name: reloader-reloader
namespace: default
---
# Deployment 组件部署
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
meta.helm.sh/release-namespace: "default"
meta.helm.sh/release-name: "reloader"
labels:
app: reloader-reloader
chart: "reloader-1.0.97"
release: "reloader"
heritage: "Helm"
app.kubernetes.io/managed-by: "Helm"
group: com.stakater.platform
provider: stakater
version: v1.0.97
name: reloader-reloader
namespace: default
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: reloader-reloader
release: "reloader"
template:
metadata:
labels:
app: reloader-reloader
chart: "reloader-1.0.97"
release: "reloader"
heritage: "Helm"
app.kubernetes.io/managed-by: "Helm"
group: com.stakater.platform
provider: stakater
version: v1.0.97
spec:
containers:
- image: "registry.cn-shanghai.aliyuncs.com/egon-k8s-test/reloader:v1.0.97"
imagePullPolicy: IfNotPresent
name: reloader-reloader
ports:
- name: http
containerPort: 9090
livenessProbe:
httpGet:
path: /live
port: http
timeoutSeconds: 5
failureThreshold: 5
periodSeconds: 10
initialDelaySeconds: 10
readinessProbe:
httpGet:
path: /metrics
port: http
timeoutSeconds: 5
failureThreshold: 5
periodSeconds: 10
initialDelaySeconds: 10
securityContext:
runAsNonRoot: true
runAsUser: 65534
seccompProfile:
type: RuntimeDefault
serviceAccountName: reloader-reloader
3、业务开启自动热更新:在Deployment注解中添加自动监听配置
metadata:
annotations:
reloader.stakater.com/auto: "true"
4、完整测试案例(Nginx配置热更新)
第一步:创建Nginx配置文件与ConfigMap
cat > www.conf << EOF
server {
server_name myapp.egon.com;
listen 80;
root /data/web/html;
}
EOF
kubectl create configmap nginx-config --from-file=./www.conf
第二步:部署关联ConfigMap的Nginx业务
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web-test
name: web-test
annotations:
reloader.stakater.com/auto: "true"
spec:
replicas: 1
selector:
matchLabels:
app: web-test
template:
metadata:
labels:
app: web-test
spec:
containers:
- image: nginx:1.18
name: nginx
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: nginxconf
configMap:
name: nginx-config
第三步:测试热更新,修改ConfigMap配置,验证Pod自动重启、配置生效
# 修改配置端口为8081
kubectl edit cm nginx-config
# 查看Pod是否自动重启
kubectl get pods -o wide
# 测试访问新端口
curl 容器IP:8081
三、Secret 敏感配置资源详解
3.1 Secret核心概念与作用
Secret是K8s用于存储敏感数据的专属配置资源,专门存放密码、Token、私钥、SSL证书、私有镜像仓库凭证等机密信息,避免敏感数据硬编码在镜像、Pod配置中,提升集群业务安全性。
核心特性:
1、编码存储:数据默认以Base64编码存储,集群查询不直接暴露明文,容器内使用时自动解码;
2、配置解耦:敏感配置独立托管,更新配置无需重新打包镜像、重构业务;
3、大小限制:单Secret最大1MB,与ConfigMap一致,受ETCD存储约束;
4、安全说明:Base64仅为编码而非加密,etcd中原始数据为明文,需严格管控Master节点与etcd访问权限,超高敏感数据需搭配Vault加密工具。
3.2 Secret四大核心类型
1、Opaque:默认通用类型,支持自定义键值对,用于存储账号密码、自定义敏感配置;
2、kubernetes.io/tls:专属证书类型,用于存储HTTPS、SSL证书与私钥,适配域名加密访问场景;
3、kubernetes.io/dockerconfigjson:私有镜像仓库认证类型,存储Docker仓库登录凭证,用于拉取私有镜像;
4、kubernetes.io/service-account-token:服务账号令牌类型,用于Pod与APIServer通信的认证凭证,1.24版本后采用动态令牌机制。
3.3 Opaque类型Secret实操详解
Opaque是最常用的通用Secret类型,支持data、stringData两个核心字段,适配绝大多数敏感配置场景。
3.3.1 核心字段区别
1、data字段:必须传入Base64编码后的字符串,适合固定、无需频繁修改的敏感数据;
2、stringData字段:直接传入明文字符串,集群创建资源后自动完成Base64编码,无需手动转换,适合快速编写配置。
Base64编码/解码命令:
# 明文转Base64编码
echo -n 'egon' | base64
echo -n '123456' | base64
# Base64解码为明文
echo -n '编码内容' | base64 -d
3.3.2 两种字段创建案例
1、data字段创建(手动编码)
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
username: ZWdvbg==
password: MTIzNDU2
type: Opaque
2、stringData字段创建(直接写明文)
apiVersion: v1
kind: Secret
metadata:
name: demo-secret
type: Opaque
stringData:
config.yaml: |
apiUrl: "https://my.api.com/api/v1"
username: egon
password: 123
3.3.3 Secret两种Pod注入方式
1、数据卷挂载方式:挂载到容器目录,文件自动解码为明文,支持配置热更新(仅文件层级);
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- image: busybox
name: busybox
command: ["/bin/sh","-c","cat /etc/my-secret;sleep 10000"]
volumeMounts:
- name: xxx
mountPath: /etc/my-secret
volumes:
- name: xxx
secret:
secretName: test-secret
2、环境变量注入方式:注入为容器环境变量,不支持热更新,修改Secret后必须重启Pod生效;
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- image: busybox
name: busybox
args: ["sleep","36000"]
env:
- name: BIG_SB
valueFrom:
secretKeyRef:
name: test-secret
key: username
- name: BIG_NB
valueFrom:
secretKeyRef:
name: test-secret
key: password
- name: BIG_CONFIG
valueFrom:
secretKeyRef:
name: demo-secret
key: config.yaml
补充:Secret热更新规则与ConfigMap一致,仅文件同步更新,业务进程不生效,需依赖Reloader组件自动重启Pod。
3.4 dockerconfigjson类型Secret(私有镜像仓库认证)
该类型Secret专门用于存储私有Docker镜像仓库的登录凭证,让Kubelet可以拉取集群私有镜像,是私有仓库部署的核心配置。
1、命令行快速创建私有仓库Secret
# 定义私有仓库信息
export DOCKER_REGISTRY_SERVER=10.0.0.100
export DOCKER_USER=root
export DOCKER_PASSWORD=root@123
export DOCKER_EMAIL=root@123.com
# 创建仓库认证Secret
kubectl create secret docker-registry myregistrykey \
--docker-server=$DOCKER_REGISTRY_SERVER \
--docker-username=$DOCKER_USER \
--docker-password=$DOCKER_PASSWORD \
--docker-email=$DOCKER_EMAIL
# 查看Secret详情
kubectl describe secret myregistrykey
kubectl get secret myregistrykey -o yaml
2、Pod/Deployment引用私有仓库凭证
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: test
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: test
spec:
containers:
- image: 192.168.1.100:5000/test:v1
name: alpine
args: ["sleep","36000"]
# 引用私有仓库认证Secret
imagePullSecrets:
- name: myregistrykey
3、全局生效配置(ServiceAccount绑定)
无需每个Pod单独配置imagePullSecrets,直接绑定ServiceAccount,所有引用该SA的Pod自动生效私有仓库认证。
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
imagePullSecrets:
- name: myregistrykey
核心注意点:imagePullSecrets凭证仅Kubelet组件可读取使用,业务容器无法获取仓库账号密码,安全性更高。
3.5 service-account-token 令牌机制详解
service-account-token是绑定服务账号(SA)的专属Secret,用于Pod与K8s APIServer通信的身份认证,1.24版本前后机制差异极大。
3.5.1 K8s 1.24旧版本机制缺陷
1、每创建一个ServiceAccount,集群自动生成固定Secret令牌,长期绑定无法动态更新;
2、大规模集群中大量SA会生成大量冗余Secret,占用集群资源、影响扩容;
3、JWT令牌无过期时间,一旦泄露会长期存在风险,易被非法冒用、提权。
3.5.2 K8s 1.24+ 新版令牌投影机制
1、创建ServiceAccount不再自动生成Secret,Pod引用SA时,集群动态临时生成令牌;
2、Kubelet自动监控令牌有效期,临近过期时自动轮换刷新,无需人工干预;
3、支持自定义令牌过期时间,最小可设置10分钟,大幅降低泄露风险;
4、令牌默认挂载路径:/var/run/secrets/kubernetes.io/serviceaccount,包含ca.crt、namespace、token三个认证文件。
新版自定义令牌挂载案例:
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
serviceAccountName: build-robot
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 600
audience: vault
效果:令牌每10分钟自动更新,无需重建Pod、无需手动维护,安全性、扩展性大幅提升。
3.6 资源不可变配置(ConfigMap/Secret通用)
ConfigMap和Secret均支持immutable不可变属性,开启后资源的data字段禁止任何修改操作,仅支持删除重建,可防止核心配置被误修改,提升集群稳定性。
metadata:
immutable: true
生效规则:已挂载旧配置的存量Pod继续使用旧配置,新创建Pod会加载删除重建后的最新配置。
四、ConfigMap与Secret 完整对比总结
4.1 相同点
1、存储格式:均采用key/value键值对格式存储配置数据;
2、资源隔离:均归属命名空间管理,仅同命名空间资源可相互引用;
3、使用方式:均支持环境变量注入、数据卷挂载两种Pod关联方式;
4、热更新特性:数据卷挂载模式均支持集群文件层级热更新,环境变量模式均不支持;
5、资源限制:单资源最大存储1MB,遵循ETCD集群存储规范;
6、高级特性:均支持immutable不可变配置,防止配置误改。
4.2 不同点
1、数据安全:ConfigMap存储明文普通配置,无安全防护;Secret通过Base64编码存储敏感数据,规避明文泄露风险;
2、资源类型:ConfigMap无细分类型,仅通用配置功能;Secret细分Opaque、tls、dockerconfigjson、service-account-token多类专属类型;
3、专属能力:Secret支持ServiceAccount绑定、私有镜像拉取(imagePullSecrets),ConfigMap无此类安全认证能力;
4、适用场景:ConfigMap适配所有非敏感业务配置(配置文件、通用参数);Secret适配密码、证书、镜像凭证、集群认证等敏感场景;
5、安全层级:ConfigMap完全明文展示,无防护;Secret默认编码展示,普通用户无法直接读取明文,需解码查看。

浙公网安备 33010602011771号