前言:
在Kubernetes系统中,将对容器应用所需的存储资源抽象为存储卷(Volume)。Volume是与Pod绑定的(独立于容器)与Pod具有相同生命周期的资源对象。
可以将Volume的内容理解为目录或文件,容器如需使用某个Volume,则仅需设置volumeMounts将一个或多个Volume挂载为容器中的目录或文件,即可访问Volume中的数据。
在Kubernetes中有一些资源对象可以以存储卷的形式挂载为容器内的目录或文件,目前包括ConfigMap、Secret、Downward API、 ServiceAccountToken、Projected Volume。
ConfigMap可以用作命令行参数、环境变量、作为文件或目录直接挂载。
ConfigMap主要保存应用程序所需的配置文件,然后在容器中通过volumeMounts将ConfigMap类型的 Volume挂载到/configfiles目录下。
1)configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: appconfig
data:
key-serverxml: |
......
key-loggingproperities: "handles
......
\r\n\r\n"
2)pod挂载
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: nginx
command: ["/bin/sh","-c","sleep 36000"]
ports:
-containerPort:8088
volumeMounts:
- name: config-volume
mountPath: /configfiles
volumes:
- name: config-volume
configMap:
name: appconfig
items:
- key: key-serverxml
path: server.xml
- key: key-loggingproperities
path: logging.properties
restartPolicy: Never
在Pod成功创建之后,进入容器内查看,可以看到在/configfiles目录下存在server.xml和logging.properties文件。
可以使用 kubectl create configmap
从文件、目录或者 key-value 字符串创建等创建 ConfigMap。也可以通过 kubectl create -f
从描述文件创建。
1)key-value 字符串创建
kubectl create configmap special-config --from-literal=special.how=very
创建了一个名为special-config,拥有一条key为special.how,value为very的键值对数据。
2)从env文件创建
echo -e "a=b\nc=d" | tee config.env
kubectl create configmap special-config --from-env-file=config.env
从一个env文件读取键值对,然后存入一个名为special-config的ConfigMap中。
3)从目录创建
kubectl create configmap special-config --from-file=config/
4)从yaml文件
apiVersion: v1
kind: ConfigMap
metadata:
name: appconfig
data:
key-serverxml: |
......
key-loggingproperities: "handles
......
\r\n\r\n"
k8s secrets用于存储和管理一些敏感数据,比如密码,token,密钥等敏感信息。它把 Pod 想要访问的加密数据存放到 Etcd 中。然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息了。
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type:Opaque
data:
username:dmfsdYUUr
password:dmfsdYUUr
注:data域各子域的值必须为BASE64编码值。
可以通过下面三种方式使用它:
1)创建Pod时,通过为Pod指定Service Account来自动使用该 Secret。
2)通过挂载该Secret到Pod的Volume来使用它。
3) 在 Docker 镜 像 下 载 时 使 用 , 通 过 指 定 Pod 的 spc.ImagePullSecrets来使用它。
1)方式一主要用在API Server鉴权方面
Service Account也是一种账号,但它并不是给Kubernetes集群的用 户(系统管理员、运维人员、租户用户等)用的,而是给运行在Pod 里的进程用的,它为Pod里的进程提供了必要的身份证明。一个Service Account可以包括多个Secret对象:
2)方式二——将一个Secret通过挂载的方 式添加到Pod的Volume中
3)方式三
a. 运行login命令,登录私有Registry: docker login localhost:5000
输入用户名和密码,如果是第1次登录系统,则会创建新用户,相 关信息被会写入~/.dockercfg文件中。
b. 用BASE64编码dockercfg的内容: cat ~/.dockercfg | base64
c. 将上一步命令的输出结果作为Secret的data.dockercfg域的内 容,由此来创建一个Secret
d. 在创建Pod时引用该Secret
通过Downward API可以将Pod或Container的某些元数据信息(例 如Pod名称、Pod IP、Node IP、Label、Annotation、容器资源限制等) 以文件的形式挂载到容器内,供容器内的应用使用。
什么是Downward API?
Kubernetes在成功创建 Pod之后,会为Pod和容器设置一些额外的信息,例如Pod级别的Pod名 称、Pod IP、Node IP、Label、Annotation、容器级别的资源限制等。
为了在容器内获取Pod级别的这些信息,Kubernetes提供了Downward API机制来将Pod和容器的某些元数据信息注入容器环境内,供容器应用方便地使用。
目前常用的两种元数据注入方式:
(1)环境变量:将Pod或Container信息设置为容器内的环境变量。
1)将Pod信息设置为容器内的环境变量
2)将Container信息设置为容器内的环境变量
(2)Volume挂载:将Pod或Container信息以文件的形式挂载到容器内部。
1)pod信息挂载
# dapi-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example
labels:
zone: us-est-coast
cluster: test-cluster
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'; /etc/podinfo/labels; fi;
if [[ -e /etc/podinfo/annotations ]]; then
echo -en '\n\n'; /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的volumes字段中使用Downward API的方法:通过fieldRef字 段设置需要引用Pod的元数据信息,将其设置到volume的items中。系统将在容器内 的/etc/podinfo目录下生成labelsannotations两个文件。
通过fieldRef设置的元数据如下:
◎ metadata.name:Pod名称。
◎ metadata.namespace:Pod所在的命名空间名称。
◎ metadata.uid:Pod的UID,从Kubernetes 1.8.0-alpha.2版本开始 支持。
◎ metadata.labels:Pod的Label列表,每个Label都以key为文件 名,value为文件内容,每个Label各占一行。
◎ metadata.namannotations : Pod 的 Annotation 列表 , 每个 Annotation都以key为文件名,value为文件内容,每个Annotation各占一行。
2)container信息挂载
# dapi-volume-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example-2
spec:
containers:
- name: client-container
image: busybox
command: ["sh","-c"]
args:
- while true; do
echo -en '\n';
if [[ -e /etc/podinfo/cpu_limit ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
if [[ -e /etc/podinfo/cpu_request ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
if [[ -e /etc/podinfo/mem_limit ]]; then
echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
if [[ -e /etc/podinfo/mem_request ]]; then
echo -en '\n'; cat /etc/podinfo/mem_request; fi;
sleep 5;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
volumes:
- name: podinfo
downwardAPI:
items:
- path: "cpu_limit"
resourceFieldRef:
containerName: client-container
resource: limits.cpu
divisor: 1m
- path: "cpu_request"
resourceFieldRef:
containerName: client-container
resource: requests.cpu
divisor: 1m
- path: "mem_limit"
resourceFieldRef:
containerName: client-container
resource: limits.memory
divisor: 1Mi
- path: "mem_request"
resourceFieldRef:
containerName: client-container
resource: requests.memory
divisor: 1Mi
Projected Volume是一种特殊的存储卷类型,用于将一个或多个上 述资源对象(ConfigMap、Secret、Downward API)一次性挂载到容器 内的同一个目录下。
Kubernetes管理的Node本地存储卷(Volume)的类型如下:
◎ EmptyDir:与Pod同生命周期的Node临时存储。
◎ HostPath:Node目录。
◎ Local:基于持久卷(PV)管理的Node目录,详见下节的说 明。
在Pod被调度到Node时进行创建,在初始状态下目录中是空的,所以命名为“空目录”(Empty Directory),它与Pod具有相同的生命周期。
在 默 认 情 况 下 , kubelet 会 在 Node 的 工 作 目 录 下 为 Pod 创 建 EmptyDir目录,这个目录的存储介质可能是本地磁盘、SSD磁盘或者 网络存储设备,取决于环境的配置。
EmptyDir 可 以 通 过 medium 字 段 设 置 存 储 介 质 为 “Memory”,表示使用基于内存的文件系统(tmpfs、RAM-backed filesystem)。虽然tmpfs的读写速度非常快,但与磁盘中的目录不同, 在主机重启之后,tmpfs的内容就会被清空。
apiVersion: v1
kind: Pod
metadata:
name: volume-emptydir
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
volumeMounts:
- name: logs-volume
mountPath: /var/log/nginx
- name: busybox
image: busybox:1.30
command: ["/bin/sh","-c","tail -f /logs/access.log"]
volumeMounts:
- name: logs-volume
mountPath: /logs
volumes:
- name: logs-volume
emptyDir: {}
HostPath类型的存储卷用于将Node文件系统的目录或文件挂载到容器内部使用。对于大多数容器应用来说,都不需要使用宿主机的文件系统。
HostPath存储卷的主要配置参数为path,设置为宿主机的目录或文 件路径;还可以设置一个可选的参数type,表示宿主机路径的类型。
在Kubernetes中,对存储资源的管理方式与计算资源(CPU/内存)截然不同。Kubernetes从1.0版本开始就引入了Persistent Volume(PV)和Persistent Volume Claim(PVC)两个资源对象来实现存储管理子系统。
PV(持久卷)是对存储资源的抽象,将存储定义为一种容器应用 可以使用的资源。PV由管理员创建和配置,通过插件式的机制进行管理,供应用访问和使用。
PVC则是用户对存储资源的一个申请。就像Pod消耗Node的资源 一样,PVC消耗PV资源。PVC可以申请存储空间的大小(size)和访 问模式(例如ReadWriteOnce、ReadOnlyMany或ReadWriteMany)。
使用PVC满足不了现在的资源需求时,Kubernetes从1.4 版本开始引入了一个新的资源对象StorageClass,用于标记存储资源的特性和性能等;Kubernetes从1.9版本开始引入容器存储接口Container Storage Interface(CSI)机制,目标是在Kubernetes和外部存储系统之间建立一套标准的存储管理接口。
PV 和 PVC 之间的交互过程有着自己的生命周期,这个生命周期分为5个阶段:
根据上述的5个阶段,存储卷的存在下面的 4 种状态:
资源供应的两种模式:
资源回收:
用户在使用存储资源完毕后,可以删除PVC。与该PVC绑定的PV 将被标记为“已释放”,但还不能立刻与其他PVC绑定。通过之前PVC 写入的数据可能还被留在存储设备上,只有在清除这些数据之后,该 PV才能再次使用。可以设置 3种回收策略:
rm-rf /thevolume/*
(NFS、HostPath 存储支持);资源扩容:
如需扩容PVC,则首先需要在PVC对应的StorageClass定义中设置allowVolumeExpansion=true。对 PVC 进 行 扩 容 操 作 时 , 只 需 修 改 PVC 的 定 义 , 将 resources.requests.storage设置为一个更大的值即可。
PV作为对存储资源的定义,主要涉及存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。
声明PV格式如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity: #容量
storage: 5Gi
volumeMode: Filesystem #存储卷模式
accessModes: #访问模式
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle #持久化卷回收策略
storageClassName: slow #存储类
mountOptions: #挂接选项
- hard
- nfsvers=4.1
nfs:
path:/tmp
server:172.17.0.2
1)PV支持设置字段介绍:
2)挂载选项:
Kubernetes不会对挂载选项进行验证,如果设置了错误的挂载选项,则挂载将会失败。目前,以下PV类型支持设置挂载参数:
AWSElasticBlockStore、AzureDisk、AzureFile、CephFS、Cinder (OpenStack block storage)、GCEPersistentDisk、Glusterfs、NFS、Quobyte Volumes、RBD (Ceph Block Device)、StorageOS、VsphereVolume、iSCSI
3)亲和性Node Affinity:
PV可以设置节点亲和性来限制只能通过某些Node访问Volume, 可以在PV定义的nodeAffinity字段中进行设置。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- my-node
4)创建一个loacl PV的案例
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/vol1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node01
PVC作为用户对存储资源的需求申请,主要涉及存储空间请求、 访问模式、PV选择条件和存储类别等信息的设置。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes: #访问模式
- ReadWriteOnce
volumeMode: Filesystem #存储卷模式
resources: #资源
requests:
storage: 8Gi
storageClassName: slow #存储类
selector: #选择器
matchLabels:
release: "stable"
matchExpressions: #匹配表达式
- {key: environment, operator: In, values: [dev]}
PVC设置的存储卷模式应该与PV 存储卷模式相同,以实现绑定;如果不同,则可能出现不同的绑定结 果:
系统在Pod所在的命名空 间中找到其配置的PVC,然后找到PVC绑定的后端PV,将PV存储挂载 到Pod所在Node的目录下,最后将Node的目录挂载到Pod的容器内。
需要在YAML配置中设置PVC类型的 Volume,然后在容器中通过volumeMounts.mountPath设置容器内的挂载目录。
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd # 挂载的存储卷的名称
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim # PVC名称
当PVC越来越多时,手动创建PV效率显得太慢。所以推出自动创建PV的StorageClass。
StorageClass对象会定义下面两部分内容:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Retain
allowVolumeExpansions:true
mountOptions:
- debug
volumeBindingMode:Immeidate
K8S自身资源对象映射为容器内的目录或文件:
◎ ConfigMap:应用配置。
◎ Secret:加密数据。
◎ DownwardAPI:Pod或Container的元数据信息。
◎ ServiceAccountToken:Service Account中的token数据。
◎ Projected Volume:一种特殊的存储卷类型,用于将一个或多个上述资源对象一次性挂载到容器内的同一个目录下。
本地存储卷:
◎ EmptyDir:临时存储。
◎ HostPath:宿主机目录。
PV持久卷和网络存储卷:
◎ CephFS:一种开源共享存储系统。
◎ Cinder:一种开源共享存储系统。
◎ CSI:容器存储接口(由存储提供商提供驱动程序和存储管理程序)。
◎ FC(Fibre Channel):光纤存储设备。
◎ FlexVolume:一种基于插件式驱动的存储。
◎ Flocker:一种开源共享存储系统。
◎ Glusterfs:一种开源共享存储系统。
◎ iSCSI:iSCSI存储设备。
◎ Local:本地持久化存储。
◎ NFS:网络文件系统。
◎ PersistentVolumeClaim:简称PVC,持久化存储的申请空间。
◎ Portworx Volumes:Portworx提供的存储服务。
◎ Quobyte Volumes:Quobyte提供的存储服务。
◎ RBD(Ceph Block Device):Ceph块存储。
公有云提供的存储卷类型如下:
◎ AWSElasticBlockStore : AWS 公 有 云 提 供 的 Elastic BlockStore。
◎ AzureDisk:Azure公有云提供的Disk。
◎ AzureFile:Azure公有云提供的File。
◎ GCEPersistentDisk:GCE公有云提供的Persistent Disk。
常见存储提供商(Provisioner)提供的StorageClass存储参数示例。
1)AWSElasticBlockStore存储卷
可以配置的参数如下(详细说明请参考AWSElasticBlockStore文 档)。
◎ type:可选项为io1、gp2、sc1、st1,默认值为gp2。
◎ iopsPerGB:仅用于io1类型的Volume,意为每秒每GiB的I/O 操作数量。
◎ fsType:文件系统类型,默认值为ext4。
◎ encrypted:是否加密。
◎ kmsKeyId:加密时使用的Amazon Resource Name。
2)GCEPersistentDisk存储卷
可以配置的参数如下(详细说明请参考GCEPersistentDisk文 档)。
◎ type:可选项为pd-standard、pd-ssd,默认值为pd-standard。
◎ fsType:文件系统类型,默认值为ext4。
◎ replication-type:复制类型,可选项为none、regional-pd,默 认值为none。
3)GlusterFS存储卷
可以配置的参数如下(详细说明请参考GlusterFS和Heketi的文 档)。
◎ resturl:Gluster REST服务(Heketi)的URL地址,用于自动 完成GlusterFSvolume的设置。
◎ restauthenabled:是否对Gluster REST服务启用安全机制。
◎ restuser:访问Gluster REST服务的用户名。
◎ restuserkey:访问Gluster REST服务的密码。
◎ secretNamespace和secretName:保存访问Gluster REST服务密 码的Secret资源对象名。
◎ clusterid:GlusterFS的Cluster ID。
◎ gidMin和gidMax:StorageClass的GID范围,用于动态资源供 应时为PV设置的GID。
◎ volumetype : 设 置 GlusterFS 的 内 部 Volume 类 型 , 例 如 replicate:3(Replicate类型,3份副本);disperse:4:2(Disperse类 型,数据4份,冗余两份);none(Distribute类型)。
4)Local存储卷
◎ AWSElasticBlockStore:AWS公有云提供的ElasticBlockStore。
◎ AzureFile:Azure公有云提供的File。
◎ AzureDisk:Azure公有云提供的Disk。
◎ CephFS:一种开源共享存储系统。
◎ FC(Fibre Channel):光纤存储设备。
◎ FlexVolume:一种插件式的存储机制。
◎ Flocker:一种开源共享存储系统。
◎ GCEPersistentDisk:GCE公有云提供的PersistentDisk。
◎ Glusterfs:一种开源共享存储系统。
◎ HostPath:宿主机目录,仅用于单机测试。
◎ iSCSI:iSCSI存储设备。
◎ Local:本地存储设备,目前可以通过指定块(Block)设备提供Local PV,或通过社区开发的sig-storage-local-static-provisioner插件( https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner )来管理Local PV的生命周期。
◎ NFS:网络文件系统。
◎ Portworx Volumes:Portworx提供的存储服务。
◎ Quobyte Volumes:Quobyte提供的存储服务。
◎ RBD(Ceph Block Device):Ceph块存储。
◎ ScaleIO Volumes:DellEMC的存储设备。
◎ StorageOS:StorageOS提供的存储服务。
◎ VsphereVolume:VMWare提供的存储系统。