目录
- 思考,为什么需要ConfigMap、Secret
- 通过环境变量传递配置参数
- 环境变量的缺点
- ConfigMap介绍
- 命令行创建ConfigMap资源对象,(ConfigMap简写cm)
- pod中以环境变量的形式引用ConfigMap的条目
- 一次性传递ConfigMap的所有条目作为环境变量
- 传递configmap条目作为命令行参数
- 修改ConfigMap,查看是否可以实现应用实时更新配置(以环境变量形式传递的,不能实现更新)
- 使用ConfigMap卷将条目暴露为文件
- 修改ConfigMap,查看是否可以实现应用实时更新配置(以configmap卷挂载的,能实现更新)
- 了解文件被自动更新的过程
- configmap条目作为文件被挂载且不隐藏原目录中的其他文件(这种方式的挂载不能实现热更新)
- Secret资源对象
- 使用kubectl create 命令行创建Secret
- 使用yaml资源清单创建secret
- 解码 Secret
- 环境变量引用Secret(不能实现热更新)
- pod中挂载Secret卷
- 修改Secret,查看是否可以实现应用实时更新配置(以Secret卷挂载的,能实现更新)
- 总结
环境:centos7.9 docker-ce-20.10.9 kubernetes-version v1.22.6
思考,为什么需要ConfigMap、Secret
传统的方式下,当我们需要传一些配置给我们的应用,比如Oracle的IP地址,端口号,用户名密码等配置时,最容易想到的办法就是直接在打包镜像的时候写在应用配置文件里面,但是这种方式的坏处显而易见而且非常明显;
我们也可以通过在定义pod模板时,使用env字段定义配置参数,然后容器里面的应用程序就能通过环境变量来读取配置参数,但是这样的话,当配置参数发现变化,就必须修改修改yaml文件的pod模板的env字段的参数,而且还需要重启所有的pod,让容器重新加载新参数才行。
为了解决配置参数存储的问题,也为了解耦应用程序与配置参数,k8s提供了两种资源的对象来专门存储配置参数,即ConfigMap和Secret,前者ConfigMap主要存储不敏感配置信息,后者Secret存储加密的敏感配置信息。
通过环境变量传递配置参数
我们首先来看下pod是如何通过env字段传递配置参数,k8s允许pod为每一个容器自定义环境变量集合。
[root@master configmap]# cat deployment_nginx_env.yaml #创建一个deploy,pod模板中使用环境变量的方式传递数据库配置参数
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-env
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx-env
template:
metadata:
labels:
app: nginx-env
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
env: #定会环境变量
- name: dbtype #定义一个环境变量dbtype
value: "Oracle" #环境变量dbtype的值是Oracle
- name: ip #定义一个环境变量ip
value: "192.168.44.145" #环境变量ip的值是192.168.44.145
- name: port #定义一个环境变量port
value: "1521" #环境变量port的值1521
- name: dbtype_1
value: $(dbtype) #可以通过引用的方式引用前一个环境变量的值,前提是引用的环境变量必须先存在
- name: dbtype_2
value: "$(dbtype)_2" #可以通过引用的方式引用前一个环境变量的值,前提是引用的环境变量必须先存在
ports:
- name: http
containerPort: 80
[root@master configmap]#
[root@master configmap]# kubectl get pods -l app=nginx-env #查看pod,发现pod已经创建成功
NAME READY STATUS RESTARTS AGE
deployment-nginx-env-bdc55ff9b-jd88z 1/1 Running 0 2m21s
deployment-nginx-env-bdc55ff9b-k88hx 1/1 Running 0 2m21s
#查看一下pod
[root@master configmap]# kubectl describe pod deployment-nginx-env-5c987dcfb8-5qjrz
.........
Environment:
dbtype: Oracle
ip: 192.168.44.145
port: 1521
dbtype_1: $(dbtype) #这里不要觉得奇怪,因为yaml文件本身就是这样定义的,等下进到容器里echo $dbtype_1就能看到其值
dbtype_2: $(dbtype)_2
................
#现在查看pod中容器的所有环境变量,直接传递env命令给容器,打印所有的环境变量
[root@master configmap]# kubectl exec -it deployment-nginx-env-6cb87f5db8-5p45x -c nginx-container -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
dbtype=Oracle
ip=192.168.44.145
port=1521
dbtype_1=Oracle
dbtype_2=Oracle_2
.......
#当然,也可以进入容器查看环境变量
[root@master configmap]# kubectl exec -it deployment-nginx-env-5c987dcfb8-5qjrz -c nginx-container -- bash
root@deployment-nginx-env-5c987dcfb8-5qjrz:/# echo $dbtype; echo $dbtype_1; echo $dbtype_2;echo $ip; echo $port;
Oracle
Oracle
Oracle_2
192.168.44.145
1521
#以上,我们以环境变量的形式来传递配置参数给容器应用程序已经生效了,这样配置参数就能在容器中被应用程序使用环境变量的方式引用了
环境变量的缺点
如果多个应用使用到的相同的配置,那么就需要在每一个deployment的pod模板中以环境变量的形式定义配置,如果修改某个配置,如Oracle的ip地址,显然就需要修改每一个pod定义,这种做法简直就是灾难,这样也违背了k8s最基本的原则,所以,为了能在多个环境下复用配置,急需将配置从pod定义中解耦出来,k8s提供了ConfigMap资源来完成解耦。
ConfigMap介绍
kubernetes允许将配置选项分离到单独的资源对象ConfigMap中,其本质就是一个键值对key/value的映射,我们称之为条目,value既可以是简单的数值,也可以是一个完整的配置文件。
命令行创建ConfigMap资源对象,(ConfigMap简写cm)
ConfigMap的条目(key/value)既可以是简单的字面量,也可以是一个文件,下面将进行演示:
注意:ConfigMap的键名必须是合法的DNS子域,仅包含数字字母、破折号、下划线、英语圆点。
#首先,先创建两个配置文件
[root@master configmap]# mkdir my-config #创建存放my-config,该目录存放配置文件
[root@master configmap]# cd my-config/
[root@master my-config]# touch oracle.config #创建Oracle的配置文件,并写入Oracle的各项配置参数
[root@master my-config]# touch redis.config #创建redis的配置文件,并写入redis的各项配置参数
[root@master configmap]# cd ../
1、创建一个包含简单字面量的ConfigMap,名为my-config1
[root@master ~]# kubectl create configmap my-config1 --from-literal=dbtpye=Oracle --from-literal=ip=192.168.118.129 \
--from-literal=port=1521
configmap/my-config1 created
#以上创建了有3个条目的cm,key的名称和value的都能很清晰的看得出来
[root@master my-config]# kubectl get configmaps my-config1 -o yaml #以yaml格式查看我们创建的ConfigMap
apiVersion: v1
data: #下面这些就是该cm的条目
dbtpye: Oracle #第一个条目名为dbtype,其值为Oracle
ip: 192.168.118.129 #第二个条目名为ip,其值为192.168.118.129
port: "1521" #第三个条目名为port,其值为1521
kind: ConfigMap #资源类型
metadata:
creationTimestamp: "2022-03-25T09:37:18Z"
name: my-config1
namespace: default
resourceVersion: "1652307"
selfLink: /api/v1/namespaces/default/configmaps/my-config1
uid: 2f78d370-dcac-40c1-bcbf-351ba2b66799
[root@master my-config]#
2、从文件内容创建ConfigMap,名为my-config2,一个指定键名,一个不写键名
[root@master my-config]# kubectl create configmap my-config2 --from-file=oracle.config --from-file=redis=redis.config
configmap/my-config2 created
#以上,我们就从文件内容创建了一个configmap,其中的一个条目的key定义了名称,另一个条目没有写key名称k8s会默认采用文件名作为key名称
[root@master my-config]# kubectl describe cm my-config2 #查看我们创建的ConfigMap
Name: my-config2 #cm的名称
Namespace: default #所属命名空间
Labels: <none>
Annotations: <none>
Data #DATA表示该cm用有的条目
====
oracle.config: #第一个条目,没有指定key的名字,所以默认key名就是文件名
----
dbtype=Oracle #这三行都是条目oracle.config的值
ip=192.168.44.145
port=1521
redis: #同理,这是第二个条目,名为redis,下面的内容就是redis条目的值
----
port 6380
tcp-backlog 2048
bind redis1
timeout 0
loglevel notice
logfile "/usr/local/redis.log"
syslog-enabled no
stop-writes-on-bgsave-error yes
rdbcompression yes
dir /usr/local/data/redis/
maxmemory 5gbslaveof redis2 6379
slave-serve-stale-data yes
BinaryData
====
Events: <none>
3、从目录创建ConfigMap,这种创建方式下,kubernetes会为该目录下的所有合法ConfigMap键名的每个文件单独创建条目
[root@master configmap]# kubectl create configmap my-config3 --from-file=my-config/
configmap/my-config1 created
#这就创建一个名为my-config的cm,文件来自my-config目录下的文件,kubernetes会为该目录下的所有合法ConfigMap键名的每个文件单独创建条目
#注意:当来源是目录时,并不能指定key名,k8s会报错,因为一个key怎么能对应目录下这多文件呢,是吧。
以上就演示使用命令行时如何创建包含各种类型的条目的ConfigMap,当然,也可以将所有的选项全部混合使用,如:kubectl create configmap my-config4 --from-literal=dbtype=redis --from-file=mysql=my.cnf --from-file=my-config
pod中以环境变量的形式引用ConfigMap的条目
[root@master ~]# cat deployment_nginx_cm_env.yaml #创建一个deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-cm-env
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-cm-env
template:
metadata:
labels:
app: nginx-cm-env
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
env:
- name: DBTYPE #环境变量,名为DBTYPE
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: dbtype #指定来自my-config1的名称为dbtype的key
- name: IP #环境变量,名为IP
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: ip #指定来自my-config1的名称为ip的key
- name: PORT #环境变量,名为PORT
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: port #指定来自my-config1的名称为port的key
ports:
- name: http
containerPort: 80
[root@master ~]#
#以上,可以指定不同的环境变量来自不同的ConfigMap的key,并不一定要全部指定来之同一个ConfigMap的key
[root@master ~]# kubectl apply -f deployment_nginx_cm_env.yaml
deployment.apps/deployment-nginx-cm-env created
[root@master configmap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-nginx-cm-env-cfd697954-4hdc9 1/1 Running 0 6s
[root@master ~]# kubectl describe pod deployment-nginx-cm-env-cfd697954-4hdc9 #查看pod的详细描述
#可以看到,该pod的环境变量已经是来源于my-config这个ConfigMap的key
Environment:
DBTYPE: <set to the key 'dbtype' of config map 'my-config1'> Optional: false
IP: <set to the key 'ip' of config map 'my-config1'> Optional: false
PORT: <set to the key 'port' of config map 'my-config1'> Optional: false
..............
[root@master ~]# kubectl exec -it deployment-nginx-cm-env-cfd697954-4hdc9 -c nginx-container -- env #打印容器的环境变量
DBTYPE=Oracle
IP=192.168.118.129
PORT=1521
一次性传递ConfigMap的所有条目作为环境变量
上面我们使用env来一个个传递ConfigMap的条目作为环境变量实在是太麻烦,如果想一次性传递ConfigMap的所有条目作为环境变量,我们可以使用envfrom字段。
[root@master configmap]# cat deployment_nginx_cm_envfrom.yaml #创建pod,使用envFrom参数一次性传递全部cm的条目
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-cm-envfrom
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-cm-envfrom
template:
metadata:
labels:
app: nginx-cm-envfrom
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
imagePullPolicy: IfNotPresent
envFrom: #使用envFrom参数一次性传递全部cm的条目
- prefix: mydb- #前缀,表示为所有环境变量加前缀,前缀是可选的,如果不写,环境变量名就是configmap的条目名
configMapRef: #定义引用哪个configmap
name: my-config1 #configmap的名称
optional: true #可选参数,表示是否要求configmap先存在
ports:
- name: http
containerPort: 80
[root@master configmap]#
[root@master configmap]# kubectl apply -f deployment_nginx_cm_envfrom.yaml #创建deployment
deployment.apps/deployment-nginx-cm-envfrom created
[root@master configmap]# kubectl get pods -l app=nginx-cm-envfrom
NAME READY STATUS RESTARTS AGE
deployment-nginx-cm-envfrom-7d6d4fbdbd-n4tsg 1/1 Running 0 23s
[root@master configmap]# kubectl exec deployment-nginx-cm-envfrom-7d6d4fbdbd-n4tsg -- printenv #打印pod中容器环境变量
mydb-dbtype=Mysql #configmap的dbtype条目已经映射进来了,而且加了前缀
mydb-ip=192.168.118.129 #configmap的ip条目已经映射进来了,而且加了前缀
mydb-port=3306 #configmap的port条目已经映射进来了,而且加了前缀
再次说明,可以一次性传递configmap的所有条目作为环境变量,只需要在容器中使用envFrom属性字段将所有条目暴露作为环境变量即可,可以为所有的环境变量设置前缀,若不设置,环境变量的名称与configmap中的条目键名相同。
传递configmap条目作为命令行参数
虽然无法在pod.spec.containers.arges中直接引用configmap条目,但是可以利用configmap条目初始化某个环境变量,然后再在参数字段中引用该环境变量,如下所示:
........
env:
- name: DBTYPE #环境变量,名为DBTYPE
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: dbtype #指定来自my-config1的名称为dbtype的key
args: ["$(DBTYPE)"] #arges中直接引用环境变量,而环境变量引用了configmap条目
.......
修改ConfigMap,查看是否可以实现应用实时更新配置(以环境变量形式传递的,不能实现更新)
下面我们来修改my-config的条目,然后查看pod里的容器是否能正确读取ConfigMap的变更。
[root@master configmap]# kubectl edit cm my-config1
[root@master configmap]# kubectl describe cm my-config1
Name: my-config1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
ip:
----
192.168.118.129
port: #修改了port的值,变为3306
----
3306
dbtype: #修改了dbtype的值,变为mysql
----
Mysql
BinaryData
====
Events: <none>
[root@master configmap]#
我们发现,以环境变量传递的key,当ConfigMap更新条目时,并不会更新容器里环境变量,这一点是环境变量的缺陷。下面将通过卷的形式挂载ConfigMap。
使用ConfigMap卷将条目暴露为文件
以上,我们讲解了如何使用环境变量引用configmap的条目,但是configmap的条目还可以是整个配置文件,并且ConfigMap最主要的功能就是向容器传递配置文件,所以,kubernetes主要使用ConfigMap卷的形式将条目暴露为容器内的文件从而来实现向容器传递配置文件。
前面我们学习volume的时候,除了emptyDir、hostPath、nfs卷之外,还有一种特殊格式的卷,即configMap卷,configMap卷会将configmap资源对象中的每个条目暴露成一个文件,这样运行在容器中的进程就可以通过读取文件的内容来获取对应的条目值。
[root@master configmap]# cat deployment_nginx_cm_configmapvolume.yaml #创建一个挂载configmap卷的deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-cm-configmapvolume
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx-cm-configmapvolume
template:
metadata:
labels:
app: nginx-cm-configmapvolume
spec:
containers:
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
name: nginx-container
volumeMounts: #定义挂载点
- name: configmap-volume #挂载的卷的名称
mountPath: /etc/config/ #挂载目录
ports:
- name: http
containerPort: 80
volumes: #定义卷
- name: configmap-volume #卷的名称
configMap: #表示这是一个configmap卷
name: my-config4 #卷定义引用名为my-config4的configmap资源对象
[root@master configmap]
[root@master ~]# kubectl apply -f deployment_nginx_cm_configmapvolume.yaml #创建deployment
deployment.apps/deployment-nginx-cm-configmapvolume created
[root@master ~]# kubectl get pods -l app=nginx-cm-configmapvolume #查看pod
NAME READY STATUS RESTARTS AGE
deployment-nginx-cm-configmapvolume-85b4647db4-smhrz 1/1 Running 0 14s
#查看我们的容器内的/etc/config/目录,发现my-config4的条目已经被暴露成了文件
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- ls -l /etc/config/
total 0
lrwxrwxrwx 1 root root 13 Apr 23 17:08 dbtype -> ..data/dbtype
lrwxrwxrwx 1 root root 12 Apr 23 17:08 mysql -> ..data/mysql
lrwxrwxrwx 1 root root 20 Apr 23 17:08 oracle.config -> ..data/oracle.config
lrwxrwxrwx 1 root root 19 Apr 23 17:08 redis.config -> ..data/redis.config
#查看文件的内容,其实就是条目的值,自此,使用configmap卷的形式挂载到容器中去已经成功了
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- cat /etc/config/dbtype
redis[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- cat /etc/config/mysql
port 3306
修改ConfigMap,查看是否可以实现应用实时更新配置(以configmap卷挂载的,能实现更新)
#修改my-config4的oracle.config条目,如下
# dbtype=Oracle
# ip=192.168.44.100 #将ip和port都改了
# port=1527
#等待一会儿,查看容器是否更新了,如下所示,说明configmap卷挂载的,当修改ConfigMap时,容器时可以读取到最新的配置的。
# 但是注意一点,虽然容器内的配置文件是更新了的,但并不能保证应用程序是否读取了最新的配置文件内容,这取决于应用程序是否实时监听
# 配置文件,比如nginx程序,nginx程序就不能动态读取配置文件,还需要nginx -s reload
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- cat /etc/config/oracle.config
dbtype=Oracle
ip=192.168.44.100
port=1527
[root@master configmap]#
注意:以上我们使用configmap卷的形式挂载了configmap资源对象的所有条目到容器内的某个目录,从Linux挂载的概念我们得知,当挂载点存在文件时,那么挂载点之前存在的文件就会被隐藏,有时候这一点Linux的特性会造成严重后果,如当挂载到/etc目录时就会造成/etc目录下的所有配置文件被隐藏,这样程序就会出问题,为了解决隐藏的问题,configmap卷允许挂载configmap的单独条目为文件,如下所示。
了解文件被自动更新的过程
当修改configmap后,容器内的文件是如何被更新的呢,下面来看下:
#进入我们上面创建的pod中,查看,发现config4已经被挂载到了容器里面,并且4个条目已经映射为4个文件,如下:
[root@master configmap]# kubectl exec -it deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- bash
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/# cd /etc/config/
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config# ls -l
total 0
lrwxrwxrwx 1 root root 13 Apr 23 17:08 dbtype -> ..data/dbtype
lrwxrwxrwx 1 root root 12 Apr 23 17:08 mysql -> ..data/mysql
lrwxrwxrwx 1 root root 20 Apr 23 17:08 oracle.config -> ..data/oracle.config
lrwxrwxrwx 1 root root 19 Apr 23 17:08 redis.config -> ..data/redis.config
#列出隐藏文件
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config# ls -la
total 0
drwxrwxrwx 3 root root 127 Apr 23 19:28 .
drwxr-xr-x 1 root root 20 Apr 23 19:24 ..
drwxr-xr-x 2 root root 74 Apr 23 19:28 ..2022_04_23_19_28_32.662811324 #目录
lrwxrwxrwx 1 root root 31 Apr 23 19:28 ..data -> ..2022_04_23_19_28_32.662811324 #软链接
lrwxrwxrwx 1 root root 13 Apr 23 17:08 dbtype -> ..data/dbtype #软链接
lrwxrwxrwx 1 root root 12 Apr 23 17:08 mysql -> ..data/mysql #软链接
lrwxrwxrwx 1 root root 20 Apr 23 17:08 oracle.config -> ..data/oracle.config #软链接
lrwxrwxrwx 1 root root 19 Apr 23 17:08 redis.config -> ..data/redis.config #软链接
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config#
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config# ls -lda ..data #data也是一个软链接,链接到一个目录
lrwxrwxrwx 1 root root 31 Apr 23 19:28 ..data -> ..2022_04_23_19_28_32.662811324
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config# ls -ld ..2022_04_23_19_28_32.662811324 #目录
drwxr-xr-x 2 root root 74 Apr 23 19:28 ..2022_04_23_19_28_32.662811324
root@deployment-nginx-cm-configmapvolume-85b4647db4-smhrz:/etc/config# ls -l ..2022_04_23_19_28_32.662811324 #该目录下才是真正的条目映射的文件
total 16
-rw-r--r-- 1 root root 5 Apr 23 19:28 dbtype
-rw-r--r-- 1 root root 10 Apr 23 19:28 mysql
-rw-r--r-- 1 root root 42 Apr 23 19:28 oracle.config
-rw-r--r-- 1 root root 252 Apr 23 19:28 redis.config
#以上,我们可以看到,被挂载的configmap卷中的文件是..data目录中文件的符号链接,而..data同样是..2022_04_23_19_28_32.662811324的符号链接,这样,当configmap被更新后,kubernetes会创建这样一个目录,写入所有的文件并重新将符号链接..data链接值新的目录,通过这种方式就可以已重新修改所有文件
configmap条目作为文件被挂载且不隐藏原目录中的其他文件(这种方式的挂载不能实现热更新)
[root@master configmap]# cat deployment_nginx_cm_configmapvolume_all_item.yaml
apiVersion: apps/v1
.........
volumeMounts:
- name: configmap-volume #要挂载的卷名称
mountPath: /etc/dbtype1.config #挂载到某一文件,文件名可以自己定义
subPath: dbtype #表示挂载dbtype条目,必须是my-config4的条目名
- name: configmap-volume #要挂载的卷名称
mountPath: /etc/oracle.config1 #挂载到某一文件,文件名可以自己定义
subPath: oracle.config #表示挂载oracle.config条目,必须是my-config4的条目名
ports:
- name: http
containerPort: 80
volumes:
- name: configmap-volume #卷名
configMap: #表示引用的是configmap类型的卷
name: my-config4 #configmap资源对象名称
optional: true #表示configmap必须实现存在
defaultMode: 0777 #这里指定了挂载后的文件的权限为777,该参数默认为0644
#以上,就挂载了2个my-config4条目,即dbtype和oracle.config,dbtype被挂载为/etc/dbtype1.config文件,oracle.config被挂载
#为/etc/oracle.config1
#进入容器查看,我们发现这种将configmap条目作为文件挂载的形式并不会隐藏文件夹下的其他文件,而且挂载后的文件内容也是条目对应的值,同时我
# 们设置的defaultMode权限也生效了
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# ls /etc/
adduser.conf cron.daily dpkg group- init insserv.conf.d ld.so.conf.d mtab
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/#
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# cat /etc/dbtype1.config
redis
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# cat /etc/oracle.config1
dbtype=Oracle
ip=192.168.44.100
port=1527
注意:以上这样独立挂载文件的挂载方式是有缺陷的,即当修改了configmap时,容器无法实现配置文件更新,这一点与env环境变量传递条目一样。
Secret资源对象
k8s中的secret资源主要用于存储和管理一些敏感数据,比如密码,token,密钥,令牌等敏感信息,然后通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息了,pod会自动解密Secret 的信息,这样应用程序就能使用这些数据了。
Secret 数据的 JSON 和 YAML 序列化结果是以 base64 编码的。
Pod 可以用三种方式之一来使用 Secret:
1、以卷的形式将Secret挂载到一个或多个容器上,Secret条目映射文件以供应用程序读取数据;
2、以环境变量的形式来使用Secret;
3、使用拉取私有仓库时,由 kubelet 在为 Pod 拉取镜像时使用;
使用kubectl create 命令行创建Secret
一个 Secret 可以包含 Pod 访问数据库所需的用户凭证。 例如,由用户名和密码组成的数据库连接字符串。 可以将用户名存储在文件 username.txt
中,将密码存储在文件password.txt 中。
--from-literal=<key>=<value> :来源于字面值
--from-file=[key=]source:来源于文件
#创建一个secret,generic表示从本地文件、目录或字面值中创建secret,如下所示,即可以指定key,也可以不指定可以,不指定默认key就是文件名
[root@master ~]# kubectl create secret generic db-user-pass1 --from-file=username.txt --from-file=password.txt
[root@master ~]# kubectl create secret generic db-user-pass2 --from-file=username=username.txt --from-file=password=password.txt
#如果包含特殊字符还需要使用斜杠进行转义,如下所示:
[root@master ~]# kubectl create secret generic db-user-pass3 --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb='
使用yaml资源清单创建secret
通过编写一个yaml资源清单来创建secret,secret有两个字段,data字段中所有键值都必须是 base64编码的密文字符串,但是如果你想要明文显示,k8s提供了stringData字段,stringData可以使用任何字符串作为其取值。
[root@master secrets]# echo -n "root" |base64 #先进行编码加密,要加-n
cm9vdA==
[root@master secrets]# echo -n "fujiseiko123" |base64 #先进行编码加密,要加-n
ZnVqaXNlaWtvMTIz
[root@master secrets]#
[root@master secrets]# vim secret.yaml #编写一个secret资源清单文件
apiVersion: v1
data: #data字段,用于定义base64编码的key-value
username: cm9vdA== #key为username,value为编码后的值
password: ZnVqaXNlaWtvMTIz #key为password,value为编码后的值
kind: Secret #资源类型
metadata:
name: mysecret #名称
namespace: default #所属命名空间
labels: #标签
app: mysecret
type: Opaque #secret的类型,Opaque表示类型为用户自定义的任意数据
stringData: #如果你想要明文显示,则可以使用stringData字段属性
name: "Liming"
age: "25"
[root@master secrets]# kubectl apply -f secret.yaml
解码 Secret
kubectl get 和 kubectl describe 命令默认不显示 Secret 的内容。 这是为了防止 Secret 被意外暴露或存储在终端日志中。要查看创建的 Secret 的内容,运行以下命令:
[root@master secrets]# kubectl get secret db-user-pass1 -o jsonpath='{.data}' #查看secret的内容,测试仍是加密后的数据
{"password.txt":"MWYyZDFlMmU2N2Rm","username.txt":"YWRtaW4="}
[root@master secrets]#
[root@master secrets]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode #使用base64 --decode进行解码
1f2d1e2e67df #输出的就是password.txt文件的原始文本
[root@master secrets]# echo 'YWRtaW4=' | base64 --decode #使用base64 --decode进行解码
admin #输出的就是password.txt文件的原始文本
环境变量引用Secret(不能实现热更新)
[root@master secrets]# cat deployment_nginx_env_secret.yaml
........
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
imagePullPolicy: IfNotPresent
env: #以环境变量来引用secret的key
- name: username
valueFrom:
secretKeyRef:
name: db-user-pass2
key: username
- name: password #以环境变量来引用secret的key
valueFrom:
secretKeyRef:
name: db-user-pass2
key: password
ports:
- name: http
containerPort: 80
[root@master secrets]#
#查看容器环境变量,secret的key的值已经被自动解密了,这样容器内的应用程序就能使用该环境变量的值了
[root@master secrets]# kubectl exec deployment-nginx-env-secret-6685b66596-mj67k -- printenv
username=admin
password=1f2d1e2e67df
pod中挂载Secret卷
将Secret资源以卷的形式挂载到容器中,这是pod引用Secret资源的最佳方式,如下:
[root@master secrets]# vim deployment_nginx_secretvolume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx-secretvolume
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: deployment-nginx-secretvolume
template:
metadata:
labels:
app: deployment-nginx-secretvolume
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
imagePullPolicy: IfNotPresent
volumeMounts: #挂载点
- name: secret-volume #name指定要挂载secret-volume卷
mountPath: /etc/config/ #挂载路径
ports:
- name: http
containerPort: 80
volumes:
- name: secret-volume #卷的名称secret-volume
secret: #这里使用的是secret卷来挂载secret资源对象
secretName: mysecret #指定要挂载哪个secret对象
optional: true #TRUE 表示secret对象和它的key必须事先存在
defaultMode: 0777 #表示挂载到容器里面后的文件权限是777
[root@master secrets]# kubectl apply -f deployment_nginx_secretvolume.yaml
deployment.apps/deployment-nginx-secretvolume created
#查看容器,secret资源对象已经挂载进去了并且每一个key都被映射为一个文件,文件内容就是key的value值,并且内容自动解密了
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -l /etc/config/
total 0
lrwxrwxrwx 1 root root 10 Apr 23 23:33 age -> ..data/age
lrwxrwxrwx 1 root root 11 Apr 23 23:33 name -> ..data/name
lrwxrwxrwx 1 root root 15 Apr 23 23:33 password -> ..data/password
lrwxrwxrwx 1 root root 15 Apr 23 23:33 username -> ..data/username
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/age
25
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/name
Liming
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/password
fujiseiko123
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/username
root
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -a /etc/config/
.
..
..2022_04_23_23_33_11.524364074
..data
age
name
password
username
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -l /etc/config/..2022_04_23_23_33_11.524364074
total 16
-rwxrwxrwx 1 root root 2 Apr 23 23:33 age #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 6 Apr 23 23:33 name #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 12 Apr 23 23:33 password #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 4 Apr 23 23:33 username #文件权限也是777,说明defaultMode生效
[root@master secrets]#
修改Secret,查看是否可以实现应用实时更新配置(以Secret卷挂载的,能实现更新)
[root@master ~]# echo "fujiseiko" | base64 #先生成加密后的秘文
ZnVqaXNlaWtvCg==
[root@master ~]# kubectl edit secrets mysecret #在线编辑mysecret,使用上面的秘文替换username这个key的秘文,即修改用户名
#查看容器是否读取到了新的配置文件内容,如下所示,发现uaername这个文件的内容已经被更新了,之前是root,现在是fujiseiko,说明以Secret卷挂载secret资源对象,当修改secret对象时,能实现实时更新容器里的文件
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/username
fujiseiko
[root@master secrets]#
总结
1、传递环境变量给容器可以通过pod的env字段来实现,如下:
[root@master configmap]# vim deployment_nginx_env.yaml #创建一个deploy,pod模板中使用环境变量的方式传递数据库配置参数
................
env: #定会环境变量
- name: dbtype #定义一个环境变量dbtype
value: "Oracle" #环境变量dbtype的值是Oracle
- name: ip #定义一个环境变量ip
value: "192.168.44.145" #环境变量ip的值是192.168.44.145
- name: port #定义一个环境变量port
value: "1521" #环境变量port的值1521
- name: dbtype_1
value: $(dbtype) #可以通过引用的方式引用前一个环境变量的值,前提是引用的环境变量必须先存在
- name: dbtype_2
value: "$(dbtype)_2" #可以通过引用的方式引用前一个环境变量的值,前提是引用的环境变量必须先存在
..................
[root@master configmap]# kubectl create -f deployment_nginx_env.yaml
#现在查看pod中容器的所有环境变量,直接传递env命令给容器,打印所有的环境变量
[root@master configmap]# kubectl exec -it deployment-nginx-env-6cb87f5db8-5p45x -c nginx-container -- env
dbtype=Oracle
ip=192.168.44.145
port=1521
dbtype_1=Oracle
dbtype_2=Oracle_2
2、先创建configmap资源对象
kubernetes允许将配置选项分离到单独的资源对象ConfigMap中,其本质就是一个键值对key/value的映射,我们称之为条目,value既可以是简单的数
值,也可以是一个完整的配置文件。
2-1、创建一个包含简单字面量的ConfigMap,名为my-config1
[root@master ~]# kubectl create configmap my-config1 --from-literal=dbtpye=Oracle --from-literal=ip=192.168.118.129 \
--from-literal=port=1521
configmap/my-config1 created
2-2、从文件内容创建ConfigMap,名为my-config2,一个指定键名,一个不写键名
[root@master my-config]# kubectl create configmap my-config2 --from-file=oracle.config --from-file=redis=redis.config
configmap/my-config2 created
2-3、从目录创建ConfigMap,这种创建方式下,kubernetes会为该目录下的所有合法ConfigMap键名的每个文件单独创建条目
[root@master configmap]# kubectl create configmap my-config3 --from-file=my-config/
configmap/my-config1 created
#这就创建一个名为my-config的cm,文件来自my-config目录下的文件,kubernetes会为该目录下的所有合法ConfigMap键名的每个文件单独创建条目
#注意:当来源是目录时,并不能指定key名,k8s会报错,因为一个key怎么能对应目录下这多文件呢,是吧。
以上就演示使用命令行时如何创建包含各种类型的条目的ConfigMap,当然,也可以将所有的选项全部混合使用,如:kubectl create configmap my-config4 --from-literal=dbtype=redis --from-file=mysql=my.cnf --from-file=my-config
3、pod中以环境变量的形式引用ConfigMap的条目
[root@master ~]# cat deployment_nginx_cm_env.yaml #创建一个deploy
................
env:
- name: DBTYPE #环境变量,名为DBTYPE
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: dbtype #指定来自my-config1的名称为dbtype的key
- name: IP #环境变量,名为IP
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: ip #指定来自my-config1的名称为ip的key
- name: PORT #环境变量,名为PORT
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: port #指定来自my-config1的名称为port的key
ports:
- name: http
containerPort: 80
[root@master ~]#
#以上,可以指定不同的环境变量来自不同的ConfigMap的key,并不一定要全部指定来之同一个ConfigMap的key
[root@master ~]# kubectl apply -f deployment_nginx_cm_env.yaml
deployment.apps/deployment-nginx-cm-env created
[root@master ~]# kubectl exec -it deployment-nginx-cm-env-cfd697954-4hdc9 -c nginx-container -- env #打印容器的环境变量
DBTYPE=Oracle
IP=192.168.118.129
PORT=1521
4、 一次性传递ConfigMap的所有条目作为环境变量
[root@master configmap]# cat deployment_nginx_cm_envfrom.yaml #创建pod,使用envFrom参数一次性传递全部cm的条目
......
envFrom: #使用envFrom参数一次性传递全部cm的条目
- prefix: mydb- #前缀,表示为所有环境变量加前缀,前缀是可选的,如果不写,环境变量名就是configmap的条目名
configMapRef: #定义引用哪个configmap
name: my-config1 #configmap的名称
optional: true #可选参数,表示是否要求configmap先存在
......
[root@master configmap]# kubectl exec deployment-nginx-cm-envfrom-7d6d4fbdbd-n4tsg -- printenv #打印pod中容器环境变量
mydb-dbtype=Mysql #configmap的dbtype条目已经映射进来了,而且加了前缀
mydb-ip=192.168.118.129 #configmap的ip条目已经映射进来了,而且加了前缀
mydb-port=3306 #configmap的port条目已经映射进来了,而且加了前缀
5、 传递configmap条目作为命令行参数
虽然无法在pod.spec.containers.arges中直接引用configmap条目,但是可以利用configmap条目初始化某个环境变量,然后再在参数字段中引用该环境变量,如下所示:
........
env:
- name: DBTYPE #环境变量,名为DBTYPE
valueFrom: #valueFrom表示变量值来自哪里
configMapKeyRef: #表示引用的是ConfigMap
name: my-config1 #指定来源于my-config1
key: dbtype #指定来自my-config1的名称为dbtype的key
args: ["$(DBTYPE)"] #arges中直接引用环境变量,而环境变量引用了configmap条目
.......
6、使用ConfigMap卷将条目挂载到容器中并暴露为文件
ConfigMap卷挂载将configmap条目暴露为一个个配置文件,然后容器内的应用程序就能读取这些配置文件,标签当configmap资源对象更新后,容器能读取到更新后的配置文件内容,至于应用程序是否能读取最新的配置文件内容,取决于应用程序是否支持重载配置文件,使用ConfigMap卷将条目暴露为文件,这种用法也是ConfigMap存在意义。
注意:这种挂载方式存在一个缺点,即如果挂载目录存在旧文件,那么挂载后旧文件会被隐藏,这也是Linux 中mount机制所决定的。
[root@master configmap]# cat deployment_nginx_cm_configmapvolume.yaml #创建一个挂载configmap卷的deployment
.......
imagePullPolicy: IfNotPresent
name: nginx-container
volumeMounts: #定义挂载点
- name: configmap-volume #挂载的卷的名称
mountPath: /etc/config/ #挂载目录
ports:
- name: http
containerPort: 80
volumes: #定义卷
- name: configmap-volume #卷的名称
configMap: #表示这是一个configmap卷
name: my-config4 #卷定义引用名为my-config4的configmap资源对象
[root@master configmap]
#查看我们的容器内的/etc/config/目录,发现my-config4的条目已经被暴露成了文件
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- ls -l /etc/config/
total 0
lrwxrwxrwx 1 root root 13 Apr 23 17:08 dbtype -> ..data/dbtype
lrwxrwxrwx 1 root root 12 Apr 23 17:08 mysql -> ..data/mysql
lrwxrwxrwx 1 root root 20 Apr 23 17:08 oracle.config -> ..data/oracle.config
lrwxrwxrwx 1 root root 19 Apr 23 17:08 redis.config -> ..data/redis.config
#查看文件的内容,其实就是条目的值,自此,使用configmap卷的形式挂载到容器中去已经成功了
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- cat /etc/config/dbtype
redis
[root@master ~]# kubectl exec deployment-nginx-cm-configmapvolume-85b4647db4-smhrz -- cat /etc/config/mysql
port 3306
7、configmap条目作为文件被挂载且不隐藏原目录中的其他文件(这种方式的挂载不能实现热更新)
[root@master configmap]# cat deployment_nginx_cm_configmapvolume_all_item.yaml
apiVersion: apps/v1
.........
volumeMounts:
- name: configmap-volume #要挂载的卷名称
mountPath: /etc/dbtype1.config #挂载到某一文件,文件名可以自己定义
subPath: dbtype #表示挂载dbtype条目,必须是 my-config4的条目
- name: configmap-volume #要挂载的卷名称
mountPath: /etc/oracle.config1 #挂载到某一文件,文件名可以自己定义
subPath: oracle.config #表示挂载oracle.config条目,必须是 my-config4的条目
ports:
- name: http
containerPort: 80
volumes:
- name: configmap-volume #卷名
configMap: #表示引用的是configmap类型的卷
name: my-config4 #configmap资源对象名称
optional: true #表示configmap必须实现存在
defaultMode: 0777 #这里指定了挂载后的文件的权限为777,该参数默认为0644
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# ls /etc/ #目录下的文件没有被隐藏
adduser.conf cron.daily dpkg group- init insserv.conf.d ld.so.conf.d mtab
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/#
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# cat /etc/dbtype1.config #该文件对应条目dbtype ,其文件内容也是dbtype的值
redis
root@deployment-nginx-cm-configmapvolume-all-item-8696fbd9f4-zd827:/# cat /etc/oracle.config1 #该文件对应条目oracle.config,其文件内容也是oracle.config的值
dbtype=Oracle
ip=192.168.44.100
port=1527
8、使用secret资源对象存储敏感数据,使用命令行创建Secret资源对象
--from-literal=<key>=<value> :来源于字面值
--from-file=[key=]source:来源于文件
#创建一个secret,generic表示从本地文件、目录或字面值中创建secret,如下所示,即可以指定key,也可以不指定可以,不指定默认key就是文件名
[root@master ~]# kubectl create secret generic db-user-pass1 --from-file=username.txt --from-file=password.txt
[root@master ~]# kubectl create secret generic db-user-pass2 --from-file=username=username.txt --from-file=password=password.txt
#如果包含特殊字符还需要使用斜杠进行转义,如下所示:
[root@master ~]# kubectl create secret generic db-user-pass3 --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb='
9、使用yaml资源清单创建secret
通过编写一个yaml资源清单来创建secret,secret有两个字段,data字段中所有key键值都必须是 base64编码后的字符串,但是如果你想要明文显示,k8s提供了stringData字段,stringData可以使用任何字符串作为其取值。
[root@master secrets]# echo -n "root" |base64 #先进行编码加密,要加-n
cm9vdA==
[root@master secrets]# echo -n "fujiseiko123" |base64 #先进行编码加密,要加-n
ZnVqaXNlaWtvMTIz
[root@master secrets]#
[root@master secrets]# vim secret.yaml.yaml #编写一个secret资源清单文件
apiVersion: v1
data: #data字段,用于定义base64编码的key-value
username: cm9vdA== #key为username,value为base64编码后的值
password: ZnVqaXNlaWtvMTIz #key为password,value为base64编码后的值
kind: Secret #资源类型
metadata:
name: mysecret #名称
namespace: default #所属命名空间
labels: #标签
app: mysecret
type: Opaque #secret的类型,Opaque表示类型为用户自定义的任意数据
stringData: #如果想使用明文,则使用stringData字段属性
name: "Liming" #明文
age: "25" #明文
[root@master secrets]# kubectl apply -f secret.yaml
10、解码 Secret
kubectl get 和 kubectl describe 命令默认不显示 Secret 的内容。 这是为了防止 Secret 被意外暴露或存储在终端日志中。要查看创建的 Secret 的内容,运行以下命令:
[root@master secrets]# kubectl get secret db-user-pass1 -o jsonpath='{.data}' #查看secret的内容,测试仍是加密后的数据
{"password.txt":"MWYyZDFlMmU2N2Rm","username.txt":"YWRtaW4="}
[root@master secrets]#
[root@master secrets]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode #使用base64 --decode进行解码
1f2d1e2e67df #输出的就是password.txt文件的原始文本
[root@master secrets]# echo 'YWRtaW4=' | base64 --decode #使用base64 --decode进行解码
admin #输出的就是password.txt文件的原始文本
11、环境变量引用Secret(不能实现热更新)
[root@master secrets]# cat deployment_nginx_env_secret.yaml
........
imagePullPolicy: IfNotPresent
env: #以环境变量来引用secret的key
- name: username
valueFrom:
secretKeyRef:
name: db-user-pass2
key: username
- name: password #以环境变量来引用secret的key
valueFrom:
secretKeyRef:
name: db-user-pass2
key: password
ports:
- name: http
containerPort: 80
[root@master secrets]#
#查看容器环境变量,secret的key的值已经被自动解密了,这样容器内的应用程序就能使用该环境变量的值了
[root@master secrets]# kubectl exec deployment-nginx-env-secret-6685b66596-mj67k -- printenv
username=admin
password=1f2d1e2e67df
12、 pod中挂载Secret卷
将Secret资源以卷的形式挂载到容器中,这是pod引用Secret资源的最佳方式,如下:
[root@master secrets]# vim deployment_nginx_secretvolume.yaml
..........
imagePullPolicy: IfNotPresent
volumeMounts: #挂载点
- name: secret-volume #name指定要挂载secret-volume卷
mountPath: /etc/config/ #挂载路径
ports:
- name: http
containerPort: 80
volumes:
- name: secret-volume #卷的名称secret-volume
secret: #这里使用的是secret卷来挂载secret资源对象
secretName: mysecret #指定要挂载哪个secret对象
optional: true #TRUE 表示secret对象和它的key必须事先存在
defaultMode: 0777 #表示挂载到容器里面后的文件权限是777
#查看容器,secret资源对象已经挂载进去了并且每一个key都被映射为一个文件,文件内容就是key的value值,并且内容自动解密了
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -l /etc/config/
total 0
lrwxrwxrwx 1 root root 10 Apr 23 23:33 age -> ..data/age
lrwxrwxrwx 1 root root 11 Apr 23 23:33 name -> ..data/name
lrwxrwxrwx 1 root root 15 Apr 23 23:33 password -> ..data/password
lrwxrwxrwx 1 root root 15 Apr 23 23:33 username -> ..data/username
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/age
25
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/name
Liming
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/password
fujiseiko123
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- cat /etc/config/username
root
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -a /etc/config/
.
..
..2022_04_23_23_33_11.524364074
..data
age
name
password
username
[root@master secrets]# kubectl exec deployment-nginx-secretvolume-5bb94c74f8-j8hgc -- ls -l /etc/config/..2022_04_23_23_33_11.524364074
total 16
-rwxrwxrwx 1 root root 2 Apr 23 23:33 age #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 6 Apr 23 23:33 name #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 12 Apr 23 23:33 password #文件权限也是777,说明defaultMode生效
-rwxrwxrwx 1 root root 4 Apr 23 23:33 username #文件权限也是777,说明defaultMode生效
[root@master secrets]#