7.kubernetes存储卷、持久卷、pv和pvc、NFS CSI部署示例
  IS4yhiOomKTv 2023年11月02日 34 0

pod资源规范总结

    资源类型获取:
        kubectl aip-resources
    资源群组获取:
        kubectl aip-versions
    特定资源的规范获取:
        kubectl explain <Kind>.

pod运行

自主式pod,非受控于工作负载型控制器
   直接由kubelet管理
   
    apiVersion: v1
    kind: Pod
    metadata:
      name: 
      namespace:
      lables:
        key1: value1:
    spec:
      containers:     (唯一的必选字段,对象列表)
        - name:
          image:
        - name:
          image:
        - name:
          image:
          securityContext: {}(安全上下文)用在容器里
          startProbe:{}(初始化探针)
          livenessProbe:{}(就 绪状态探针,会重启)
          readinessProbe:{}(探测service会不会把pod作为端点)
          command:[]string (自定义要运行的命令,字串列表)
          args: []string(自定义传参数)
          resources:{}(需求,预留资源)
              cpu: 100m
              memory: 512Mi
          limits:{}(上限,最大资源的边界)
          env: {}(环境变量)
            - name:
              value:
        imagePullPolicy:{}(镜像下载策略) ----明细
        restartPolicy: (重启策略) ----明细
        securityContext: {}(安全上下文)用在pod里

编写声明式资源配置,生成yaml文件模板:
   kubectl run POD_NAME --image=<image> --dry-run=client -o yaml
   
或者使用Web UI:资源配置生成向导
   华为云CCE
   阿里云ACK

超亲密关系

关于容器设计模式

单节点多容器模式:
  Sidecar模式:辅助容器用于为主容器提供辅助服务以增强主容器的功能
  Ambassador模式:大使模式
  Adapter模式:将自己的业务读取并转换为外部能识别的业务
  Init Container模式:初始化容器,在主容器运行之前

存储卷

卷类型及插件

In-Tree存储卷插件
  ◼ 临时存储卷
     ◆emptyDir
  ◼ 节点本地存储卷
     ◆hostPath, local
  ◼ 网络存储卷
     ◆文件系统:NFS、GlusterFS、CephFS和Cinder
     ◆块设备:iSCSI、FC、RBD和vSphereVolume
     ◆存储平台:Quobyte、PortworxVolume、StorageOS和ScaleIO
     ◆云存储:awsElasticBlockStore、gcePersistentDisk、azureDisk和azureFile
  ◼ 特殊存储卷
     ◆Secret、ConfigMap、DownwardAPI和Projected
  ◼ 扩展接口
     ◆CSI和FlexVolume
Out-of-Tree存储卷插件
  ◼ 经由CSI或FlexVolume接口扩展出的存储系统称为Out-of-Tree类的存储插件
存储卷资源规范
定义存储卷
    ◼ 存储卷对象并非Kubernetes系统一等公民,它需要定义在
Pod上
    ◼ 卷本身的生命周期同Pod,但其后端的存储及相关数据的
生命周期通常要取决于存储介质
存储卷的配置由两部分组成
    ◼ 通过.spec.volumes字段定义在Pod之上的存储卷列表,它经
由特定的存储卷插件并结合特定的存储供给方的访问接口
进行定义
    ◼ 嵌套定义在容器的volumeMounts字段上的存储卷挂载列表,
它只能挂载当前Pod对象中定义的存储卷


spec:
  volumes:
  - name <string> 
  # 卷名称标识,仅可使用DNS标签格式的字符,在当前Pod中必须惟一;
    VOL_TYPE <Object> 
    # 存储卷插件及具体的目标存储供给方的相关配置;
  containers:
  - name: …
    image: …
    volumeMounts:
    - name <string> 
     # 要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义;
      mountPath <string> 
       # 容器文件系统上的挂载点路径;
      readOnly <boolean> 
       # 是否挂载为只读模式,默认为否;
      subPath <string> 
       # 挂载存储卷上的一个子目录至指定的挂载点;
      subPathExpr <string> 
       # 挂载由指定的模式匹配到的存储卷的文件或目录至挂载点;
      mountPropagation <string> 
       # 挂载卷的传播模式;
       
        
获取内置的卷插件类型:
   kubectl explain pods.spec.volumes
emptyDir存储卷
emptyDir存储卷
  ◼ Pod对象上的一个临时目录
  ◼ 在Pod对象启动时即被创建,而在Pod对象被移
除时一并被删除
  ◼ 通常只能用于某些特殊场景中
    ◆同一Pod内的多个容器间文件共享
    ◆作为容器数据的临时存储目录用于数据缓存系统
配置参数
  ◼ medium:此目录所在的存储介质的类型,可用
值为“default”或“Memory”
  ◼ sizeLimit:当前存储卷的空间限额,默认值为nil,
表示不限制

emptyDir存储卷示例

生成配置模板:
[root@k8s-master02 ~]#kubectl run pods-with-emptyDir-vol --image=ikubernetes/admin-box:v1.2 --dry-run=client -o yaml > pods-with-emptyDir-vol.yaml
修改完善配置文件:
[root@k8s-master02 ~]#vim pods-with-emptyDir-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: pods-with-emptyDir-vol
spec:
  containers:
  - image: ikubernetes/admin-box:v1.2
    name: admin
    command: ["/bin/sh", "-c"]
    args: ["sleep 99999"]
    resources: {}
    volumeMounts:
    - name: data
      mountPath: /data
  - image: ikubernetes/demoapp:v1.0
    name: demoapp
    resources: {}
    volumeMounts:
    - name: data
      mountPath: /var/www/html
  volumes:
  - name: data
    emptydir:
      medium: Memory
      sizelimit: 16Mi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

[root@k8s-master02 ~]#kubectl apply -f pods-with-emptyDir-vol.yaml 
pod/pods-with-emptydir-vol created

进入admin的交互式接口,进入挂载目录创建一个文件:
[root@k8s-master02 ~]#kubectl exec -it pods-with-emptydir-vol -c admin -- /bin/sh
root@pods-with-emptydir-vol # cd /data
root@pods-with-emptydir-vol data# ls
root@pods-with-emptydir-vol data# touch test.txt
root@pods-with-emptydir-vol data# vi test.txt 
root@pods-with-emptydir-vol data# exit

进入demoapp的交互式接口,查看挂载目录已经有admin创建的文件:
[root@k8s-master02 ~]#kubectl exec -it pods-with-emptydir-vol -c demoapp -- /bin/sh
[root@pods-with-emptydir-vol /]# cd /var/www/html/
[root@pods-with-emptydir-vol /var/www/html]# ls
test.txt
[root@pods-with-emptydir-vol /var/www/html]# cat test.txt 
Hi demoapp
追加数据进去:
[root@pods-with-emptydir-vol /var/www/html]# echo "Hi admin" >> test.txt 
[root@pods-with-emptydir-vol /var/www/html]# exit
在admin里面能看到追加的数据:
[root@k8s-master02 ~]#kubectl exec -it pods-with-emptydir-vol -c admin -- /bin/sh
root@pods-with-emptydir-vol # cd data/
root@pods-with-emptydir-vol data# cat test.txt 
Hi demoapp
Hi admin
root@pods-with-emptydir-vol data#
实现了两个pod共同挂载一个存储卷,挂载到各自不同的目录,实现数据共享

卷的生命周期跟pod一样,pod删除,卷的数据也就没了
hostPath存储卷
hostPath卷
  ◼ 将Pod所在节点上的文件系统的某目录用作存储卷
  ◼ 数据的生命周期与节点相同
配置参数
  ◼ path:指定工作节点上的目录路径,必选字段
  ◼ type:指定节点之上存储类型

hostpath存储卷示例

[root@k8s-master02 ~]#vim pod-with-hostpath-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis:6
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: redisdata
      mountPath: /data
  volumes:
  - name: redisdata
    hostPath:
      type: DirectoryOrCreate
      path: /data/redis

[root@k8s-master02 ~]#kubectl apply -f pod-with-hostpath-vol.yaml
pod/redis created

查询redis运行的节点:在node02上
[root@k8s-master02 ~]#kubectl get pods -o wide
redis                        1/1     Running       0             84s   10.244.4.10   k8s-node02   <none>
在主服务器进入redis交互式:并写入数据
[root@k8s-master02 ~]#kubectl exec -it redis -- /bin/sh
# redis-cli             
127.0.0.1:6379> SET mykey magedu.com
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit
# ls /data
dump.rdb

到运行redis的node02节点上查看挂载目录下:
[root@k8s-node02 ~]#cd /data/redis/
[root@k8s-node02 redis]#ls
dump.rdb
说明redis的存储数据实在node02节点上的

此时,pod删除,利用相同的yaml文件重建redis,如果刚好重载在同一个节点,那么redis下的数据会依然在,得到数据保持
NFS存储卷
nfs存储卷
  ◼ 将nfs服务器上导出(export)的文件系统用作存储卷
  ◼ nfs是文件系统级共享服务,它支持多路挂载请求,可由多
个Pod对象同时用作存储卷后端
配置参数
  ◼ server <string>:NFS服务器的IP地址或主机名,必选字段
  ◼ path <string>:NFS服务器导出(共享)的文件系统路径,
必选字段
  ◼ readOnly <boolean>:是否以只读方式挂载,默认为false

NFS存储卷示例

新的服务器下载nfs-kernel-server,作为nfs服务端:ip:10.0.0.106
apt -y install nfs-kernel-server
创建目录:
mkdir /data/redis00{1,2,3} -pv
将此目录共享出去:
vim /etc/exports
/data/redis001   10.0.0.0/24(rw,no_subtree_check,no_root_squash)
启动服务:
systemctl start nfs-server
检查:
exports -ar
查看2049端口是否开启:
ss -ntl

应kubernetes客户端节点,下载nfs客户端
apt install nfs-common
mkdir /data
将nfs服务器共享的目录挂载到本节点/data下:
mount -t nfs 10.0.0.106:/data/redis001 /data
在客户节点data下创建文件:
cd /data
touch a.txt

再查看服务节点:所有节点写的数据实际存在了nfs-server上
cd /data/redis001
ls
a.txt


基于pod实现nfs
所有节点下载nfs客户端:
apt install nfs-common
写yaml配置文件:
[root@k8s-master02 ~]#vim pod-with-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-nfs
spec:
  containers:
  - name: redis
    image: redis:6
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: redisdata
      mountPath: /data
  volumes:
  - name: redisdata
    nfs:
      server: 10.0.0.106
      path: /data/redis001
进入交互式页面创建数据:
Kubectl exec -it redis-nfs -- /bin/sh
#redis-cli
#SET testkey www.magedu.com
ok
#BGSAVE
#exit
#ls /data
dump.rdb

此时在NFS-server上查看:
cd /data/redis001
ls
dump.rdb

此时,如果重建redis或再建一个新的redis,不管被分配到哪个节点上,都能加载到nfs下的数据,删除redis,也不会删除nfs的数据
持久卷
PV如何满足PVC期望?
1、管理员事先创建多种规格的PV; 
2、管理流程:提交工单;

  PV静态置备(Static Provisioning)
            
3、管理员不去创建PV,取而代之,创建StorageClass(PV模板)
   管理员创建SC资源对象:配置了远程存储服务管理接口的API调用操作
   远程存储服务:有管理API,而且还要支持远程访问

  PV动态置备(Dynamic Provisioning)

PV和PVC示例:

基于NFS的静态PV和PVC示例

access modes支持的模块:
RWO - ReadWriteOnce  单路可写
ROX - ReadOnlyMany   多路只读
RWX - ReadWriteMany  多路可写
RWOP - ReadWriteOncePod  单路单pod可写
NFS PV 资源定义示例
[root@k8s-master02 chapter5]#vim pv-nfs-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-demo
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path:  "/data/redis002"
    server: 10.0.0.106

kubectl apply -f pv-nfs-demo.yaml
kubectl get pv
在NFS-server上共享/data/redis002出目录:
[root@NFS]#vim /etc/exports
/data/redis002  10.0.0.0/24(rw,no_subtree_check,no_root_squash)
[root@NFS]#exportfs -ar
[root@NFS]#showmount -e 10.0.0.106
PVC 资源定义示例
[root@k8s-master02 chapter5]#vim 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

kubectl apply -f pvc-demo-0001.yaml
kubectl get pvc -n default
此时再看Pv属于bind状态
[root@ubuntu2004 chapter5]#kubectl get pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
pv-nfs-demo   5Gi        RWO,ROX,RWX    Retain           Bound    default/pvc-demo-0001                           24s
在Pod上使用PVC卷
[root@k8s-master02 chapter5]#vim volumes-pvc-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc-demo
  namespace: default
spec:
  containers:
  - name: redis
    image: redis:6
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-pvc-vol
  volumes:
  - name: redis-pvc-vol
    persistentVolumeClaim:
      claimName: pvc-demo-0001
      
kubectl apply -f volumes-pvc-demo.yaml
此时redis基于NFS的PV已创建好
进入pod-pvc-demo的交互式接口:
kubectl exec -it pod-pvc-demo -- /bin/sh
#redis-cli
172.20.0.1:6379> SET hikey www.mm.com
ok
172.20.0.1:6379> BGSAVE
172.20.0.1:6379> exit
#ls /data
dump.rdb

到后端NFS-server上验证
ls /data/redis002
dump.rdb

即使删除pod,PV和PVC还在,只删除PVC那么PV会处于pending状态,新建的PVC不会再绑定在上面
PVC需要单独删除:kubectl delete pvc pvc-demo-001

动态pv

storageclass

StorageClass资源
   ◼ Kubernetes支持的标准资源类型之一
   ◼ 为管理PV资源之便而按需创建的存储资源类别(逻辑组)
   ◼ 是PVC筛选PV时的过滤条件之一
   ◼ 为动态创建PV提供“模板”
      ◆需要存储服务提供管理API
      ◆StorageClass资源上配置接入API的各种参数
          ⚫ 定义在parameters字段中
          ⚫ 还需要使用provisioner字段指明存储服务类型
   ◼ 一般由集群管理员定义,隶属集群级别
StorageClass资源示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io     #后端存储服务器
parameters:
  server: nfs-server.default.svc.cluster.local #IP或名字
  share: /                                #共享挂载的目录
reclaimPolicy: Delete                     #回收策略
volumeBindingMode: Immediate              #绑定模式
mountOptions:
  - hard
  - nfsvers=4.1

PVC和动态PV示例

PVC向StorageClass申请绑定PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
spec:
  accessModes:
    - ReadWriteMany
resources:
requests:
  storage: 10Gi
storageClassName: nfs-csi


Out-of-Tree存储

◼容器存储接口规范,与平台无关
◼驱动程序组件
  CSI Controller:负责与存储服务的API通信从而完成后端存储的管理操作
  node plugin:node插件,每个节点都要部署,也称为CSI Node,负责在节点级别完成存储卷的管理,用于扩展卷插件类型以及卷管理器所能支持的卷插件管理类型

CSI存储组件和部署架构

CSI Controller:由StatefulSet控制器对象编排运行,副本量需要设置为1,以保证只会该存储服务运行单
个CSI Controller实例;
Node Plugin:由DaemonSet控制器对象编排运行,以确保每个节点上精确运行一个相关的Pod副本

部署NFS CSI

1.部署nfs server;
2.部署nfs csi driver;
3.创建storageclass,配置CSI Driver引用前面部署的nfs server为存储后端;
4.测试:在storageclass内部,创建一个PVC,验证PVC的动态置备功能
1.部署nfs server
默认部署在default名称空间下,我们可以自己创建名称空间
[root@k8s-master02 ~]#kubectl create namespace nfs
namespace/nfs created
[root@k8s-master02 ~]#kubectl get ns
NAME              STATUS   AGE
default           Active   2d10h
demo              Active   2d10h
kube-flannel      Active   2d10h
kube-node-lease   Active   2d10h
kube-public       Active   2d10h
kube-system       Active   2d10h
nfs               Active   34s
下载镜像并生成pod:
[root@k8s-master02 ~]#kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/deploy/example/nfs-provisioner/nfs-server.yaml --namespace nfs
service/nfs-server created
deployment.apps/nfs-server created
查看生成的pod:
[root@k8s-master02 ~]#kubectl get pods -n nfs
NAME                          READY   STATUS    RESTARTS   AGE
nfs-server-5847b99d99-lqbp8   0/1     Pending   0          96s
并且还创建了一个server:
[root@k8s-master02 ~]#kubectl get svc -n nfs -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE     SELECTOR
nfs-server   ClusterIP   10.100.177.177   <none>        2049/TCP,111/UDP   3m47s   app=nfs-server
2.部署nfs csi driver
在线部署NFS CSI driver v3.1.0:会自动部署到所有节点
[root@k8s-master02 ~]#curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v3.1.0/deploy/install-driver.sh | bash -s v3.1.0 --
Installing NFS CSI driver, version: v3.1.0 ...
serviceaccount/csi-nfs-controller-sa created
clusterrole.rbac.authorization.k8s.io/nfs-external-provisioner-role created
clusterrolebinding.rbac.authorization.k8s.io/nfs-csi-provisioner-binding created
csidriver.storage.k8s.io/nfs.csi.k8s.io created
deployment.apps/csi-nfs-controller created
daemonset.apps/csi-nfs-node created
NFS CSI driver installed successfully.

检查pod执行状态:
kubectl -n kube-system get pod -o wide -l app=csi-nfs-controller
kubectl -n kube-system get pod -o wide -l app=csi-nfs-node
     确保状态为running即可:
NAME                                       READY   STATUS    RESTARTS   AGE     IP             NODE
csi-nfs-controller-56bfddd689-dh5tk       4/4     Running   0          35s     10.240.0.19    k8s-agentpool-22533604-0
csi-nfs-controller-56bfddd689-8pgr4       4/4     Running   0          35s     10.240.0.35    k8s-agentpool-22533604-1
csi-nfs-node-cvgbs                        3/3     Running   0          35s     10.240.0.35    k8s-agentpool-22533604-1
csi-nfs-node-dr4s4                        3/3     Running   0          35s     10.240.0.4     k8s-agentpool-22533604-0
3.创建storageclass,配置CSI Driver引用前面部署的nfs server为存储后端
[root@k8s-master02 ~]#vim storageclass-nfs.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  #server: nfs-server.default.svc.cluster.local
  server: nfs-server.nfs.svc.cluster.local
  share: /
#reclaimPolicy: Delete
reclaimPolicy: Retain
volumeBindingMode: Immediate
mountOptions:
  - hard
  - nfsvers=4.1
  
创建pod:storageclass是集群级别的资源,不需要指定名称空间
[root@k8s-master02 ~]#kubectl apply -f storageclass-nfs.yaml 
storageclass.storage.k8s.io/nfs-csi created

查看可以看到有一个nfs-csi的sc:
[root@k8s-master02 ~]#kubectl get sc
NAME      PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-csi   nfs.csi.k8s.io   Retain          Immediate           false                  74s
4.测试:在storageclass内部,创建一个PVC,验证PVC的动态置备功能
请求创建PVC,里面指定了sc指向刚才创建的nfs-csi:
(1)在线创建:
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/release-3.1/deploy/example/pvc-nfs-csi-dynamic.yaml
(2)本地创建:
[root@k8s-master02 ~]#vim dynamic-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi
[root@k8s-master02 ~]#kubectl apply -f dynamic-pvc.yaml 
persistentvolumeclaim/pvc-nfs-dynamic created
[root@k8s-master02 ~]#kubectl get pvc
会看见处于bound状态,自动创建了一个PV
结果验证:
创建pod,测试动态置备的PVC卷是否可用
[root@k8s-master02 chapter5]#vim volumes-pvc-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-dyn-pvc
  namespace: default
spec:
  containers:
  - name: redis
    image: redis:6
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
      name: redisport
    volumeMounts:
    - mountPath: /data
      name: redis-pvc-vol
  volumes:
  - name: redis-pvc-vol
    persistentVolumeClaim:
      claimName: pvc-nfs-dynamic
[root@k8s-master02 chapter5]#kubectl apply -f volumes-pvc-demo.yaml
pod/redis-dyn-pvc created

进入交互式接口:
[root@k8s-master02 chapter5]#kubectl exec -it redis-dyn-pvc -- /bin/sh
创建数据,退出后删除pod,重新创建pod,再进入交互式接口查看之前的数据,会发现之前的数据还在
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  cO5zyEmh8RH6   2023年12月09日   27   0   0 k8s证书
  eHipUjOuzYYH   2023年12月07日   28   0   0 数据乐观锁redis
  ozzp9aSSE46S   2023年11月30日   33   0   0 DNSIPPod
  YKMEHzdP8aoh   2023年12月11日   67   0   0 DNSidePod