k8s配置管理-ConfigMap和Secret 十八岁 2025-12-02 2025-12-02
配置管理-ConfigaMap和Secret
1.ConfigMap-配置管理 1.1ConfigMap介绍 ConfigMap也是K8s的一种资源,主要用于存储非机密配置数据,如程序的环境变量、程序配置文件等。ConfigMap可以实现把应用程序的配置信息从容器镜像或者代码中分离出来,从而可以更容易的管理和更新配置,而不必重新构建应用程序,实现程序和配置的分离。
在实际生产环境中,程序的配置应该和容器分离,这样如果仅需要修改配置 可以灵活修改,不需要重新制作镜像。
主要用途:
1.2ConfigMap资源定义 定义环境变量形式的ConfigMap
1 2 3 4 5 6 7 8 9 apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: default data: database.host: "mysql.example.com" database.port: "3306"
pod中引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 [root@k8s-master01 configmap ] apiVersion: v1 kind: ConfigMap metadata: name: basic-cm namespace: default data: database.host: "mysql.example.com" database.port: "3306" name: "John Doe" age: "30" [root@k8s-master01 configmap ] configmap/basic-cm created [root@k8s-master01 configmap ] NAME DATA AGE basic-cm 4 61s [root@k8s-master01 configmap ] 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 [root@k8s-master01 configmap ] apiVersion: v1 kind: ConfigMap metadata: 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.conf 和 mysql.conf就是一个多行的 value,其值是整个配置文件内容。
在上述my-config配置中会发现两种写法,nginx.conf: | 和 mysql.conf: |- ,他们区别如下:
|:保留所有换行 ,包括结尾换行。
|-:去除结尾换行 ,其余保留。
它们都表示按原格式保留换行的多行文本 ,区别只在于“结尾是否带换行”。
在以下场景中**坚决使用 |**:
所有 bash、sh、python 等脚本
.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 ~ ] NAME DATA AGE literal-cm 3 4m19s prod-cm 10 5d5h [root@k8s-master01 ~ ] 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
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 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 { ... } volumes: - name: nginx-config-volume configMap: name: nginx-config-cm items: - key: cm.nginx.org.conf 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 [root@k8s-master01 conf ] 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 items: - key: sdbfjb.conf 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 [root@k8s-master01 conf ] 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: cm.nginx.org.conf path: default.conf mode: 0777 [root@k8s-master01 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 volumeMounts: - name: nginx-config-volume mountPath: /etc/nginx/nginx.conf subPath: nginx.conf
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字段;
方式一:通过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 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 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 ] [root@k8s-master01 conf ] 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),这样才能正确读取。
方式二:通过envFrom 参数将prod-env-cm中的内容全部注入为环境变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@k8s-master01 conf ] 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 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: - configMapRef: name: prod-env-cm 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 ] [root@k8s-master01 conf ] 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
2.Secret-敏感配置管理 2.1Secret介绍 Secret 和 ConfigMap类似,Secret也是k8s的一种资源,同样可以存储配置数据。和ConfigMap不同的是Secret提供了一个相对安全的方式来管理这些数据。同时相对于ConfigMap,Secret也有不同的类型,不同的类型具有不同的使用场景。比如kubernetes.io/dockerconfigjson 可以用来管理镜像仓库的用户名和密码。
主要用途:
2.2Secret资源定义 1 2 3 4 5 6 7 8 apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: MWYyZDFlMmU2N2Rm
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 apiVersion: v1 kind: Secret metadata: name: stringdata-secret type: Opaque stringData: username: admin password: 123456 [root@k8s-master01 Secret ] secret/stringdata-secret created [root@k8s-master01 Secret ] NAME TYPE DATA AGE basic-auth-secret Opaque 2 82m mysecret Opaque 2 10m stringdata-secret Opaque 2 19s [root@k8s-master01 Secret ] apiVersion: v1 data: password: MTIzNDU2 username: YWRtaW4= 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-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 apiVersion: v1 kind: Pod metadata: name: private-pod spec: containers: - name: private-container image: 192.168 .0 .89 /kubernetes/nginx:1.24.0 imagePullSecrets: - name: myregistryauth
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 ] NAME TYPE DATA AGE test-tls kubernetes.io/tls 2 4m28s [root@k8s-master01 Secret ] 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 apiVersion: v1 kind: Pod metadata: name: secret-volume-pod spec: containers: - name: myapp image: nginx:latest volumeMounts: - name: secret-volume mountPath: "/etc/secrets" readOnly: true - name: tls-secret-volume mountPath: "/etc/tls" readOnly: true - name: config-volume mountPath: "/etc/config" readOnly: true volumes: - name: secret-volume secret: secretName: my-app-secret defaultMode: 0400 - name: tls-secret-volume secret: secretName: my-tls-secret defaultMode: 0400 - 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 valueFrom: secretKeyRef: name: my-secret key: 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: name: 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 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 [root@k8s-master01 Secret ] pod/secret-pod-harbor created [root@k8s-master01 Secret ] NAME READY STATUS RESTARTS AGE secret-pod-harbor 0 /1 ImagePullBackOff 0 3s [root@k8s-master01 Secret ] 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 [root@k8s-master01 Secret ] 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 支持热更新,但是程序未必支持!