k8s配置管理-ConfigMap和Secret

配置管理-ConfigaMap和Secret

  • 认识ConfigMap和Secret
  • 创建ConfigMap和Secret的方式
  • 以配置文件形式挂载ConfigMap和Secret
  • 以环境变量形式挂载ConfigMap和Secret
  • 更改挂载文件的名称和权
  • 限解决挂载覆盖目录的问题
  • Secret管理域名证书
  • Secret管理镜像仓库密钥
  • Secret和ConfigMap配置只读
  • Secret和ConfigMap备份还原
  • Secret和ConfigMap使用注意事项

1.ConfigMap-配置管理

1.1ConfigMap介绍

ConfigMap也是K8s的一种资源,主要用于存储非机密配置数据,如程序的环境变量、程序配置文件等。ConfigMap可以实现把应用程序的配置信息从容器镜像或者代码中分离出来,从而可以更容易的管理和更新配置,而不必重新构建应用程序,实现程序和配置的分离。

在实际生产环境中,程序的配置应该和容器分离,这样如果仅需要修改配置 可以灵活修改,不需要重新制作镜像。

主要用途:

  • 存储配置信息:剥离应用程序配置,实现配置分离

  • 动态配置:动态更改程序的配置,无需重新部署整个应用

  • 共享配置:数据共享,多个Pod可以共享ConfigMap数据

1.2ConfigMap资源定义

定义环境变量形式的ConfigMap

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
# 简单的键值对(key:value)形式,pod中会使用database.host和database.port
database.host: "mysql.example.com"
database.port: "3306"

pod中引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 假设该pod需要连接数据库
env:
- name: DB_HOST
value: "mysql-service"
- name: DB_PORT
value: "3306"
- name: DB_USER
value: "dev"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: db-password

1.3创建ConfigMap

1.3.1基于yaml文件创建ConfigMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 通过yaml方式定义ConfigMap资源
[root@k8s-master01 configmap]# cat basic-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: basic-cm
namespace: default
data:
# 简单的键值对(key:value)形式,pod中会使用database.host和database.port
database.host: "mysql.example.com"
database.port: "3306"
name: "John Doe"
age: "30"

# 基于basic-cm.yaml创建ConfigMap
[root@k8s-master01 configmap]# kubectl create -f basic-cm.yaml
configmap/basic-cm created

# 查看创建的ConfigMap
[root@k8s-master01 configmap]# kubectl get cm
NAME DATA AGE
basic-cm 4 61s

# 查看ConfigMap的数据
[root@k8s-master01 configmap]# kubectl get cm basic-cm -oyaml
apiVersion: v1
data:
age: "30"
database.host: mysql.example.com
database.port: "3306"
name: John Doe
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-15T03:08:31Z"
name: basic-cm
namespace: default
resourceVersion: "11567466"
uid: 398332d9-14e7-44d2-9e83-13d702ec8f4c

1.3.2基于多行value创建ConfigMap

在 Kubernetes 中,“基于多行 value 创建 ConfigMap”指的是 ConfigMap 中某个键(key)对应的值(value)是一个多行字符串,而不是简单的一行 key-value 对。这通常用于存储配置文件的完整内容,而不是分散的配置项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 定义多行value的ConfigMap
[root@k8s-master01 configmap]# vim duohang-value-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config #定义ConfigMap的名字,pod中spec.会引用my-config.volumes.name字段会应用该my-config名字
data:
nginx.conf: |
server {
listen 80;
server_name example.com;

location / {
proxy_pass http://backend;
}
}
mysql.conf: |-
[mysqld]
bind-address = 0.0.0.0
port = 3306
default-storage-engine = InnoDB
log-error = /var/log/mysql/error.log
slow-query-log-file = /var/log/mysql/slow.log

这里的 nginx.confmysql.conf就是一个多行的 value,其值是整个配置文件内容。

在上述my-config配置中会发现两种写法,nginx.conf: |mysql.conf: |- ,他们区别如下:

  • |保留所有换行,包括结尾换行。
  • |-去除结尾换行,其余保留。

它们都表示按原格式保留换行的多行文本,区别只在于“结尾是否带换行”。

在以下场景中**坚决使用 |**:

  • 所有 bashshpython 等脚本
  • .properties.conf.ini 等以行为单位解析的配置文件
  • YAML 或 JSON 配置片段拼接时若后续跟随内容(避免粘连)

1.3.3基于文件创建ConfigMap

基于单个文件创建ConfigMap

1
2
3
4
5
6
7
8
[root@k8s-master01 configmap]# ll
total 24
-rw-r--r-- 1 root root 268 Jul 15 11:08 basic-cm.yaml
-rw-r--r-- 1 root root 208 Jul 15 15:04 duohang-value-cmcp.yaml
-rw-r--r-- 1 root root 411 Jul 15 15:33 duohang-value-cm.yaml
-rw-r--r-- 1 root root 2404 Jul 15 16:30 my.cnf #实现准备的配置文件,自己根据实际情况定义内容即可
-rw-r--r-- 1 root root 725 Jul 15 16:26 nginx.conf #实现准备的配置文件,自己根据实际情况定义内容即可
-rw-r--r-- 1 root root 2859 Jul 15 16:30 redis.conf #实现准备的配置文件,自己根据实际情况定义内容即可

使用nginx.conf 创建ConfigMap,默认文件nginx.conf名作为ConfigMap的Key名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl create cm nginx-cm --from-file=nginx.conf
# kubectl create cm 表示创建一个ConfigMap资源,这里的cm是ConfigMap的缩写
# nginx-cm 是为这个 ConfigMap 指定的名字。可以根据需要自定义这个名字。
# --from-file=nginx.conf 这个参数是关键,它告诉 kubectl 从指定的文件nginx.conf来创建 ConfigMap,这个ConfigMap的键名 默认使用文件名(这里是 nginx.conf),值是文件的全部内容


#创建ConfigMap,这个ConfigMap的key名默认是nginx.conf文件名
[root@k8s-master01 configmap]# kubectl create cm nginx-cm --from-file=nginx.conf
configmap/nginx-cm created

#查看创建的ConfigMap
[root@k8s-master01 configmap]# kubectl get cm
NAME DATA AGE
nginx-cm 1 23m

指定ConfigMap的key名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#指定ConfigMap的key名,参数--from-file=nginxconf=nginx.conf中的nginxconf是指定这个ConfigMap中的key名
kubectl create cm nginx-cm2 --from-file=nginxconf=nginx.conf

# 通过kubectl get cm查看ConfigMap中的key名是nginxconf
[root@k8s-master01 configmap]# kubectl get cm nginx-cm2 -oyaml
apiVersion: v1
data:
nginxconf: "server {\n listen 80;\n listen [::]:80;\n server_name
\ localhost;\n\n access_log /var/log/nginx/default.access.log;\n error_log
\ /var/log/nginx/default.error.log;\n\n\n\n location / {\n root /usr/share/nginx/html/innovationCenter;\n\tindex
index.html;\n try_files $uri $uri/ /index.html;\n }\n\n location
/api/ {\n proxy_pass http://localhost:8080/;\n proxy_set_header
Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header
X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto
$scheme;\n }\n\n error_page 500 502 503 504 /50x.html;\n location
= /50x.html {\n root /usr/share/nginx/html;\n }\n}\n"
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-15T09:12:06Z"
name: nginx-cm2
namespace: default
resourceVersion: "11643911"
uid: 7d47ff11-3deb-4e68-a960-4e695183d87c

基于多个文件创建ConfigMap

1
2
3
4
5
6
7
8
9
# 基于多个文件创建ConfigMap,指定多个--from-file参数即可,默认文件名作为ConfigMap的key名
kubectl create cm multile-file --from-file=my.cn --from-file=redis.conf

#指定ConfigMap的key名,该ConfigMap中有两个数据,key名分别是mysqlconf和redisconf
kubectl create cm multile-file2 --from-file=mysqlconf=my.cn --from-file=redisconf=redis.conf

[root@k8s-master01 configmap]# kubectl get cm
NAME DATA AGE
multile-file2 2 109s

基于目录(目录中多个文件)创建ConfigMap

1
2
3
kubectl create  cm multile-dir --from-file=conf
# multile-dir是指定的创建的cm资源的名字
# --from-file=conf 指定从文件创建ConfigMap,不过这里conf是一个目录,该命令会把conf中所有的文件创建在一个cm中,文件名是cm中的key名,同时需要注意的是基于目录创建的cm不支持自定义ConfigMap的key名,可以提前修改好conf目录中的文件名,也可以在pod中挂载的时候进行修改

1.3.4基于环境变量创建ConfigMap

Kubernetes 支持从一个环境变量文件中创建 ConfigMap,或者将 ConfigMap 中的键值对注入到容器的环境变量中。

创建ConfigMap时,可以通过指定–from-env-file参数,从一个环境变量文件中创建环境变量类型的ConfigMap,创建环境变量类型的ConfigMap只需要在文件内写入key=value格式的内容即可,案例如下:

假设Java/Spring Boot 项目需要环境变量配置(程序连接mysql、redis、mq等服务)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#准备环境变量的配置文件,注意格式:key=value
[root@k8s-master01 configmap]# vim prod.env #这里的文件名可以自定义,不必须是.env结尾
# 在prod.env文件中假如以下内容
DB_HOST=prod-mysql.internal
DB_PORT=3306
DB_USER=order_service
REDIS_HOST=prod-redis.internal
REDIS_PORT=6379
MQ_HOST=prod-rabbitmq.internal
MQ_PORT=5672
LOG_LEVEL=info
MAX_CONNECTIONS=100
CACHE_TTL=300


#创建这个configmap
[root@k8s-master01 configmap]# kubectl create cm prod-cm --from-env-file=prod.env
configmap/prod-cm created

1.3.5基于literal创建

基于字面环境变量形式创建ConfigMap,也就是通过 --from-literal 参数传递多个键值对。

1
2
3
4
5
6
[root@k8s-master01 ~]# kubectl create  cm literal-cm --from-literal=key=value --from-literal=DB_HOST=123.54.55.8 --from-literal=MQ_HOST=11.15.14.4
configmap/literal-cm created

# kubectl create cm literal-cm :创建一个名为 literal-cm 的 ConfigMap。
# --from-literal=key=value:添加一个键值对到 ConfigMap 中;--from-literal :表示直接提供一个明文的键值对(不是从文件读取)。key=value分别表示指定的key和value。
# --from-literal=MQ_HOST=11.15.14.4 指定要添加的键值对,key是 MQ_HOST;value是11.15.14.4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@k8s-master01 ~]# kubectl get cm
NAME DATA AGE
literal-cm 3 4m19s
prod-cm 10 5d5h


[root@k8s-master01 ~]# kubectl get cm literal-cm -o yaml
apiVersion: v1
data:
DB_HOST: 123.54.55.8 #DB_HOST是指定的key;123.54.55.8是指定的value
MQ_HOST: 11.15.14.4
key: value
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-21T08:32:44Z"
name: literal-cm
namespace: default
resourceVersion: "12223752"
uid: 665ce685-6b17-43a9-a25e-822790d8f13a

1.3更新ConfigMap

1.3.1基于yaml文件修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# 基于basic-cm.yaml文件创建configmap
[root@k8s-master01 configmap]# cat basic-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: basic-cm
namespace: default
data:
# 简单的键值对(key:value)形式,pod中会使用database.host和database.port
database.host: "mysql.example.com"
database.port: "3306"
name: "John Doe"
age: "30"

# 创建 cm
[root@k8s-master01 configmap]# kubectl create -f basic-cm.yaml
configmap/basic-cm created
[root@k8s-master01 configmap]# kubectl get cm
NAME DATA AGE
basic-cm 4 4s

[root@k8s-master01 configmap]# kubectl get cm basic-cm -oyaml
apiVersion: v1
data:
age: "30"
database.host: mysql.example.com
database.port: "3306"
name: John Doe
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T03:20:18Z"
name: basic-cm
namespace: default
resourceVersion: "12461064"
uid: 91d92d63-a1c8-42be-adfc-262b661b9111

# 更新该cm,通过文件更新cm前提是没有通过edit指令编辑过cm,否则cm资源可能会和配置文件不一致
[root@k8s-master01 configmap]# vim basic-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: basic-cm
namespace: default
data:
# 简单的键值对(key:value)形式,pod中会使用database.host和database.port
database.host: "mysql.example.com"
database.port: "3306"
name: "John Doe"
age: "30"
email: "1223584670@qq.com" #新增配置
~
~
# 通过 kubectl replace -f 指令更新configmap资源
[root@k8s-master01 configmap]# kubectl replace -f basic-cm.yaml
configmap/basic-cm replaced
[root@k8s-master01 configmap]# kubectl get cm
basic-cm kube-root-ca.crt prod-cm redis-health
istio-ca-root-cert literal-cm redis-configuration redis-scripts

# 查看cm详细配置
[root@k8s-master01 configmap]# kubectl get cm basic-cm -oyaml
apiVersion: v1
data:
age: "30"
database.host: mysql.example.com
database.port: "3306"
email: 1223584670@qq.com #新增加的配置已经更新
name: John Doe
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T03:20:18Z"
name: basic-cm
namespace: default
resourceVersion: "12461271"
uid: 91d92d63-a1c8-42be-adfc-262b661b9111

1.3.2通过eidt直接修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 通过 kubectl edit直接编辑cm
[root@k8s-master01 configmap]# kubectl edit cm basic-cm
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
age: "30" #删除该配置
database.host: mysql.example.com
database.port: "3306"
email: 1223584670@qq.com #删除该配置
name: John Doe #删除该配置
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T03:20:18Z"
name: basic-cm
namespace: default
resourceVersion: "12461271"
uid: 91d92d63-a1c8-42be-adfc-262b661b9111

# 查看编辑后的cm,上述删除的字段已经不存在
[root@k8s-master01 configmap]# kubectl get cm basic-cm -oyaml
apiVersion: v1
data:
database.host: mysql.example.com
database.port: "3306"
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T03:20:18Z"
name: basic-cm
namespace: default
resourceVersion: "12512702"
uid: 91d92d63-a1c8-42be-adfc-262b661b9111

#需要集群权限允许 update 操作
#修改后 Pod 不会自动重启 ,已有 Pod 仍使用旧配置(除非使用 Reloader 工具或手动重启)

1.3.3通过修改源文件更新

这里的源文件指的是通过nginx.conf或者redis.conf的配置文件创建的cm。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 先基于nginx.conf配置文件创建一个cm
[root@k8s-master01 conf]# kubectl create cm nginx-conf --from-file=nginx.conf

#此时需求是nginx-conf这个cm配置有修改需要更新,也就是nginx.conf文件需要进行修改
#nginx.conf中的配置根据自己需要进行修改
vim nginx.conf
# 增加配置
user root;

#更新这个cm:先转成yaml,在进行replace,nginx-conf这个configmap要存在才行
[root@k8s-master01 conf]# kubectl create cm nginx-conf --from-file=nginx.conf --dry-run=client -oyaml |kubectl replace -f -
configmap/nginx-conf replaced

#查看更新内容是否存在,可以看到user root;已经更新到cm中
[root@k8s-master01 conf]# kubectl get cm nginx-conf -oyaml
apiVersion: v1
data:
nginx.conf: "user root;\nserver {\n listen 80;\n listen [::]:80;\n
\ server_name localhost;\n\n access_log /var/log/nginx/default.access.log;\n
\ error_log /var/log/nginx/default.error.log;\n\n\n\n location / {\n root
\ /usr/share/nginx/html/innovationCenter;\n\tindex index.html;\n try_files
$uri $uri/ /index.html;\n }\n\n location /api/ {\n proxy_pass http://localhost:8080/;\n
\ proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n
\ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header
X-Forwarded-Proto $scheme;\n }\n\n error_page 500 502 503 504 /50x.html;\n
\ location = /50x.html {\n root /usr/share/nginx/html;\n }\n}\n"
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T07:33:20Z"
name: nginx-conf
namespace: default
resourceVersion: "12516230"
uid: f30fa6d1-d872-48c7-996e-ae9cb76c0e5b

1.3.4基于literal创建的ConfigMap更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 查看literal-cm的配置
[root@k8s-master01 conf]# kubectl get cm literal-cm -oyaml
apiVersion: v1
data:
DB_HOST: 123.54.55.8
MQ_HOST: 11.15.14.4
key: value
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-21T08:32:44Z"
name: literal-cm
namespace: default
resourceVersion: "12223752"
uid: 665ce685-6b17-43a9-a25e-822790d8f13a

#同样使用--dry-run=client -oyaml|kubectl replace -f - 来更新literal-cm(ConfigMap)资源
[root@k8s-master01 conf]# kubectl create cm literal-cm --from-literal=DB_HOST=123.54.55.8 --from-literal=MQ_HOST=11.15.14.4 --dry-run=client -oyaml|kubectl replace -f -
configmap/literal-cm replaced

#查看资源是否更新
[root@k8s-master01 conf]# kubectl get cm literal-cm -oyaml
apiVersion: v1
data: #此时data下已经没有 key: value配置,说明已经更新成功
DB_HOST: 123.54.55.8
MQ_HOST: 11.15.14.4
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-21T08:32:44Z"
name: literal-cm
namespace: default
resourceVersion: "12517507"
uid: 665ce685-6b17-43a9-a25e-822790d8f13a

1.4挂载ConfigMap

1.4.1以文件形式挂载ConfigMap

该方式适用于nginx、mysql、redis以及应用程序外挂配置,也就是配置分离,接下来以nginx配置 为例演示: 使用nginx.conf 作为配置文件,通过 ConfigMap 挂载到 Nginx 容器中,替代容器中默认的 nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#以 nginx.conf配置文件为例
[root@k8s-master01 conf]# cat nginx.conf
server {
listen 80;
server_name cm.nginx.org;

access_log /var/log/nginx/default.access.log;
error_log /var/log/nginx/default.error.log;



location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}


error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}


# 基于nginx.conf文件创建ConfigMap,cm的名字是nginx-config-cm,--from-file=cm.nginx.org.conf=nginx.conf表示基于nginx.conf创建configmap,cm.nginx.org.conf表示这个cm的key; nginx.conf是文件名,文件中的内容是key的value
[root@k8s-master01 conf]# kubectl create cm nginx-config-cm --from-file=cm.nginx.org.conf=nginx.conf
configmap/nginx-config-cm created

[root@k8s-master01 conf]# kubectl get cm
NAME DATA AGE
nginx-config-cm 1 4s

#在deploy资源中挂载名字是nginx-config-cm的ConfigMap
[root@k8s-master01 conf]# vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deployment
strategy: {}
template:
metadata:
labels:
app: nginx-deployment
spec:
volumes: #定义卷,因为卷属于pod范围的资源,所以volumes和containers同级
- name: nginx-config-volume #name是自定义卷的名称,在容器中引用时会用
configMap: #表示卷挂载的类型是configMap
name: nginx-config-cm #表示引用的ConfigMap资源名称是nginx-config-cm
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
name: nginx
ports:
- containerPort: 80 #这里的端口知识声明容器监听80端口,没有实际指定容器监听端口的功能
volumeMounts: #定义卷挂载配置,属于容器级别操作,决定容器要把哪个卷挂载到自己的文件系统里
- name: nginx-config-volume #指定挂载卷的名称,在这个案例中这里应该和上述volumes.name字段保持一致
mountPath: /etc/nginx/conf.d #这里指定挂载到容器内部的路径

#查看pod中容器的挂载情况
[root@k8s-master01 conf]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f6c69c7bd-b7wh2 1/1 Running 0 43m
nginx-deployment-6f6c69c7bd-crhn5 1/1 Running 0 43m


[root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-6f6c69c7bd-b7wh2 -- bash
root@nginx-deployment-6f6c69c7bd-b7wh2:/# cd /etc/nginx/conf.d/
root@nginx-deployment-6f6c69c7bd-b7wh2:/etc/nginx/conf.d# ls -l
total 0
lrwxrwxrwx 1 root root 24 Jul 23 07:18 cm.nginx.org.conf -> ..data/cm.nginx.org.conf

#ConfigMap的key就是挂载的文件名-cm.nginx.org.conf
[root@k8s-master01 conf]# kubectl get cm nginx-config-cm -oyaml
apiVersion: v1
data:
cm.nginx.org.conf: "server {\n listen 81;\n server_name cm.nginx.org;\n\n
\ access_log /var/log/nginx/default.access.log;\n error_log /var/log/nginx/default.error.log;\n\n\n\n
\ location / {\n root /usr/share/nginx/html;\n\tindex index.html;\n
\ try_files $uri $uri/ /index.html;\n }\n\n\n error_page 500 502
503 504 /50x.html;\n location = /50x.html {\n root /usr/share/nginx/html;\n
\ }\n}\n"
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-22T09:19:51Z"
name: nginx-config-cm
namespace: default
resourceVersion: "12536846"
uid: 84d4ee5e-4a76-4f79-b9b5-c7d1e29e85f1

1.4.2指定挂载的文件名

在1.4.1的案例中,没有指定文件名那么默认挂载的文件名是ConfigMap的key作为文件名,在挂载时可以通过items参数指定挂载的文件名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#假设ConfigMap内容如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config-cm
data:
cm.nginx.org.conf: |
server {
listen 80;
server_name cm.nginx.org;
...
}
other.conf: |
server { ... }


# 使用 items 配置后,只有 cm.nginx.org.conf 会被挂载,并且在容器中会以 default.conf 的名字出现;other.conf 不会被挂载
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config-cm
items: # 选择性的挂载ConfigMap中的key
- key: cm.nginx.org.conf #key指定的是ConfigMap中的键名
path: default.conf # path指定挂载到容器的文件名,文件中的内容就是 cm.nginx.org.conf这个key对应的value
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
name: nginx
ports:
- containerPort: 80 #这里的端口知识声明容器监听80端口,没有实际指定容器监听端口的功能
volumeMounts: #定义卷挂载配置,属于容器级别操作,决定容器要把哪个卷挂载到自己的文件系统里
- name: nginx-config-volume #指定挂载卷的名称,在这个案例中这里应该和上述volumes.name字段保持一致
mountPath: /etc/nginx/conf.d #这里指定挂载到容器内部的路径
#查看容器中挂载情况
[root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-66798f9ff7-mmfjg -- ls /etc/nginx/conf.d
default.conf

# 工作原理
ConfigMap (nginx-config-cm)
├── cm.nginx.org.conf ────┐ (key)
├── other.conf
重命名

default.conf (path)


Container: /etc/nginx/conf.d/
└── default.conf

默认情况下items中指定的 - key要在ConfigMap中存在,pod才能正常启动,如果指定的key不存在则会报错找不到ConfigMap;但是会有一种需求是,如果指定的key不存在也不要影响pod的启动,存在就挂载,不在就不挂载了而已,不能影响pod的启动,此时可以添加optional: true来把key必须存在改为非必须。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deployment
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx-deployment
spec:
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config-cm
optional: true #optional字段是在configMap中配置的,不是在items中配置
items:
- key: sdbfjb.conf #当指定了optional: true,即使指定的key是错误或者不存在的也不会影响pod启动
path: default.conf
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/conf.d

# 进入容器中查看/etc/nginx/conf.d目录下没有任何挂载
[root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-6f5d9b879c-9dxrj -- ls -l /etc/nginx/conf.d
total 0


1.4.3自定义挂载的权限

在linxu中文件权限是用8进制的格式定义的,k8s中可以是8进制也可以用10进制。进制转换https://tool.oschina.net/hexconvert

ConfigMap和Secret挂载时,默认的挂载权限是644,也就是-rw-r–r–权限(八进制)

如果挂载的是一个脚本文件,此时需要可执行权限,可以通过mode和defaultMode来定义权限,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#可以在挂载时指定文件的权限
configMap:
name: nginx-config-cm
optional: true
defaultMode: 420 #默认权限,对items中所有的key都生效,十进制511=八进制的0777
items:
- key: cm.nginx.org.conf
path: default.conf
mode: 0777 #局部权限,仅限对单个的item生效,八进制
# 如果mode 和defaultMode同时配置了,那么mode优先级高于defaultMode

#查看配置的权限已经改为777
[root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-84b7bfc778-jz4tb -- ls -l /etc/nginx/conf.d/..data/default.conf
-rwxrwxrwx 1 root root 408 Jul 23 09:33 /etc/nginx/conf.d/..data/default.conf

1.4.4解决文件挂载覆盖的问题

ConfigMap和Secret挂载时,会直接覆盖原目录的内容,所以在挂载时需要注意。

比如需要挂载nginx.conf配置文件时,如果直接挂载到容器的/etc/nginx目录,会导致nginx无法启动,因为/etc/nginx目录中有nginx启动依赖的模块,ConfigMap挂载时会将/etc/nginx目录中的所有内容覆盖,nginx启动所依赖的文件会丢失,导致nginx无法启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    spec:
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config-cm
containers:
- image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx
# 按照上述配置挂载时,在容器的/etc/nginx目录中只会有名字是nginx-config-cm的ConfigMap的内容。

# 使用subPath参数解决挂载覆盖问题
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf #mountPath指定容器内挂载的文件路径
subPath: nginx.conf #subPath中nginx.conf是ConfigMap 中的 key。
# 该事例实现的效果是:在容器内/etc/nginx/nginx.conf 文件中的内容是configmap中nginx.conf这个key的内容

1.4.5以环境变量形式挂载ConfigMap

该方法适用于通过环境变量创建的ConfigMap

步骤一:准备ConfigMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 假设程序需要连接mysql和nacos服务,这个ConfigMap定义mysql和nacos的连接信息,通过环境变量的形式注入到容器中

# 基于文件prod.env创建ConfigMap,注意文件中内容的格式
[root@k8s-master01 conf]# cat prod.env
# 定义生产环境MySQL和nacos的连接信息

# Nacos
NACOS_SERVER_ADDR=192.168.0.88:8848
NACOS_USERNAME=nacos
NACOS_NAMESPACE=prod

#MySQL
DB_HOST=192.168.0.66
DB_PORT=3306

#创建COnfigMap,名字定义为prod-env-cm
[root@k8s-master01 conf]# kubectl create cm prod-env-cm --from-env-file=prod.env
configmap/prod-env-cm created


#查看创建的configmap,
[root@k8s-master01 conf]# kubectl get cm prod-env-cm -oyaml
apiVersion: v1
data:
DB_HOST: 192.168.0.66
DB_PORT: "3306"
NACOS_NAMESPACE: prod
NACOS_SERVER_ADDR: 192.168.0.88:8848
NACOS_USERNAME: nacos
kind: ConfigMap
metadata:
creationTimestamp: "2025-07-24T09:13:38Z"
name: prod-env-cm
namespace: default
resourceVersion: "13142429"
uid: 530076a7-4a2a-42da-ae5e-164a8e1192c0

步骤二:在 Pod/Deployment 中引用 ConfigMap

在pod中注入环境变量时,不需要配置volumes字段;当挂载为文件时需要配置volumes字段;

  1. 方式一:通过env参数选择性的从prod-env-cm注入为环境变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    # nginx-deploy.yaml的内容如下:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    creationTimestamp: null
    labels:
    app: nginx-deployment
    name: nginx-deployment
    spec:
    replicas: 2
    selector:
    matchLabels:
    app: nginx-deployment
    strategy: {}
    template:
    metadata:
    creationTimestamp: null
    labels:
    app: nginx-deployment
    spec:
    containers:
    - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
    name: nginx # 定义pod中容器的名字是nginx
    env: #定义这个容器的环境变量列表,下面的 - name: ... 是一个或多个环境变量的定义。
    - name: MYSQL_HOST #定义容器内环境变量的名称是MYSQL_HOST,该字段要在代码代码中约定好
    valueFrom: #表示这个环境变量的值 不是直接写死的(不是 value: xxx) ,而是从某个外部资源中获取。
    configMapKeyRef: #全称ConfigMap Key Reference(对 ConfigMap 中某个 key 的引用),表示环境变量的值来自某个ConfigMap对象的某个key
    name: prod-env-cm #要引用的 ConfigMap 的 名称是prod-env-cm 。
    key: DB_HOST #从名为 prod-env-cm 的 ConfigMap 中,提取键为 DB_HOST 的值。赋值给MYSQL_HOST
    - name: MYSQL_PORT
    valueFrom:
    configMapKeyRef:
    name: prod-env-cm
    key: DB_PORT
    ports:
    - containerPort: 80

    # 创建并查看容器中定义的环境变量
    [root@k8s-master01 conf]# kubectl replace -f nginx-deploy.yaml
    [root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-757b6dfb94-jr746 -- env|grep MYSQL
    MYSQL_HOST=192.168.0.66
    MYSQL_PORT=3306

    总结:在上述配置的案例中,把 ConfigMap prod-env-cm 里的 DB_HOST 这个 key 的值,注入到容器的环境变量 MYSQL_HOST 里。

    • 假设 prod-env-cm 里的 DB_HOST: 192.168.0.88,那么容器启动后,环境变量会是:MYSQL_HOST=192.168.0.88

    • Java 程序只需要读取环境变量 MYSQL_HOST,就能拿到数据库地址。

    • 这样,程序和配置解耦,你只需改 ConfigMap 就能切换数据库地址,无需改代码或镜像。

    • 程序和运维/配置人员需要约定好环境变量名(如 MYSQL_HOST),这样才能正确读取。

  2. 方式二:通过envFrom参数将prod-env-cm中的内容全部注入为环境变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 还是以 prod-env-cm  ConfigMap为例
    [root@k8s-master01 conf]# kubectl get cm prod-env-cm -oyaml
    apiVersion: v1
    data:
    DB_HOST: 192.168.0.66
    DB_PORT: "3306"
    NACOS_NAMESPACE: prod
    NACOS_SERVER_ADDR: 192.168.0.88:8848
    NACOS_USERNAME: nacos
    kind: ConfigMap
    metadata:
    creationTimestamp: "2025-07-24T09:13:38Z"
    name: prod-env-cm
    namespace: default
    resourceVersion: "13142429"
    uid: 530076a7-4a2a-42da-ae5e-164a8e1192c0

    通过envFrom将名字是prod-env-cm的ConfigMap中对应的key和value全部注入为环境变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    # nginx-deploy.yaml的内容如下:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    creationTimestamp: null
    labels:
    app: nginx-deployment
    name: nginx-deployment
    spec:
    replicas: 2
    selector:
    matchLabels:
    app: nginx-deployment
    strategy: {}
    template:
    metadata:
    creationTimestamp: null
    labels:
    app: nginx-deployment
    spec:
    containers:
    - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx
    name: nginx
    envFrom: #表示将 ConfigMap 或 Secret 中所有的键值对作为环境变量批量导入到容器中,无需逐一指定。
    - configMapRef: #表示要从哪个 ConfigMap 引用环境变量
    name: prod-env-cm #指定引用的 ConfigMap 的名字。
    prefix: "PREFIX_" #为环境变量添加前缀,根据需求使用该参数
    env:
    - name: MYSQL_HOST
    valueFrom:
    configMapKeyRef:
    name: prod-env-cm
    key: DB_HOST
    - name: MYSQL_PORT
    valueFrom:
    configMapKeyRef:
    name: prod-env-cm
    key: DB_PORT
    ports:
    - containerPort: 80
    # 创建资源,并查看容器中的环境变量
    [root@k8s-master01 conf]# kubectl replace -f nginx-deploy.yaml

    [root@k8s-master01 conf]# kubectl exec -ti nginx-deployment-7b778c4d44-5nmfm -- env|grep -E "MYSQL|PREFIX"
    PREFIX_DB_PORT=3306
    PREFIX_NACOS_NAMESPACE=prod
    PREFIX_NACOS_SERVER_ADDR=192.168.0.88:8848
    PREFIX_NACOS_USERNAME=nacos
    PREFIX_DB_HOST=192.168.0.66
    MYSQL_HOST=192.168.0.66
    MYSQL_PORT=3306

    #可以看到使用envFrom参数批量添加的环境变量都有一个前缀PREFIX_,而通过env参数单独指定的环境变量并没有前缀,同时这也说明如果env单独指定的环境变量的优先级高于envFrom配置的环境变量

2.Secret-敏感配置管理

2.1Secret介绍

Secret 和 ConfigMap类似,Secret也是k8s的一种资源,同样可以存储配置数据。和ConfigMap不同的是Secret提供了一个相对安全的方式来管理这些数据。同时相对于ConfigMap,Secret也有不同的类型,不同的类型具有不同的使用场景。比如kubernetes.io/dockerconfigjson 可以用来管理镜像仓库的用户名和密码。

主要用途:

  • 存储敏感数据:可以存储密码、key等信息;

  • 数据保护:Secret的数据可以被加密存储,防止未经授权的访问

  • 动态配置:和ConfigMap类似

  • 共享配置:和ConfigMap类似

2.2Secret资源定义

1
2
3
4
5
6
7
8
apiVersion: v1 #表示使用 Kubernetes 核心 API 版本。
kind: Secret #定义这是一个 Secret 对象。
metadata: #定义资源元数据
name: mysecret #定义这个 Secret资源的名字是 mysecret
type: Opaque # 定义或者Secret的类型,表示该 Secret 的内容是任意的非结构化数据。
data: #字段中的键值必须是 Base64 编码 :
username: YWRtaW4= # base64 编码的 "admin"。username: YWRtaW4= ➝ echo 'YWRtaW4=' | base64 --decode ➝ admin
password: MWYyZDFlMmU2N2Rm # base64 编码的密码

2.3Secret常用类型

  • 0paque:通用型Secret,默认类型;常用
  • kubernetes.io/dockerconfigjson:下载私有仓库镜像使用的Secret,和宿主机的/root/.docker/config.json一致,宿主机登录后即可产生该文件;常用
  • kubernetes.io/tls:用于存储HTTPS域名证书文件的Secret,可以被Ingress使用;常用
  • bootstrap.kubernetes.io/token:一种简单的bearer token,用于创建新集群或将新节点添加到现有集群,在集群安装时可用于自动颁发集群的证书。
  • kubernetes.io/basic-auth:用于使用基本认证(账号密码)的Secret,可以使用0paque取代;
  • kubernetes.io/ssh-auth:用于存储ssh密钥的Secret;
  • kubernetes.io/service-account-token:作用于ServiceAccount,包含一个令牌,用于标识API服务账户;

2.4创建Secret

2.4.1基于literal创建Secret

literal是字面值的意思,基于 literal(字面值) 直接创建Secret。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# kubectl create secret表示创建一个secret资源
# generic 表示使用默认类型 Opaque,即自定义键值对的通用用途 Secret。
# basic-auth-secret 是创建的secret的名字,可以在pod中引用这个名称
# --from-literal=username=admin 指定一个键值对,作为Secret中的一项数据;将 username作为 key,admin作为 value 存储。
# --from-literal=password=asdqwe123@ 同样是指定一个键值对;将 password 作为 key,asdqwe123@ 作为 value 存储。

[root@k8s-master01 conf]# kubectl create secret generic basic-auth-secret --from-literal=username=admin --from-literal=password=asdqwe123@
secret/basic-auth-secret created

#查看创建的secret
[root@k8s-master01 conf]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth-secret Opaque 2 7m5s

[root@k8s-master01 conf]# kubectl get secrets basic-auth-secret -oyaml
apiVersion: v1
data:
password: YXNkcXdlMTIzQA== #显示的是base64编码后的内容
username: YWRtaW4= #这里的看到的YWRtaW4=是admin经过base64编码后的值
kind: Secret
metadata:
creationTimestamp: "2025-07-24T13:58:19Z"
name: basic-auth-secret
namespace: default
resourceVersion: "13180212"
uid: 2831a035-663f-48f3-9ff8-cb792aab836c
type: Opaque

# 加密解密查看,和secret中加密后的内容一致
[root@k8s-master01 conf]# echo -n "asdqwe123@"|base64
YXNkcXdlMTIzQA==
[root@k8s-master01 conf]# echo "YXNkcXdlMTIzQA=="|base64 -d
asdqwe123@

2.4.2基于yaml文件创建Secret

基于yaml文件形式创建有两种方式,第一种直接写在data下,需要对数据先进行base64加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 先将数据进行base64加密
[root@k8s-master01 conf]# echo -n 'admin' | base64 # 输出:YWRtaW4=
YWRtaW4=
[root@k8s-master01 conf]# echo -n '123456' | base64 # 输出:MTIzNDU2
MTIzNDU2

# 编写yaml文件创建secret
vim secret.yaml
# 添加下面内容
kind: Secret
apiVersion: v1
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4= # base64编码后的admin
password: MTIzNDU2 # base64编码后的123456

# 应用yaml文件创建Secret
[root@k8s-master01 Secret]# kubectl create -f secret.yaml
secret/mysecret created

#查看创建的secret
[root@k8s-master01 Secret]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth-secret Opaque 2 72m
mysecret Opaque 2 4s

[root@k8s-master01 Secret]# kubectl get secrets mysecret -oyaml
apiVersion: v1
data:
password: MTIzNDU2
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2025-07-24T15:10:44Z"
name: mysecret
namespace: default
resourceVersion: "13195397"
uid: 38f2a586-6dc7-4450-a403-3e5aa08d4139
type: Opaque

第一种方式需要先手动对数据进行base64加密,这样有点麻烦,可以直接将data字段换成stringData,yaml文件中可以直接写成明文,Kubernetes 会自动转成 base64。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
vim stringData.yaml
#添加下面内容,注意stringData
apiVersion: v1
kind: Secret
metadata:
name: stringdata-secret
type: Opaque
stringData:
username: admin
password: 123456

# 应用yaml文件创建Secret
[root@k8s-master01 Secret]# kubectl create -f stringData.yaml
secret/stringdata-secret created

#查看创建的secret
[root@k8s-master01 Secret]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth-secret Opaque 2 82m
mysecret Opaque 2 10m
stringdata-secret Opaque 2 19s

[root@k8s-master01 Secret]# kubectl get secrets stringdata-secret -oyaml
apiVersion: v1
data:
password: MTIzNDU2 #这里已经自动进行base64加密
username: YWRtaW4= #这里已经自动进行base64加密
kind: Secret
metadata:
creationTimestamp: "2025-07-24T15:20:31Z"
name: stringdata-secret
namespace: default
resourceVersion: "13197442"
uid: 49a672bf-9c1f-49b1-9c68-cb94735ddb95
type: Opaque

2.4.3基于文件和目录创建Secret

基于文件和目录创建Secret和ConfigMap类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@k8s-master01 ~]# kubectl create secret generic nginx-conf-secret --from-file=/root/configmap/conf/nginx.conf
secret/nginx-conf-secret created

# 创建后文件内容会被base64加密
[root@k8s-master01 ~]# kubectl get secrets
NAME TYPE DATA AGE
nginx-conf-secret Opaque 1 20s

[root@k8s-master01 ~]# kubectl get secrets nginx-conf-secret -oyaml
apiVersion: v1
data:
nginx.conf: c2VydmVyIHsKICAgIGxpc3RlbiAgICAgICA4MTsKICAgIHNlcnZlcl9uYW1lICBjbS5uZ2lueC5vcmc7CgogICAgYWNjZXNzX2xvZyAgL3Zhci9sb2cvbmdpbngvZGVmYXVsdC5hY2Nlc3MubG9nOwogICAgZXJyb3JfbG9nICAgL3Zhci9sb2cvbmdpbngvZGVmYXVsdC5lcnJvci5sb2c7CgoKCiAgICBsb2NhdGlvbiAvIHsKICAgICAgICByb290ICAgL3Vzci9zaGFyZS9uZ2lueC9odG1sOwoJaW5kZXggaW5kZXguaHRtbDsKICAgICAgICB0cnlfZmlsZXMgJHVyaSAkdXJpLyAvaW5kZXguaHRtbDsKICAgIH0KCgogICAgZXJyb3JfcGFnZSAgIDUwMCA1MDIgNTAzIDUwNCAgLzUweC5odG1sOwogICAgbG9jYXRpb24gPSAvNTB4Lmh0bWwgewogICAgICAgIHJvb3QgICAvdXNyL3NoYXJlL25naW54L2h0bWw7CiAgICB9Cn0KCgogICAgc2VydmVyIHsKICAgICAgICBsaXN0ZW4gODA7CiAgICAgICAgc2VydmVyX25hbWUgd3d3LmV4YW1wbGUuY29tOwogICAgICAgIGxvY2F0aW9uIC8gewogICAgICAgICAgICByb290IC91c3Ivc2hhcmUvbmdpbngvaHRtbDsKICAgICAgICAgICAgaW5kZXggaW5kZXguaHRtbDsKICAgICAgICB9CiAgICB9Cg==
kind: Secret
metadata:
creationTimestamp: "2025-07-25T03:48:24Z"
name: nginx-conf-secret
namespace: default
resourceVersion: "13236269"
uid: 4933f87b-ecf1-4373-a77b-58cb8a9f67a8
type: Opaque

基于目录创建(参考ConfigMap):

1
kubectl create secret generic secret-dir --from-file=/root/configmap/conf/

2.4.4使用Secret管理镜像仓库密钥

在录取私有仓库的镜像时,需要为资源配置镜像仓库的密钥,此时可以先创建一个Secret来存储私有 Docker Registry 的认证信息。

1
2
3
4
5
6
7
8
9
10
# 这里以自建的Harbor私有仓库为例
kubectl create secret docker-registry myregistryauth --docker-server=192.168.0.89 --docker-username=admin --docker-password=Harbor12345
# kubectl create secret 创建secret的指令
# docker-registry 表示创建 Secret 的类型,专门用于存储 Docker Registry 的认证信息。这是固定的类型名称,不需要修改。
# myregistryauth 这是 Secret 的名称,可以根据需要自定义
# --docker-server=192.168.0.89 #定义 Docker Registry 的服务器地址。【Docker Hub(默认)--docker-server=https://index.docker.io/v1/ 】 【私有 Registry:--docker-server=registry.mycompany.com 或者 --docker-server=192.168.1.100:5000 】
# --docker-username=admin 指定 Registry 的用户名是admin
# --docker-password=Harbor12345 指定admin用户的密码,这哥用户要有仓库的权限才能拉取镜像,如果没有权限即使配置账号密码也不能拉取镜像

#知识点:nerdctl login 192.168.0.89:80 和 docker login 192.168.0.89 的认证信息默认会保存在同一个位置,即用户目录下的 .docker/config.json 文件中。

在pod中引用这个镜像仓库的Secret:

1
2
3
4
5
6
7
8
9
10
11
# pod中引用
apiVersion: v1
kind: Pod
metadata:
name: private-pod
spec:
containers:
- name: private-container
image: 192.168.0.89/kubernetes/nginx:1.24.0
imagePullSecrets: # imagePullSecrets和containers字段保持同级
- name: myregistryauth # 引用创建的镜像仓库的 Secret 名称

2.4.5使用Secret管理域名证书

最常见的场景是管理 HTTPS 证书。你可以将证书文件(.crt)和私钥文件(.key)打包成 Secret,Secret 可以使用 kubernetes.io/tls 类型管理域名的证书,然后用于 Ingress :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 生成一个自签名的 X.509 证书和对应的私钥,通常用于测试环境或内部服务的 HTTPS 配置。生产环境要使用由受信任的 CA 签发的证书。
[root@k8s-master01 Secret]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=test.com"

#上述openssl指令会在当前目录生成两个文件,tls.key 和 tls.crt
[root@k8s-master01 Secret]# ll -a
total 24
drwxr-xr-x 2 root root 101 Jul 25 16:57 .
dr-xr-x---. 22 root root 4096 Jul 25 16:06 ..
-rw-r--r-- 1 root root 162 Jul 25 16:41 pod-secret.yaml
-rw-r--r-- 1 root root 176 Jul 24 23:09 secret.yaml
-rw-r--r-- 1 root root 136 Jul 24 23:20 stringData.yaml
-rw-r--r-- 1 root root 1111 Jul 25 16:57 tls.crt
-rw------- 1 root root 1704 Jul 25 16:57 tls.key

-------------------------------------------------------------------------
参数详解:
1. openssl req
openssl: OpenSSL 命令行工具
req: 证书请求(Certificate Request)子命令,用于创建和处理证书请求

2. -x509
直接生成自签名证书,而不是生成证书签名请求(CSR)
如果没有这个参数,会生成 CSR 文件,需要 CA 签名
加上这个参数,直接生成可用的证书

3. -nodes
"no DES" 的缩写
不对私钥进行加密
如果没有这个参数,生成私钥时会要求输入密码保护
在自动化场景中很有用,避免每次使用私钥都要输入密码

4. -days 365
证书有效期天数
这里设置为 365 天(1年)
可以根据需要调整,如 -days 730(2年)

5. -newkey rsa:2048
生成新的私钥
rsa:2048: 使用 RSA 算法,密钥长度 2048 位
其他选项:rsa:4096: 更安全但性能稍差
ec:secp384r1: 使用椭圆曲线算法

6. -keyout tls.key
指定私钥输出文件名
这里输出到 tls.key 文件
这是服务器的私钥,需要妥善保管

7. -out tls.crt
指定证书输出文件名
这里输出到 tls.crt 文件
这是公开的证书文件

8. -subj "/CN=test.com"
设置证书的主题(Subject)信息
/CN=test.com: Common Name 设置为 test.com
避免交互式输入证书信息
Subject 参数详解
完整的 Subject 可以包含更多信息:
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=test.com/emailAddress=admin@test.com"
各字段含义:
C: Country(国家),2个字母的国家代码
ST: State(州/省)
L: Locality(城市)
O: Organization(组织/公司)
OU: Organizational Unit(部门)
CN: Common Name(通用名称),要和域名保持一致
emailAddress: 邮箱地址

实际应用示例:
1. 生成通配符证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=*.test.com"

2. 生成包含多个域名的证书(SAN)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=test.com" \
-addext "subjectAltName=DNS:test.com,DNS:www.test.com,DNS:api.test.com"

3. 生成更强的加密证书
openssl req -x509 -nodes -days 365 -newkey rsa:4096 \
-keyout tls.key -out tls.crt \
-subj "/CN=test.com"

4. 生成需要密码保护的私钥
# 去掉 -nodes 参数
openssl req -x509 -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=test.com"


查看证书内容:
# 查看证书详细信息
openssl x509 -in tls.crt -text -noout

# 查看证书有效期
openssl x509 -in tls.crt -noout -dates

# 查看证书主题
openssl x509 -in tls.crt -noout -subject

利用证书文件生成Secret,Ingress中会用到这个Secret:

1
2
3
4
5
6
7
8
[root@k8s-master01 Secret]# kubectl create secret tls test-tls --key=/root/Secret/tls.key --cert=/root/Secret/tls.crt
secret/test-tls created

#kubectl create secret创建secret指令
#tls 表示 Secret 的类型,专门用于存储 TLS/SSL 证书和私钥
# test-tls 是Secret 的名称,ingress中可以通过这个名称引用该 Secret
# --key=/root/Secret/tls.key 指定 TLS 私钥文件的路径,该文件内容会被存储在 Secret 的 tls.key 字段中
# --cert=/root/Secret/tls.crt 指定 TLS 证书文件的路径该文件内容会被存储在 Secret 的 tls.crt 字段中

查看创建的Secret:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master01 Secret]# kubectl get secrets
NAME TYPE DATA AGE
test-tls kubernetes.io/tls 2 4m28s


[root@k8s-master01 Secret]# kubectl get secrets test-tls -oyaml
apiVersion: v1
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCekNDQWUrZ0F3SUJBZ0lVYTlNOHR5ZWhHZEUrSnBSV3RsMzdQeDVWbDQwd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lkR1Z6ZEM1amIyMHdIaGNOTWpVd056STFNRGcxTnpFeldoY05Nall3TnpJMQpNRGcxTnpFeldqQVRNUkV3RHdZRFZRUUREQWgwWlhOMExtTnZiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBTWJyZHBOQ1VlbEkwcjViTGVuYitNRlAxL3FFVmFyL056cUUyWENGTzE1azJSalQKL2Z3VURCOVcwRkZRRUJPTXVuZUpqSVkvOGh3eFJwUjAzVzlNQXJkcnlVMnp5K05lZUFianYyK094QTVFVnZPTwpUVHRXUDlBbXpQOHIweXVNMThlRUxMcVRpUDdRcDZ0T1czNnRBNHM3dGc0OTFsVWN5Z094dmJkSjlUWUYzWEFyCmZ6L3ZuM1pNaHRDeHNGb2FpNGJ2WHVHTWZqMDI5QWkzYlFvT1ZsenMrbmVtN3JyZTBtbHRFakRPMGFiV1R6dmkKOVBRMW54bmpOZklqSXlRNlVDMUxzZzZyTjhrc0EzNGV3Zmlrbm9JbDBWL25ObEQvV3l1bytLRlZiL0dhbXJkcQp6MXJnN2Q1M2ZrdktEd0pEYkJNMExVdnBoMFZNTmhCTkc0OE1VazhDQXdFQUFhTlRNRkV3SFFZRFZSME9CQllFCkZJZUp6MU0yNEtsRDRXM1dOdTV6UFlJdmdmMDJNQjhHQTFVZEl3UVlNQmFBRkllSnoxTTI0S2xENFczV051NXoKUFlJdmdmMDJNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRkRiYVFiZAphYlpoRHNNMFpUYmxkdVgwbzJKMlVSWS9aOGpPTnVvSEkrSzNIamkvVVNZNTVwLys5Um1NT1hPai96QVBVV3FhCmlWVGRTSzVRQU9CbVprd3Ria0xta1hFdVhycGFJb3JUUmVPQ0VrTkxMdzRvQTBCSDdHMkxXblozVkxXRE5CdmUKWSsvNTVTVDVyQ1Z2M0hoVk9JZGVBdEl0MWgyUSt5NDQ0bXYwZVNBbmVLaVRtTnY2bWZjb0g0MDFqWi81dTgwbwoxV2Y0ZGpNYTIvOXBvNE5wQ0V2d2FmU1pWdHYwaTVvZU1hQWRqa1FHMlFESGkxV2JhM21meUhiY1BaS3lTMituCmhNSndIWGxtbzVmWkNhTmJxOTFDV2FETUc0N24xbzRDSkJSVlNFNzg0dGE5emw1MjlMeW5OaHU1NHQ5bmxUTEYKSnVrNjEwd0lyODhDNS9JPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRREc2M2FUUWxIcFNOSysKV3kzcDIvakJUOWY2aEZXcS96YzZoTmx3aFR0ZVpOa1kwLzM4RkF3ZlZ0QlJVQkFUakxwM2lZeUdQL0ljTVVhVQpkTjF2VEFLM2E4bE5zOHZqWG5nRzQ3OXZqc1FPUkZiemprMDdWai9RSnN6L0s5TXJqTmZIaEN5Nms0aiswS2VyClRsdCtyUU9MTzdZT1BkWlZITW9Ec2IyM1NmVTJCZDF3SzM4Lzc1OTJUSWJRc2JCYUdvdUc3MTdoakg0OU52UUkKdDIwS0RsWmM3UHAzcHU2NjN0SnBiUkl3enRHbTFrODc0dlQwTlo4WjR6WHlJeU1rT2xBdFM3SU9xemZKTEFOKwpIc0g0cEo2Q0pkRmY1elpRLzFzcnFQaWhWVy94bXBxM2FzOWE0TzNlZDM1THlnOENRMndUTkMxTDZZZEZURFlRClRSdVBERkpQQWdNQkFBRUNnZ0VBQmEyc0VyUEJJSVBlZ1pEd2J4Z1luUFZ1czIwNnF0UE5SazQyTjMyVGZuUXEKTkY0U01UTjdUY1pqSjZjUzhSUHRNTU5obW1WOGxRSEh3NE43TWhXbjVZZUlxcjlZQnlpOURCUDM5TjNNOVV2NApkWGNab2s0cDFTM1R0VWNSZmZ2dnlhSVpkWEZkRVovRmpEWXVRTXFuUUJRWGRER2ZZRFQwV1ZyN1pram1CMEdOCkFBdmloYTlYUWVTVjZ6MnZ3ZytPWXJkaklWQktqS3o4RGhBK28xTnBwa0J2MStZbDdHY053RHJ1WHFNRGdlcUMKa3pKR0xwTERDRVVqeVVwZ0pvOFJ2STdlMHRaaldDZEwvVVdtcklxU1VXS1VEamRDenc0VjlXdmNwMmladGl4bgplN3lQZVhkK2xDcndpRjVLdjI5d0FTb29BSllFdVE2QlA0R0tFNXEwNVFLQmdRRDNXNWZxQjl0YmFZWGgyRFRWCmwveVByREtTbXA2bzhJemxYUTZ3akh1U09UVklVU1dmTHhuQkpNYjgwc21XLzk0WU4xQXhTb1dyZXJITWdtdFIKMncxWktockZVMG50bVpqbVRPdEhBS01hM2JxUGJpaHF5ek82Z1IzMms0OERua1VtSVBUUjBvOXFlTzJmd2hjVgpxRmttc2dUTWpROHNleHZWd0FNdktwY0FPd0tCZ1FETjNxSDIxODlhYjdzYmZ0N1Vpejk0ZjdRSjN6MW1hNG9OCktLUlVkaTFacUZMeW40L1JKWm5aK0VUQmJsZkVtQTFLQXBCdWtpTGJtajVLSitFSlZHbHQ3ZmQ0SGpkVEFaUDIKREJsVU42dU4wZHo2UlFrMVdJL3hHbEZ2VGVUcjQ1RkJOWFhCbUE4WVkvQ0owUEp0aW12akYvUjkvdDRCeWlLUApQMVBEcjduSS9RS0JnUUNmTW5qa0syaFhQZVBueGFIRGNrMGZIcUZ4ejBlYnpTMnhGS0kycUVPRGlZUXNaZVdECnZPbWpjQXNOZnBBMXVibHo5bTJMTzc0cDdnNXVZK1cwU2ZvZVQ4WHBCOERGeFp3dFpJWHNMWkhMNGJhSFIwdUYKNkFBRDRjT3FCYS8ra1NkSjhkMy9DTGc2dTFlY0FXdWdDYmhPK2pXeWZIcXVreEVJRWNzNjJQdFVMd0tCZ0QxMwpIaVpqOHIzT3BDK21ab05RKytkUFFZSzlDMGo4REtDM0pMRXZBNFZFVTFlck9qWTRvc0hJZFViSFdoOFJRczU1CkM0Um56MDUvczk5U0hzYzVVNjBGb3FCVGJUTTBRbWZ3M3RNZE4vUkUxMVJGcm1VbUJ2djJYcC83d3NDSEZrUkEKNE9Lbk1zS1dmQ2U1b2RnQXZ3dHppSVRoeG9rRVArTkRCaEJqOC9WRkFvR0FKOHhTZk4vellidkZwRUc0NURqTQo5S0h3U25ibUlqcGZ5M3hEL2h6QWRCYjFzeDJGMGtoRnE5b1hNMlJYQlB1OEgzSmF3UmJZODltZ1FMRlhPMWRyClJ0NXpkU1hWNjA1U3R1cEpiTmdSMHd4YUZaWUtGeng1RUJwdzQya3RSbENpbVA0T3ozd0NxT042cUVQOG9tSWwKNkxyNnYyUTAzTDRWaC82RWJMaTNVYTg9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
kind: Secret
metadata:
creationTimestamp: "2025-07-25T09:50:07Z"
name: test-tls
namespace: default
resourceVersion: "13312660"
uid: 369a4398-d06a-41aa-8453-aa8f4f239d1a
type: kubernetes.io/tls

更新Secret和ConfigMap方式一样:

1
2
3
4
kubectl create secret tls test-tls --cert=tls.crt --key=tls.key  --dry-run=client -oyaml|kubectl replace -f -

#如果使用yaml文件创建的,直接replace更新即可。
kubectl replace -f stringData.yaml

2.5挂载Secret

挂载Secret 和 ConfigMap 类似,也可以以文件或者环境变量的方式挂载

2.5.1以文件形式挂载Secret

使用 Volume 挂载 Secret,和 ConfigMap 类似,主要注意选择 Secret 的字段由 name 变成了secretName,volumeMounts 配置相同:

创建Secret:(该案例只是演示Secret的几种挂载方式,实际根据自己的情况选择合适的挂载方式即可)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 方式1:使用命令创建 TLS Secret
kubectl create secret tls my-tls-secret \
--key=/path/to/tls.key \
--cert=/path/to/tls.crt

# 方式2:使用 YAML 文件创建通用 Secret
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: my-app-secret
type: Opaque
data:
# 注意:值必须是 base64 编码的
database.conf: |
ZGF0YWJhc2VfaG9zdD0xMjcuMC4wLjEKZGF0YWJhc2VfcG9ydD0zMzA2CmRhdGFiYXNlX3VzZXI9cm9vdA==
app.properties: |
YXBwLm5hbWU9bXlhcHAKYXBwLnZlcnNpb249MS4wCmFwcC5kZWJ1Zz10cnVl

在pod中挂载Secret为文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# pod-with-secret.yaml,配置中volumes和volumeMounts与ConfigMap相似,参数的意思可以参考ConfigMap中的参数
apiVersion: v1
kind: Pod
metadata:
name: secret-volume-pod
spec:
containers:
- name: myapp
image: nginx:latest
volumeMounts:
# 挂载整个 Secret 到目录
- name: secret-volume
mountPath: "/etc/secrets"
readOnly: true
# 挂载 TLS Secret
- name: tls-secret-volume
mountPath: "/etc/tls"
readOnly: true
# 挂载特定的 Secret 文件
- name: config-volume
mountPath: "/etc/config"
readOnly: true
volumes:
# 挂载整个 Secret
- name: secret-volume #定义卷的名字
secret: #卷的类型是secret
secretName: my-app-secret #secret的名字
# 可选:设置文件权限
defaultMode: 0400

# 挂载 TLS Secret
- name: tls-secret-volume
secret:
secretName: my-tls-secret
defaultMode: 0400

# 只挂载 Secret 中的特定键
- name: config-volume
secret:
secretName: my-app-secret
items:
- key: database.conf
path: db.conf # 重命名文件
- key: app.properties
path: application.properties

2.5.2以环境变量形式挂载Secret

Secret以环境变量方式挂载和ConfigMap类似,只是一些字段上有差异,如secretKeyRef和secretRef

将 Secret 的单个键作为环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Pod
metadata:
name: env-secret-pod
spec:
containers:
- name: myapp
image: nginx:latest
env: #定义环境的
- name: DB_PASSWORD #定义环境变量的key为 DB_PASSWORD,程序中要使用该环境变量要在代码中约定好该key的名字
valueFrom: #表示环境变量的值来自哪里
secretKeyRef: #secretKeyRef表示从Secret中获取环境变量的值
name: my-secret # Secret 名称
key: password # Secret 中的键,也就是把该key的内容赋值给DB_PASSWORD

将 Secret 的所有键作为环境变量

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: env-secret-pod
spec:
containers:
- name: myapp
image: nginx:latest
envFrom: #批量添加环境变量
- secretRef: #表示从Secret中获取环境变量
name: my-secret #表示Secret的名字是my-secret,也就是从my-secret获取环境变量

总结:

  • 单个键:用 env + valueFrom.secretKeyRef
  • 全部键:用 envFrom.secretRef
  • 用法与ConfigMap相似,注意个别关键字段即可。

2.5.3使用Secret拉取私有仓库的镜像

假设创建的deployment等资源拉取的镜像在私有仓库中,需要使用账号密码才能拉取镜像,那么需要先创建一个docker-registry类型的Secret,然后在deployment资源中引用该Secret才能成功拉取镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 当创建一个deployment,所用的镜像在私有仓库中,如果没有配置密钥,在创建资源时会报错ImagePullBackOff,查看详细信息会提示仓库认证失败

cat pod-secret.yaml
kind: Pod
apiVersion: v1
metadata:
name: secret-pod-harbor
spec:

containers:
- name: harbor-container
image: 192.168.0.89/kubernetes/nginx:1.24.0
imagePullPolicy: Always

#创建pod资源查看镜像拉取情况
[root@k8s-master01 Secret]# kubectl create -f pod-secret.yaml
pod/secret-pod-harbor created
[root@k8s-master01 Secret]# kubectl get pod
NAME READY STATUS RESTARTS AGE
secret-pod-harbor 0/1 ImagePullBackOff 0 3s

#查看详细信息
[root@k8s-master01 Secret]# kubectl describe pod secret-pod-harbor
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 115s default-scheduler Successfully assigned default/secret-pod-harbor to k8s-master03
Warning Failed 37s (x6 over 113s) kubelet Error: ImagePullBackOff
Normal Pulling 23s (x4 over 114s) kubelet Pulling image "192.168.0.89/kubernetes/nginx:1.24.0"
Warning Failed 23s (x4 over 114s) kubelet Failed to pull image "192.168.0.89/kubernetes/nginx:1.24.0": failed to pull and unpack image "192.168.0.89/kubernetes/nginx:1.24.0": failed to resolve reference "192.168.0.89/kubernetes/nginx:1.24.0": pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials #提示权限拒绝,需要授权认证
Warning Failed 23s (x4 over 114s) kubelet Error: ErrImagePull
Normal BackOff 8s (x7 over 113s) kubelet Back-off pulling image "192.168.0.89/kubernetes/nginx:1.24.0"

创建一个Secret来存储私有 Docker Registry 的认证信息,然后在资源中通过imagePullSecrets参数引用该Secret,就可以正常拉取镜像了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[root@k8s-master01 Secret]# kubectl create secret docker-registry myregistryauth --docker-server=192.168.0.89 --docker-username=admin --docker-password=Harbor12345

#查看这个Secret
[root@k8s-master01 Secret]# kubectl get secrets myregistryauth -oyaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyIxOTIuMTY4LjAuODkiOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiSGFyYm9yMTIzNDUiLCJhdXRoIjoiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9In19fQ==
kind: Secret
metadata:
creationTimestamp: "2025-07-25T07:51:03Z"
name: myregistryauth
namespace: default
resourceVersion: "13287462"
uid: 7da08ee0-1399-4e33-a9b8-c3e5b2469881
type: kubernetes.io/dockerconfigjson

#在资源中引用这个Secret,pod的yaml资源定义如下:
kind: Pod
apiVersion: v1
metadata:
name: secret-pod-harbor
spec:
imagePullSecrets: #定义镜像拉取的Secret,注意imagePullSecrets和containers属于同级
- name: myregistryauth #定义Secret的名字是myregistryauth
containers:
- name: harbor-container
image: 192.168.0.89/kubernetes/nginx:1.24.0
imagePullPolicy: Always

#创建pod资源,发现pod正常运行,已经拉取到镜像
[root@k8s-master01 Secret]# kubectl create -f pod-secret.yaml
pod/secret-pod-harbor created
[root@k8s-master01 Secret]# kubectl get po
NAME READY STATUS RESTARTS AGE
secret-pod-harbor 1/1 Running 0 100s

2.6ConfigMap 和 Secret 只读配置

ConfigMap 和 Secret 资源中可以使用immutable字段把资源设置为(不可变更)只读,当ConfigMap 或 Secret 的 immutable 字段设置为 true 时,该资源将变为只读状态,无法再进行任何修改或删除操作(除非删除整个资源)。

immutable: true只是不允许编辑data下的数据

1
2
3
4
5
6
7
8
9
10
#ConfigMap资源定义如下:
[root@k8s-master01 Secret]# cat immutable-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: immutable-cm
data:
MYSQL_HOST: '192.168.0.66'
MYSQL_PORT: '3306'
immutable: true # 设置为不可变

创建ConfigMap:

1
2
[root@k8s-master01 Secret]# kubectl create -f immutable-cm.yaml
configmap/immutable-cm created

查看CM

1
2
3
[root@k8s-master01 Secret]# kubectl get cm
NAME DATA AGE
immutable-cm 2 18s

此时当需要编辑这个ConfigMap时会发现不允许编辑,编辑后无法保存,会报错

1
2
# configmaps "immutable-cm" was not valid:
# * data: Forbidden: field is immutable when `immutable` is set

2.7ConfigMap 和 Secret 备份还原

ConfigMap 和 Secret 目前并不支持备份和还原,不过可以使用 git 仓库管理 ConfigMap 和Secret 的版本,也可以使用 KRM 进行管理。

查看集群安装时的 KRM 端口号:

1
2
3
4
[root@k8s-master01 Secret]# kubectl get svc -n krm
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
krm-backend ClusterIP 10.96.252.180 <none> 8080/TCP 222d
krm-frontend NodePort 10.96.17.251 <none> 80:31740/TCP 222d

如果未安装可以参考如下步骤进行安装:

1
2
3
git clone https://gitee.com/dukuan/k8s-ha-install.git

kubectl create -f k8s-ha-install/krm.yaml

使用默认的 admin:admin 登录 krm,之后对 ConfigMap 或者 Secret 进行修改:每次修改后都会自动创建一个备份,还原是把备份的ConfigMap或者Secret中的data下的数据复制粘贴到原来的资源中即可。

2.8ConfigMap 和 Secret 注意事项

  • 需提前创建 ConfigMap 和 Secret
  • ConfigMap 和 Secret 必须要和 Pod 或者是引用它资源在同一个命名空间
  • 如果引用了某个 key,需要确保引用的 Key 必须存在
  • envFrom、valueFrom 无法热更新环境变量,subPath 也是无法热更新的
  • envFrom 配置环境变量,如果 key 是无效的,它会忽略掉无效的 key
  • ConfigMap 和 Secret 最好不要太大
  • ConfigMap 和 Secret 支持热更新,但是程序未必支持!