侧边栏壁纸
博主头像
DJ's Blog博主等级

行动起来,活在当下

  • 累计撰写 133 篇文章
  • 累计创建 51 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

【Kubernetes】Volume

Administrator
2022-03-25 / 0 评论 / 0 点赞 / 150 阅读 / 17706 字

【Kubernetes】Volume

Storage Requirements

Storage Use Case

Local vs Remote Volume Types

Local Volume

官方文档:https://kubernetes.io/docs/concepts/storage/volumes/

  • 定义使用Host类型Volume的Pod
vim volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  # 一个pod中的多个容器可以都绑定宿主机中的路径,达到共享宿主机的存储目录
  containers:
    - name: nginx-container
      image: nginx
      ports:
        - containerPort: 80
      # 定义容器中绑定的存储,即将容器中的某个路径和宿主机中的某个路径互相绑定
      volumeMounts:
        - name: volume-pod
          mountPath: /nginx-volume
    - name: busybox-container
      image: busybox
      command: [ 'sh', '-c', 'echo The app is running! && sleep 3600' ]
      # 定义容器中绑定的存储,即将容器中的某个路径和宿主机中的某个路径互相绑定
      volumeMounts:
        - name: volume-pod
          mountPath: /busybox-volume
  # 定义host类型的存储
  volumes:
    - name: volume-pod
      hostPath:
        path: /tmp/volume-pod
  • 创建Host类型Volume的Pod
kubectl apply -f volume-pod.yaml
  • 分别进入这个pod中的两个容器中mountPath
docker ps | grep volume
5c3ebca91431        busybox                "sh -c 'echo The app…"   45 seconds ago       Up 44 seconds                           k8s_busybox-container_volume-pod_default_e17f43ed-ac43-11ec-8b81-00163e18d0d0_0
a7e00097e55a        nginx                  "/docker-entrypoint.…"   About a minute ago   Up About a minute                       k8s_nginx-container_volume-pod_default_e17f43ed-ac43-11ec-8b81-00163e18d0d0_0
a86724b8049d        k8s.gcr.io/pause:3.1   "/pause"                 About a minute ago   Up About a minute                       k8s_POD_volume-pod_default_e17f43ed-ac43-11ec-8b81-00163e18d0d0_0
docker exec -it 5c3ebca91431 sh
cd /busybox-volume

在宿主机中/tmp/volume-pod路径上创建文件,会同样的在两个容器中的mountPath路径下创建相同的文件,说明他们之间是互相绑定了

  • 查看两个容器的hosts文件
docker exec -it 5c3ebca91431 cat /etc/hosts

发现两个容器中的hosts文件都相同,并且都是由pod来统一管理;所以一般容器中的存储或者网络的内容,不要在容器层面修改,而是在pod中修改。

  • 修改pod中的所有容器的网络
...
spec:
  # 是否使用主机的网络
  hostNetwork: true
  # 是否使用主机的PID命令空间
  hostPID: true
  # 自定义容器的IP地址
  hostAliases:
    - ip: "192.168.8.61"
  # 自定义容器的主机名
  hostname: test.jack.com
  # 一个pod中的多个容器可以都绑定宿主机中的路径,达到共享宿主机的存储目录
  containers:
...

ConfigMap and Secret


Remote Volume

NFS

nfs(network file system)网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源

  • 安装nfs
yum install -y nfs-utils
  • 创建nfs目录
mkdir -p /nfs/data/
  • 目录授予权限
chmod -R 777 /nfs/data
  • 编辑export文件
vim /etc/exports
/nfs/data *(rw,no_root_squash,sync)
  • 使得配置生效
exportfs -r
  • 查看配置是否生效
exportfs
  • 启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs
  • 查看rpc服务的注册情况
rpcinfo -p localhost
  • showmount测试
showmount -e master节点ip
  • 集群其他节点安装客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs

Different Volume Types in a Pod

Persistent Volume

官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

  • PV是K8s中的资源,volume的plugin实现,生命周期独立于Pod,封装了底层存储卷实现的细节。

Persistent Volumes are NOT namespaced

Yaml Example

  • 创建一个PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
spec:
  # 定义PV的访问模式
  accessModes:
    - ReadWriteMany
  # 定义PV的存储容量
  capacity:
    storage: 2Gi
  # 远端服务器配置
  nfs:
    path: /nfs/data/nginx
    server: 172.24.253.248
  • 查看所有的namespace下的PV资源
kubectl get pv --all-namespaces
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
nginx-pv   2Gi        RWX            Retain           Bound    default/nginx-pvc                           2d23h

状态为Bound表示这个PV已经和namespace为default下面的nginx-pvc这个PVC进行绑定

  • PV的状态:
  1. Available:表示当前的pv没有被绑定
  2. Bound:表示已经被pvc挂载
  3. Released:pvc没有在使用pv, 需要管理员手工释放pv
  4. Failed:资源回收失败
  • PV回收策略:
  1. Retain:表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理
  2. Recycle:在Kubernetes新版本就不用了,采用动态PV供给来替代
  3. Delete:表示删除PVC的时候,PV也会一起删除,同时也删除PV所指向的实际存储空间

目前只有NFS和HostPath支持Recycle策略。AWS EBS、GCE PD、Azure Disk和Cinder支持Delete策略

Persistent Volume Claim

官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims
image-1664337080341
image-1664337105897
PVC是Pod使用PV资源的纽带
PVC会根据accessModes和storage来匹配对应的PV,然后进行一一绑定,绑定之后他们的状态就变成Bound

  • 创建一个PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  # 定义PVC的访问模式
  accessModes:
    - ReadWriteMany
  resources:
    # 定义PVC请求的PV的存储容量
    requests:
      storage: 2Gi
  • 查看所有的namespace下的PVC资源
kubectl get pvc --all-namespaces
NAMESPACE   NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
default     nginx-pvc   Bound    nginx-pv   2Gi        RWX                           3d

状态为Bound表示这个PVC已经和nginx-pv这个PV进行绑定

Persistent Volume Claim Use Case


Claims must be in the same namespace!

  • 创建Pod使用上面定义好的PVC
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          name: mysql
          ports:
            - containerPort: 80
          # 定义容器中使用pvc的方式将容器中的某一个路径和pv对应的nfs上的指定路径互相绑定,从而将容器的存储不依赖于宿主机
          volumeMounts:
            - name: nginx-persistent-storage
              mountPath: /usr/share/nginx/html
      # 定义pvc类型的存储
      volumes:
        - name: nginx-persistent-storage
          persistentVolumeClaim:
            claimName: nginx-pvc
  • 到此为止,这个Pod中的/usr/share/nginx/html目录已经和nfs服务器上/nfs/data/nginx目录互相绑定了,下面进行简单测试:
  1. 在/nfs/data/nginx新建文件1.html,写上内容
  2. 获取Pod的详情信息:kubectl get pods -o wide
  3. 进入Pod:kubectl exec -it nginx-pod bash
  4. 进入/usr/share/nginx/html目录查看,发现存在1.html文件
  5. 手动删除这个Pod:kubectl delete pod nginx-pod
  6. 再次进入新的Pod中查看/usr/share/nginx/html目录是否存在1.html文件

Storage Class

官方文档:https://kubernetes.io/docs/concepts/storage/storage-classes/


StorageClass声明存储插件,用于自动创建PV,也就是创建PV的模板。
StorageClass和PV的关系相关于Java中的类和实例的关系
StorageClass的两个重要部分:PV属性,创建此PV所需要的插件(Provisioner)

  • 创建一个StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
# 使用内部集成的AWSElasticBlockStore这个Volume Plugin来创建AWSElasticBlockStore类型的PV
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

Storage Class Use Cases

NFS Type Provisioner

如图所示,因为NFS类型的存储没有Internal Provisioner,所有需要手动创建,才能供StorageClass使用

  • 根据rbac.yaml文件创建资源
vim rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-provisioner-runner
rules:
  - 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" ]
  - apiGroups: [ "" ]
    resources: [ "services", "endpoints" ]
    verbs: [ "get" ]
  - apiGroups: [ "extensions" ]
    resources: [ "podsecuritypolicies" ]
    resourceNames: [ "nfs-provisioner" ]
    verbs: [ "use" ]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
rules:
  - apiGroups: [ "" ]
    resources: [ "endpoints" ]
    verbs: [ "get", "list", "watch", "create", "update", "patch" ]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-provisioner
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
  • 根据deployment.yaml文件创建资源
vim deployment.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              # 指定手动创建的NFS类型的provisioner的名称,提供给StorageClass使用
              value: example.com/nfs
            - name: NFS_SERVER
              # 指定NFS服务器的IP地址
              value: 172.24.253.248
            - name: NFS_PATH
              # 指定NFS服务器的路径
              value: /nfs/data/storageclass
      volumes:
        - name: nfs-client-root
          nfs:
            # 指定NFS服务器的IP地址
            server: 172.24.253.248
            # 指定NFS服务器的路径
            path: /nfs/data/storageclass
kubectl apply -f deployment.yaml
  • 根据class.yaml创建StorageClass
vim class.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: example-nfs
# 使用上面手动创建好的provisioner来创建NFS类型的PV
provisioner: example.com/nfs
kubectl apply -f class.yaml
  • 根据pvc.yaml创建PVC
vim my-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  # 这个名字要和上面创建的StorageClass名称一致
  storageClassName: example-nfs
kubectl apply -f my-pvc.yaml
  • 查看创建的PVC资源
kubectl get pvc -o wide
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc   Bound    pvc-2fca01a6-b042-11ec-8b81-00163e18d0d0   1Mi        RWX            example-nfs    6s

可以看到此时PVC的状态为Bound,说明已经和PV绑定了

  • 创建Pod,并使用上面创建的PVC
vim nginx-pod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: my-pvc
          mountPath: /usr/storageclass
  restartPolicy: "Never"
  volumes:
    - name: my-pvc
      persistentVolumeClaim:
        claimName: my-pvc
kubectl apply -f nginx-pod.yaml
  • 查看创建的Pod
kubectl get pods -o wide
  • 这样Pod中的容器的/usr/storageclass路径就和NFS上的/nfs/data/storageclass路径进行绑定,接下来可以测试一下
  • 进入Pod的容器
kubectl exec -it nginx bash
  • 进入/usr/storageclass目录,新增1.html文件,看下NFS服务器上/nfs/data/storageclass路径下是否也新增同样的文件。

Pod PV PVC and StorageClass

  • 一个Pod可以使用多个PVC,一个PVC也可以给多个Pod使用
  • 一个PVC只能绑定一个使用StorageClass创建的PV或者直接绑定一个提前创建好的PV,一个PV只能对应一种后端存储
  • 对于手动的情况,一般我们会创建很多的PV,等有PVC需要使用的时候就可以直接使用了
  • 对于自动的情况,那么就由StorageClass来自动管理创建PV
  • 如果Pod想要使用共享存储,比如NFS,一般会创建PVC,PVC中描述了想要什么类型的后端存储、空间等,K8s从而会匹配对应的PV,如果没有匹配成功,Pod就会处于Pending状态。Pod中使用只需要像使用volumes一样,指定名字就可以使用了
  • K8S集群管理员负责创建PV并进行管理,K8S用户负责创建PVC,并按照需求使用PV
0

评论区