第13节 存储抽象


❤️💕💕新时代拥抱云原生,云原生具有环境统一、按需付费、即开即用、稳定性强特点。Myblog:http://nsddd.topopen in new window


[TOC]

存储抽象

STOP

这一部分内容非常重要~

我们在前面学docker的时候实现挂载–mount

同样对于k8s来说,我们也需要这个挂载的实现,而且挂载功能更强。

我们如果使用了k8s,这样挂载会有一个很严重的问题,如果pod宕机,重新启动到别的机器~那么此时可能会出现挂载失败。

⚡ k8s将所有的挂载的层次统一管理起来,形成存储层。

kubernetes 集群不会为你处理数据的存储,我们可以为数据库挂载一个磁盘来确保数据的安全。 你可以选择云存储、本地磁盘、NFS。

  • 本地磁盘:可以挂载某个节点上的目录,但是这需要限定 pod 在这个节点上运行
  • 云存储:不限定节点,不受集群影响,安全稳定;需要云服务商提供,裸机集群是没有的。
  • NFS:不限定节点,不受集群影响

环境准备NFS

所有结点

安装NFS:

apt install -y nfs-utils
yum install -y nfs-utils

主节点

给master结点暴露文件夹/nfs/data/

#nfs 主节点
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports

创建文件夹:

mkdir -p /nfs/data

启动rpc远程绑定(设置开机启动):

systemctl enable rpcbind --now
systemctl enable nfs-server --now

检查:

exportfs

image-20221022204801491

查看私有网络的ip地址给从结点使用:

[root@k8s-master01 ~]# ip a | grep "eth0"
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 192.168.0.2/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0

从结点

测试结点检查:

[root@k8s-master03 ~]# showmount -e 192.168.0.2
Export list for 192.168.0.2:
/nfs/data *

创建/nfs/data

mkdir -p /nfs/data

同步:

mount -t nfs 192.168.0.2:/nfs/data /nfs/data

验证

在主节点中,创建文件,在其他结点就可以发现同步了~

[root@k8s-master01 ~]# mount -t nfs 192.168.0.2:/nfs/data /nfs/data
[root@k8s-master01 ~]# cd /nfs/data/
[root@k8s-master01 data]# echo "111" >> README.md

image-20221022210439304

原生方式数据挂载

创建文件deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-pv-demo
  name: nginx-pv-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pv-demo
  template:
    metadata:
      labels:
        app: nginx-pv-demo
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          nfs:
            server: 172.31.0.4
            path: /nfs/data/nginx-pv

提示

/usr/share/nginx/html/nfs/data/nginx-pv形成一个映射关系(类似于docker -v

🚀 编译结果如下:

image-20221022213410525

提醒

我们发现一直没办法刷新出来(0/1),我们使用描述命令来打开看看

kubectl describe pod nginx-pv-demo-75ff4fbcf7-5prbw 

image-20221022214019506

failedmount表示挂载失败

⬇️ 重新部署一下:

[root@k8s-master02 data]# kubectl delete -f deploy.yaml 
deployment.apps "nginx-pv-demo" deleted
[root@k8s-master02 data]# kubectl apply -f deploy.yaml 
deployment.apps/nginx-pv-demo created

PV&PVC

pv & pvc

原生方式的问题: 删除deploy.yaml 文件不会删除,浪费空间。

PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置,比如Volume的类型、挂载目录、远程存储服务器地址等

PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格,比如存储大小、读写权限等。

image-20221022220215815

我们的pod需要用多大的空间,需要用PVC写一份申请书,按照申请书给出一个实际的大小空间,申请书删除掉,那么这个空间就会被回收,空间删除掉,申请书也被删除了~

StorageClass:充当PV的模板,自动为PVC创建PV

存储的时候需要StorageClass指定块存储或者文件存储~

我们在前面也是知道了存储是分类的,我们需要指定StorageClass

image-20221022220407744

创建pv池

#nfs主节点
mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03

创建PV

注意:server修改为自己的eth0地址

[root@k8s-master01 data]# ip a | grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 192.168.0.2/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0

写入配置文件pv.yaml

apiVersion: v1
kind: PersistentVolume  # 资源类型pv
metadata:
  name: pv01-10m  # 名字无所谓
spec:
  capacity:   # 限制容量
    storage: 10M
  accessModes:
    - ReadWriteMany  # 可读可写
  storageClassName: nfs   # 指定为nfs
  nfs:
    path: /nfs/data/01 # 01文件夹位置
    server: 192.168.0.2  # 修改eth0地址
---  # 三个横线代表分割完整文档
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02-1gi
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/02
    server: 192.168.0.2
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv03-3gi
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/03
    server: 192.168.0.2

🚀 编译结果如下:

[root@k8s-master01 data]# kubectl apply -f pv.yaml 
persistentvolume/pv01-10m created
persistentvolume/pv02-1gi created
persistentvolume/pv03-3gi created

获取系统资源命令:

kubectl get persistentvolume
# 也可以简写
kubectl get pv

image-20221022221346394

PVC创建与绑定

⚡ 创建PVC pvc.ymal

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi  # 我需要200M,找到合适的空间绑定
  storageClassName: nfs  # 对应的是上面的空间名称(分组)

image-20221022222002874

📜 对上面的解释:

绑定了合适的PV

⚡ 创建Pod绑定PVC

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-pvc
  name: nginx-deploy-pvc
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deploy-pvc
  template:
    metadata:
      labels:
        app: nginx-deploy-pvc
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: nginx-pvc

删除策略

删除PVC时候是有回收策略的,比如说是要一起删除掉或者是把PV保留。

ConfigMap

为什么需要ConfigMap

我们在使用docker的时候,通常是将某一个容器创建时候就挂载,这样就会保存下来。

ConfigMap就是把之前的配置文件创建为配置集合

redis把之前文件创建为一个配置集

创建文件:

[root@k8s-master03 data]#  echo "appendonly yes # 表示数据需要持久化存储" >> redis.conf && cat redis.conf
appendonly yes # 表示数据需要持久化存储

创建一个配置集:

[root@k8s-master03 data]# kubectl create cm redis-conf --from-file=redis.conf
configmap/redis-conf created
[root@k8s-master03 data]# rm redis.conf -f
[root@k8s-master03 data]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      2d11h
redis-conf         1      19s

注意:

这个配置集存在etcd档案库中,只要k8s还活着,配置集就不会丢。

查看配置集:

kubectl get cm redis-conf -oyaml

image-20221022224249770

⚠️ 如何引用上面的配置集:

创建一个Pod

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    command:
      - redis-server
      - "/redis-master/redis.conf"  #指的是redis容器内部的位置
    ports:
    - containerPort: 6379
    volumeMounts:
    - mountPath: /data
      name: data
    - mountPath: /redis-master  # 挂载路径
      name: config
  volumes:
    - name: data
      emptyDir: {}
    - name: config
      configMap: # 你想要的配置文件从配置集configMap中取出
        name: redis-conf  # 取出上面redis-conf 配置集
        items:
        - key: redis.conf
          path: redis.conf

测试

我们修改配置文件:

kubectl edit cm redis-conf

在redis-config下面:

  redis.conf: |
    appendonly yes # 表示数据需要持久化存储
    requirepass 123456  # 添加

记住

  • 挂载目录用PV & PVC
  • 挂载配置文件用configMap

统一管理的思想很重要:

  • 所有的配置文件统一管理,这就是调度的特色
  • 类似还有用户名和密码统一管理~

Secret

Secret作用和介绍

secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。

  • 用户可以创建自己的secret,系统也会有自己的secret

  • Pod需要先引用才能使用某个secret

Secret 类似于 ConfigMapopen in new window 但专门用于保存机密数据。

secret的使用

Pod有2种方式来使用secret

  1. 作为volume的一个域被一个或多个容器挂载
  2. 在拉取镜像的时候被kubelet引用。
  3. 或许也可以作为容器的环境变量

注意

默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。 任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。 此外,任何有权限在命名空间中创建 Pod 的人都可以使用该访问权限读取该命名空间中的任何 Secret; 这包括间接访问,例如创建 Deployment 的能力。

创建一个secret:

kubectl create secret docke-registry xiongxinwei-docker \
--docker-username=3293172751 \
--docker-password=24643..... \
--docker-email=3293172751@qq.com

命令格式:

🧷命令格式:

  • --docker-server:Docker仓库地址。
  • --docker-username:Docker仓库用户名。
  • --docker-password:Docker仓库密码。
  • --docker-email:Docker仓库邮箱。

获取secret:

kuberctl get secret

END 链接