1.Volumes

1.1HostPath

将节点上的文件或者目录挂载在pod上,此时该目录会变成持久化存储目录。即使pod被删除后重启,也可以重新加载到该目录,该目录下的文件不会丢失。

创建hostpath-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: nginx-volume
    volumeMounts:
    - mountPath: /test-pd # 挂载到容器的哪个目录
      name: test-volume # 挂载哪个 volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data-volume # 节点中的目录
      type: DirectoryOrCreate # 检查类型,在挂载前对挂载目录做什么检查操作,有多种选项,默认为空字符串,不做任何检查


类型:
空字符串:默认类型,不做任何检查
DirectoryOrCreate:如果给定的 path 不存在,就创建一个 755 的空目录
Directory:这个目录必须存在
FileOrCreate:如果给定的文件不存在,则创建一个空文件,权限为 644
File:这个文件必须存在
Socket:UNIX 套接字,必须存在
CharDevice:字符设备,必须存在
BlockDevice:块设备,必须存在
[root@master volume]# kubectl apply -f hostpath-demo.yaml 
pod/test-pd created

[root@master volume]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
test-pd   1/1     Running   0          65s   10.244.2.84   node2   <none>           <none>


#进入到node2中查看,目录已经被创建
[root@node2 data-volume]# pwd
/data-volume

#在容器中创建一个文件
[root@master volume]# kubectl exec -it test-pd -- bin/sh
# cd /test-pd
# touch bbb.txt

#在node2中查看
[root@node2 data-volume]# ls
bbb.txt

1.2EmptyDir

EmptyDir 主要用于一个 Pod 中不同的 Container 共享数据使用的,由于只是在 Pod 内部使用,因此与其他 volume 比较大的区别是,当 Pod 如果被删除了,那么 emptyDir 也会被删除。

存储介质可以是任意类型,如 SSD、磁盘或网络存储。可以将 emptyDir.medium 设置为 Memory 让 k8s 使用 tmpfs(内存支持文件系统),速度比较快,但是重启 tmpfs 节点时,数据会被清除,且设置的大小会计入到 Container 的内存限制中。

创建 emptydir-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: alpine
    name: alpine-emptydir1
    command: ["/bin/sh","-c","sleep 3600"]
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - image: alpine
    name: alpine-emptydir2
    command: ["/bin/sh","-c","sleep 3600"]
    volumeMounts:
    - mountPath: /opt
      name: cache-volume   
  volumes:
  - name: cache-volume
    emptyDir: {}
[root@master volume]# kubectl apply -f emptydir-demo.yaml 
pod/test-pd configured

[root@master volume]# kubectl get po
NAME      READY   STATUS    RESTARTS   AGE
test-pd   2/2     Running   0          3m56s

#进入到容器1创建文件
[root@master volume]# kubectl exec -it test-pd  -c alpine-emptydir1 -- /bin/sh
/ # cd /
bin/    dev/    home/   media/  opt/    root/   sbin/   sys/    usr/
cache/  etc/    lib/    mnt/    proc/   run/    srv/    tmp/    var/
/ # cd /cache
/cache # touch a.txt
/cache # ls
a.txt

#进入到容器2查看
[root@master ~]# kubectl exec -it test-pd  -c alpine-emptydir2 -- /bin/sh
/ # cd opt/
/opt # ls
/opt # ls
a.txt

2.NFS挂载

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

# 安装 nfs
yum install nfs-utils -y

# 启动 nfs
systemctl start nfs-server

# 查看 nfs 版本
cat /proc/fs/nfsd/versions

# 创建共享目录
mkdir -p /data/nfs
cd /data/nfs
mkdir rw
mkdir ro

# 设置共享目录 export
vim /etc/exports
/data/nfs/rw 192.168.113.0/24(rw,sync,no_subtree_check,no_root_squash)
/data/nfs/ro 192.168.113.0/24(ro,sync,no_subtree_check,no_root_squash)

# 重新加载
exportfs -f
systemctl reload nfs-server

# 到其他测试节点安装 nfs-utils 并加载测试
mkdir -p /mnt/nfs/rw
mount -t nfs 192.168.10.91:/data/nfs/rw /mnt/nfs/rw

在k8s中使用nfs

创建nfs-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nfs-demo-pod
spec:
  containers:
  - image: nginx
    name: nfs-demo-pod
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: 192.168.10.91 # 网络存储服务地址
      path: /data/nfs/rw/www # 网络存储路径
      readOnly: false # 是否只读

在nfs服务器中创建

[root@ck-1 rw]# cd www/
[root@ck-1 www]# echo "111">index.html

创建pod

[root@master volume]# kubectl apply -f nfs-demo.yaml 
pod/nfs-demo-pod created

[root@master volume]# kubectl get pods -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nfs-demo-pod   1/1     Running   0          32s   10.244.2.86   node2   <none>           <none>

[root@master volume]# curl 10.244.2.86
1111

3.PV和PVC

持久卷(PersistentVolume,PV) 持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。

持久卷申领(PersistentVolumeClaim,PVC) 是持久卷声明的意思,是用户对于存储需求的一种声明。

img

当用户创建一个 PVC 对象后,主节点会监测新的 PVC 对象,并且寻找与之匹配的 PV 卷,找到 PV 卷后将二者绑定在一起。

如果找不到对应的 PV,则需要看 PVC 是否设置 StorageClass 来决定是否动态创建 PV,若没有配置,PVC 就会一致处于未绑定状态,直到有与之匹配的 PV 后才会申领绑定关系。

回收策略

当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除, 从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群, 当其被从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)。

Retained:回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:
删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在。
根据情况,手动清除所关联的存储资产上的数据。
手动删除所关联的存储资产。
如果你希望重用该存储资产,可以基于存储资产的定义创建新的 PersistentVolume 卷对象。

对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态制备的卷会继承其 StorageClass 中设置的回收策略, 该策略默认为 Delete。管理员需要根据用户的期望来配置 StorageClass; 否则 PV 卷被创建之后必须要被编辑或者修补。

警告: 回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。

如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的擦除 (rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领。 

pv的状态

  • Available:空闲,未被绑定
  • Bound:已经被 PVC 绑定
  • Released:PVC 被删除,资源已回收,但是 PV 未被重新使用
  • Failed:自动回收失败

3.1创建pv

创建pv-nfs-demo.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 5Gi # pv 的容量
  volumeMode: Filesystem # 存储类型为文件系统
  accessModes: # 访问模式:ReadWriteOnce、ReadWriteMany、ReadOnlyMany
    - ReadWriteOnce # 可被单节点独写
  persistentVolumeReclaimPolicy: Retain # 回收策略
  storageClassName: slow # 创建 PV 的存储类名,需要与 pvc 的相同
  mountOptions: # 加载配置
    - hard
    - nfsvers=4.1
  nfs: # 连接到 nfs
    path: /data/nfs/rw/test-pv # 存储路径
    server: 192.168.10.91 # nfs 服务地址
[root@master pv-pvc]# kubectl apply -f pv-nfs-demo.yaml 
persistentvolume/pv0001 created
[root@master pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv0001   5Gi        RWO            Retain           Available           slow                    2s

3.2创建pvc

创建pvc-demo.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteOnce # 权限需要与对应的 pv 相同
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi # 资源可以小于 pv 的,但是不能大于,如果大于就会匹配不到 pv
  storageClassName: slow # 名字需要与对应的 pv 相同
#  selector: # 使用选择器选择对应的 pv
#    matchLabels:
#      release: "stable"
#    matchExpressions:
#      - {key: environment, operator: In, values: [dev]}

[root@master pv-pvc]# kubectl apply -f pvc-demo.yaml 
persistentvolumeclaim/nfs-pvc created

[root@master pv-pvc]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound    pv0001   5Gi        RWO            slow           4s

[root@master pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv0001   5Gi        RWO            Retain           Bound    default/nfs-pvc   slow                    6m17s

3.3pod绑定Pvc

在 pod 的挂载容器配置中,增加 pvc 挂载
containers:
  ......
  volumeMounts:
    - mountPath: /tmp/pvc
      name: nfs-pvc-test
volumes:
  - name: nfs-pvc-test
    persistentVolumeClaim:
      claimName: nfs-pvc # pvc 的名称

创建pvc-pod-demo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: nginx-volume
    volumeMounts:
    - mountPath: /usr/share/nginx/html # 挂载到容器的哪个目录
      name: nfs-pvc-test # 挂载哪个 volume
  volumes:
  - name: nfs-pvc-test
    persistentVolumeClaim:
      claimName: nfs-pvc # pvc 的名称

[root@master pv-pvc]# kubectl apply -f pvc-pod-demo.yaml 
[root@master pv-pvc]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
test-pd   1/1     Running   0          33s


#在nfs服务器中
[root@ck-1 test-pv]# echo "111111" > index.html
[root@ck-1 test-pv]# cat index.html 
111111


[root@master pv-pvc]# curl 10.244.2.88
111111

4.StorageClass

k8s 中提供了一套自动创建 PV 的机制,就是基于 StorageClass 进行的,通过 StorageClass 可以实现仅仅配置 PVC,然后交由 StorageClass 根据 PVC 的需求动态创建 PV。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个SC都有一个制备器,通过制备器决定创建哪个类型PV。

4.1NFS动态制备案例

1.rbac-storageclass.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: nfs-storageclass
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: nfs-storageclass
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: nfs-storageclass
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: nfs-storageclass
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: nfs-storageclass
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

2.nfs-provisioner-deployment.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
  namespace: nfs-storageclass
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-client-provisioner #自己的名字
            - name: NFS_SERVER
              value: 192.168.10.91 #改为自己nfs服务地址
            - name: NFS_PATH
              value: /data/nfs/rw #改为自己路径
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.10.91
            path: /data/nfs/rw

3.nfs-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
  namespace: kube-system
provisioner: fuseim.pri/ifs # 外部制备器提供者,编写为提供者的名称
parameters:
  server: 192.168.10.91 #nfs服务地址
  path: /data/nfs/rw
  readOnly: "false"
  archiveOnDelete: "false" # 是否存档,false 表示不存档,会删除 oldPath 下面的数据,true 表示存档,会重命名路径
reclaimPolicy: Retain # 回收策略,默认为 Delete 可以配置为 Retain
volumeBindingMode: Immediate # 默认为 Immediate,表示创建 PVC 立即进行绑定,只有 azuredisk 和 AWSelasticblockstore 支持其他值

4.pvc设置

test-PVC.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  storageClassName: my-nfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐