k8s数据管理(八)

volume

我们经常会说:容器和 Pod 是短暂的。
其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。文章源自靠谱运维-https://www.ixdba.net/archives/1422

为了持久化保存容器的数据,可以使用 Kubernetes Volume。文章源自靠谱运维-https://www.ixdba.net/archives/1422

Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。文章源自靠谱运维-https://www.ixdba.net/archives/1422

本质上,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文章源自靠谱运维-https://www.ixdba.net/archives/1422

Volume 提供了对各种 backend 的抽象,容器在使用 Volume 读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的 Volume 都只是一个目录。文章源自靠谱运维-https://www.ixdba.net/archives/1422

emptyDir

emptyDir 是最基础的 Volume 类型。一个 emptyDir Volume 是 Host 上的一个空目录。文章源自靠谱运维-https://www.ixdba.net/archives/1422

emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。文章源自靠谱运维-https://www.ixdba.net/archives/1422

也就是说:emptyDir Volume 的生命周期与 Pod 一致。文章源自靠谱运维-https://www.ixdba.net/archives/1422

Pod 中的所有容器都可以共享 Volume,它们可以指定各自的 mount 路径。文章源自靠谱运维-https://www.ixdba.net/archives/1422

下面通过例子来实践 emptyDir文章源自靠谱运维-https://www.ixdba.net/archives/1422

第一步:配置文件如下:文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

这里我们模拟了一个 producer-consumer 场景。Pod 有两个容器 producer和 consumer,它们共享一个 Volume。producer 负责往 Volume中写数据,consumer 则是从 Volume 读取数据。文章源自靠谱运维-https://www.ixdba.net/archives/1422

① 文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-volume。文章源自靠谱运维-https://www.ixdba.net/archives/1422

② producer 容器将 shared-volume mount 到 /producer_dir 目录。文章源自靠谱运维-https://www.ixdba.net/archives/1422

③ producer 通过 echo 将数据写到文件 hello 里。文章源自靠谱运维-https://www.ixdba.net/archives/1422

④ consumer 容器将 shared-volume mount 到 /consumer_dir 目录。文章源自靠谱运维-https://www.ixdba.net/archives/1422

⑤ consumer 通过 cat 从文件 hello 读数据。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第二步:执行如下命令创建 Pod:文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
producer-consumer   2/2     Running   0          2m1s
[root@ken ~]# kubectl logs producer-consumer consumer
hello world

注意:一个pod里面运行多个容器的时候,查看容器日志,需要指定pod名称及容器名文章源自靠谱运维-https://www.ixdba.net/archives/1422

kubectl logs 显示容器 consumer 成功读到了 producer 写入的数据,验证了两个容器共享 emptyDir Volume。文章源自靠谱运维-https://www.ixdba.net/archives/1422

因为 emptyDir 是 Docker Host 文件系统里的目录,其效果相当于执行了 docker run -v /producer_dir 和 docker run -v /consumer_dir。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第三步:通过 docker inspect 查看容器的详细配置信息,我们发现两个容器都 mount 了同一个目录:文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

这里 /var/lib/kubelet/pods/4dcc0366-245f-11e9-9172-000c292d5bb8/volumes/kubernetes.io~empty-dir/shared-volume 就是 emptyDir在 Host 上的真正路径。文章源自靠谱运维-https://www.ixdba.net/archives/1422

emptyDir 是 Host 上创建的临时目录,其优点是能够方便地为 Pod 中的容器提供共享存储,不需要额外的配置。但它不具备持久性,如果 Pod 不存在了,emptyDir 也就没有了。根据这个特性,emptyDir 特别适合 Pod 中的容器需要临时共享存储空间的场景,比如前面的生产者消费者用例。文章源自靠谱运维-https://www.ixdba.net/archives/1422

hostpath

hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器。大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。文章源自靠谱运维-https://www.ixdba.net/archives/1422

比如 kube-apiserver 和 kube-controller-manager 就是这样的应用,通过文章源自靠谱运维-https://www.ixdba.net/archives/1422

kubectl edit –namespace=kube-system pod kube-apiserver-k8s-master文章源自靠谱运维-https://www.ixdba.net/archives/1422

查看 kube-apiserver Pod 的配置,下面是 Volume 的相关部分:文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

这里定义了三个 hostPath volume k8s、certs 和 pki,分别对应 Host 目录 /etc/kubernetes、/etc/ssl/certs 和 /etc/pki。文章源自靠谱运维-https://www.ixdba.net/archives/1422

如果 Pod 被销毁了,hostPath 对应的目录也还会被保留,从这点看,hostPath 的持久性比 emptyDir 强。不过一旦 Host 崩溃,hostPath 也就没法访问了。文章源自靠谱运维-https://www.ixdba.net/archives/1422

示例:把节点上的tmp目录挂载到容器中文章源自靠谱运维-https://www.ixdba.net/archives/1422

第一步:编写yml文件文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# cat hostpath.yml 
apiVersion: v1
kind: Pod
metadata:
   name: myhostpath
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: hostpath
      mountPath: /usr/share/nginx/html
  volumes:
  - name: hostpath
    hostPath:
      path: /tmp
      type: Directory

启动nginx,把主机的/tmp目录挂载到nginx容器的网站根目录文章源自靠谱运维-https://www.ixdba.net/archives/1422

这里共享的是tmp目录,如果是挂载其他的目录要确保节点有这个目录文章源自靠谱运维-https://www.ixdba.net/archives/1422

第二步:启动文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# kubectl apply -f hostpath.yml

第三步:在tmp目录下编写测试文件文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# echo "hostpath" > /tmp/index.html

第四步:查看podIP并尝试访问文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# kubectl get pods -o wide
NAME                         READY   STATUS             RESTARTS   AGE     IP            NODE        NOMINATED NODE   READIN
myhostpath                   1/1     Running            0          8m8s    10.244.1.59   ken-node2   <none>           <none>

第五步:访问文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# curl 10.244.1.59
hostpath

对接NFS

第一步:在控制节点部署NFS文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# yum install nfs-utils rpcbind -y
[root@ken-node1 ~]# rm -rf /ken
[root@ken-node1 ~]# mkdir /ken
[root@ken-node1 ~]# chown -R nfsnobody: /ken
[root@ken-node1 ~]# echo "/ken *(rw)" > /etc/exports
[root@ken-node1 ~]# systemctl restart nfs rpcbind

第二步:编写yml文件文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# cat nfs.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nfs
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: nfsback
      mountPath: /usr/share/nginx/html
  volumes:
    - name: nfsback
      nfs:
        path: /ken
        server: 192.168.163.132

第三步:节点需要下载nfs-utils去支持nfs文件类型,否则会报错文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node2 ~]# yum install nfs-utils -y

第四步:执行yml文件文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# kubectl apply -f nfs.yml

第五步:查看pod的IP文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# kubectl get pods -o wide
NAME                         READY   STATUS             RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
nfs                          1/1     Running            0          3m3s    10.244.2.61   ken-node3   <none>           <none>

第六步:编写测试文件在/ken共享目录下文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# echo "nfs" > /ken/index.html

第七步: 访问测试文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# curl 10.244.2.61
nfs

PV & PVC

PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。文章源自靠谱运维-https://www.ixdba.net/archives/1422

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

有了 PersistentVolumeClaim,用户只需要告诉 Kubernetes 需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息。这些 Storage Provider 的底层信息交给管理员来处理,只有管理员才应该关心创建 PersistentVolume 的细节信息。文章源自靠谱运维-https://www.ixdba.net/archives/1422

Kubernetes 支持多种类型的 PersistentVolume,比如 AWS EBS、Ceph、NFS 等,完整列表请参考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

NFS PV

第一步:需在 k8s-master 节点上搭建了一个 NFS 服务器,目录为 /nfsdata:文章源自靠谱运维-https://www.ixdba.net/archives/1422

要更改目录属主,否则没有写入权限: chown -R nfsnobody.nfsnobody /nfsdata文章源自靠谱运维-https://www.ixdba.net/archives/1422

注意:文章源自靠谱运维-https://www.ixdba.net/archives/1422

  1. nfs可以安装在任意节点,不一定是在k8s集群当中的一台服务器
  2. k8s集群内的每台节点必须都要安装nfs-utils否则识别不到nfs类型
[root@ken ~]# showmount -e
Export list for ken:
/nfsdata *

第二步:创建一个 PV mypv1,配置文件 nfs-pv1.yml 如下:文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# cat nfs-pv1.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfsdata/pv1   #需要创建pv1目录,否则pod起不来
    server: 172.20.10.2

① capacity 指定 PV 的容量为 1G。文章源自靠谱运维-https://www.ixdba.net/archives/1422

② accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:文章源自靠谱运维-https://www.ixdba.net/archives/1422

ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。文章源自靠谱运维-https://www.ixdba.net/archives/1422

ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。文章源自靠谱运维-https://www.ixdba.net/archives/1422

ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。文章源自靠谱运维-https://www.ixdba.net/archives/1422

③ persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有:文章源自靠谱运维-https://www.ixdba.net/archives/1422

Retain – 需要管理员手工回收。文章源自靠谱运维-https://www.ixdba.net/archives/1422

Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。文章源自靠谱运维-https://www.ixdba.net/archives/1422

Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。文章源自靠谱运维-https://www.ixdba.net/archives/1422

④ storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。文章源自靠谱运维-https://www.ixdba.net/archives/1422

⑤ 指定 PV 在 NFS 服务器上对应的目录。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第三步:创建 mypv1:文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 created

第四步:查看pv文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Available           nfs                     48s

STATUS 为 Available,表示 mypv1 就绪,可以被 PVC 申请。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第五步:接下来创建 PVC mypvc1,配置文件 nfs-pvc1.yml 如下:文章源自靠谱运维-https://www.ixdba.net/archives/1422

注意:文章源自靠谱运维-https://www.ixdba.net/archives/1422

1. 各个节点都需要下载nfs-utils文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken-node1 ~]# cat pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
   requests:
     storage: 1Gi
  volumeName: mypv   #pv名字

PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl apply -f nfs-pvc1.yml
persistentvolumeclaim/mypvc1 created

第六步:查看pvc文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc1   Bound    mypv1    1Gi        RWO            nfs            112s
[root@ken ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Bound    default/mypvc1   nfs                     6m5s

从 kubectl get pvc 和 kubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第七步:接下来就可以在 Pod 中使用存储了,Pod 配置文件 pod1.yml 如下:文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用 mypvc1 申请的 Volume。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第八步:创建 mypod1:文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl apply -f pod1.yml
pod/mypod1 created

[root@ken ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypod1 1/1 Running 0 51s 10.244.1.59 host1 <none> <none>文章源自靠谱运维-https://www.ixdba.net/archives/1422

第九步:验证 PV 是否可用:文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# kubectl exec mypod1 touch /mydata/hello

[root@ken ~]# ls /nfsdata/pv1/
hello

可见,在 Pod 中创建的文件 /mydata/hello 确实已经保存到了 NFS 服务器目录 /nfsdata/pv1 中。文章源自靠谱运维-https://www.ixdba.net/archives/1422

回收PV

当 PV 不再需要时,可通过删除 PVC 回收。文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

当 PVC mypvc1 被删除后,Kubernetes 启动了一个新 Pod recycler-for-mypv1,这个 Pod 的作用就是清除 PV mypv1 的数据。此时 mypv1 的状态为 Released,表示已经解除了与 mypvc1 的 Bound,正在清除数据,不过此时还不可用。文章源自靠谱运维-https://www.ixdba.net/archives/1422

当数据清除完毕,mypv1 的状态重新变为 Available,此时则可以被新的 PVC 申请。文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

因为 PV 的回收策略设置为 Recycle,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain。文章源自靠谱运维-https://www.ixdba.net/archives/1422

第一步:将策略设置为 Retain。文章源自靠谱运维-https://www.ixdba.net/archives/1422

[root@ken ~]# cat nfs-pv1.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 172.20.10.2

第二步:通过 kubectl apply 更新 PV:文章源自靠谱运维-https://www.ixdba.net/archives/1422

root@ken ~]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 configured
[root@ken ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Retain           Available                        nfs                     65m

回收策略已经变为 Retain,通过下面步骤验证其效果:文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

① 重新创建 mypvc1文章源自靠谱运维-https://www.ixdba.net/archives/1422

② 在 mypv1 中创建文件 hello文章源自靠谱运维-https://www.ixdba.net/archives/1422

③ mypv1 状态变为 Released文章源自靠谱运维-https://www.ixdba.net/archives/1422

④ Kubernetes 并没有启动 Pod recycler-for-mypv1文章源自靠谱运维-https://www.ixdba.net/archives/1422

⑤ PV 中的数据被完整保留。文章源自靠谱运维-https://www.ixdba.net/archives/1422

另外使用retain虽然删除pod后的数据得到了保留,但其 PV 状态会一直处于 Released,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建 PV。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。文章源自靠谱运维-https://www.ixdba.net/archives/1422

k8s数据管理(八)文章源自靠谱运维-https://www.ixdba.net/archives/1422

新建的 mypv1 状态为 Available,已经可以被 PVC 申请。文章源自靠谱运维-https://www.ixdba.net/archives/1422

小结

本章我们讨论了 Kubernetes 如何管理存储资源。文章源自靠谱运维-https://www.ixdba.net/archives/1422

emptyDir 和 hostPath 类型的 Volume 很方便,但可持久性不强,Kubernetes 支持多种外部存储系统的 Volume。文章源自靠谱运维-https://www.ixdba.net/archives/1422

PV 和 PVC 分离了管理员和普通用户的职责,更适合生产环境。文章源自靠谱运维-https://www.ixdba.net/archives/1422

  • 本文由 发表于 2020年3月25日12:57:39
  • 转载请务必保留本文链接:https://www.ixdba.net/archives/1422
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: