本文介绍Kubernetes中的基本概念和术语 — Volume、Persistent Volume(PV)、Namespace、Annotation。
1. Volume
Volume 是 Pod 中能够被多个容器访问的共享目录。 Kubernetes 的 Volume 概念、用途和目的与 Docker Volume 比较类似,但两者不能等价,区别如下:
- Kubernetes 中的 Volume 定义在 Pod 上,然后被 一个Pod 里的多个容器挂载到具体的文件目录下。
- Kubernetes 中的 Volume 与Pod 的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时, Volume 中的数据 也不会丢失。
Volume的使用
要给之前的 Tomcat Pod 增加个名字为 datavol Volume ,并且 Mount 到容器的/mydata-data 目录上:
1 | template: |
Volume的类型
1.emptyDir
一个emptyDir Volume 是在 Pod 分配到 Node 时创建的。从它的名称就可以看出,它的初始内容为空,并且无须指定宿主机上对应的目录文件,因为这是 Kubernetes 自动分配的一个目录,当Pod 从 Node 上移除时, emptyDir 中的数据也会被永久删除。 emptyDir 的一些用途如下:
临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留 。
长时间任务的中间过程 CheckPoint 的临时保存目录 。
一个容器需要从另一个容器中获取数据的目录(多容器共享目录)。
目前,用户无法控制 emptyDir 使用的介质种类。如果 kubelet 的配置是使用硬盘,那么所有emptyDir让都将创建在该硬盘上。 Pod 在将来可以设置 emptyDir 是位于硬盘、固态硬盘上还是基于内存的tmpfs 上,上面的例子便采用了 emptyDir 类的 Volume 。
2.hostPath
hostPath 为在 Pod 上挂载宿主机上的文件或目录,它通常可以用于以下几方面:
- 容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统进行存储。
- 需要访问宿主机上 Docker 引擎内部数据结构的容器应用时,可以通过定义 hostPath 为宿主机/var/lib/docker 目录,使容器内部应用可以直接访问 Docker 的文件系统 。
在使用这种类型的 Volume 时, 需要注意以下几点 :
- 在不同的 Node 上具有相同配置的 Pod 可能会因为宿主机上的目录和文件不同而导致对 Volume 上目录和文件的访问结果不一致。
- 如果使用了资源配额管理,则 Kubernetes 无法将 hostPath 在宿主机上使用的资源纳入管理。
在下面的例子中使用宿主机的/data 录定义了一个hostPath 类型的 Volume:
1 | volumes: |
3.gcePersistentDisk
使用这种类型的 Volume 表示使用谷歌公有云提供的永久磁盘( Persistent Disk, PD )存放 Volume 的数据,它与emptyDir 不同, PD 上的内容会被永久保存, 当Pod 被删除时, PD 只是被卸载(Unmount ),但不会被删除。需要注意的是,你需要先创建一个永久磁盘(PD),才能 使用 gcePersistentDisk。
使用 gcePersistentDisk 有以下一些限制条件:
Node (运行 kubelet 节点〉需要是 GCE 虚拟机 。
这些虚拟机需要与 PD 存在于相同的 GCE 项目和 Zone 中。
通过 gcloud 命令即可创建一个PD:
1 | gcloud compute disks create --size=5OOGB -- zone=us-centrall-a my-data-disk |
定义 gcePersistentDisk 类型的 Volume 的示例如下:
1 | volumes : |
4.awsElasticBlockStore
与GCE 类似该类型的 Volume 使用亚马逊公有云提供的 EBS Volume 存储数据, 需要先创建一个 EBS Volume 才能使用 awsElasticBlockStore。
使用 awsElasticBlockStore 一些限制条件如下:
Node (运行 kubelet 节点)需要是 AWS EC2 实例。
这些 AWS EC2 实例需要与 EBS volume 存在于相同的 region 和 availability-zone 中。
EBS 只支持单个 EC2 实例 mount 一个 volume。
通过 aws ec2 create-volume 命令可以创建一个 EBS volume
1 | aws ec2 create-volume --avalability-zone eu-west-la --size 10 --volume-type gp2 |
定义 awsElasticBlockStore 类型的 Volume的示例如下:
1 | volumes: |
5.NFS
使用 NFS 网络文件系统提供的共享目录存储数据时,我们需要在系统中部署一个 NFS Server。 定义 NFS 类型的 Volume 示例如下:
1 | volumes : |
6.其他类型
iscsi :使用 iSCSI 存储设备上的目录挂载到 Pod 中。
flocker :使用 Flocker 来管理存储卷。
glusterfs :使用开源 GlusterFS 网络文件系统的目录挂载到 Pod 中
rbd :使用 Ceph 块设备共享存储( Rados Block Device )挂载到 Pod 中。
gitRepo :通过挂载一个空目录,并从 GIT库clone一个git repository 以供 Pod 使用 。
secret:一个secret volume 用于为 Pod 提供加密的信息,你可以将定义在 Kubernetes 中的secret 直接挂载为文件让 Pod 访问。 secret volume 是通过tmfs(内存文件系统)实现的,所以这种类型的 volume 总是不会持久化的。
2. Persistent Volume
PV 可以理解成 Kubernetes 集群中的某个网络存储中对应的一块存储,它与 Volume 很类似, 但有以下区别:
- PV 只能是网络存储,不属于任何 Node ,但可以在每个 Node 上访问。
- PV 井不是定义在 Pod 上的 ,而是独立于 Pod 之外定义。
- PV 目前 支持 类型包括 gcePersistentDisk 、AWSElasticBlockStore 、AzureFile 、AzureDisk 、FC ( Fibre Channel)、 Flocker、 NFS 、iSCSI 、RBD (Rados Block Device )、 CephFS 、Cinder、 GlusterFS、 Vsphere Volume 、Quobyte Volumes 、VMware Photon 、Portwonc Volumes、 ScaleIO Volumes 和 HostPath (仅供单机测试)。
下面给出了 NFS 类型 PV 的一个 yaml定义文件,声明了需要 5Gi 的存储空间:
1 | apiVersion: v1 |
比较重要的是 PV 的 accessModes 属性,目前有以下类型:
ReadWriteOnce 读写权限、并且只 能被单个 Node 挂载
ReadOnlyMany 只读权限、允许被多 Node 挂载
ReadWriteMany 读写权限、允许被多个 Node 挂载
如果某个 Pod 想申请某种类型的 PV ,则首先需要定义一个 PersistentVolurneClaim (PVC ) 对象:
1 | kind: PersistentVolumeClaim |
然后,在 Pod Volume 定义中引用上述 PVC 即可:
1 | volumes: |
最后,我们说说 PV 的状态, PV 是有状态的对象,它有以下几种状态:
Available :空闲状态。
Bound :己经绑定到某个 PVC 上。
Released :对应的 PVC 己经删除,但资源还没有被集群收回 。
Failed : PV 自动回收失败。
3. Namespace
Namespace (命名空间)是 Kubernetes 系统中的另 个非常重要的概念, Namespace 在很多 情况下用于实现多租户的资源隔离。 Namespace 通过将集群内部的资源对象“分配”到不同的 Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个 集群的资源的同时还能被分别管理。
Kubernetes 集群在启动后,会创建一个名为“default ”的 Namespace ,通过kubectl 可以查看到:
1 | kubectl get namespaces |
接下来,如果不特别指明 Namespace ,则用户创建的 Pod 、RC 和 Service 都将被系统创建到这个默认的名为 default 的 Namespace 中。Namespace 的定义很简单。如下所示的 yaml 定义了名为 development Namespace:
1 | apiVersion: v1 |
一旦创建了 Namespace ,我们在创建资源对象时就可以指定这个资源对象属于哪个 Namespace 。比如在下面的例子中,我们定义了一个名为 busybox 的 Pod ,放入 development 这个Namespace 里:
1 | apiVersion: v1 |
此时,使用 kubectl get 命令查看将无法显示。
1 | kubectl get pods |
这是因为如果不加参数,则 kubectl get 命令将仅显示属于“default ”命名空间的资源对象。
可以在 kubectl 命令中加入–namespace 参数来查看某个命名空间中的对象:
1 | kubectl get pods --namespace=development |
当我们给每个租户创建一个 Namespace 来实现多租户的资源隔离时,还能结合 kubernetes 的资源配额管理,限定不同租户能占用的资源,例如 CPU 使用量、内存使用量等。
4. Annotation
Annotation 与Label 类似,也使用 key/value 键值对的形式进行定义。不同的是 Label 具有 严格的命名规则,它定义的是 Kubernetes 对象的元数据( Metadata ),并且用于 Label Selector 。而Annotation 则是用户任意定义的“附加”信息,以便于外部工具进行查找,很多时候, Kubernetes 的模块自身会通过 Annotation 的方式标记资源对象的一些特殊信息。
通常来说,用 Annotation 来记录的信息如下:
- build 信息、 release 信息、 Docker 镜像信息等,例如时间戳、 release id 号、 PR 号、镜像hash 值、 docker registry 地址等 。
- 日志库、监控库、分析库等资源库的地址信息。
- 程序调试工具信息,例如工具名称、版本号等。
- 团队的联系信息,例如电话号码、负责人名称、网址等。