在k8s上还存在3个特殊的存储卷,ConfigMapSecretDownwardAPI

  • ConfigMap用来向容器注入配置信息。
  • SecretConfigMap一样也是用来向容器注入配置信息,但是其注入信息时进行了base64的编码,用来向容器注入一些敏感信息
  • DownwardAPI用来将Pod所运行的外部的一些元数据信息注入到Pod内部,如当前容器运行的pod的名称,Pod的资源限制等等。

容器的配置信息

docker为容器化应用提供配置信息的方法有4种:

  1. 启动容器时,直接向应用容器传递参数,args: []
  2. 将定义好的配置文件焙进镜像中
  3. 通过环境变量向容器传递配置数据,这种方法有个前提,应用得支持从环境变量加载配置信息。
  4. 制作镜像时使用entrypoint脚本来预处理变量,常见的做法是使用非交互式编辑工具,将环境变量的值替换到应用配置文件中。
  5. 基于存储卷向容器传递配置文件。
  6. 运行中的改变,需要由应用程序重载。

k8s为容器提供配置信息的方法

  1. 使用ConfigMap,以k/v格式保存配置项的名称和配置数据;而后由pod中的容器以环境变量的方式从ConfigMap中加载特定的键值。
  2. 可以让pod直接将CongifMap以存储卷的方式进行附加而后由容器挂载至指定目录下从而获取到完整的配置文件。

k8s向pod中的环境变量赋值方法

通过环境变量的配置容器化应用时,需要在容器配置段中嵌套使用env字段,它的值是一个由环境变量构建的列表。每个环境变量通常由name和value(或valueFrom)字段构成。

1
2
3
4
5
6
7
8
name <string>:环境变量的名称,必选字段;
value <string>:环境变量的值,通过$(VAR_NAME)引用,逃逸格式为“$$(VAR_NAME)”默认值为空;
valueFrom <Object>:环境变量值的引用源,例如当前Pod资源的名称、名称空间、标签等,不能与非空值的value字段同时使用,即环境变量的值要么源于value字段,要么源于valueFrom字段,二者不可同时提供数据。
valueFrom字段可引用的值有多种来源,包括当前Pod资源的属性值,容器相关的系统资源配置、ConfigMap对象中的Key以及Secret对象中的Key,它们分别要使用不同的嵌套字段进行定义。
fieldRef <Object>:当前Pod资源的指定字段,目前支持使用的字段包括metadata.name、metadata.namespace、metadata.labels、metadata.annotations、spec.nodeName、spec.serviceAccountName、status.hostIP和status.podIP等;
configMapKeyRef <Object>:ConfigMap对象中的特定Key;
secretKeyRef <Object>:Secret对象中的特定Key;
resourceFieldRef <Object>:当前容器的特定系统资源的最小值(配额)或最大值(限额),目前支持的引用包括limits.cpu、limits.memory、limits.ephemeral-storage、requests.cpu、requests.memory 和requests.ephemeral-storage。

ConfigMap使用示例

方法1:使用命令式命令创建CM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用命令创建出ConfigMap
root@k8s-master01:~/yaml/chapter06# kubectl create cm demoapp-config --from-literal=host=0.0.0.0 --from-literal=port=8080
configmap/demoapp-config created

# 查看ConfigMap的内容
root@k8s-master01:~/yaml/chapter06# kubectl get cm demoapp-config -o yaml
apiVersion: v1
data:
host: 0.0.0.0
port: "8080"
kind: ConfigMap
metadata:
creationTimestamp: "2021-07-15T13:40:34Z"
name: demoapp-config
namespace: default
resourceVersion: "61981"
uid: 33517e6d-9ea4-46ab-9d16-600a26f4104e

方法2:使用配置文件创建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
43
44
45
46
47
# 当前目录下存在3配置文件
root@k8s-master01:~/yaml/chapter06# cd nginx-conf.d/
root@k8s-master01:~/yaml/chapter06/nginx-conf.d# cat myserver.conf
server {
listen 8080;
server_name www.mylinuxops.com;

include /etc/nginx/conf.d/myserver-*.cfg;

location / {
root /usr/share/nginx/html;
}
}

root@k8s-master01:~/yaml/chapter06/nginx-conf.d# cat myserver-gzip.cfg
gzip on;
gzip_comp_level 5;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;

root@k8s-master01:~/yaml/chapter06/nginx-conf.d# cat myserver-status.cfg
location /nginx-status {
stub_status on;
access_log off;
}

# 将以上三个文件制作成一个configMap,文件名为键文件内容为值,若不使用默认文件名作为键,可以在fromfile中重新指定
root@k8s-master01:~/yaml/chapter06/nginx-conf.d# kubectl create configmap nginx-confs --from-file=./myserver.conf --from-file=status.cfg=./myserver-status.cfg
configmap/nginx-confs created
root@k8s-master01:~/yaml/chapter06/nginx-conf.d# kubectl get cm nginx-confs -o yaml
apiVersion: v1
data:
myserver.conf: "server {\n listen 8080;\n server_name www.mylinuxops.com;\n
\ \n include /etc/nginx/conf.d/myserver-*.cfg;\n\n location / {\n root
/usr/share/nginx/html;\n }\n}\n"
status.cfg: |
location /nginx-status {
stub_status on;
access_log off;
}
kind: ConfigMap
metadata:
creationTimestamp: "2021-07-15T13:56:08Z"
name: nginx-confs
namespace: default
resourceVersion: "64123"
uid: 40e8822e-258f-453c-a00d-a33dc0f1252f

方法3:直接指定目录创建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
41
42
43
44
45
# nginx-conf.d目录下有3个文件
root@k8s-master01:~/yaml/chapter06# ls nginx-conf.d/
myserver.conf myserver-gzip.cfg myserver-status.cfg

# 直接指定目录创建configMap,此方法创建的cm无法改变键名
root@k8s-master01:~/yaml/chapter06# ls nginx-conf.d/
myserver.conf myserver-gzip.cfg myserver-status.cfg
root@k8s-master01:~/yaml/chapter06# kubectl create configmap nginx-config-files --from-file=./nginx-conf.d/
configmap/nginx-config-files created

# 查看configmap
root@k8s-master01:~/yaml/chapter06# kubectl describe cm nginx-config-files
Name: nginx-config-files
Namespace: default
Labels: <none>
Annotations: <none>

Data
====
myserver-gzip.cfg:
----
gzip on;
gzip_comp_level 5;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;

myserver-status.cfg:
----
location /nginx-status {
stub_status on;
access_log off;
}

myserver.conf:
----
server {
listen 8080;
server_name www.mylinuxops.com;

include /etc/nginx/conf.d/myserver-*.cfg;

location / {
root /usr/share/nginx/html;
}
}

引用键值数据完成应用配置

示例1:从configmap中,以键值对方式为POD引入变量

1.编写资源清单文件

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
root@k8s-master01:~/yaml/chapter06# vim configmaps-env-demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: demoapp-config
namespace: default
data:
demoapp.port: "8080"
demoapp.host: 0.0.0.0
---
apiVersion: v1
kind: Pod
metadata:
name: configmaps-env-demo
namespace: default
spec:
containers:
- name: demoapp
image: ikubernetes/demoapp:v1.0
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: demoapp-config
key: demoapp.port
optional: false # 表示次数据项是否为可选,false表示必选
- name: HOST
valueFrom:
configMapKeyRef:
name: demoapp-config
key: demoapp.host
optional: true # 表示此键可有可无。

2.应用资源清单

1
2
3
4
5
6
7
8
root@k8s-master01:~/yaml/chapter06# kubectl apply -f configmaps-env-demo.yaml
configmap/demoapp-config created
pod/configmaps-env-demo created

# pod已经运行起来
root@k8s-master01:~/yaml/chapter06# kubectl get pods configmaps-env-demo
NAME READY STATUS RESTARTS AGE
configmaps-env-demo 1/1 Running 0 37s

3.进入容器查看监听地址和端口

1
2
3
4
root@k8s-master01:~/yaml/chapter06# kubectl exec configmaps-env-demo -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN

示例2:基于存储卷的方式引用

1.之前已经使用配置文件创建了多nginx的configMap

1
2
3
4
5
6
root@k8s-master01:~/yaml/chapter06# kubectl get cm
NAME DATA AGE
demoapp-config 2 12m
kube-root-ca.crt 1 20h
nginx-config-files 3 12h # 挂载此configmap
nginx-confs 2 12h

2.编写资源清单将nginx-config-files作为volume进行挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@k8s-master01:~/yaml/chapter06# vim configmaps-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmaps-volume-demo
namespace: default
spec:
containers:
- name: nginx-server
image: nginx:alpine
volumeMounts:
- name: ngxconfs
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: ngxconfs
configMap:
name: nginx-config-files
optional: false

3.应用资源清单创建出pod

1
2
3
4
5
6
root@k8s-master01:~/yaml/chapter06# kubectl apply -f configmaps-volume-demo.yaml
pod/configmaps-volume-demo created

root@k8s-master01:~/yaml/chapter06# kubectl get pods configmaps-volume-demo
NAME READY STATUS RESTARTS AGE
configmaps-volume-demo 1/1 Running 0 3m17s

4.验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@k8s-master01:~/yaml/chapter06# kubectl exec configmaps-volume-demo -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN # 监听端口为定义的8080

# 验证容器内的文件是否存在
root@k8s-master01:~/yaml/chapter06# kubectl exec configmaps-volume-demo -- ls /etc/nginx/conf.d/
myserver-gzip.cfg
myserver-status.cfg
myserver.conf

# 访问虚拟主机测试
root@k8s-master01:~/yaml/chapter06# curl -H "Host:www.mylinuxops.com " `kubectl get pods configmaps-volume-demo -o go-template={{.status.podIP}}`:8080/nginx-status
Active connections: 1
server accepts handled requests
4 4 4
Reading: 0 Writing: 1 Waiting: 0

示例3:综合使用

1.创建出拥有4个key的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
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
102
103
104
105
# 当前目录下存在2个配置文件
root@k8s-master01:~/yaml/chapter06# ls demoapp-conf.d/
envoy.yaml lds.conf

# 创建configmap
root@k8s-master01:~/yaml/chapter06# kubectl create cm demoapp-confs --from-literal=demoapp.port="8080" --from-literal=demoapp.host=127.0.0.1 --from-file=./demoapp-conf.d/
configmap/demoapp-confs created

# 查看configMap
root@k8s-master01:~/yaml/chapter06# kubectl get cm demoapp-confs -o yaml
apiVersion: v1
data:
demoapp.host: 127.0.0.1
demoapp.port: "8080"
envoy.yaml: |
node:
id: sidecar-proxy
cluster: demoapp-cluster

admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }

dynamic_resources:
lds_config:
path: '/etc/envoy/lds.conf'

static_resources:
clusters:
- name: local_service
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8080
lds.conf: |
{
"version_info": "0",
"resources": [
{
"@type": "type.googleapis.com/envoy.api.v2.Listener",
"name": "listener_0",
"address": {
"socket_address": {
"address": "0.0.0.0",
"port_value": 80
}
},
"filter_chains": [
{
"filters": [
{
"name": "envoy.http_connection_manager",
"config": {
"stat_prefix": "ingress_http",
"codec_type": "AUTO",
"route_config": {
"name": "local_route",
"virtual_hosts": [
{
"name": "local_service",
"domains": [
"*"
],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"cluster": "local_service"
}
}
]
}
]
},
"http_filters": [
{
"name": "envoy.router"
}
]
}
}
]
}
]
}
]
}
kind: ConfigMap
metadata:
creationTimestamp: "2021-07-16T06:15:52Z"
name: demoapp-confs
namespace: default
resourceVersion: "199051"
uid: 4c59230d-ade6-4aee-9946-8deb89bde0d7

2.在pod中引用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
41
42
43
44
45
root@k8s-master01:~/yaml/chapter06# vim configmaps-volume-demo2.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmaps-volume-demo2
namespace: default
spec:
containers:
- name: proxy
image: envoyproxy/envoy-alpine:v1.14.1
command: ['/bin/sh','-c','envoy -c /etc/envoy/..data/envoy.yaml']
volumeMounts:
- name: appconfs
mountPath: /etc/envoy # 此处卷被加载时只会加载到envoy.yaml和lds.conf这两个键
readOnly: true
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: demoapp-confs
key: demoapp.port
optional: false
- name: HOST
valueFrom:
configMapKeyRef:
name: demoapp-confs
key: demoapp.port
optional: false
volumes:
- name: appconfs
configMap:
name: demoapp-confs # 挂载demoapp-confs这个configMap
items:
- key: envoy.yaml # 只将demoapp-confs中的envoy.yaml这个key进行挂载
path: envoy.yaml # 挂载后使用的名字为envoy.yaml.
mode: 0644
- key: lds.conf # 只将demoapp-confs中的lds.conf这个key进行挂载
path: lds.conf # 挂载后使用的名字为lds.conf
mode: 0644
optional: false

# 此configMap表示不关心demoapp-confs中有多少信息,只加载有限的2个配置。

3.应用资源清单

1
2
3
4
5
6
root@k8s-master01:~/yaml/chapter06# kubectl apply -f configmaps-volume-demo2.yaml
pod/configmaps-volume-demo2 created

root@k8s-master01:~/yaml/chapter06# kubectl get pod configmaps-volume-demo2 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
configmaps-volume-demo2 2/2 Running 0 71s 10.244.1.14 k8s-node01 <none> <none>

4.测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 测试访问
root@k8s-master01:~/yaml/chapter06# curl 10.244.1.14
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.1, ServerName: configmaps-volume-demo2, ServerIP: 10.244.1.14!

# 查看2个文件的配置文件是否都生效
root@k8s-master01:~/yaml/chapter06# kubectl exec -it configmaps-volume-demo2 -c demo -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:9901 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
root@k8s-master01:~/yaml/chapter06# kubectl exec -it configmaps-volume-demo2 -c proxy -- netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:9901 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN

示例4:挂载整个存储卷,在容器中挑需要的配置

1.此示例使用的为上面cm中已定义的nginx-config-files

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:~/yaml/chapter06# kubectl get cm nginx-config-files -o yaml
apiVersion: v1
data:
myserver-gzip.cfg: |
gzip on;
gzip_comp_level 5;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/xml text/javascript;
myserver-status.cfg: |
location /nginx-status {
stub_status on;
access_log off;
}
myserver.conf: "server {\n listen 8080;\n server_name www.mylinuxops.com;\n
\ \n include /etc/nginx/conf.d/myserver-*.cfg;\n\n location / {\n root
/usr/share/nginx/html;\n }\n}\n"
kind: ConfigMap
metadata:
creationTimestamp: "2021-07-15T14:01:48Z"
name: nginx-config-files
namespace: default
resourceVersion: "64908"
uid: fec6d779-8b54-4dc3-bddb-87d8872b61f3

2.编写pod资源配置清单

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:~/yaml/chapter06# vim configmaps-volume-demo3.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmaps-volume-demo3
namespace: default
spec:
containers:
- image: nginx:alpine
name: nginx-server
volumeMounts:
- name: ngxconfs
mountPath: /etc/nginx/conf.d/myserver.conf #
subPath: myserver.conf # 表示只加载并获取存储卷中的指定路径文件或目录,此处为挂载卷中的myserver.conf
- name: ngxconfs
mountPath: /etc/nginx/conf.d/myserver-gzip.cfg
subPath: myserver-gzip.cfg # 表示挂载卷中的myserver-gzip.cfg
readOnly: true
volumes:
- name: ngxconfs
configMap:
name: nginx-config-files # volume中引用了nginx-config-files,其中有3个key
# 在Pod中只挂载了其中的两个key

3.应用资源清单

1
2
3
4
5
6
root@k8s-master01:~/yaml/chapter06# kubectl apply -f configmaps-volume-demo3.yaml
pod/configmap-volume-demo3 created

root@k8s-master01:~/yaml/chapter06# kubectl get pods configmaps-volume-demo3 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
configmaps-volume-demo3 1/1 Running 0 46s 10.244.2.16 k8s-node02 <none> <none>

4.进入容器查看

1
2
3
4
root@k8s-master01:~/yaml/chapter06# kubectl exec -it configmaps-volume-demo3 -- /bin/sh
/ # cd /etc/nginx/conf.d
/etc/nginx/conf.d # ls
default.conf myserver-gzip.cfg myserver.conf