Kubernetes的基本概念和术语(三)

本文介绍Kubernetes中的基本概念和术语 — Volume、Persistent Volume(PV)、Namespace、Annotation。

1. Volume

Volume 是 Pod 中能够被多个容器访问的共享目录。 Kubernetes 的 Volume 概念、用途和目的与 Docker Volume 比较类似,但两者不能等价,区别如下:

  1. Kubernetes 中的 Volume 定义在 Pod 上,然后被 一个Pod 里的多个容器挂载到具体的文件目录下。
  2. Kubernetes 中的 Volume 与Pod 的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时, Volume 中的数据 也不会丢失。

Volume的使用

要给之前的 Tomcat Pod 增加个名字为 datavol Volume ,并且 Mount 到容器的/mydata-data 目录上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template: 
metadata:
labels:
app: app-demo
tier: frontend
spec:
volumes:
- name: datavol
emptyDir: { }
containers:
- name : tomcat-demo
image : tomcat
volumeMounts:
- mountPath: /mydata-data
name: datavol
imagePullPolicy: IfNotPresent

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 上挂载宿主机上的文件或目录,它通常可以用于以下几方面:

  1. 容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的高速文件系统进行存储。
  2. 需要访问宿主机上 Docker 引擎内部数据结构的容器应用时,可以通过定义 hostPath 为宿主机/var/lib/docker 目录,使容器内部应用可以直接访问 Docker 的文件系统 。

在使用这种类型的 Volume 时, 需要注意以下几点 :

  1. 在不同的 Node 上具有相同配置的 Pod 可能会因为宿主机上的目录和文件不同而导致对 Volume 上目录和文件的访问结果不一致。
  2. 如果使用了资源配额管理,则 Kubernetes 无法将 hostPath 在宿主机上使用的资源纳入管理。

在下面的例子中使用宿主机的/data 录定义了一个hostPath 类型的 Volume:

1
2
3
4
volumes: 
- name : "persistent-storage”
hostPath :
path : "/data"

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
2
3
4
5
6
volumes : 
- name: test-volume
# This GCE PD must already exist .
gcePersistentDisk :
pdName: my-data-disk
fsType: ext4

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
2
3
4
5
6
volumes: 
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore :
volumeID: aws://<availability-zone>/<volume-id>
fsType: ext4

5.NFS

使用 NFS 网络文件系统提供的共享目录存储数据时,我们需要在系统中部署一个 NFS Server。 定义 NFS 类型的 Volume 示例如下:

1
2
3
4
5
6
volumes : 
- name: nfs
nfs:
改为你的 NFS 服务器地址
server: nfs-server.localhost
path: "/"

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 很类似, 但有以下区别:

  1. PV 只能是网络存储,不属于任何 Node ,但可以在每个 Node 上访问。
  2. PV 井不是定义在 Pod 上的 ,而是独立于 Pod 之外定义。
  3. 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
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind : PersistentVolume
metadata:
name: pv0003
spec:
capacity :
storage : 5Gi
accessModes:
- ReadWriteOnce
nfs:
path: /somepath
server: 172.17.0.2

比较重要的是 PV 的 accessModes 属性,目前有以下类型:

ReadWriteOnce 读写权限、并且只 能被单个 Node 挂载

ReadOnlyMany 只读权限、允许被多 Node 挂载

ReadWriteMany 读写权限、允许被多个 Node 挂载

如果某个 Pod 想申请某种类型的 PV ,则首先需要定义一个 PersistentVolurneClaim (PVC ) 对象:

1
2
3
4
5
6
7
8
9
10
kind: PersistentVolumeClaim 
apiVersion : v1
metadata:
name: myclaim
spec:
accessModes :
- ReadWriteOnce
resources :
requests:
storage: 8Gi

然后,在 Pod Volume 定义中引用上述 PVC 即可:

1
2
3
4
volumes: 
- name: mypd
persistentVolumeClaim:
claimName : myclaim

最后,我们说说 PV 的状态, PV 是有状态的对象,它有以下几种状态:

Available :空闲状态。

Bound :己经绑定到某个 PVC 上。

Released :对应的 PVC 己经删除,但资源还没有被集群收回 。

Failed : PV 自动回收失败。

3. Namespace

Namespace (命名空间)是 Kubernetes 系统中的另 个非常重要的概念, Namespace 在很多 情况下用于实现多租户的资源隔离。 Namespace 通过将集群内部的资源对象“分配”到不同的 Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个 集群的资源的同时还能被分别管理。

Kubernetes 集群在启动后,会创建一个名为“default ”的 Namespace ,通过kubectl 可以查看到:

1
2
3
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active

接下来,如果不特别指明 Namespace ,则用户创建的 Pod 、RC 和 Service 都将被系统创建到这个默认的名为 default 的 Namespace 中。Namespace 的定义很简单。如下所示的 yaml 定义了名为 development Namespace:

1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
name: development

一旦创建了 Namespace ,我们在创建资源对象时就可以指定这个资源对象属于哪个 Namespace 。比如在下面的例子中,我们定义了一个名为 busybox 的 Pod ,放入 development 这个Namespace 里:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1 
kind: Pod
metadata:
name: busybox
namespace: development
spec:
containers:
- image : busybox
command:
- sleep
- "3600"
name: busybox

此时,使用 kubectl get 命令查看将无法显示。

1
2
$ kubectl get pods 
NAME READY STATUS RESTARTS AGE

这是因为如果不加参数,则 kubectl get 命令将仅显示属于“default ”命名空间的资源对象。

可以在 kubectl 命令中加入–namespace 参数来查看某个命名空间中的对象:

1
2
3
$ kubectl get pods --namespace=development 
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 1m

当我们给每个租户创建一个 Namespace 来实现多租户的资源隔离时,还能结合 kubernetes 的资源配额管理,限定不同租户能占用的资源,例如 CPU 使用量、内存使用量等。

4. Annotation

Annotation 与Label 类似,也使用 key/value 键值对的形式进行定义。不同的是 Label 具有 严格的命名规则,它定义的是 Kubernetes 对象的元数据( Metadata ),并且用于 Label Selector 。而Annotation 则是用户任意定义的“附加”信息,以便于外部工具进行查找,很多时候, Kubernetes 的模块自身会通过 Annotation 的方式标记资源对象的一些特殊信息。

通常来说,用 Annotation 来记录的信息如下:

  1. build 信息、 release 信息、 Docker 镜像信息等,例如时间戳、 release id 号、 PR 号、镜像hash 值、 docker registry 地址等 。
  2. 日志库、监控库、分析库等资源库的地址信息。
  3. 程序调试工具信息,例如工具名称、版本号等。
  4. 团队的联系信息,例如电话号码、负责人名称、网址等。
坚持原创技术分享,您的支持将鼓励我继续创作!

------本文结束 感谢您的阅读------