k8s-存储卷-1

需要脱离容器和主机的生命周期。

存储卷不属于容器,而属于pod,k8s基本调度单元是pod .pod 本身就是抽象出来的。

一个pod当中可能运行一到多个容器。有一个主容器叫做maincontainer,其他容器叫做sidercar

一个pod 中多个容器是可以使用同一组存储卷的。因为存储卷属于pod 的

pod 中有一个底层的基础架构容器叫做pause.运行的每个容器都有一个pause 容器存在。容器借助于内核中的6个名称空间提供服务,其中pause提供一个基础的容器,其他加入进pod中的其他容器都共享网络名称空间,ipc ,uts

存储卷也属于pause,每个加入pod中的容器可以复制pause 中存储卷。谁复制就能使用添加进来的存储卷,k8s pod 中容器要使用存储卷,自己明确挂载存储卷挂载到本地某个目录下。

共享式存储设备:
  多路并行读写
  多路只读
  单路读写

Pod使用Volume步骤:
  1、在Pod上定义存储卷,并关联至目标存储服务上; 
  2、在需要用到存储卷的容器上,挂载其所属的Pod的存储卷; 

存储卷类型:
  Host级别:hostPath, Local
  网络级别:NFS、GlusterFS、rbd(块设备)、CephFS(文件系统)、...
  临时存储:emptyDir

kubelet 通过volumn plugin要支持这种存储卷类型。

csi:容器存储接口

k8s 特性:作为用户来讲。运行一个程序,以pod 规范定义出pod和容器。至于如何运行,如何分配在底层,资源等。用户不用管。要想使用存储卷在pod上,节点级别要能驱动存储服务外。所有的关于服务的配置都是在pod上通过卷插件来指定的, 在pod上使用volume 来定义的。volumn 卷插件时kubelet 级别的,需要通过pod向kubelet 传递配置参数 

查看支持的类型配置详解:kubectl explain pods.spec.volumes

 kubectl explain pods.spec.volumes.rbd

如何使用存储卷?

案例  :创建hostpath类型存储卷。

[root@master ~]# mkdir volumes
[root@master ~]# vi vol-demo.yaml
[root@master ~]# kubectl create ns vol
namespace/vol created
[root@master ~]# kubectl apply -f vol-demo.yaml
pod/myapp created
[root@master ~]# cat vol-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp
  namespace: vol
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: webstor
      mountPath: /usr/share/nginx/html
      readOnly: true
  volumes:
  - name: webstor
    hostPath:
      path: /volumes/myapp
      type: DirectoryOrCreate

#查看详细信息


[root@master ~]#
[root@master ~]# kubectl get pods  -n vol
NAME    READY   STATUS    RESTARTS   AGE
myapp   1/1     Running   0          96s
[root@master ~]# kubectl describe pods myapp -n vol
Name:         myapp
Namespace:    vol
 

#去宿主机上查看挂载

ster ~]#
[root@master ~]#
[root@master ~]# kubectl get pods -n vol -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
myapp   1/1     Running   0          5m58s   10.244.2.41   node2.k8s.com   <none>           <none>
登录node2 的相应节点,多了一个volumes  的目录

ls /
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volumes

#创建一个index.html
[root@node2 ~]# cd   /volumes/myapp/
[root@node2 myapp]# vi index.html
[root@node2 myapp]# cat index.html
<h1>Page @pod_volumes_hostpath</h1>

#curl 检测

oot@master ~]# curl   10.244.2.41
<h1>Page @pod_volumes_hostpath</h1>
[root@master ~]#
 

#以上问题是,如果被删除了,并且pod 不在这个node 了,那么就不能共享挂载这个目录了。

还有就是硬绑定到这个节点上

nodename这个字段可以硬绑定到这个节点上。

案例:local 类型。可以直接使用设备文件。可以

案例:emptydir 

场景一 : 可以为容器提供缓存存储空间。

场景二:两个容器共享数据。

案例:nfs 存储卷

 yum install -y nfs-utils
 mkdir /vols/v{1,2,3,4,5} -p

[root@localhost ~]# systemctl start nfs
[root@localhost ~]# cat /etc/exports
/vols/v1 10.0.0.0/24(rw,no_root_squash)

[root@localhost ~]# exportfs -rav
exporting 10.0.0.0/24:/vols/v1
 

其他node 节点也需要安装util包。其他节点进行挂载测试

[root@master mnt]# mount -t nfs 10.0.0.120:/vols/v1 /mnt

[root@master /]# kubectl explain pods.spec.volumes.nfs


[root@master chapter7]# cat vol-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vol-nfs-pod
  namespace: vol
  labels:
    app: redis
spec:
  containers:
  - name: redis
    image: redis:alpine
    ports:
    - containerPort: 6379
      name: redis
    volumeMounts:
    - mountPath: /data
      name: data
  volumes:
    - name: data
      nfs:
        server: 10.0.0.120
        path: /vols/v1
[root@master chapter7]# kubectl  apply -f vol-nfs.yaml
pod/vol-nfs-pod created

# kubectl describe pods vol-nfs-pod  -n vol            #查看报错
 

之后将pod 删除,重建后看这个文件是否存在

=====================================================================

pv 和存储系统间没有一一对应关系,对应存储系统逻辑上可被访问的逻辑单元,nfs  是一个可被导出的路径,rbd 是个img.

pv 属于集群级别的资源。要想在名称空间使用pv.还需要把pv 注册到名称空间中去。pv是一对一的。A名称空间占用,B 就不能在用了。现在有一个名称空间叫做myns---->pvc(请求占住一个pv)

pv和pvc 之间没有直接关系,但pvc 是请求占住pv的。被占用的叫做binding, 没占用的叫做available.一旦占住,这个名称空间中就有pod 能使用pvc 了。  pod--->pvc--->pv

 kubectl explain pods.spec.volumes.persistentVolumeClaim
 

在pod 上定义了存储卷,容器是不能使用他的。在容器上还要挂载它。container 应该使用volumemounts 进行挂载。  

如何使用pvc:

         pod上使用pvc 插件,pod 同一个名称空间当中,使用一种资源,pvc 资源来创建申请。

存储类:pv 创建模板。按用户的需求生成pv.  nfs 要不定义在pv 上了。而定义在模板上

spec:
  volumes:
  - name <string>  # 存储卷名称标识,仅可使用DNS标签格式的字符,在当前Pod中必须唯一
    VOL_TYPE <Object>  # 存储卷插件及具体的目标存储供给方的相关配置
  containers:
  - name: …
    image: …
    volumeMounts:
    - name <string>  # 要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义
      mountPath <string> # 容器文件系统上的挂载点路径
      readOnly <boolean>  # 是否挂载为只读模式,默认为“否”
      subPath <string>     # 挂载存储卷上的一个子目录至指定的挂载点
      subPathExpr <string>  # 挂载由指定的模式匹配到的存储卷的文件或目录至挂载点

============================================

回顾:在pod 上要想使用存储卷,1,在pod级别定义存储卷,定义的过程(卷名称,卷插件类型,卷插件对接下的存储设备)。2.在特定的容器使用 volumeMounts挂载之前定义的卷,

示例1:emptydir 存储卷

       tmptydir :临时存储卷,借助于外部的高速存储,或内存空间来临时存储某些数据,为应用提供缓存,为同一个pod内不同的容器提供共享的数据

                medium:    存储介质,默认磁盘

[root@node01 chapter5]# cat volumes-emptydir-demo.yaml 
apiVersion: v1 
kind: Pod
metadata:
  name: volumes-emptydir-demo
  namespace: default
spec:
  initContainers:
  - name: config-file-downloader
    image: ikubernetes/admin-box
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c','wget -O /data/envoy.yaml http://ilinux.io/envoy.yaml']
    volumeMounts:
    - name: config-file-store
      mountPath: /data
  containers:
  - name: envoy
    image: envoyproxy/envoy-alpine:v1.13.1
    command: ['/bin/sh','-c']
    args: ['envoy -c /etc/envoy/envoy.yaml']                          
    volumeMounts:
    - name: config-file-store
      mountPath: /etc/envoy
      readOnly: true
  volumes:
  - name: config-file-store
    emptyDir:                                                               
      medium: Memory
      sizeLimit: 16Mi

kubectl describe pods volumes-emptydir-demo 如果容器不能启动,或者有其他问题,可以用此命令查看详细的状态

示例2:hostPath(docker 默认)

kubectl explain pods.spec.volumes.hostPath

        path:宿主机的路径

hostPath的文件类型

 File:事先必须存在的文件路径;
 Directory:事先必须存在的目录路径;


 DirectoryOrCreate:指定的路径不存时自动将其创建为0755权限的空目录,属主属组均为kubelet;

 FileOrCreate:指定的路径不存时自动将其创建为0644权限的空文件,属主和属组同为kubelet;

 Socket:事先必须存在的Socket文件路径;

 CharDevice:事先必须存在的字符设备文件路径;

 BlockDevice:事先必须存在的块设备文件路径;

 "":空字符串,默认配置,在关联hostPath存储卷之前不进行任何检查。

[root@node01 chapter5]# cat volumes-hostpath-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: volumes-hostpath-demo
spec:
  containers:
  - name: filebeat
    image: ikubernetes/filebeat:5.6.7-alpine
    env:
    - name: REDIS_HOST
      value: redis.ilinux.io:6379
    - name: LOG_LEVEL
      value: info
    volumeMounts:
    - name: varlog
      mountPath: /var/log
    - name: socket
      mountPath: /var/run/docker.sock
    - name: varlibdockercontainers
      mountPath: /var/lib/docker/containers
      readOnly: true
  volumes:
  - name: varlog
    hostPath:
      path: /var/log
  - name: varlibdockercontainers
    hostPath:
      path: /var/lib/docker/containers
  - name: socket
    hostPath:
      path: /var/run/docker.sock
 

kubectl exec -it volumes-hostpath-demo   -- /bin/sh  #进入容器内部查看相关挂载,有的目录和宿主机的目录内内容一致。

示例3:nfs存储卷

节点配置好nfs的驱动,但是不需要挂载,也就时安装nfs-utils

===========================

pvc

        消费和供给职能分离开来,管理员去管理存储设备的细节,用户表明需求就能创建出来。

pv有两种供给方式,1.管理员手动事先创建好,按照开发需求    2.借助stroge class所创建的模版来实现,动态供给。(需要存储本身支持,nfs不支持。ceph 支持)

#pv 也属于集群级别,不属于任何名称空间。 

 Dev 需要claims pv,需要通过claim去跟某一个由管理员手动创建的pv建立绑定关系(有那么多pv ,那到底分配那个呢。是有申请需求来决定的)

                需求:希望的存储空间多大,是否支持单路读写,多路读写。期望到那个存储类上去申请(存储类既是动态创建存储卷pv的模版也是pv和pvc的名称空间 ,一旦创建一个存储类叫storage class,任何pvc申请的目标只能在同一存储类中去找pv,pvc去绑定pv 时只能在同一存储类中实现。而pv与pvc 的关联关系,我们称为bound。一个pv 和一个pvc一一对应。pvc 的作用是可以被pod当中 使用类似hostpath 一样的存储卷来使用)

 kubectl explain pods.spec.volumes.persistentVolumeClaim
 

使用过程

管理员设置一个pv的供给方,在存储集群上创建一到多个pv,每一个pv 一定要关联到真正的存储空间上。

当用户使用pv的存储空间的时候 1.先创建一个pvc资源,pvc资源与pv建立关联关系2.创建pod,使用pvc类型的存储卷与pvc建立关联关系,

=====================

马哥笔记

PVC和PV
  PVC: Persistent Volume Claim,持久卷申请,简称PVC;k8s上标准的资源类型之一; 由用户使用;名称空间级别; 
  PV: Persistent Volume,持久卷,可被PVC绑定;而PV一定要与某个真正的存储空间(一般是网络存储服务上的存储空间)对应起来,才能真正存储数据。由集群管理员负责管理。集群级别。

  PVC创建完成后,需要找到最为匹配的PV,并与之绑定。
    在哪儿找:
      二者要么都不属于任何StorageClass资源,要么属于同一个StorageClass资源;
    怎么找:

===============================================================

除了存储卷插件之外,PersistentVolume资源规范Spec字段主要支持嵌套以下几个通用字段,它们用于定义PV的容量、访问模式和回收策略等属性。
 capacity <map[string]string>:指定PV的容量;目前,Capacity仅支持存储容量设定,将来还应该可以指定IOPS和吞吐量(throughput)。

 accessModes  <[]string>:指定当前PV支持访问模式;存储系统支持存取能力大体可分为ReadWriteOnce(单路读写)、ReadOnlyMany(多路只读)和ReadWriteMany(多路读写)三种类型,某个特定的存储系统可能会支持其中的部分或全部的能力。

 persistentVolumeReclaimPolicy <string>:PV空间被释放时的处理机制;可用类型仅为Retain(默认)、Recycle或Delete。目前,仅nfs和hostPath支持Recycle策略,也仅有部分存储系统支持Delete策略。

#pv 回收策略,删掉pvc后,pv 保留--Retain,其余略

存储类动态创建默认是delete

Recycle :只把pv 上的数据删掉。--新版被废弃

delete   :不但删除数据,连pv 都删掉 

所以pv 的状态就有binding   available,reclaim(回收状态)

总结pv 的生命周期

provisioning

binding

Using

Reclaiming     回收又有上述三种回收策略

问题:为什么pvc 创建就能触发动态供给pv ?

依赖于存储类,将外部系统在k8s 之上定义另外一个类型资源叫做存储类,sc.   sc 定义了如何链接外置存储系统的管理接口,api 的。它配置了各种各样的参数,并且知道怎么链接到管理接口上,如果需要认证还能认证过去,必要时调管理命令,创建逻辑单元。并在sc 内部创建pv.所以pv 是属于sc 的。pvc去请求pv 时如果通过sc 来实现。那么pvc 也属于sc.pvc 只能向同一个sc 请求绑定。pvc 只能向同一个sc 请求绑定,pvc 属于存储类1,那么只能向存储类1提供申请。

以上是动态供给内容,

没有动态存储类那么就要自己pv.

1.k8s 管理员负责把外部系统之上的存储空间映射到集群上定义pv

2.用户使用时定义pvc绑定pv,定义pod 使用pvc

3;.pod 容器挂载存储卷

集群访问模式的几种类型。

 volumeMode <string>:该PV的卷模型,用于指定此存储卷被格式化为文件系统使用还是直接使用裸格式的块设备;默认值为Filesystem,仅块设备接口的存储系统支持该功能。

 storageClassName <string>:当前PV所属的StorageClass资源的名称,指定的存储类需要事先存在;默认为空值,即不属于任何存储类。

 mountOptions <string>:挂载选项组成的列表,例如ro、soft和hard等。

 nodeAffinity <Object>:节点亲和性,用于限制能够访问该PV的节点,进而会影响到使用与该PV关联的PVC的Pod的调度结果。

创建pvc

NFS服务器操作:

 mkdir /data/redis00{1..5} -p

 yum install nfs-utils

 mkdir /data/redis

[root@yuanlichao ~]# cat /etc/exports
/data/redis   172.16.1.0/24(rw)
/data/redis001   172.16.1.0/24(rw)

exportfs  -ar   #不用重启直接导出

showmount  -e 

useradd redis -u 1005
chown redis  /data/*

客户端查看:showmount  -e  172.16.1.203

pv 演示:pv 不属于名称空间,不能定义namespace,只不过将volume资源让管理员来做了。加了一个中间层。

[root@node01 chapter5]# cat  pv-nfs-002.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-002
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path:  "/data/redis002"
    server: 172.16.1.203

创建pvc : pvc 是属于名称空间的。

[root@node01 chapter5]# cat pvc-demo-0001.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo-0001
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  volumeMode: Filesystem
  resources:
    requests:
      storage: 3Gi
    limits:
      storage: 10Gi
 

 创建pod 使用pvc。pod 使用,容器挂载

[root@node01 chapter5]# cat volumes-pvc-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: volumes-pvc-demo
  namespace: default
spec:
  containers:
  - name: redis
    image: redis:alpine
    imagePullPolicy: IfNotPresent
    securityContext:
      runAsUser: 1005
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-rbd-vol
  volumes:
  - name: redis-rbd-vol
    persistentVolumeClaim:
      claimName: pvc-demo-0001
 

即使pod删掉重建数据也没有问题

pv  删除保护机制。

用户需要删除一个pv的时候,pv 正在被pvc所使用着呢。是不会被删掉的,1.11版本引入的

1.删除一个pvc 测试

2.一直处于等待状态,并没有被真正删除

3.删除pod,pvc 返回删除成功

4.pv 状态

released 表示曾经有用过这个数据,只不过被释放了。不允许再被绑定

5.手动删除pv

6.手动删除数据

在处处上手动删除数据,需要很谨慎。

动态类

目前只能了解

特殊类型的存储卷,configmap ,secret

环境变量配置缺陷:启动时被装入,被替换的。一旦替换,无法更改。

存储卷方式去做:也是启动时被装入。即使更改,进程也需要reload.

如果一个控制器下要求有5个pod ,那么配置信息应该是一样的。共享一个存储卷,才是正确的。

================================================

OCI:open container initiative     属于LSF

        RUNTIME-SPEC:运行时规范.容器运行时

        image-spec:        镜像规范

 docker将容器镜像格式,runtime(runc),捐给了       OCI。之后将更高级运行时,containerd又捐给了CNCF

 

Pod使用这类存储的步骤:
  Admin:创建好PV;
  User: 按需创建PVC,而后创建Pod,在Pod调用persistentVolumeClaim类型的存储卷插件调用同一个名称空间中的PVC资源;

存储卷:隶属于Pod,而非容器; pause容器支撑
    
    kubelet为了支持存储卷,内建了很多存储服务的客户端; 
        临时存储:emptyDir
        主机级别的存储:hostPath
        网络级别的存储:具有持久能力的存储; 
            云存储:awsEBS、...
            NAS(network attached storage):NFS、...
            SAN(Storage Area Network):FC,iSCSI, ...
            SDS(Software Defined Storage): Ceph(rbd, cephfs)、...
        pvc: 
            Pod(pvc plugin) -> PVC(同一名称空间) -> PV

        In-Tree 存储插件

    PV、PVC:将存储消费,存储创建的职能分离开来,
        PV:由管理员定义的,将真正的存储设备上的一段存储空间抽象成的k8s的对象; 集群级别;
            NFS exported 目录;
        PVC:由用户定义出存储消费需求,而后根据需求条件与现有各PV进行匹配检测,找出一个最佳的使用。名称空间级别,Pod只能调用与自己在同一名称空间中的PVC;

    StorageClass:模板, 简称SC;PV和PVC都可属于某个特定的SC;
        模拟为名称空间:一个PVC只能够在自己所处的SC内找PV;或者,一个不属于任何SC的PVC只能够在不属于任何SC的PV中进行筛选;
        创建PV的模板:可以将某个存储服务与SC关联起来,并且将该存储服务的管理接口提供给SC,从而让SC能够在存储服务上CRUD(Create、Read、Update和Delete)存储单元;
            因而,在同一个SC上声明PVC时,若无现存可匹配的PV,则SC能够调用管理接口直接创建出一个符合PVC声明的需求的PV来。这种PV的提供机制,就称为Dynamic Provision。


        ceph中的rbd支持动态预配,但kubeadm部署的k8s集群,却不支持该功能,原因在于kube-controller-manager镜像内部未内置ceph客户端工具。

        Controller Manager,静态Pod,PV Controller和PVC Controller都在controller manager 的pod中,容器的文件系统与其他容器的文件系统是隔离的。与宿主机的文件系统也是隔离的。任何一个对应的组件想访问存储服务。要有存储服务的客户端,这个镜像没有客户端,所以不能对ceph进行增删改查。

    Out-of-Tree:存储卷,由管理员通过flexVolume或CSI接入的第三方存储卷类型; 

=======================================================

 kubeadm token create --print-join-command
单独生成token加入节点命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值