存储卷管理

卷是什么?

  • 卷是一个抽象化的存储设备.

为什么要使用卷?

  • 卷可以解决容器崩溃或重启后历史数据丢失的问题
  • 卷可以解决容器或Pod被删除后数据持久保存的问题
  • 卷可以解决在多个容器内共享数据的问题
  • Pod可以同时使用任意数目的卷。

k8s支持的卷类型

  • 持久卷:持久卷是集群中的存储资源,就像他的名字一样,在里面存储的数据不会随着Pod的删除而丢失。
  • 临时卷:有些应用程序需要额外的存储,但并不关心数据在重启后是否仍然可用。卷会遵从Pod的生命周期,与Pod一起创建和删除。
  • 投射卷:它允许您将多个现有卷源映射到同一个目录。通过将这些不同类型的卷源组合成一个统一的卷,可以更方便地管理和使用这些资源。

Pod 资源文件

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  containers:

  - name: nginx

    image: myos:nginx

持久卷

hostPath是持久卷

  • hostPath卷的本质是使用本地设备,例如磁盘、分区、目录、Socket、 CharDevice 和 BlockDevice 等等。 hostPath卷的可用性取决于底层节点的可用性,如果节点变得不健康,那么hostPath卷也将不可被访问。
  • hostPath卷里面的数据不会随着Pod的结束而消失。
  • 注意事项:配置相同的Pod,可能在不同的节点上表现不同,因为不同节点上映射的文件内容不同
hostPath 卷

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:                              # 卷定义

  - name: logdata                       # 卷名称

    hostPath:                           # 使用hostPath 创建卷

      path: /var/weblog                 # 在节点上存放的路径

      type: DirectoryOrCreate           # 目录不存在就创建

  containers:

  - name: nginx

    image: myos:nginx

    volumeMounts:                       # mount 卷

    - name: logdata                     # 卷名称

      mountPath: /usr/local/nginx/logs  # 容器内路径

  • 验证 hostPath 卷

[root@master ~]# kubectl apply -f web1.yaml 

pod/web1 created

[root@master ~]# kubectl get pods -o wide

NAME   READY   STATUS    RESTARTS   AGE     IP             NODE

web1   1/1     Running   0          45m     10.244.2.16    node-0002

[root@master ~]# curl http://10.244.2.16/

Nginx is running !

# 删除Pod ,日志数据也不会丢失

[root@master ~]# kubectl delete pod web1

pod "web1" deleted

# 来到 node 上查看日志

[root@node-0002 ~]# cat /var/weblog/access.log 

10.244.0.0 - - [27/Jun/2022:02:00:12 +0000] "GET / HTTP/1.1" 200 19 "-" "curl/7.29.0"

NFS 卷

NFS存储

  • k8s中允许将nfs存储以卷的方式挂载到你的Pod中。
  • 在删除Pod时,nfs存储卷会被卸载(umount),而不是被删除。nfs卷可以在不同节点的Pod之间共享数据。

NFS卷的用途

  • NFS最大的功能就是在不同节点的不同Pod中共享读写数据。本地NFS的客户端可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。
名称 IP地址
nfs 192.168.88.240
  • 配置 NFS 服务

# 创建共享目录,并部署测试页面

[root@harbor ~]# mkdir -p /var/webroot

[root@harbor ~]# echo "nfs server" >/var/webroot/index.html

# 部署 NFS 服务

[root@harbor ~]# dnf install -y nfs-utils

[root@harbor ~]# vim /etc/exports

/var/webroot    192.168.0.0/16(rw,no_root_squash)

[root@harbor ~]# systemctl enable --now nfs-server.service

#----------------------------------------------------------#

# 所有 node 节点都要安装 nfs 软件包

[root@node ~]# dnf install -y nfs-utils

  • Pod调用NFS卷

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:

  - name: logdata

    hostPath:

      path: /var/weblog

      type: DirectoryOrCreate

  - name: website                       # 卷名称

    nfs:                                # NFS 资源类型

      server: 192.168.88.240            # NFS 服务器地址

      path: /var/webroot                # NFS 共享目录

  containers:

  - name: nginx

    image: myos:nginx

    volumeMounts:                     #映射存储卷

    - name: logdata

      mountPath: /usr/local/nginx/logs

    - name: website                     # 映射的存储卷名称

      mountPath: /usr/local/nginx/html  # 映射到容器中的路径

[root@master ~]# kubectl apply -f web1.yaml 

pod/web1 created

[root@master ~]# kubectl get pods -o wide

NAME   READY   STATUS    RESTARTS   AGE   IP            NODE

web1   1/1     Running   0          12m   10.244.1.19    node-0001

  • 访问验证 nfs 卷

[root@master ~]# curl http://10.244.1.19 

nfs server

PV/PVC

PV/PVC 是什么?

  • PV的全称是PersistentVolume,是持久卷-PVC的全称是 PersistentVolumeClaim,是持久卷声明

PV/PVC有什么用途?

  • 存储的管理是一个与计算实例的管理完全不同的问题。管理员希望能提供一种通用的API来完成Pod对卷的部署管理与使用。PV/PVC就是为了满足这种需求而诞生的,PV/PVC的引入使集群具备了存储的逻辑抽象能力。
持久卷

[root@master ~]# vim pv.yaml

---

kind: PersistentVolume

apiVersion: v1

metadata:

  name: pv-local

spec:

  volumeMode: Filesystem                # 提供资源的类型[Filesystem, Block]

  accessModes:                                 # 存储卷能提供的访问模式

  - ReadWriteOnce                            # hostPath 只支持RWO

  capacity:                                         # 存储卷能提供的存储空间

    storage: 10Gi                               # 空间大小

  persistentVolumeReclaimPolicy: Retain      # 数据回收方式

  hostPath:                                       # hostPath 配置

    path: /var/weblog

    type: DirectoryOrCreate

---

kind: PersistentVolume

apiVersion: v1

metadata:                       

  name: pv-nfs

spec:

  volumeMode: Filesystem            # 提供资源的类型Filesystem

  accessModes:                             # 卷支持的模式,支持多种,RWO,ROX, RWX, RWOP

  - ReadWriteOnce

  - ReadOnlyMany

  - ReadWriteMany

  capacity:

    storage: 5Gi

  persistentVolumeReclaimPolicy: Retain

  mountOptions:

  - nolock

  nfs:

    server: 192.168.88.240

    path: /var/webroot

[root@master ~]# kubectl apply -f pv.yaml 

persistentvolume/pv-local created

persistentvolume/pv-nfs created

[root@master ~]# kubectl get persistentvolume

NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS       AGE

pv-local   10Gi       RWO            Retain           Available    2s

pv-nfs      5Gi       RWO,ROX,RWX    Retain           Available    2s

持久卷声明

[root@master ~]# vim pvc.yaml

---

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: pvc1

spec:                                                 # 定义需求

  volumeMode: Filesystem                 # 需要使用Filesystem 的存储卷

  accessModes:                                 # 需要支持 RWO 的存储卷

  - ReadWriteOnce

  resources:

    requests:

      storage: 8Gi                                 # 最小磁盘空间需求

---

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: pvc2

spec:                                            # 定义需求

  volumeMode: Filesystem            # 需要使用Filesystem 的存储卷

  accessModes:                              # 需要支持 RWO 的存储卷

  - ReadWriteMany                      

  resources:

    requests:

      storage: 3Gi                                # 最小磁盘空间需求

[root@master ~]# kubectl apply -f pvc.yaml 

persistentvolumeclaim/pvc1 created

persistentvolumeclaim/pvc2 created

[root@master ~]# kubectl get persistentvolumeclaims 

NAME   STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE

pvc1   Bound    pv-local   10Gi       RWO                           8s

pvc2   Bound    pv-nfs      5Gi       RWO,ROX,RWX                   8s

  • Pod 挂载 PVC

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:                   # 卷定义

  - name: logdata            # 卷名称

    persistentVolumeClaim:   # 通过PVC引用存储资源

      claimName: pvc1        # PVC名称

  - name: website            # 卷名称

    persistentVolumeClaim:   # 通过PVC引用存储资源

      claimName: pvc2        # PVC名称

  containers:

  - name: nginx

    image: myos:nginx

    volumeMounts:                  

    - name: logdata                 # PVC卷名称

      mountPath: /usr/local/nginx/logs       # 挂载路径 

    - name: website                            # PVC卷名称

      mountPath: /usr/local/nginx/html    # 挂载路径

  • 服务验证

[root@master ~]# kubectl delete pods web1

pod "web1" deleted

[root@master ~]# kubectl apply -f web1.yaml 

pod/web1 created

[root@master ~]# kubectl get pods -o wide

NAME   READY   STATUS    RESTARTS   AGE   IP             NODE

web1   1/1     Running   0          45m   10.244.2.16    node-0002

[root@master ~]# curl http://10.244.2.16 

nfs server

临时卷

configMap是一种临时卷

  • configMap卷提供了向Pod注入配置数据的方法,允许你将配置文件与镜像分离,使容器化的应用具有可移植性。-configMap在使用之前需要先创建它,configMap不是用来保存大量数据的,在其中保存的数据不可超过1MiB。

configMap的用途:

  • 配置环境变量
  • 修改配置文件的参数,数据库的地址等
configMap

# 使用命令创建 configMap

[root@master ~]# kubectl create configmap timezone --from-literal=TZ="Asia/Shanghai" --dry-run=client -o yaml

[root@master ~]# vim timezone.yaml

---

kind: ConfigMap

apiVersion: v1

metadata:

  name: timezone

data:

  TZ: Asia/Shanghai

[root@master ~]# kubectl apply -f timezone.yaml

configmap/timezone created

[root@master ~]# kubectl get configmaps 

NAME               DATA   AGE

kube-root-ca.crt   1      9d

timezone           1      15s

tz                 1      50s

修改系统时区

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:

  - name: logdata

    persistentVolumeClaim:

      claimName: pvc1

  - name: website

    persistentVolumeClaim:

      claimName: pvc2

  containers:

  - name: nginx

    image: myos:nginx

    envFrom:              # 配置环境变量

    - configMapRef:       # 调用资源对象

        name: timezone    # 资源对象名称

    volumeMounts:

    - name: logdata

      mountPath: /usr/local/nginx/logs

    - name: website

      mountPath: /usr/local/nginx/html

[root@master ~]# kubectl delete pods web1

pod "web1" deleted

[root@master ~]# kubectl apply -f web1.yaml 

pod/web1 created

[root@master ~]# kubectl exec -it web1 -- date +%T

10:41:27

nginx 解析 php
添加容器

# 在 Pod 中增加 php 容器,与 nginx 共享同一块网卡

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:

  - name: logdata

    persistentVolumeClaim:

      claimName: pvc1

  - name: website

    persistentVolumeClaim:

      claimName: pvc2

  containers:

  - name: nginx

    image: myos:nginx

    envFrom:

    - configMapRef:

        name: timezone

    volumeMounts:

    - name: logdata

      mountPath: /usr/local/nginx/logs

    - name: website

      mountPath: /usr/local/nginx/html

  - name: php                            # 以下为新增加内容

    image: myos:php-fpm

    envFrom:                             # 不同容器需要单独配置时区

    - configMapRef:

        name: timezone

    volumeMounts:

    - name: website                      # 不同容器需要单独挂载NFS

      mountPath: /usr/local/nginx/html

[root@master ~]# kubectl delete pod web1

pod "web1" deleted

[root@master ~]# kubectl apply -f web1.yaml 

pod/web1 created

[root@master ~]# kubectl get pods

NAME   READY   STATUS    RESTARTS   AGE

web1   2/2     Running   0          5s

[root@master ~]# kubectl exec -it web1 -c nginx -- ss -ltun

Netid     State      Recv-Q     Send-Q    Local Address:Port     ... ...

tcp       LISTEN     0          128             0.0.0.0:80       ... ...

tcp       LISTEN     0          128           127.0.0.1:9000     ... ...

创建 ConfigMap

# 使用 nginx 配置文件创建 configMap

[root@master ~]# kubectl cp -c nginx web1:/usr/local/nginx/conf/nginx.conf nginx.conf

[root@master ~]# vim nginx.conf

        location ~ \.php$ {

            root            html;

            fastcgi_pass    127.0.0.1:9000;

            fastcgi_index   index.php;

            include         fastcgi.conf;

        }

# 使用命令创建 configMap

[root@master ~]# kubectl create configmap nginx-php --from-file=nginx.conf 

configmap/nginx-php created

[root@master ~]# cat nginx-conf.yaml

---

kind: ConfigMap

apiVersion: v1

metadata:

  name: nginx-conf

data:

  nginx.conf: |

    # 以下为原始配置文件内容

    # 注意缩进对其

    # ......

挂载 ConfigMap

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:

  - name: logdata

    persistentVolumeClaim:

      claimName: pvc1

  - name: website

    persistentVolumeClaim:

      claimName: pvc2

  - name: nginx-php     # 卷名称

    configMap:          # 引用资源对象

      name: nginx-php   # 资源对象名称

  containers:

  - name: nginx

    image: myos:nginx

    envFrom:

    - configMapRef:

        name: timezone

    volumeMounts:

    - name: nginx-php                              # 卷名称

      subPath: nginx.conf                          # 键值(文件名称)

      mountPath: /usr/local/nginx/conf/nginx.conf  # 路径

    - name: logdata

      mountPath: /usr/local/nginx/logs

    - name: website

      mountPath: /usr/local/nginx/html

  - name: php

    image: myos:php-fpm

    envFrom:

    - configMapRef:

        name: timezone

    volumeMounts:

    - name: website

      mountPath: /usr/local/nginx/html

[root@master ~]# kubectl replace --force -f web1.yaml 

pod "web1" deleted 

pod/web1 created

解析验证

# 拷贝测试页面 s4/public/info.php

[root@server s4]# rsync -av public/info.php 192.168.88.240:/var/webroot/info.php

#------------------------------------------------------------

[root@master ~]# kubectl get pods -o wide

NAME   READY   STATUS    RESTARTS   AGE   IP             NODE

web1   2/2     Running   0          18s   10.244.3.17    node-0003

[root@master ~]# curl http://10.244.3.17/info.php

<pre>

Array

(

    [REMOTE_ADDR] => 10.244.0.0

    [REQUEST_METHOD] => GET

    [HTTP_USER_AGENT] => curl/7.29.0

    [REQUEST_URI] => /info.php

)

php_host:   web1

1229

secret 卷

secret是一种临时卷

  • Secret类似于ConfigMap但专门用于保存机密数据-在设置Secret.data字段时,所有键值都必须是经过base64编码的字符串

secret的用途:

  • 配置一些需要加密的环境变量或文件(例如:https证书)-访问需要认证登录的私有镜像仓库(例如:harbor私有仓库)
创建变量

[root@master ~]# kubectl create secret generic timezone --from-literal 'TZ="Asia/Shanghai"'

secret/timezone created

[root@master ~]# vim web1.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web1

spec:

  volumes:

  - name: logdata

    persistentVolumeClaim:

      claimName: pvc1

  - name: website

    persistentVolumeClaim:

      claimName: pvc2

  - name: nginx-php

    configMap:

      name: nginx-conf

  containers:

  - name: nginx

    image: myos:nginx

    envFrom:

    - secretRef:         # 使用 secret 设置环境变量

        name: timezone

    volumeMounts:

    - name: nginx-php

      subPath: nginx.conf

      mountPath: /usr/local/nginx/conf/nginx.conf

    - name: logdata

      mountPath: /usr/local/nginx/logs

    - name: website

      mountPath: /usr/local/nginx/html

  - name: php

    image: myos:php-fpm

    envFrom:

    - configMapRef:

        name: timezone

    volumeMounts:

    - name: website

      mountPath: /usr/local/nginx/html

仓库秘钥

[root@master ~]# kubectl create secret docker-registry harbor-auth \

                         --docker-server=harbor:443 \           # 仓库主机端口号

                         --docker-username="用户名" \         # 登录用户名

                         --docker-password="密码"               

secret/harbor-auth created

[root@master ~]# kubectl get secrets harbor-auth -o yaml

apiVersion: v1

data:

  .dockerconfigjson: <经过加密的数据>

kind: Secret

metadata:

  name: harbor-auth

  namespace: default

  resourceVersion: "1558265"

  uid: 08f55ee7-2753-41fa-8aec-98a292115fa6

type: kubernetes.io/dockerconfigjson

认证登录

[root@master ~]# vim web2.yaml 

---

kind: Pod

apiVersion: v1

metadata:

  name: web2

spec:

  imagePullSecrets:                # 引用secret 数据

  - name: harbor-auth             # 资源对象名称

  containers:

  - name: apache

    image: harbor:443/private/httpd:latest         # 使用私有仓库里的镜像

[root@master ~]# kubectl apply -f web2.yaml

pod/web2 created

[root@master ~]# kubectl get pods

NAME   READY   STATUS    RESTARTS   AGE

web1   2/2     Running   0          33m

web2   1/1     Running   0          18m

emptyDir 卷

emptyDir临时卷

  • emptyDir的本质是一个简单的空目录
  • emptyDir可以提供临时空间,同一个Pod中容器也可以用来共享数据。案例:缓存服务器、数据统计分析、排序等。
  • emptyDir随Pod创建而创建,Pod在该节点上运行期间,一直存在。当Pod被从节点上删除时,临时卷中的数据也会被永久删除。
  • 重启Pod中的容器不会造成emptyDir数据的丢失。
临时空间

[root@master ~]# vim web2.yaml

---

kind: Pod

apiVersion: v1

metadata:

  name: web2

spec:

  imagePullSecrets:

  - name: harbor-auth

  volumes:                   # 卷配置

  - name: cache              # 卷名称

    emptyDir: {}             # 资源类型

  containers:

  - name: apache

    image: harbor:443/private/httpd:latest

    volumeMounts:            # 挂载卷

    - name: cache            # 卷名称

      mountPath: /var/cache  # 路径  路径如果不存在,就创建出来路径如果存在,就覆盖

[root@master ~]# kubectl replace --force -f web2.yaml 

pod "web2" deleted

pod/web2 replaced

[root@master ~]# kubectl exec -it web2 -- bash

[root@web2 html]# mount -l |grep cache

/dev/vda1 on /var/cache type xfs (rw,relatime,attr2)

# 清理实验配置

[root@master ~]# kubectl delete pods --all

[root@master ~]# kubectl delete pvc --all

[root@master ~]# kubectl delete pv --all

传递文件

---

kind: Pod

apiVersion: v1

metadata:

  name: web2

spec:

  imagePullSecrets:

  - name: harbor-auth

  volumes:

  - name: cache

    emptyDir: {}

  initContainers:

  - name: task1

    image: myos:latest

    volumeMounts:                         # 初始化任务可以把结果放在卷中

    - name: cache                               # 可以通过卷把数据传递给主容器

      mountPath: /var/cache

    command: ["sh"]                           # 初始化任务

    args:

    - -c

    - |

      echo -e "\n#-----------------#" |tee -a /var/cache/init.log

      ID=${RANDOM}

      echo "获取随机数: ${ID}" |tee -a /var/cache/init.log

      echo "执行初始化任务" |tee -a /var/cache/init.log

      echo "随机数取余 $((ID%2))" |tee -a /var/cache/init.log

      echo "执行初始化任务完成" |tee -a /var/cache/init.log

      sleep 1

      exit $((ID%2))

  containers:

  - name: apache

    image: harbor:443/private/httpd:latest

    volumeMounts:

    - name: cache

      mountPath: /var/cache

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐