7-1、存储卷

存储卷
SAN:iSCSI,
NAS:nfs,cifs,http
分布式存储:glusterfs,rbd(ceph),cephfs
云存储:EBS,Azure Disk,

储存方式:emptyDir,hostPath
Volumes:卷
Persistent Volumes:持久卷(pvc)
Volume Snapshots
CSI Volume Cloning
Storage Classes:存储类

存储卷常用类型
 非持久性存储
 emptyDir
 hostPath
 网络连接性存储
 SAN:iSCSI
 NFS:nfs,cfs
 分布式存储
 glusterfs、rbd、cephfs
 云端存储
 EBS、Azure Disk、阿里云、gitRepo


https://www.cnblogs.com/caibao666/p/11268826.html

1 emptyDir
在节点上运行pod实例时才会创建emptyDir volume。它首先是节点上的一个空目录,pod中的任何容器都可以用volume的形式挂载使用它。如果容器因为某种原因被删除并重新启动,创建的emptyDir不会删除也不会被清空。当pod实例离开节点调度到其它节点或因为缩容被删除时,emptyDir被删除,相当于pod还在但数据丢了
常用于作为临时目录、或缓存使用。
medium:此目录所在的存储介质的类型,可取值为default或Memory,默认default,表示使用节点的默认存储介质;Memory表示使用基于ram的临时文件系统
tmpfs:空间受限于内存,但性能非常好,通常用于为容器中的应用提供缓存空间。
sizeLimit:当前存储卷的空间限额,默认值为nil,表示不限制;在medium字段值为Memory时,建议务必定义此限额。
# kubectl explain pods.spec.volumes
# vi pod-volumes-demo.yaml
apiVsersion: v1
kind: Pod
metadata: 
    name: pod-volumes
    namespace: default
    labels:
        app: myapp
        tier: frontend
    annotations:
        cluster.com/created-by: "cluster domain"
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      ports:
      - name: http
        containerPort: 80
      - name: https
        containerPort: 443
      volumeMounts:
      - name: html
      mountPath: /data/web/html
    - name: busybox
      image: busybox:latest
      imagePolicy: IfNotPresent
      volumeMounts:
      - name: html
      mountPath: /data
      command:
      - "/bin/bash"
      - "-C"
      - "echo $(data) >> /data/index.htnl"
    volumes:
    - name: html
      emptyDir: {}

# kubectl exec -it pod-demo {myapp,busybox}  -- /bin/sh   #都可以看到index.html
------------
# vi pod-volumes-demo.yaml
apiVsersion: v1
kind: Pod
metadata: 
    name: pod-volumes
    namespace: default
    labels:
        app: myapp
        tier: frontend
    annotations:
        cluster.com/created-by: "cluster domain"
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      ports:
      - name: http
        containerPort: 80
      - name: https
        containerPort: 443
      volumeMounts:
      - name: html
      mountPath: /data/web/html
      
    volumes:
    - name: html
      emptyDir: {}

2 使用hostPath
https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
这种类型的卷将文件或目录从宿主机节点的文件系统挂载到您的Pod中,当pod删除时,本地仍然保留文件
type:
值为空:空字符串(默认)用于向后兼容,这意味着在安装hostPath卷之前不会执行任何检查。
DirectoryOrCreate: 如果给定路径中不存在任何内容,则将根据需要创建一个空目录,权限设置为0755,与Kubelet具有相同的组和所有权。
Directory: 目录必须存在于给定路径中
FileOrCreate:如果给定路径中不存在任何内容,则会根据需要创建一个空文件,权限设置为0644,与Kubelet具有相同的组和所有权。
File:文件必须存在于给定路径中

Socket:UNIX套接字必须存在于给定路径中

CharDevice:字符设备必须存在于给定路径中

BlockDevice:块设备必须存在于给定路径中

# vi pod-hostpath-volumes.yaml
apiVersion: v1
kind: Pod
metadata: 
    name: pod-volumes-hostpath
    namespace: default
spec:
    containers:
    - name: myapp
      image: ikuebernetes/myapp:v1
      voloumesMounts:
       - name: html
         mountPath: /usr/share/nginx/html/
    volumes:
    - name: html
      hostPath: 
          path: /data/pod/volumes
          type: DirectoryOrCreate

# mkdir /data/pod/volumes
# kubectl apply -f  pod-hostpath-volumes.yaml

3 使用共享存储:nfs:
NFS 是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。Pod被删除时,Volume被卸载,内容被保留。这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递。
有nfs存储,各节点挂载nfs 
# yum -y install nfs-utils
# vi /etc/exports
/data/volumes 172.20.0.0/16(rw,no_root_squash)
# systemctl start nfs
# showmount -e nfs-机器ip
节点上挂载:
# mount -t nfs stor01.cluster.com:/data/volumes  /data/volumes

# vi pod-volumes-nfs.yaml
apiVsersion: v1
kind: Pod
metadata: 
    name: pod-volumes-nfs
    namespace: default
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
      volumeMounts:
      - name: html
      mountPath: /data/web/html      
    volumes:
    - name: html
      nfs:
        path: /data/volumes
        server: stor01.cluster.com
        readOnly: false
server:nfs服务器的IP地址或主机名,必选字段
path:nfs服务器共享的文件系统路径,必选字段
readOnly:是否以只读方式挂载,默认为false


4、Persistent Volume(PV)和Persistent Volume Claim(PVC)
pv:持久卷,是底层的共享存储的一种抽象
pvc:持久卷声明,是对于存储需求的一种声明,就是向k8s系统发出的一种资源需求申请
PV的访问模型:

    accessModes:

        ReadWriteOnce【简写:RWO】: 单路读写,即仅能有一个节点挂载读写

        ReadOnlyMany【ROX】: 多路只读

        ReadWriteMany【RWX】:多路读写

创建持久卷pv:
cat local-pv.yaml


kind: PersistentVolume

apiVersion: v1

metadata:

   name: pv0001

   labels:

      type: local

spec:

   capacity:

      storage: 10Gi

   accessModes:

      - ReadWriteOnce

      hostPath:

         path: "/tmp/data01"


kind:PersistentVolume → 我们已将种类定义为PersistentVolume,它告诉kubernetes使用的yaml文件是用于创建持久卷的。

name:pv0001 → 我们正在创建的PersistentVolume的名称。

capacity: → 此规格将定义我们尝试创建的PV的容量。

storage:10Gi → 这告诉底层基础结构我们正在尝试在定义的路径上声明10Gi空间。

ReadWriteOnce → 这将告诉我们正在创建的卷的访问权限。

path: "/tmp/data01" → 此定义告诉计算机我们正在尝试在基础结构的该路径下创建卷。

persistentVolumeReclaimPolicy:指定当PV的回收策略为Recycle,
支持的策略有:

    Retain – 需要管理员手工回收。

    Recycle – 清除PV中的数据,效果相当于执行rm -rf /thevolume/*。

    Delete – 删除Storage Provider上的对应存储资源,例如AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume等。



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

RWX:为ReadWriteMany的简写

Retain:是回收策略
。Retain表示需要不使用了需要手动回收



# kubectl apply -f local-pv.yaml
# kubectl get pv
# kubectl describe pv pv0001

创建pvc:
cat myclaim-1.yaml


kind: PersistentVolumeClaim

apiVersion: v1

metadata:

   name: myclaim-1

spec:

   accessModes:

      - ReadWriteOnce

   resources:

      requests:

         storage: 3Gi


kind:PersistentVolumeClaim → 它指示基础结构我们正在尝试声明指定的空间量。

name:myclaim-1 → 我们尝试创建的声明的名称。

ReadWriteOnce → 这将指定我们尝试创建的声明的模式。

storage:3Gi → 这将告诉kubernetes我们正在尝试声明的空间量。

# kubectl apply -f myclaim-1.yaml
# kubectl get pvc

在POD中使用pv和pvc
cat pod-pv.yaml


kind: Pod

apiVersion: v1

metadata:

   name: mypod

   labels:

      name: frontendhttp

spec:

   containers:

   - name: myfrontend

      image: nginx

      ports:

      - containerPort: 80

         name: "http-server"

      volumeMounts:

      - mountPath: "/usr/share/tomcat/html"

         name: mypd

   volumes:

      - name: mypd

         persistentVolumeClaim:

         claimName: myclaim-1


volumeMounts: →这是容器中将要进行安装的路径。

volumes: →此定义定义了我们要声明的体积定义。

persistentVolumeClaim: →在此之下,我们定义将在定义的pod中使用的卷名。


5、local
与emptyDir相似,它也占用节点的存储空间。不同点是它是kubernetes中的一种对象类型,用户可以像管理普通对象一样管理它。emptyDir在pod实例开时运行时分配,当pod离节点时删除。local类型的volume则由用户创建,系统在合适的节点上为其分配资源,调度到这个节点上的pod可以挂载它,pod离开时它也不会消失,除非用户删除。示例:
示例:
apiVersion: v1

kind: PersistentVolume

metadata:

  name: example-pv

spec:

  capacity:

    storage: 100Gi

  # volumeMode field requires BlockVolume Alpha feature gate to be enabled.

  volumeMode: Filesystem

  accessModes:

  - ReadWriteOnce

  persistentVolumeReclaimPolicy: Delete

  storageClassName: local-storage

  local:

    path: /mnt/disks/ssd1

  nodeAffinity:

    required:

      nodeSelectorTerms:

      - matchExpressions:

        - key: kubernetes.io/hostname

          operator: In

          values:

          - example-node


6、存储的动态供给
什么是动态供给?

每次使用存储要先创建pv, 再创建pvc,真累! 所以我们可以实现使用存储的动态供给特性。

静态存储需要用户申请PVC时保证容量和读写类型与预置PV的容量及读写类型完全匹配, 而动态存储则无需如此.

管理员无需预先创建大量的PV作为存储资源
Kubernetes从1.4版起引入了一个新的资源对象StorageClass,可用于将存储资源定义为具有显著特性的类(Class)而不是具体的PV。用户通过PVC直接向意向的类别发出申请,匹配由管理员事先创建的PV,或者由其按需为用户动态创建PV,这样就免去
了需要先创建PV的过程。

PV对存储系统的支持可通过其插件来实现,目前,Kubernetes支持如下类 型的插件。 

官方地址:https://kubernetes.io/docs/concepts/storage/storage-classes/

官方插件是不支持NFS动态供给的,但是我们可以用第三方的插件来实现

第三方插件地址: https://github.com/kubernetes-retired/external-storage
storageclass底层可以是glusterfs,cephfs等不同的集群。
https://blog.51cto.com/u_13760351/2639942
1、下载并创建storageclass

mv class.yaml storageclass-nfs.yml
cat storageclass-nfs.yml
apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

    name: managed-nfs-storage

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner 

parameters:

    archiveOnDelete: "false"
# kubectl apply -f storageclass-nfs.yml

# kubectl get storageclass

2.下载并创建rbac

因为storage自动创建pv需要经过kube-apiserver,所以需要授权。

mv rbac.yaml storageclass-nfs-rbac.yaml

cat storageclass-nfs-rbac.yaml
apiVersion: v1

kind: ServiceAccount

metadata:

  name: nfs-client-provisioner

  namespace: default

---

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: nfs-client-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"]

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: run-nfs-client-provisioner

  namespace: default

subjects:

  - kind: ServiceAccount

    name: nfs-client-provisioner

    namespace: default

roleRef:

  kind: ClusterRole

  name: nfs-client-provisioner-runner

  apiGroup: rbac.authorization.k8s.io

# kubectl apply -f storageclass-nfs-rbac.yaml

3.创建动态供给的deployment

需要一个deployment来专门实现pv与pvc的自动创建

vim deploy-nfs-client-provisioner.yml
apiVersion: apps/v1

kind: Deployment

metadata:

  name: nfs-client-provisioner

  labels:

    app: nfs-client-provisioner

  namespace: default

spec:

  replicas: 1

  strategy:

    type: Recreate

  selector:

    matchLabels:

      app: nfs-client-provisioner

  template:

    metadata:

      labels:

        app: nfs-client-provisioner

    spec:

      serviceAccountName: nfs-client-provisioner

      containers:

        - name: nfs-client-provisioner

          image:registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner

          volumeMounts:

            - name: nfs-client-root

              mountPath: /persistentvolumes

          env:

            - name: PROVISIONER_NAME

              value: k8s-sigs.io/nfs-subdir-external-provisioner

            - name: NFS_SERVER

              value: 192.168.0.137

            - name: NFS_PATH

              value: /data

      volumes:

        - name: nfs-client-root

          nfs:

            server: 192.168.0.137

            path: /data

# kubectl apply -f deploy-nfs-client-provisioner.yml

# kubectl get pods |grep nfs-client-provisioner

7、configmap   

configmap和secret是两种特殊的存储卷,它们不是给pod提供存储空间用的,而是给我们的管理员或者用户提供了从外部向pod内部注入信息的方式。



configmap:把配置文件放在配置中心上,然后多个pod读取配置中心的配置文件。不过,configmap中的配置信息都是明文的,所以不安全。

secret:功能和configmap一样,只不过配置中心存储的配置文件不是明文的。



configmap和secret也是专属于某个名称空间的。

用户首先创建configMap并创建数据保存其中,此时数据保存在kubernetes的etcd数据库中,volume还不存在。当用户在pod中引用创建的configMap时,系统首先在节点上创建volume并将数据保存其中,这个volume占用的是节占的存储空间。此后就可以像使用普通volume一样使用它。
configMap是kubernetes中的一种对象类型,核心本质是以volume的方式将单独管理的配置信息传递给pod中的容器,并非用来存储持久化数据
http://blog.itpub.net/28916011/viewspace-2214804/
configmap内容:
server {
       server_name myapp.zhixin.com;    
       listen 80;
       root /data/web/html;
}
# kubectl describe cm nginx-www 

Name:         nginx-www

Namespace:    default

Labels:       <none>

Annotations:  <none>

Data

====

:

----

server {

      server_name myapp.xx.com;

      listen 80;

      root /data/web/html;

}

(1)用ENV方式来把configmap注入到pod中去:
cat pod-configmap.yaml 

apiVersion: v1

kind: Pod

metadata:

  name: pod-cm-1

  namespace: default

  labels:

    app: myapp  #kv格式的,也可以用花括号表示

    tier: frontend #定义所属的层次

  annotations:

    chenzx.com/created-by: "cluster-admin" #这是注解的键值对

spec:

  containers: 

  - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示

    image: tomcat 

    ports:

    - name: http

      containerPort: 80

    env: #这是一个容器的属性

    - name: NGINX_SERVER_PORT

      valueFrom: #kubectl explain pods.spec.containers.env.valueFrom

        configMapKeyRef: #表示我们要引用一个configmap来获取数据

          name: nginx-config #这是configmap的名字,也就是通过kubectl get cm获取的名字

          key: nginx_port #通过kubectl describe cm nginx-config的键

     #下面开始引用第二个环境变量

    - name: NGINX_SERVER_NAME

      valueFrom:

        configMapKeyRef:

          name: nginx-config

          key: server_name
# kubectl apply -f pod-configmap.yaml 

(2)用配置mount存储卷的方法把configmap注入到pod中。

# cat pod-configmap2.ymal 

apiVersion: v1

kind: Pod

metadata:

  name: pod-cm-2

  namespace: default

  labels:

    app: myapp  #kv格式的,也可以用花括号表示

    tier: frontend #定义所属的层次

  annotations:

    chenzx.com/created-by: "cluster-admin" #这是注解的键值对

spec:

  containers: 

  - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示

    image: ikubernetes/myapp:v1 

    ports:

    - name: http

      containerPort: 80

    volumeMounts:

    - name: nginxconf

      mountPath: /etc/nginx/conf.d/

      readOnly: true

  volumes:

  - name: nginxconf

    configMap:

      name: nginx-config

# kubectl apply -f pod-configmap2.ymal 
登录容器后:执行命令printenv结果:
NGINX_SERVER_PORT=80

NGINX_SERVER_NAME=myapp.xx.com

(3)下面我们再把前面创建的文件注入到POD中:

# cat pod-configmap3.yaml 

apiVersion: v1

kind: Pod

metadata:

  name: pod-cm-3

  namespace: default

  labels:

    app: myapp  #kv格式的,也可以用花括号表示

    tier: frontend #定义所属的层次

  annotations:

    chenzx.com/created-by: "cluster-admin" #这是注解的键值对

spec:

  containers: 

  - name: myapp  #前面的-号表示这是一个列表格式的,也可以用中括号表示

    image: ikubernetes/myapp:v1 

    ports:

    - name: http

      containerPort: 80

    volumeMounts:

    - name: nginxconf

      mountPath: /etc/nginx/conf.d/

      readOnly: true

  volumes:

  - name: nginxconf

    configMap:

      name: nginx-www


#  kubectl apply -f pod-configmap3.yaml 
登录容器后:cd /etc/nginx/conf.d/  ;cat nginx.conf

 

posted @ 2022-11-14 23:50  Sky-wings  阅读(36)  评论(0编辑  收藏  举报