Fork me on GitHub
Fork me on GitHub

Kubernetes configMap和secret

两种特殊的存储卷:configMap和secret

1
2
3
4
5
6
[root@spark32 manifests]# kubectl explain pods.spec.volumes
configMap <Object>
ConfigMap represents a configMap that should populate this volume
secret <Object>
Secret represents a secret that should populate this volume. More info:
https://kubernetes.io/docs/concepts/storage/volumes#secret

这两种存储卷多数情况下,它们的目的不是给Pod提供存储空间来用的,而是给我们的管理员或用户提供了从集群外部向Pod内部的应用程序注入配置信息的方式。
第一点,比如在集群上,有个名称空间,在这个名称空间之上,有个Pod在运行。我们启动Pod是基于镜像来运行容器的。镜像做好后,镜像内的应用程序启动时要读配置文件也是镜像内的配置文件,因此镜像内的应用启动时到底应该运行在什么配置下,在做镜像之前就确定了。做完镜像后就改不了了。除非用entrypoint脚本,去接受用户启动容器时传一些环境变量进来。把环境变量中的数据给他写到或替换到配置文件中去从而使得应用程序在启动之前就获得一个新的配置文件,而后得到新配置。否则会有个问题,做好了的镜像,它可能为了适用不同的部署方式或者不同的环境,需要做很多个镜像。比如开发、测试、线上,三套环境都要部署tomcat,但是使用的内存大小不一样,很显然我们把配置写在配置文件之中,三个环境不可能都适用的,所以不得不做三个镜像,这很麻烦。所以后来想了其他办法来解决这个配置信息的注入。在k8s上也是如此,本来镜像都是做好的,一个镜像应付不了那么多场景,就不得不做多个镜像,这个特别难受,所以能够从镜像外部向镜像内部启动为容器时给它添加配置信息,是很重要的。
第二点,假如现在部署了20个Pod,里面都是tomcat,就算我们能够从外部通过环境变量注入进去,但是运行了一段时间以后,需要改配置参数,怎么改?重新替换环境变量的值。但是entrypoint已经生过效了。你可能还要触发entrypoint脚本重新执行一次,甚至是Pod不用动,把里面容器重启下。这个过程其实是比较麻烦的,而且还得一个一个去操作,一个一个重新改环境变量的值。应用程序运行时,有一种简单地方式来实现这个功能,可以使用配置中心。把配置放在配置中心,tomcat启动时加载的文件,文件看起来存在,可能并没有内容,文件来自于配置中心,动态从配置中心拉过来,然后启动tomcat。将来在配置中心修改配置,并通知给进程,让这些进程重载配置文件。k8s也面临一样的场景,这20个Pod需要更新的时候,改配置只能通过改镜像的话,代价太大了。因此我们不把配置写死在镜像中,而是引入一个新的资源,这个新的资源甚至是整个k8s之上的一等公民,这个资源就叫configMap,它里面放的是配置信息。随后启动的每一个Pod时,都可以共享使用同一个configMap资源。这个资源对象可以当存储卷来使用,也可以从中基于环境变量的方式从里面获取到一些数据传递给环境变量从而注入到容器中使用。
总结下来,有两种较为合适的方式去解决以上出现的两个场景:

  • 1、假如现在要启动一个Pod,这个Pod启动时可以把configmap资源关联到当前Pod上来,从中读一个数据,传递给Pod内容器中的一个变量,仍然是变量注入的方式来给容器传递配置信息。
  • 2、把每一个configmap当一个存储卷,直接挂载到容器中的某个目录上,这个目录恰好是应用程序读取配置信息的文件路径。而且支持动态修改,意思是说如果configmap中内容修改下,改完后会通知给所有的Pod,让Pod里面的应用重载,当然有些应用可能不能自动重载,你需要手动触发下重载。因此configmap扮演了k8s之上的配置中心的功能。

所以要想传一个配置文件给Pod中的容器,可以把配置文件打包在configmap中,让Pod启动时把configmap挂载到配置文件目录下,就从这下面读配置文件就能ok了。但是configmap是明文存数据的,因此在里面放的各种配置文件,不能包含敏感数据,比如连mysql,不能放root账号。跟configmap有些同样功能的另外一个标准k8s资源叫secret。secret的功能和configmap功能一样,所不同的是其中的内容不是明文存放的,而是base64编码存放的。不是加密,很容易解开,但是至少对很多人来讲,是不可为的任务了。

先做一个总结:配置容器化应用的方式:

  • 1、自定义命令行参数;
    args: []
  • 2、把配置文件直接放进镜像;
    不建议,这是在用dockerfile制作镜像时就把配置文件放进去了
  • 3、环境变量
    (1) Cloud Native的应用程序一般可直接通过环境变量加载配置;
    (2) 通过entrypoint脚本来预处理变量为配置文件中的配置信息,通过SET命令之类的替换到配置文件中去;
  • 4、存储卷

Pod资源获取环境变量的方式:env、envFrom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@spark32 manifests]# kubectl explain pods.spec.containers.env
...
name <string> -required-
Name of the environment variable. Must be a C_IDENTIFIER.
value <string>
Variable references $(VAR_NAME) are expanded using the previous defined
environment variables in the container and any service environment
variables. If a variable cannot be resolved, the reference in the input
string will be unchanged. The $(VAR_NAME) syntax can be escaped with a
double $$, ie: $$(VAR_NAME). Escaped references will never be expanded,
regardless of whether the variable exists or not. Defaults to "".
valueFrom <Object>
Source for the environment variable's value. Cannot be used if value is not
empty.
...
  • valueFrom: 数据来自引用另外一个变量或另外一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@spark32 manifests]# kubectl explain pods.spec.containers.env.valueFrom
...
FIELDS:
configMapKeyRef <Object>
Selects a key of a ConfigMap.
fieldRef <Object>
Selects a field of the pod: supports metadata.name, metadata.namespace,
metadata.labels, metadata.annotations, spec.nodeName,
spec.serviceAccountName, status.hostIP, status.podIP.
resourceFieldRef <Object>
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu,
requests.memory and requests.ephemeral-storage) are currently supported.
secretKeyRef <Object>
Selects a key of a secret in the pod's namespace
...
  • configMapKeyRef: 在configMap中的某个key的vlaue,configMap也是键值对。
  • fieldRef: 某个字段,这个字段很可能是Pod自身的字段,比如像metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP.
  • resourceFieldRef: 资源需求和资源算法,后面讲到调度器算法时在解释
  • secretKeyRef: 引用secretKey

configMap

简称cm。
configMap作用:让配置信息与镜像文件解耦。从而增强了应用的可移植性以及可复用性。configMap就是一系列配置数据的集合,而这些数据将来可以注入到Pod中的容器中所使用。
在configMap中,所有的配置信息都保存为键值格式。比如name: zhangshan。但是这种格式保存的数据量很小,我们也可以保存为比较复杂的格式。比如键名叫server.conf, 值是曾经在Nginx上配置时传递的这个server的整个内容。可以是整个文件的所有内容。因为value的长度是没有限制的。
configMap是一等公民,属于名称空间的资源,但是它的字段比较独特,和之前所学的Pod、Service等都不一样。没有spec,因为它没有那么复杂的结构,不需要嵌套众多状态描述的属性或字段。只需要给数据就可以了,所以有个data字段,是个map类型的。也可以以二进制形式给数据。

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@spark32 manifests]# kubectl explain cm
KIND: ConfigMap
VERSION: v1
DESCRIPTION:
ConfigMap holds configuration data for pods to consume.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
binaryData <map[string]string>
BinaryData contains the binary data. Each key must consist of alphanumeric
characters, '-', '_' or '.'. BinaryData can contain byte sequences that are
not in the UTF-8 range. The keys stored in BinaryData must not overlap with
the ones in the Data field, this is enforced during validation process.
Using this field will require 1.10+ apiserver and kubelet.
data <map[string]string>
Data contains the configuration data. Each key must consist of alphanumeric
characters, '-', '_' or '.'. Values with non-UTF-8 byte sequences must use
the BinaryData field. The keys stored in Data must not overlap with the
keys in the BinaryData field, this is enforced during validation process.
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

data和binaryData,一般只使用其中一种。
定义configMap时,可以使用yaml文件,也可以在命令行使用kubectl create configmap来定义。如果需要长期使用,可以定义成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
39
40
[root@spark32 manifests]# kubectl create configmap -h
...
Examples:
# Create a new configmap named my-config based on folder bar
kubectl create configmap my-config --from-file=path/to/bar
# Create a new configmap named my-config with specified keys instead of file basenames on disk
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
# Create a new configmap named my-config with key1=config1 and key2=config2
kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
# Create a new configmap named my-config from the key=value pairs in the file
kubectl create configmap my-config --from-file=path/to/bar
# Create a new configmap named my-config from an env file
kubectl create configmap my-config --from-env-file=path/to/bar.env
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--append-hash=false: Append a hash of the configmap to its name.
--dry-run=false: If true, only print the object that would be sent, without sending it.
--from-env-file='': Specify the path to a file to read lines of key=val pairs to create a configmap (i.e. a Docker
.env file).
--from-file=[]: Key file can be specified using its file path, in which case file basename will be used as
configmap key, or optionally with a key and file path, in which case the given key will be used. Specifying a directory
will iterate each named file in the directory whose basename is a valid configmap key.
--from-literal=[]: Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)
--generator='configmap/v1': The name of the API generator to use.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]

【示例1】:把键值做成configMap。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@spark32 manifests]# kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=myapp.wisedu.com
configmap/nginx-config created
[root@spark32 manifests]# kubectl get cm
NAME DATA AGE
nginx-config 2 28s
[root@spark32 manifests]# kubectl describe cm nginx-config
Name: nginx-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
nginx_port:
----
80
server_name:
----
myapp.wisedu.com
Events: <none>

可以看出,直接就可以看到configMap中的内容了。

【示例2】:把一个文件内容做成configMap。

1
2
3
4
5
6
7
8
9
[root@spark32 manifests]# mkdir configmap
[root@spark32 manifests]# cd configmap/
[root@spark32 configmap]# vim www.conf
server {
server_name myapp.wisedu.com;
listen 80;
root /data/web/html;
}
[root@spark32 configmap]# kubectl create cm nginx-www --from-file=./www.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@spark32 configmap]# kubectl create cm nginx-www --from-file=./www.conf
configmap/nginx-www created
[root@spark32 configmap]# kubectl describe cm nginx-www
Name: nginx-www
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
www.conf:
----
server {
server_name myapp.wisedu.com;
listen 80;
root /data/web/html;
}
Events: <none>

configmap两种方式注入容器中:

  • 1.在容器中使用env,使用envFrom来获取。
    如果通过环境变量来注入的话,必须确保环境变量传递进去能被容器作为配置信息使用,否则传过去没用。而两种方式上面提了,cloudnative,可直接通过环境变量加载配置,要不就是通过entrypoint脚本来处理。所以不是云环境,得在容器里写了entrypoint脚本才能使用传递进来的环境变量。
  • 2.存储卷方式

【示例3】:使用env来传递环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@spark32 manifests]# kubectl explain pods.spec.containers.env.valueFrom.configMapKeyRef
KIND: Pod
VERSION: v1
RESOURCE: configMapKeyRef <Object>
DESCRIPTION:
Selects a key of a ConfigMap.
Selects a key from a ConfigMap.
FIELDS:
key <string> -required-
The key to select.
name <string>
Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
optional <boolean>
Specify whether the ConfigMap or it's key must be defined

  • optional: 如果在容器中定义了从configmap引用,万一没有这个configmap,或者configmap中没有这个key,pod就启动不了了,因为引用数据不存在,会出错的。但是我们可以optional这一项启用起来,optional: true。意思是可选的,就算没有也没关系,如果不写为true,就表示must be defined。
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
[root@spark32 configmap]# vim pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-cm-1
namespace: default
labels:
app: myapp
tier: frontend
annotations:
wisedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
env:
- name: NGINX_SERVER_PORT
valueFrom:
configMapKeyRef:
name: nginx-config
key: nginx_port
- name: NGINX_SERVER_NAME
valueFrom:
configMapKeyRef:
name: nginx-config
key: server_name
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
[root@spark32 configmap]# kubectl apply -f pod-configmap.yaml
pod/pod-cm-1 created
[root@spark32 configmap]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 0/1 Error 0 12d
myapp-deploy-67b6dfcd8-ff9xf 1/1 Running 0 12d
myapp-deploy-67b6dfcd8-msv5x 1/1 Running 0 12d
myapp-deploy-67b6dfcd8-wls6h 1/1 Running 0 12d
myapp-pod 1/1 Running 0 24h
nginx 1/1 Running 0 12d
pod-cm-1 1/1 Running 0 5s
pod-vol-pvc 1/1 Running 0 25h
redis-58b9f5776-fzslw 1/1 Running 0 9d
tomcat-deploy-56699db4f7-4lhql 1/1 Running 0 6d6h
tomcat-deploy-56699db4f7-ghz7l 1/1 Running 0 6d6h
tomcat-deploy-56699db4f7-kd5v8 1/1 Running 0 6d6h
[root@spark32 configmap]# kubectl exec -it pod-cm-1 -- printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=pod-cm-1
TERM=xterm
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=myapp.wisedu.com
MYAPP_SVC_SERVICE_HOST=10.111.183.73
KUBERNETES_SERVICE_HOST=10.96.0.1
REDIS_SERVICE_HOST=10.97.97.97
...

已经传进来了。
现在修改configmap中的key的value,看Pod中容器中的变量是否会及时生效。

1
[root@spark32 configmap]# kubectl edit cm nginx-config


查看Pod容器中变量是否发生变化:

1
2
[root@spark32 configmap]# kubectl exec -it pod-cm-1 -- printenv | grep NGINX_SERVER_PORT
NGINX_SERVER_PORT=80

实践证明修改 ConfigMap 无法更新容器中已注入的环境变量信息。
当我们使用环境变量注入时,只在容器启动时有效。因为它是Pod创建时获取的。如果通过存储卷的方式来获取,是可以实时更新的。见下面的实例

【示例4】:使用存储卷来传递环境变量。
configmap无论创建时是不是文件,比如在命令行指了个key,指了个value,我们可以把整个configmap当存储卷挂载到Pod上,然后yaml文件中指定容器把存储卷挂载到自己的某个目录下(挂载点不存在会自动创建)。在这个挂载目录下,每一个key就转换成一个文件名,那个key的value就转换成文件内容。以刚才在命令行创建的configmap nginx-config为例。

1
2
[root@spark32 configmap]# kubectl delete -f pod-configmap.yaml
pod "pod-cm-1" deleted

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
[root@spark32 configmap]# vim pod-configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-cm-vol
namespace: default
labels:
app: myapp
tier: frontend
annotations:
wisedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/config.d/
readOnly: true
volumes:
- name: nginxconf
configMap:
name: nginx-config


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
[root@spark32 configmap]# kubectl apply -f pod-configmap-volume.yaml
pod/pod-cm-vol created
[root@spark32 configmap]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 0/1 Error 0 12d
myapp-deploy-67b6dfcd8-ff9xf 1/1 Running 0 12d
myapp-deploy-67b6dfcd8-msv5x 1/1 Running 0 12d
myapp-deploy-67b6dfcd8-wls6h 1/1 Running 0 12d
myapp-pod 1/1 Running 0 24h
nginx 1/1 Running 0 12d
pod-cm-vol 1/1 Running 0 13s
pod-vol-pvc 1/1 Running 0 26h
redis-58b9f5776-fzslw 1/1 Running 0 9d
tomcat-deploy-56699db4f7-4lhql 1/1 Running 0 6d7h
tomcat-deploy-56699db4f7-ghz7l 1/1 Running 0 6d7h
tomcat-deploy-56699db4f7-kd5v8 1/1 Running 0 6d7h
[root@spark32 configmap]# kubectl exec -it pod-cm-vol -- /bin/sh
/ # cd /etc/nginx/config.d
/etc/nginx/config.d # ls
nginx_port server_name
/etc/nginx/config.d # ls -l
total 0
lrwxrwxrwx 1 root root 17 Aug 28 09:44 nginx_port -> ..data/nginx_port
lrwxrwxrwx 1 root root 18 Aug 28 09:44 server_name -> ..data/server_name
/etc/nginx/config.d # cat nginx_port
/etc/nginx/config.d # cat server_name
myapp.wisedu.com/etc/nginx/config.d #

现在去修改下cm中的key的value:

1
[root@spark32 configmap]# kubectl edit cm nginx-config


在容器中查看这个变量:

1
2
/etc/nginx/config.d # cat nginx_port
8088/etc/nginx/config.d #

需要稍微等下,因为这个修改要同步到apiserver中,apiserver在同步到Pod上。时间取决于apiserver同步速度。这里实测大概10秒才能同步更新。
其实这两个文件是链接文件,不是同步进来的,这两个文件本来就是访问原来的文件。链接改成指向新的configmap版本。是个独特路径,映射n级后能到configmap存储卷上,所以只要configmap源内容改了,就会同步改掉。

【示例5】:演示真正注入Nginx配置文件。

1
2
[root@spark32 configmap]# kubectl delete -f pod-configmap-volume.yaml
pod "pod-cm-vol" deleted

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
[root@spark32 configmap]# vim pod-configmap-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-cm-nginx
namespace: default
labels:
app: myapp
tier: frontend
annotations:
wisedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: nginxconf
configMap:
name: nginx-www


如果这个挂载点指定的目录在原来容器中有内容,会被挂载的内容覆盖掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@spark32 configmap]# kubectl exec pod-cm-nginx -it -- /bin/sh
/ # cd /etc/nginx/conf.d
/etc/nginx/conf.d # ls
www.conf
/etc/nginx/conf.d # cat www.conf
server {
server_name myapp.wisedu.com;
listen 80;
root /data/web/html;
}
/etc/nginx/conf.d # mkdir /data/web/html -p
/etc/nginx/conf.d # vi /data/web/html/index.html
<h1>Nginx Server configured by CM</h1>

接下来配置hosts解析:

1
2
3
4
5
6
[root@spark32 configmap]# kubectl get pods -o wide
...
pod-cm-nginx 1/1 Running 0 4m7s 10.244.1.26 spark17 <none> <none>
...
[root@spark32 configmap]# vim /etc/hosts
10.244.1.26 myapp.wisedu.com

访问:

1
2
[root@spark32 configmap]# curl myapp.wisedu.com
<h1>Nginx Server configured by CM</h1>

现在改下外部配置,改下监听端口:

1
[root@spark32 configmap]# kubectl edit cm nginx-www


还是等了10来秒才生效

访问:

1
2
[root@spark32 configmap]# curl myapp.wisedu.com:8080
<h1>Nginx Server configured by CM</h1>

但是刚才挂载的时候,只要configmap有的键,都挂载进去了。如果以存储卷挂载访问configmap时不希望把所有的key都挂载进来,只希望挂载部分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
[root@spark32 configmap]# kubectl explain pods.spec.volumes.configMap
FIELDS:
defaultMode <integer>
Optional: mode bits to use on created files by default. Must be a value
between 0 and 0777. Defaults to 0644. Directories within the path are not
affected by this setting. This might be in conflict with other options that
affect the file mode, like fsGroup, and the result can be other mode bits
set.
items <[]Object>
If unspecified, each key-value pair in the Data field of the referenced
ConfigMap will be projected into the volume as a file whose name is the key
and content is the value. If specified, the listed keys will be projected
into the specified paths, and unlisted keys will not be present. If a key
is specified which is not present in the ConfigMap, the volume setup will
error unless it is marked optional. Paths must be relative and may not
contain the '..' path or start with '..'.
name <string>
Name of the referent. More info:
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
optional <boolean>
Specify whether the ConfigMap or it's keys must be defined

  • itmes: 把name字段指定的configMap中的哪些字段挂载进来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@spark32 configmap]# kubectl explain pods.spec.volumes.configMap.items
FIELDS:
key <string> -required-
The key to project.
mode <integer>
Optional: mode bits to use on this file, must be a value between 0 and
0777. If not specified, the volume defaultMode will be used. This might be
in conflict with other options that affect the file mode, like fsGroup, and
the result can be other mode bits set.
path <string> -required-
The relative path of the file to map the key to. May not be an absolute
path. May not contain the path element '..'. May not start with the string
'..'.

列出键的时候,不光要列出键的名字,还要指明真正的文件名(path),key已经不是默认作为文件名了,是required。文件名和key名一样也可以,但是你需要指定。文件内容就是key所对应的value。挂载的文件可以同时指定文件权限(mode),path不能使用..,因为..有特殊作用,路径映射方式。

Secret

configMap存数据是明文的,Secret是base64编码的,但是使用Secret会麻烦一些。只有敏感数据才建议使用secret存放。私钥和证书最好是放在secret中,还有连接mysql时的密码。
对于secret而言,它有三种类型:

  • 1.generic: Create a secret from a local file, directory or literal value
    通用的secret,就是里面保存一些密码数据
  • 2.tls: Create a TLS secret
    私钥和证书。
  • 3.docker-registry: Create a secret for use with a Docker registry
    保存docker-registry的认证信息。每一个Node在运行Pod之前,它得把Pod所依赖的镜像拉取到本地,需要到某个registry上拉取。如果是去某个私有registry拉取,里面镜像也是私有的,必须要输入账号密码才能访问,账号密码放哪?也就意味着当前的Node要能够自动地认证,并从registry拉取镜像。否则Pod创建肯定是失败。现在是kubelet会认证到私有仓库,然后拉下来进行。
    1
    2
    3
    4
    5
    6
    7
    8
    [root@spark32 configmap]# kubectl explain pods.spec
    imagePullSecrets <[]Object>
    ImagePullSecrets is an optional list of references to secrets in the same
    namespace to use for pulling any of the images used by this PodSpec. If
    specified, these secrets will be passed to individual puller
    implementations for them to use. For example, in the case of docker, only
    DockerConfig type secrets are honored. More info:
    https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod

创建secret命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@spark32 configmap]# kubectl create secret -h
Create a secret using specified subcommand.
Available Commands:
docker-registry Create a secret for use with a Docker registry
generic Create a secret from a local file, directory or literal value
tls Create a TLS secret
Usage:
kubectl create secret [flags] [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

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
[root@spark32 configmap]# kubectl create secret generic -h
Create a secret based on a file, directory, or specified literal value.
A single secret may package one or more key/value pairs.
When creating a secret based on a file, the key will default to the basename of the file, and the value will default to
the file content. If the basename is an invalid key or you wish to chose your own, you may specify an alternate key.
When creating a secret based on a directory, each file whose basename is a valid key in the directory will be packaged
into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, symlinks, devices, pipes,
etc).
Examples:
# Create a new secret named my-secret with keys for each file in folder bar
kubectl create secret generic my-secret --from-file=path/to/bar
# Create a new secret named my-secret with specified keys instead of names on disk
kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa
--from-file=ssh-publickey=~/.ssh/id_rsa.pub
# Create a new secret named my-secret with key1=supersecret and key2=topsecret
kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
# Create a new secret named my-secret using a combination of a file and a literal
kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-literal=passphrase=topsecret
# Create a new secret named my-secret from an env file
kubectl create secret generic my-secret --from-env-file=path/to/bar.env
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--append-hash=false: Append a hash of the secret to its name.
--dry-run=false: If true, only print the object that would be sent, without sending it.
--from-env-file='': Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker
.env file).
--from-file=[]: Key files can be specified using their file path, in which case a default name will be given to
them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will
iterate each named file in the directory that is a valid secret key.
--from-literal=[]: Specify a key and literal value to insert in secret (i.e. mykey=somevalue)
--generator='secret/v1': The name of the API generator to use.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--type='': The type of secret to create
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]
[options]
Use "kubectl options" for a list of global command-line options (applies to all commands).

【示例1】:

1
2
3
4
5
6
7
[root@spark32 configmap]# kubectl create secret generic mysql-root-passwd --from-literal=password=Mypass@123
secret/mysql-root-passwd created
[root@spark32 configmap]# kubectl get secret
NAME TYPE DATA AGE
default-token-wb7fl kubernetes.io/service-account-token 3 138d
mysql-root-passwd Opaque 1 5s
tomcat-ingress-secret kubernetes.io/tls 2 6d22h

  • Opaque: 模糊类型,就是generic类型
1
2
3
4
5
6
7
8
9
10
11
[root@spark32 configmap]# kubectl describe secret mysql-root-passwd
Name: mysql-root-passwd
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 10 bytes

这么看是看不到secret内容的。

【示例2】:env方式引用secret中的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
[root@spark32 configmap]# vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret-1
namespace: default
labels:
app: myapp
tier: frontend
annotations:
wisedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-passwd
key: password
[root@spark32 configmap]# kubectl apply -f pod-secret.yaml
pod/pod-secret-1 created
[root@spark32 configmap]# kubectl exec pod-secret-1 -it -- printenv | grep MYSQL_ROOT_PASSWORD
MYSQL_ROOT_PASSWORD=Mypass@123

可见,变量的值是解码以后注入进去的。