Kubernetes存储

本文转载自 https://www.cnblogs.com/DaweiJ/articles/8618317.html

首先我们会学习 Volume,以及 Kubernetes 如何通过 Volume 为集群中的容器提供存储;

然后我们会实践几种常用的 Volume 类型并理解它们各自的应用场景;

最后,我们会讨论 Kubernetes 如何通过 Persistent Volume 和 Persistent Volume Claim 分离集群管理员与集群用户的职责,并实践 Volume 的静态供给。

Volume

本节我们讨论 Kubernetes 的存储模型 Volume,学习如何将各种持久化存储映射到容器。

我们经常会说:容器和 Pod 是短暂的。
其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。

为了持久化保存容器的数据,可以使用 Kubernetes Volume。

Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。

本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。

Kubernetes Volume 也支持多种 backend 类型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

Volume 提供了对各种 backend 的抽象,容器在使用 Volume 读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的 Volume 都只是一个目录。

我们将从最简单的 emptyDir 开始学习 Kubernetes Volume。

emptyDir

emptyDir 是最基础的 Volume 类型。正如其名字所示,一个 emptyDir Volume 是 Host 上的一个空目录。

emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。

也就是说:emptyDir Volume 的生命周期与 Pod 一致。

Pod 中的所有容器都可以共享 Volume,它们可以指定各自的 mount 路径。下面通过例子来实践 emptyDir,配置文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
  - name: producer
    image: 10.193.9.54:5000/library/busybox
    volumeMounts:
    - mountPath: /producer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - echo "hello world" > /producer_dir/hello ; sleep 30000

  - name: consumer
    image: 10.193.9.54:5000/library/busybox
    volumeMounts:
    - mountPath: /consumer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - cat /consumer_dir/hello ; sleep 30000

  volumes:
  - name: shared-volume
    emptyDir: {}
producer-consumer.png

这里我们模拟了一个 producer-consumer 场景。

Pod 有两个容器 producerconsumer,它们共享一个 Volume。

producer 负责往 Volume 中写数据,consumer则是从 Volume 读取数据。

① 文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-volume

producer 容器将 shared-volume mount 到 /producer_dir 目录。

producer 通过 echo 将数据写到文件 hello 里。

consumer 容器将 shared-volume mount 到 /consumer_dir 目录。

consumer 通过 cat 从文件 hello 读数据。

执行命令创建pod并查看pod日志

[root@master clay]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
producer-consumer   2/2     Running   0          8s
[root@master clay]# kubectl logs producer-consumer consumer
hello world

kubectl logs 显示容器 consumer 成功读到了 producer 写入的数据,验证了两个容器共享 emptyDir Volume。

因为 emptyDir 是 Docker Host 文件系统里的目录,其效果相当于执行了 docker run -v /producer_dirdocker run -v /consumer_dir。通过 docker inspect 查看容器的详细配置信息,我们发现两个容器都 mount 了同一个目录:

producer-mount.PNG
consumer-mount.PNG

这里/var/lib/kubelet/pods/59a1fa91-8054-11e9-8f26-000c29114255/volumes/kubernetes.io~empty-dir/shared-volume 就是 emptyDir 在 Host 上的真正路径。

emptyDir 是 Host 上创建的临时目录,其优点是能够方便地为 Pod 中的容器提供共享存储,不需要额外的配置。

但它不具备持久性,如果 Pod 不存在了,emptyDir 也就没有了。

根据这个特性,emptyDir 特别适合 Pod 中的容器需要临时共享存储空间的场景,比如前面的生产者消费者用例。

下一节我们学习 hostPath Volume。

hostPath Volume

hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器。

大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。

不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。

如果 Pod 被销毁了,hostPath 对应的目录也还会被保留,从这点看,hostPath 的持久性比 emptyDir 强。不过一旦 Host 崩溃,hostPath 也就没法访问了。

PersistentVolume & PersistentVolumeClaim

Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足。

拿前面 AWS EBS 的例子来说,要使用 Volume,Pod 必须事先知道如下信息:

  1. 当前 Volume 来自 AWS EBS。
  2. EBS Volume 已经提前创建,并且知道确切的 volume-id。

Pod 通常是由应用的开发人员维护,而 Volume 则通常是由存储系统的管理员维护。开发人员要获得上面的信息:

  1. 要么询问管理员。
  2. 要么自己就是管理员。

这样就带来一个管理上的问题:应用开发人员和系统管理员的职责耦合在一起了。如果系统规模较小或者对于开发环境这样的情况还可以接受。但当集群规模变大,特别是对于生成环境,考虑到效率和安全性,这就成了必须要解决的问题。

Kubernetes 给出的解决方案是 PersistentVolume 和 PersistentVolumeClaim。

PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。

PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。

有了 PersistentVolumeClaim,用户只需要告诉 Kubernetes 需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息。这些 Storage Provider 的底层信息交给管理员来处理,只有管理员才应该关心创建 PersistentVolume 的细节信息。

Kubernetes 支持多种类型的 PersistentVolume,比如 AWS EBS、Ceph、NFS 等,完整列表请参考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

PV

下面创建一个 PV mypv1,配置文件 my-pv1.yml 如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
  labels:
    type: local
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: manual
  hostPath:
    path: /data/pv1
mypv1.PNG

capacity 指定 PV 的容量为 1G。

accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有:
Retain – 需要管理员手工回收。
Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

storageClassName 指定 PV 的 class 为 manual。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。

⑤ 指定 PV 在服务器上对应的目录。

创建 mypv1

create-mypv1.PNG

STATUSAvailable,表示 mypv1 就绪,可以被 PVC 申请。

接下来创建 PVC mypvc1,配置文件 my-pvc1.yml 如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: manual

PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。

创建 mypvc1

create-mypvc1.PNG

kubectl get pvckubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。

接下来就可以在 Pod 中使用存储了,Pod 配置文件 pod1.yml 如下:

apiVersion: v1
kind: Pod
metadata:
  name: mypod1
spec:
  containers:
  - name: mypod1
    image: 10.193.9.54:5000/library/busybox
    args:
    - /bin/sh
    - -c
    - sleep 30000
    volumeMounts:
    - mountPath: "/mydata"
      name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: mypvc1

与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用 mypvc1 申请的 Volume。

创建 mypod1

create-mypod1.PNG

验证 PV 是否可用:


validate-mypv1.PNG

可见,在 Pod 中创建的文件 /mydata/hello 确实已经保存到了 服务器10.193.9.55/data/pv1 中。

如果不再需要使用 PV,可用删除 PVC 回收 PV,下节我们详细讨论。

回收PV

在使用本地存储时,需要删除pod以及对应的pvc,这时候pv状态为failed


delete pod and pvc.PNG

这个时候pv状态为failed,无法提供服务,需要删除重建,但是数据还会保留

delete pv.PNG

重新创建pv, pvc, pod会发现数据依然存在

recreate pv.PNG
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 前言 在K8S运行的服务,从简单到复杂可以分成三类:无状态服务、普通有状态服务和有状态集群服务。下面分别来看K8S...
    梅_梅阅读 1,026评论 0 2
  • 一、Docker中的Volume和Kubernetes中的Volume Docker中的Volume 在Docke...
    奥个特曼阅读 911评论 0 0
  • 目录 存储卷是属于Pod,不属于容器。但是可以在容器中去挂载存储卷来使用。 K8S上可用的存储卷类型: empty...
    CaiGuangyin阅读 2,757评论 2 4
  • D65,2018年5月8日 星期二 晴 中午放学后还是我去接的儿子,见到儿子后的第一句话还是昨天的话题...
    a行者无疆123阅读 252评论 0 1
  • 也许,只有医院才能让人不在胡思乱想。一大早挂号处已熙熙攘攘。走在路上谁也不会觉得身边人需要看医生,而走进医院你会发...
    小胖虫子阅读 126评论 0 0