在Kubernetes中有一些资源对象可以以存储卷的形式挂载为容器内的目录或文件,目前包括ConfigMap、Secret、Downward API、ServiceAccountToken、Projected Volume。
1. ConfigMap
ConfigMap主要保存应用程序所需的配置文件,并且通过Volume形式挂载到容器内的文件系统中,供容器内的应用程序读取。
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appconfigfiles
data:
key-serverxml: |
<?xml version='1.0' encoding='utf-8'?>
key-loggingproperties: "handlers
......
= 4host-manager.org.apache.juli.FileHandler\r\n\r\n"
---
apiVersion: v1
kind: Pod
metadata:
name: cm-test-app
spec:
containers:
- name: cm-test-app
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml # 引用Volume的名称
mountPath: /configfiles # 挂载到容器内的目录下
volumes:
- name: serverxml # 定义Volume的名称
configMap:
name: cm-appconfigfiles # 使用ConfigMap的“cm-appconfigfiles”
items:
- key: key-serverxml # key=key-serverxml
path: server.xml # 挂载为 server.xml 文件
- key: key-loggingproperties # key=key-loggingproperties
path: logging.properties # 挂载为 logging.properties文件
在Pod的YAML配置中,将ConfigMap设置为一个Volume,然后在容器中通过volumeMounts将ConfigMap类型的Volume挂载到 /configfiles 目录下
Pod创建成功之后,进入容器内查看,可以看到在/configfiles目录下存在server.xml和logging.properties文件:
[root@master1 ~]# kubectl describe configmaps cm-appconfigfiles
Name: cm-appconfigfiles
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
key-loggingproperties:
----
handlers ...... = 4host-manager.org.apache.juli.FileHandler
key-serverxml:
----
<?xml version='1.0' encoding='utf-8'?>
Events: <none>
[root@master1 ~]#
[root@master1 ~]# kubectl exec -it cm-test-app -- bash
root@cm-test-app:/usr/local/tomcat# ls /configfiles
logging.properties server.xml
root@cm-test-app:/usr/local/tomcat# cat /configfiles/server.xml
<?xml version='1.0' encoding='utf-8'?>
root@cm-test-app:/usr/local/tomcat#
root@cm-test-app:/usr/local/tomcat# cat /configfiles/logging.properties
handlers ...... = 4host-manager.org.apache.juli.FileHandler
ConfigMap中配置的内容如果是UTF-8编码的字符,则将被系统认为是文件文本。如果是其他字符,则系统将以二进制数据格式进行保存(设置为binaryData字段)。
2. Secret
与ConfigMap的用法类似,在Pod的YAML配置中可以将Secret设置为一个Volume,然后在容器内通过volumeMouns将Secret类型的Volume挂载到/etc/foo目录下。Secret中的data域各子域的值必须为BASE64编码值。
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMg0K
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
volumes:
- name: foo
secret:
secretName: mysecret
创建资源后查看该secret,并进入Pod那个查看资源:
[root@master1 ~]# kubectl describe secrets mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
username: 9 bytes
password: 9 bytes
[root@master1 ~]#
[root@master1 ~]# kubectl exec -it mypod -- bash
root@mypod:/data# ls /etc/foo/
password username
root@mypod:/data# cat /etc/foo/password
value-2
root@mypod:/data# cat /etc/foo/username
value-2
3. Downward API
名称过Downward API可以将Pod或Container的某些元数据信息(例如Pod名称、Pod IP、Node IP、Label、Annotation、容器资源限制等)以文件的形式挂载到容器内,供容器内的应用使用。
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
annotations:
build: two
builder: john-doe
spec:
containers:
- name: client-container
image: busybox
command: ["sh", "-c"]
args:
- while true; do
if [[ -e /etc/podinfo/labels ]]; then
echo -en '\n\n'; cat /etc/podinfo/labels; fi;
if [[ -e /etc/podinfo/annotations ]]; then
echo -en '\n\n'; cat /etc/podinfo/annotations; fi;
sleep 5;
done;
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
创建Pod后,查看Pod的logs信息信息:
[root@master1 ~]# kubectl logs -f kubernetes-downwardapi-volume-example
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"
build="two"
builder="john-doe"
kubernetes.io/config.seen="2022-07-08T15:04:31.388541172+08:00"
kubernetes.io/config.source="api"
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"
build="two"
builder="john-doe"
cni.projectcalico.org/containerID="d13c780eb681436e4f8d5c2e24db63f56553cfa2ca86d981a1ac3af13be1a4a9"
cni.projectcalico.org/podIP="10.0.104.30/32"
cni.projectcalico.org/podIPs="10.0.104.30/32"
kubernetes.io/config.seen="2022-07-08T15:04:31.388541172+08:00"
kubernetes.io/config.source="api"
4. Projected Volume
Projected Volume 是一种特殊的存储卷类型,用于将一个或多个上述资源对象(ConfigMap、Secret、DownwardAPI)一次性挂载到容器内的同一个目录下。
常见的应用场景如下:
- 通过Pod 的标签生成不同的配置文件,需要使用配置文件,以及用户名和密码,这时需要使用3种资源:ConfigMap、Secret、DownwardAPI。
- 自动化运维应用中使用配置文件和账号信息时,需要使用ConfigMap、Secret。
- 在配置文件内使用Pod名称(metadata.name)记录日志时,需要使用ConfigMap、DownwardAPI。
- 使用某个Secret对Pod所在命名空间(metadata.namespace)进行加密时,需要使用Secret、DownwardAPI。
Projected Volume在Pod的Volume定义中类型为projected,通过sources字段设置一个或多个ConfigMap、Secret、DownwardAPI、ServiceAccountToken资源。各种类型的资源的配置内容与被单独设置为Volume时基本一样,但是有两个不同点。
- 对于Secret类型的Volume,字段名“secretName”在projected.sources.secret中被改为“name”。
- Volume的挂载模式“defaultMode”仅可以设置在projected级别,对于各子项,仍然可以设置各自的挂载模式,使用的字段名为“mode”。
一个使用ProjectedVolume挂载ConfigMap、Secret、Downward API共3种资源的示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
config: |
timezone=Shanghai
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMg0K
---
apiVersion: v1
kind: Pod
metadata:
name: volume-test
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
spec:
containers:
- name: container-test
image: busybox
command: ["sh", "-c"]
args:
- while true; do
sleep 3600;
done;
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- key: password
path: my-group/my-password
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config
创建资源后进入Pod,查看挂载的数据:
[root@master1 ~]# kubectl exec -it volume-test -- sh
/ # cd /projected-volume/
/projected-volume # ls
cpu_limit labels my-group
/projected-volume # cat cpu_limit
2/projected-volume #
/projected-volume # cat labels
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"/projected-volume #
/projected-volume # cat my-group/my-username
value-2
/projected-volume # cat my-group/my-password
value-2
/projected-volume # cat my-group/my-config
timezone=Shanghai
/projected-volume #
下面是一个使用Projected Volume挂载两个Secret资源,其中一个设置了非默认挂载模式(mode)的示例:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: dmFsdWUtMg0K
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret2
type: Opaque
data:
password: dmFsdWUtMg0K
---
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
command: ["sh", "-c"]
args:
- while true; do
sleep 3600;
done;
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
创建资源后,查看Pod里挂载的权限信息:
[root@master1 ~]# kubectl exec -it volume-test -- sh
/ # ls /projected-volume
my-group
/ # cd /projected-volume
/projected-volume # ls -l my-group/
total 8
-rwxrwxrwx 1 root root 9 Jul 8 08:14 my-password
-rw-r--r-- 1 root root 9 Jul 8 08:14 my-username
/projected-volume #
经kubectl explain pod.spec.volumes.projected.sources.secret.items.mode
查询对mode
的解释如下:
[root@master1 ~]# kubectl explain pod.spec.volumes.projected.sources.secret.items.mode
KIND: Pod
VERSION: v1
FIELD: mode <integer>
DESCRIPTION:
Optional: mode bits used to set permissions on this file. Must be an octal
value between 0000 and 0777 or a decimal value between 0 and 511. YAML
accepts both octal and decimal values, JSON requires decimal values for
mode bits. 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.
大概意思就是:用于设置此文件权限的模式位。必须为0000 ~ 0777之间的八进制值或0 ~ 511之间的十进制值。YAML接受八进制和十进制值,JSON需要十进制值作为模式位。如果未指定,则将使用卷defaultMode。这可能与其他影响文件模式的选项(如fsGroup)冲突,结果可能是设置了其他模式位。
511的十进制转换为八进制是777,正如看到my-password的权限就是777。
参考:《kubernetes权威指南(第五版)》