OpenShift 4 - 使用 emptyDir/hostPath/local 类型 PV

59 篇文章 2 订阅
7 篇文章 0 订阅

OpenShift 4.x HOL教程汇总
说明:本文已经在OpenShift 4.10环境中验证


Kubernetes 的 emptyDir、hostPath、local 类型 PV 使用的都是 Node 节点的存储,但是功能和使用场景不同。

  • emptyDir 类型的 PV 是临时性的,因为 Pod 一旦重建,则原有的内容则被清空。
  • hostPath 类型的 PV 锁定到 Node 节点的本地存储,因此不适合集群中有多个 Node 节点的情况。因为重建的 Pod 可能会调度到其它 Node 节点上,导致无法访问存储。
  • local 类型的 PV 类似 hostPath 类型 PV,但是它具备亲和性,比较适合在集群中为容器化数据库提供存储。

emptyDir 类型 pv

emptyDir 类型的 PV 是在 Pod 内部,可以在一个 Pod 中的多个 Container 之间共享存储。emptyDir 类型的 PV 在 pod 分配到Node 上时被创建,Kubernetes 会在 Node 上自动分配一个目录,无需指定宿主机 Node 上对应的目录文件。 这个目录的初始内容为空,当 Pod 从 Node 上移除时,emptyDir 中的数据会被永久删除。
在这里插入图片描述

  1. 执行以下命令,运行 2 个使用了 emptydir 的 Pod,其中每个 Pod 中运行了 2 个 Container,而 2 个 Container 分别在 /tmp/demo1 和 /tmp/demo2 挂载了 emptydir 类型的 PV。
$ cat << EOF | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-emptydir
  labels:
    app: demo-emptydir
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-emptydir
  template:
    metadata:
      labels:
        app: demo-emptydir
    spec:
      containers:
      - name: demo-1
        image: quay.io/rhdevelopers/myboot:v4
        volumeMounts:
        - mountPath: /tmp/demo1
          name: emptydir-volume
      - name: demo-2
        image: quay.io/rhdevelopers/myboot:v4
        env:
        - name: SERVER_PORT 
          value: "8090"
        volumeMounts:
        - mountPath: /tmp/demo2
          name: emptydir-volume
      volumes:
      - name: emptydir-volume
        emptyDir: {}
EOF
  1. 查看有 2 个 Pod 已经运行。
$ oc get pod -l app=demo-emptydir
NAME                             READY   STATUS    RESTARTS   AGE
demo-emptydir-7bcf66487c-r77pz   2/2     Running   0          7s
demo-emptydir-7bcf66487c-zrs2x   2/2     Running   0          7s
  1. 执行命令,进入第 1 个 Pod 中名为 demo-1 的 Container。
$ oc rsh -c demo-1 pod/demo-emptydir-7bcf66487c-r77pz
  1. 执行以下命令,在 demo1 容器中的 /tmp/demo1 目录写入文件 hello,然后从 demo1 容器中退出来。
$ echo hello > /tmp/demo1/hello
$ cat /tmp/demo1/hello
$ exit
  1. 执行命令,进入第 1 个 Pod 中名为 demo-2 的 Container。确认有 /tmp/demo2/hello 文件,且文件内容是上一步创建的内容。
$ oc rsh -c demo-2 pod/demo-emptydir-7bcf66487c-r77pz
$ cat /tmp/demo2/hello
$ exit
  1. 针对第 2 个 Pod 进入其中的 2 个 Container,然后确认在 /tmp/demo1/tmp/demo2 中没有名为 hello 的文件。

hostPath 类型 pv

一个 hostPath 类型的 PV 将从主机节点的文件或目录挂载到 pod,因此 hostPath 类型的 PV 只能跨多个 Pod 而不能跨主机访问。hostPath PV 通常只在单节点集群中使用,因为如果 Pod 被调度到其他节点后,它将访问不到原有节点的 hostPath 了。如果要在多节点集群中使用,一定要配合 NodeSelector 部署运行 Pod。此外,hostPath 类型 pv 必须通过静态方式声明,而不能用 PVC 方式动态创建。
在这里插入图片描述

示例1

本示例使用手动创建的 PV/PVC 访问主机节点 hostpath。

  1. 查找当前状态为 Available 的 PV,然后自行执行命令删除他们。
$ oc get pv pv-mysql
  1. 查看当前集群中只有一个 Node 节点。
$ oc get node
NAME                 STATUS   ROLES           AGE   VERSION
crc-dzk9v-master-0   Ready    master,worker   88d   v1.22.0-rc.0+894a78b
$ NODE_NAME=crc-dzk9v-master-0
  1. 进入 OpenShift 集群中的 “${NODE_NAME}” 节点,先创建目录 /mnt/pv-data/mysql-data,然后修改其访问权限,最后退出 Node 节点。
$ oc debug node/${NODE_NAME}
# chroot /host
# mkdir -p /mnt/pv-data/mysql-data
# chmod -R 770 /mnt/pv-data/mysql-data
# exit
  1. 执行命令,基于主机节点上的 /mnt/pv-data/mysql-data 创建 PV。
$ cat << EOF | oc apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mysql
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Recycle
  volumeMode: Filesystem
  hostPath:
    path: "/mnt/pv-data/mysql-data"
    type: ""
EOF
  1. 执行命令,在 mysql 项目中根据 mysql-persistent 模板创建应用。
$ oc new-project mysql
$ oc new-app --template=mysql-persistent
$ oc get pod mysql
NAME             READY   STATUS    RESTARTS   AGE
mysql-1-5j4vh    1/1     Running   0          30s
mysql-1-deploy   0/1     Completed   0          37s
  1. 进入运行 mysql 的 Pod,然后查看 “/var/lib/mysql/data/” 下的文件,然后退出 Pod。
$ oc rsh dc/mysql
sh-4.4$ ls -al /var/lib/mysql/data/
sh-4.4$ exit
  1. 参照以上(3)的操作再次进入 Node 节点,然后查看 “/mnt/pv-data/mysql-data” 目录下的文件,确认和(6)看到的完全一样。
$ oc debug node/${NODE_NAME}
# chroot /host
# ls -al /mnt/pv-data/mysql-data

示例2

本示例在 Pod 中直接使用主机节点的 hostpath,而不是通过 PV/PVC 访问主机节点的 hostpath,因此此方法无需指定存储大小,设置访问存储安全特性。

  1. 执行命令创建一个 Pod,它将节点的 /mnt/my-hostpath 目录挂到 Pod 的 /tmp/demo 目录。其中容器使用了 “privileged: true” 特权后才能在 Pod 中访问主机 hostpath 中的内容。
$ cat << EOF | oc apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: my-hostpath
spec:
  containers:
  - image: quay.io/rhdevelopers/myboot:v4
    name: test-container
    securityContext:
      privileged: true
    volumeMounts:
    - mountPath: /tmp/demo
      name: hostpath-pv
  volumes:
   - name: hostpath-pv
     hostPath:
       path: /mnt/my-hostpath
EOF

注意:如果要使用非集群管理员执行以上命令,例如 developer,则需要先使用集群管理员给 developer 赋予名为 privileged 的 SCC 安全上下文。

$ oc adm policy add-scc-to-user privileged developer
  1. 确认此时在节点的 /mnt/my-hostpath 目录中没有文件。
$ oc debug node/${NODE_NAME}
# chroot /host
# ls -al /mnt/my-hostpath
  1. 执行命令,确认已经在 Pod 的 /tmp/demo 目录中生成 greeting.txt 文件。
$ oc rsh pod/my-hostpath curl localhost:8080/appendgreetingfile
$ oc rsh pod/my-hostpath ls -al /tmp/demo
total 4
drwxr-xr-x. 2 root root  26 Sep 17 14:21 .
drwxrwxrwt. 1 root root 126 Sep 17 14:07 ..
-rw-r--r--. 1 root root   5 Sep 17 14:21 greeting.txt
  1. 确认此时在节点的 /mnt/my-hostpath 目录中已经有 greeting.txt 文件了。
$ oc debug node/${NODE_NAME}
# chroot /host
# ls -al /mnt/my-hostpath
# exit
  1. 确认示例 2 不会创建新的 PV 和 PVC,这说明可以在 Pod 中通过 hostpath 直接使用节点的存储。
$ oc get pv
$ oc get pvc

local 类型 pv

local pv 虽然使用的也是节点本地存储,但它可以解决 hostPath 类型 PV 必须手动使用 NodeSelector 将 Pod 调度到特定主机节点的缺陷。
local pv 可以无需手动调度 pod 到节点的情况下使用,这是因为 Kubernetes 的 PV Controller 和 Scheduler 会对 local PV 做特殊的逻辑处理,以实现 Pod 使用本地存储时发生 re-schedule 的情况下能再次调度到 local volume 所在的节点。
local pv 使用的节点本地存储,通常可以利用本地的 SSD 高速存储来提升数据访问性能,例如分布式存储,这时单节点故障不会造成数据丢失。另外在需要频繁访问存储的 AI 数据训练场景中也可以使用 local pv。
Kubernetes 和 OpenShift 只能静态创建 local pv 。

方法1:不使用 Local Storage Operator

创建 PV

  1. 查看 OpenShift 集群中的节点。
$ oc get node
NAME                 STATUS   ROLES           AGE   VERSION
crc-dzk9v-master-0   Ready    master,worker   88d   v1.22.0-rc.0+894a78b
$ NODE_NAME=crc-dzk9v-master-0
  1. 进入 OpenShift 集群中的 “${NODE_NAME}” 节点,然后创建在后面步骤的 my-local-pv 对象中用到的 “path” 目录。最后退出集群节点。
$ oc debug node/${NODE_NAME}
# chroot /host
# DIR_NAME="vol1"
# mkdir -p /mnt/disk/${DIR_NAME}
# chcon -Rt svirt_sandbox_file_t /mnt/disk/${DIR_NAME}
# chmod 777 /mnt/disk/${DIR_NAME}
# exit
  1. 执行命令,在集群中创建一个 StorageClass。
$ cat << EOF | oc apply -f -
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: my-local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF
  1. 执行命令,基于上面创建的 StorageClass 对象在 $NODE_NAME 节点上创建一个 “local” 类型的 PersistentVolume。
    注意:
    /mnt/disk/vol1” 是以上步骤创建的 $NODE_NAME 节点本地目录。
    nodeAffinity” 保证了 “local” 类型的 PersistentVolume 和指定节点的亲和性。
$ cat << EOF | oc apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-local-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: my-local-storage
  local:
    path: /mnt/disk/vol1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ${NODE_NAME}
EOF
 
$ oc get pv my-local-pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS       REASON   AGE
my-local-pv   5Gi        RWO            Retain           Available           my-local-storage            44s

使用 local pv

  1. 执行命令,在测试项目中通过 “my-local-storage” 的 storageClassName 申请使用 Local pv。
$ oc new-project local-pv-test
$ cat << EOF | oc apply -f -
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-local-pvc
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: my-local-storage
  resources:
    requests:
      storage: 5Gi
EOF
  1. 使用 my-local-pvc 运行 Pod。
$ cat << EOF | oc apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: www
  labels:
    name: www
spec:
  containers:
  - name: www
    image: nginx:alpine
    ports:
      - containerPort: 80
        name: www
    volumeMounts:
      - name: www-persistent-storage
        mountPath: /usr/share/nginx/html
  volumes:
    - name: www-persistent-storage
      persistentVolumeClaim:
        claimName: my-local-pvc
EOF
  1. 查看运行的测试 Pod, 记录 Pod 的 IP。
$ oc get pod www -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE                 NOMINATED NODE   READINESS GATES
www    1/1     Running   0          32s   10.217.0.82   crc-dzk9v-master-0   <none>           <none>
  1. 确认 “my-local-pv” 已经中已经有 “my-local-pvc”。
$ oc get pv my-local-pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS       REASON   AGE
my-local-pv   5Gi        RWO            Retain           Bound    local-pv-test/my-local-pvc   my-local-storage            3m33s
  1. 再次进入 “NODE_NAME”。先向该 Node 节点的 “** /mnt/disk/vol1/**” 目录写入文件,然后访问测试 Pod 的 IP 地址,确认返回结果。
$ oc debug node/${NODE_NAME}
# chroot /host
# echo "Hello local persistent volume" > /mnt/disk/vol1/index.html
# url 10.217.0.82
Hello local persistent volume

方法2:使用 Local Storage Operator

为了能使用 Local Storage Operator 配置 Local Volume,需要有一个满足以下条件的本地磁盘:它附加到一个节点,并且尚未挂载,同时不包含分区。 Local Storage Operator 安装和 Local Volume 配置方法可参见:
https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.10/html/storage/persistent-storage-using-local-volume
https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.10/html/storage/local-volume-cr_persistent-storage-local

参考

https://redhat-scholars.github.io/kubernetes-tutorial/kubernetes-tutorial/volumes-persistentvolumes.html
https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.10/html/storage/persistent-storage-hostpath-pod_persistent-storage-hostpath
https://vocon-it.com/2018/12/20/kubernetes-local-persistent-volumes/
https://speakerdeck.com/msau42/2018-kubecon-eu-kubernetes-local-persistent-volumes-in-production
https://bswen.com/2020/12/others-local-vs-hostpath-k8s.html
https://cloud.tencent.com/developer/article/1195068
https://itnext.io/local-storage-for-openshift-121224daf2d9

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值