一、总览

在这里插入图片描述

Kubernetes 目前支持多达 28 种数据卷类型(其中大部分特定于具体的云环境如 GCE/AWS/Azure 等),如需查阅所有的数据卷类型,请查阅 Kubernetes 官方文档 Volumes

二、Secret-实战

secret 数据卷可以用来注入敏感信息(例如密码)到容器组。可以将敏感信息存入 kubernetes secret 对象,并通过 Volume(数据卷)以文件的形式挂载到容器组(或容器)。secret 数据卷使用 tmpfs(基于 RAM 的文件系统)挂载。

mysqpod.yaml

root_password: 123456

适用场景

  • 将 HTTPS 证书存入 kubernets secret,并挂载到 /etc/nginx/conf.d/myhost.crt、/etc/nginx/conf.d/myhost.pem 路径,用来配置 nginx 的 HTTPS 证书

1、创建secret

# kubectl create secret --help
Available Commands:
  docker-registry :docker仓库准备的秘钥
  generic         :普通秘钥
  tls             :tls

Usage:
  kubectl create secret [flags] [options]


#准备两个数据
echo -n 'admin' > ./username.txt
echo -n '123456' > ./password.txt

#1、使用文件方式创建(这种要转移文件中的特殊字符,$, \* 和 !)
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
##可以 kubectl get secret xx -o yaml看看最终定义
#直接看不到明文


#2、使用字符串方式(这种直接写就可以,特殊字符不用提前转义)
kubectl create secret generic db-user-pass –from-literal=username=admin –from-literal=password=123456

#3、手动创建yaml配置文件的方式
##这种要提前把内容使用base64编码好。
echo -n 'admin' | base64 #不加-n会得到admin+换行的编码结果; 使用-n进行不换行输出
echo -n '123456' | base64


#用文件方式创建的
apiVersion: v1
data:
  password.txt: MTIzNDU2
  username.txt: YWRtaW4=
kind: Secret
metadata:
  name: mysql-secret
  namespace: default
type: Opaque

 
#用字符串k=v创建的
apiVersion: v1
data:
  pwd: NjY2Ng==
  un: aGFoYQ==
kind: Secret
metadata:
  name: mysql-secret-02
  namespace: default
type: Opaque
 
  
 # 通过base64编码的
 #自己写yaml创建

2、使用Secret

1、环境变量中使用

apiVersion: v1
kind: Pod
metadata:
  name: mypod-secret-1
spec:
  containers:
  - name: nginx
    image: nginx
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: username.txt
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: password.txt

#进入创建好的Pod中进行验证
echo $SECRET_USERNAME
echo $SECRET_PASSWORD

2、以volume的形式挂载到pod的某个目录下

apiVersion: v1
kind: Pod
metadata:
  name: mypod-secret-2
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"	#容器内挂载路径
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      
#进入容器验证测试
cd /etc/foo
ls


#修改secret
kubectl edit secrets mysecret

3、Secret的其他形式

  • 可以创建的 Secret 类型有:
    • docker 仓库密码
    • Opaque (可自定义 key / value)
    • TLS (可存放 HTTPS 证书等)
  • 可以显示的 Secret 类型有:
    • Service Account Token
    • Bootstrap Token - 通常由系统创建
#docker secret的使用
kubectl create secret --help

kubectl create secret docker-registry my-secret --docker-server=registry.cn-zhangjiakou.aliyuncs.com --docker-username=lyt_goodtogread@163.com --docker-password=

#在下载镜像的时候声明使用即可
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: aliyun-app
  name: aliyun-app
spec:
  imagePullSecrets:
    name: my-secret  #之前创建的secret的名字
  containers:
  - image: registry.cn-zhangjiakou.aliyuncs.com/icodingdocker/icoding-java-img:v1.0
    imagePullPolicy: Always
    name: aliyun-app
    ports:
    - containerPort: 8080
      name: http80
      protocol: TCP

Secret也是有namespace的。ConfigMap一样

kubectl api-resources|grep secret。跨名称空间secret不能共享

secret数据是保存到etcd的

三、ConfigMap-实战

配置文件:

挂载到一个位置。docker把配置文件挂载到一个位置修改方便。

ConfigMap:(Volumes)【高可用的】

把cm挂载到容器的一个位置。容器启动的时候。redis-server /etc/config/redis.conf

Secret、ConfigMap把数据保存在etcd;把配置文件放在ConfigMap

配置中心,热更新。其他Pod引用的配置文件也就改了。

与secret类似,区别在于configmap保存的是不需要加密配置的信息;可以看到内容

ConfigMap 提供了一种向容器组注入配置信息的途径。ConfigMap 中的数据可以被 Pod(容器组)中的容器作为一个数据卷挂载。

在数据卷中引用 ConfigMap 时:

  • 可以直接引用整个 ConfigMap 到数据卷,此时 ConfigMap 中的每一个 key 对应一个文件名,value 对应该文件的内容
  • 也可以只引用 ConfigMap 中的某一个名值对,此时可以将 key 映射成一个新的文件名

适用场景

  • 使用 ConfigMap 中的某一 key 作为文件名,对应 value 作为文件内容,替换 nginx 容器中的 /etc/nginx/conf.d/default.conf 配置文件
  • cm也是名称空间隔离的。别的namespace用不到其他ns的cm、secret

1、创建

#1、创建配置。
vim redis.conf
redis.host=127.0.0.1
redis.port=6379
redis.password=123456


#2、创建配置
kubectl create configmap redis-config --from-file=redis.conf
cm获取到时明文

#3、yaml的方式是
apiVersion: v1
kind: ConfigMap
data:
  # k: v
  redis.conf: |
    redis.host=127.0.0.1
    redis.port=6379
    redis.password=123456
metadata:
  name: myconfig
  namespace: default
  
#4、查看 configmap简写cm
kubectl describe cm redis-config
#cm的内容可以直接看到



#5、cm使用k=v
#kubectl create cm myconfig-3 --from-literal=hello=123 --from-literal=world=456 -o yaml
apiVersion: v1
data:
  hello: "123"
  world: "456"
kind: ConfigMap
metadata:
  name: myconfig-3
  namespace: default

2、使用

1、通过挂载的方式

这种方式key是文件名。value是整个文件内容,我们无法单独获取到整个内容中的指定配置

apiVersion: v1
kind: Pod
metadata:
  name: mypod-cm
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh","-c","while true; do sleep 20;cat /etc/config/redis.conf;done;" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: redis-config
  restartPolicy: Never
  
#验证
kubectl logs mypod-cm

#测试同步更新。
kubectl edit cm redis-config
##等一分钟左右看Pod日志,更新是基于内容的事件订阅做的


#容器里面挂载目录内容确实更新的了。redis能不用用到最新的配置。redis-server /etc/config/redis.conf
#虽然有热更新。
一般使用方式。
cm改掉。直接把Pod删了。Pod是通过Deploy部署的。旧Pod删除以后,deploy拉起一个新的,重新引用新的cm。

#修改k8s的资源
kubectl edit pod/deploy/cm/secret... 名字
#如果有yaml。直接修改yaml
kubectl apply -f new.yaml(当前正在运行的Pod的配置输出进行这个文件的对比)


2、通过参数方式

这种方式。cm是kv pair。我们可以在任何位置获取到k,v进行使用

#创建cm   vim myconfig.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfig
  namespace: default
data:
  my.level: info
  my.msg: hello



#测试使用
apiVersion: v1
kind: Pod
metadata:
  name: ceshicmpod
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh", "-c", "while true; do sleep 20;echo $(LEVEL) $(TYPE);done" ]
      env:
        - name: LEVEL
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: my.level
        - name: TYPE
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: my.msg
  restartPolicy: Never
  
  
  #env环境变量的方式引用的cm。热更新暂时没用。最终希望Deploy-部署的Pod删除了,重新拉起就行。
  

四、emptyDir与hostPath-实战

1、emptyDir

把容器产生的数据挂载到emptyDir指定的地方;Pod不挂,数据就存储在宿主机的一个目录。docker的匿名卷,因为Pod重新拉起,新的Pod,开一个随机的匿名卷,emptyDir的数据其实是在了。

  • emptyDir类型的数据卷在容器组被创建时分配给该容器组,并且直到容器组被移除(也就是整个Pod移除),该数据卷才被释放。该数据卷初始分配时,始终是一个空目录。同一容器组中的不同容器都可以对该目录执行读写操作,并且共享其中的数据,(尽管不同的容器可能将该数据卷挂载到容器中的不同路径)。当容器组被移除时,emptyDir数据卷中的数据将被永久删除

    容器崩溃时,kubelet 并不会删除容器组,而仅仅是将容器重启,因此 emptyDir 中的数据在容器崩溃并重启后,仍然是存在的。

    无状态服务,运行期间的一些数据

    MySQL

  • 适用场景

    • 空白的初始空间,例如合并/排序算法中,临时将数据存在磁盘上
    • 长时间计算中存储检查点(中间结果),以便容器崩溃时,可以从上一次存储的检查点(中间结果)继续进行,而不是从头开始
    • 作为两个容器的共享存储,使得第一个内容管理的容器可以将生成的页面存入其中,同时由一个 webserver 容器对外提供这些页面
    • 默认情况下,emptyDir 数据卷被存储在 node(节点)的存储介质(机械硬盘、SSD、或者网络存储)上。此外,您可以设置 emptyDir.medium 字段为 “Memory”,此时 Kubernetes 将挂载一个 tmpfs(基于 RAM 的文件系统)。tmpfs 的读写速度非常快,但是与磁盘不一样,tmpfs 在节点重启后将被清空,且您向该 emptyDir 写入文件时,将消耗对应容器的内存限制。
#一个多容器协同的场景实例
apiVersion: v1
kind: Pod
metadata:
  annotations:
   hello: world
  labels:
    app: tomcat
  name: nginx-pod-volume-test
spec:
  volumes:
   - emptyDir: {}  #关联宿主机的一个临时目录
     name: ourfile
  containers:
  - image: nginx
    imagePullPolicy: Always
    name: nginx
    ports:
    - containerPort: 80
      name: http80
      protocol: TCP
    volumeMounts:
      - mountPath: /usr/share/nginx/html
        name: ourfile

2、hostPath

把宿主机的文件挂载进容器中

  • 警告

    使用 hostPath 数据卷时,必须十分小心,因为:

    • 不同节点上配置完全相同的容器组(例如同一个Deployment的容器组)可能执行结果不一样,因为不同节点上 hostPath 所对应的文件内容不同;
    • Kubernetes 计划增加基于资源的调度,但这个特性将不会考虑对 hostPath 的支持
    • hostPath 对应的文件/文件夹只有 root 可以写入。您要么在 privileged Container 以 root 身份运行您的进程,要么修改与 hostPath 数据卷对应的节点上的文件/文件夹的权限,
  • 适用场景

    绝大多数容器组并不需要使用 hostPath 数据卷,但是少数情况下,hostPath 数据卷非常有用:

    • 某容器需要访问 Docker,可使用 hostPath 挂载宿主节点的 /var/lib/docker
    • 在容器中运行 cAdvisor,使用 hostPath 挂载宿主节点的 /sys

kubectl explain pod.spec.volumes.hostPath

支持的 type 值如下:

取值行为
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。
Directory在给定路径上必须存在的目录。
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。
File在给定路径上必须存在的文件。
Socket在给定路径上必须存在的 UNIX 套接字。
CharDevice在给定路径上必须存在的字符设备。
BlockDevice在给定路径上必须存在的块设备。
apiVersion: v1
kind: Pod
metadata:
  name: test-pd-hostpath
spec:
  containers:
  - image: tomcat:7
    name: test-container
    
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /var/lib/docker
      # this field is optional
      type: Directory
   # pvc:
      # 哪个pvc
      
#进入Pod验证。
但是默认 容器里面的这些文件的执行权限是宿主机定义的。很多容器启动。root(当成普通用户),特权容器的方式;
--privileged   Give extended privileges to this container:特权容器的方式。能穿透到宿主机的root

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eqI2TgE7-1593216370154)(05%E3%80%81kubernetes%E8%BF%9B%E9%98%B6-%E5%AD%98%E5%82%A8.assets/image-20200523211409905.png)]

安装CICD平台。Jenkins–》jenkins就得获取到当前机器的运行权限,root。

五、持久化

在这里插入图片描述

1、PV与PVC的概念

与管理计算资源相比,管理存储资源是一个完全不同的问题。为了更好的管理存储,Kubernetes 引入了 PersistentVolumePersistentVolumeClaim 两个概念,将存储管理抽象成如何提供存储以及如何使用存储两个关注点。

PersistentVolume(PV 存储卷)

  • 是集群中的一块存储空间,由集群管理员管理、或者由 Storage Class(存储类)自动管理。PV(存储卷)和 node(节点)一样,是集群中的资源(kubernetes 集群由存储资源和计算资源组成)。
  • PersistentVolume(存储卷)描述了如何提供存储的细节信息(NFS、cephfs等存储的具体参数)。

PersistentVolumeClaim(存储卷声明)

  • 是一种类型的 Volume(数据卷),PersistentVolumeClaim(存储卷声明)引用的 PersistentVolume(存储卷)有自己的生命周期,该生命周期独立于任何使用它的容器组。
  • (PVC 存储卷声明)代表用户使用存储的请求。Pod 容器组消耗 node 计算资源,PVC 存储卷声明消耗 PersistentVolume 存储资源。Pod 容器组可以请求特定数量的计算资源(CPU / 内存);PersistentVolumeClaim 可以请求特定大小/特定访问模式(只能被单节点读写/可被多节点只读/可被多节点读写)的存储资源。

StorageClass(存储类)

  • 根据应用程序的特点不同,其所需要的存储资源也存在不同的要求,例如读写性能等。集群管理员必须能够提供关于 PersistentVolume(存储卷)的更多选择,无需用户关心存储卷背后的实现细节。为了解决这个问题,Kubernetes 引入了 StorageClass(存储类)的概念

在这里插入图片描述

存储卷和存储卷声明的关系图说明:

  • PersistentVolume 是集群中的存储资源,通常由集群管理员创建和管理
  • StorageClass 用于对 PersistentVolume 进行分类,如果正确配置,StorageClass 也可以根据 PersistentVolumeClaim 的请求动态创建 Persistent Volume
  • PersistentVolumeClaim 是使用该资源的请求,通常由应用程序提出请求,并指定对应的 StorageClass 和需求的空间大小
  • PersistentVolumeClaim 可以做为数据卷的一种,被挂载到容器组/容器中使用
    在这里插入图片描述

2、Provisioning(供应) - 为PVC提供PV

为pvc供应( Provisioning )pv有两种方式,静态和动态

1、 静态供应 (Static)

集群管理员实现创建好一系列 PersistentVolume,它们包含了可供集群中应用程序使用的关于实际存储的具体信息。

在这里插入图片描述

2、动态供应 (Dynamic)

在配置有合适的 **StorageClass(存储类)**且 PersistentVolumeClaim 关联了该 StorageClass 的情况下,kubernetes 集群可以为应用程序动态创建 PersistentVolume。
在这里插入图片描述

3、其他概念关系

绑定 (Binding)

1、用户创建了一个 PersistentVolumeClaim 存储卷声明,并指定了需求的存储空间大小以及访问模式。

2、Kubernets master 将立刻为其匹配一个 PersistentVolume 存储卷,并将存储卷声明和存储卷绑定到一起。

3、除动态提供,应用程序将被绑定一个不小于(可能大于)其 PersistentVolumeClaim 中请求的存储空间大小的 PersistentVolume。一旦绑定,PersistentVolumeClaim 将拒绝其他 PersistentVolume 的绑定关系。PVC 与 PV 之间的绑定关系是一对一的映射

4、PersistentVolumeClaim 将始终停留在 未绑定 unbound 状态,直到有合适的 PersistentVolume 可用。举个例子:集群中已经存在一个 50Gi 的 PersistentVolume,同时有一个 100Gi 的 PersistentVolumeClaim,在这种情况下,该 PVC 将一直处于 未绑定 unbound 状态,直到管理员向集群中添加了一个 100Gi 的 PersistentVolume。

使用 (Using)

对于 Pod 容器组来说,PersistentVolumeClaim 存储卷声明是一种类型的 Volume 数据卷。Kubernetes 集群将 PersistentVolumeClaim 所绑定的 PersistentVolume 挂载到容器组供其使用。

使用中保护 (Storage Object in Use Protection)
  • 使用中保护(Storage Object in Use Protection)的目的是确保正在被容器组使用的 PersistentVolumeClaim 以及其绑定的 PersistentVolume 不能被系统删除,以避免可能的数据丢失。

  • 如果用户删除一个正在使用中的 PersistentVolumeClaim,则该 PVC 不会立即被移除掉,而是推迟到该 PVC 不在被任何容器组使用时才移除;同样的如果管理员删除了一个已经绑定到 PVC 的 PersistentVolume,则该 PV 也不会立刻被移除掉,而是推迟到其绑定的 PVC 被删除后才移除掉。

回收 (Reclaiming)

当用户不在需要其数据卷时,可以删除掉其 PersistentVolumeClaim,此时其对应的 PersistentVolume 将被集群回收并再利用。Kubernetes 集群根据 PersistentVolume 中的 reclaim policy(回收策略)决定在其被回收时做对应的处理。当前支持的回收策略有:Retained(保留)、Recycled(重复利用)、Deleted(删除)

  • 保留 (Retain)

    保留策略需要集群管理员手工回收该资源。当绑定的 PersistentVolumeClaim 被删除后,PersistentVolume 仍然存在,并被认为是”已释放“。但是此时该存储卷仍然不能被其他 PersistentVolumeClaim 绑定,因为前一个绑定的 PersistentVolumeClaim 对应容器组的数据还在其中。集群管理员可以通过如下步骤回收该 PersistentVolume:

    • 删除该 PersistentVolume。PV 删除后,其数据仍然存在于对应的外部存储介质中(nfs、cefpfs、glusterfs 等)
    • 手工删除对应存储介质上的数据
    • 手工删除对应的存储介质,您也可以创建一个新的 PersistentVolume 并再次使用该存储介质
  • 删除 (Delete)

    删除策略将从 kubernete 集群移除 PersistentVolume 以及其关联的外部存储介质(云环境中的 AWA EBS、GCE PD、Azure Disk 或 Cinder volume)。

  • **再利用 (Recycle) **

    • 再利用策略将在 PersistentVolume 回收时,执行一个基本的清除操作(rm -rf /thevolume/*),并使其可以再次被新的 PersistentVolumeClaim 绑定。
    • Warning: The Recycle reclaim policy is deprecated. Instead, the recommended approach is to use dynamic provisioning.(动态供应)
PV字段

PersistentVolume 字段描述如下表所示:

字段名称可选项/备注
容量 Capacity通常,一个 PersistentVolume 具有一个固定的存储容量(capacity)
Volume ModeFEATURE STATE: Kubernetes v1.13 beta Kubernetes 1.9 之前的版本,所有的存储卷都被初始化一个文件系统。当前可选项有:
block:使用一个 块设备(raw block device)
filesystem(默认值):使用一个文件系统
Access Modes可被单节点读写-ReadWriteOnce【RWO】
可被多节点只读-ReadOnlyMany【ROX】
可被多节点读写-ReadWriteMany【RWX】
注意:不同的存储支持的不同,见下表
存储类 StorageClassName带有存储类 StorageClassName 属性的 PersistentVolume 只能绑定到请求该 StorageClass 存储类的 PersistentVolumeClaim。 没有 StorageClassName 属性的 PersistentVolume 只能绑定到无特定 StorageClass 存储类要求的 PVC。
回收策略 Reclaim Policy保留 Retain – 手工回收
再利用Recycle – 清除后重新可用 (rm -rf /thevolume/*)
删除 Delete – 删除 PV 及存储介质
Mount Options挂载选项用来在挂载时作为 mount 命令的参数
状态 PhaseAvailable – 可用的 PV,尚未绑定到 PVC
Bound – 已经绑定到 PVC
Released – PVC 已经被删除,但是资源还未被集群回收
Failed – 自动回收失败

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes

Volume PluginReadWriteOnceReadOnlyManyReadWriteMany
AWSElasticBlockStore--
AzureFile
AzureDisk--
CephFS
Cinder--
CSIdepends on the driverdepends on the driverdepends on the driver
FC-
FlexVolumedepends on the driver
Flocker--
GCEPersistentDisk-
Glusterfs
HostPath--
iSCSI-
Quobyte
NFS
RBD-
VsphereVolume-- (works when Pods are collocated)
PortworxVolume-
ScaleIO-
StorageOS--

Important! A volume can only be mounted using one access mode at a time, even if it supports many. For example, a GCEPersistentDisk can be mounted as ReadWriteOnce by a single node or ReadOnlyMany by many nodes, but not at the same time.

PVC相关字段
字段名称可选项/备注
存储类只有该 StorageClass 存储类的 PV 才可以绑定到此 PVC
读写模式 Access Modes可被单节点读写-ReadWriteOnce可被多节点只读-ReadOnlyMany可被多节点读写-ReadWriteMany
Volume Modesblockfilesystem - default
总量请求存储空间的大小

3、实战前准备-安装NFS环境

1、搭建NFS-Server环境

#配置NFS服务器
yum install -y nfs-utils

#执行命令 vi /etc/exports,创建 exports 文件,文件内容如下:
echo "/data/volumes/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
#/data/volumes  172.26.248.0/20(rw,no_root_squash)

#执行以下命令,启动 nfs 服务
# 创建共享目录
mkdir -p /data/volumes

systemctl enable rpcbind
systemctl enable nfs-server

systemctl start rpcbind
systemctl start nfs-server
exportfs -r

#检查配置是否生效
exportfs
# 输出结果如下所示
/data/volumes /data/volumes

#以后就可以直接挂载了
apiVersion: v1
kind: Pod
metadata:
  name: vol-nfs
  namespace: default
spec:
  volumes:
  - name: html
    nfs:
      path: /data/volumes   #1000G
      server: 自己的nfs服务器地址
  containers:
  - name: myapp
    image: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  
 #原生的方式整个数据管理不整体。

2、搭建NFS-Client环境(选测)

#服务器端防火墙开放111、662、875、892、2049的 tcp / udp 允许,否则远端客户无法连接。
#安装客户端工具
yum install -y nfs-utils


#执行以下命令检查 nfs 服务器端是否有设置共享目录
# showmount -e $(nfs服务器的IP)
showmount -e 172.26.248.150
# 输出结果如下所示
Export list for 172.26.248.150
/data/volumes *

#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
mkdir /root/nfsmount
# mount -t nfs $(nfs服务器的IP):/root/nfs_root /root/nfsmount
#高可用备份的方式
mount -t nfs 172.26.248.165:/nfs/data /nfs/data
# 写入一个测试文件
echo "hello nfs server" > /root/nfsmount/test.txt

#在 nfs 服务器上执行以下命令,验证文件写入成功
cat /data/volumes/test.txt

4、实战-静态提供 PV

  • 缺点:手动创建pv比较繁琐、不适合大工程
  • 优点:小规模使用方便灵活

1、准备环境

#1、在nfs服务器上先建立存储卷对应的目录
[root@nfs ~]# cd /data/volumes/
[root@nfs volumes]# mkdir v{1,2,3,4,5}
[root@nfs volumes]# ls
index.html  v1  v2  v3  v4  v5
[root@nfs volumes]# echo "<h1>NFS stor 01</h1>" > v1/index.html
[root@nfs volumes]# echo "<h1>NFS stor 02</h1>" > v2/index.html
[root@nfs volumes]# echo "<h1>NFS stor 03</h1>" > v3/index.html
[root@nfs volumes]# echo "<h1>NFS stor 04</h1>" > v4/index.html
[root@nfs volumes]# echo "<h1>NFS stor 05</h1>" > v5/index.html

#2、修改nfs的配置
[root@nfs volumes]# vim /etc/exports
/data/volumes/v1        *(insecure,rw,sync,no_root_squash)
/data/volumes/v2        *(insecure,rw,sync,no_root_squash)
/data/volumes/v3        *(insecure,rw,sync,no_root_squash)
/data/volumes/v4        *(insecure,rw,sync,no_root_squash)
/data/volumes/v5        *(insecure,rw,sync,no_root_squash)
/nfs/data				*(insecure,rw,sync,no_root_squash)
#最后的这个nfs/data是给后面预留的

#3、查看nfs的配置
exportfs -arv

#4、查看配置是否生效
showmount -e

2、创建大量PV

#用pv的最大好处,可以直接进行资源限定。
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: 172.26.248.150  #说明当前pv是和nfs-server的/data/volumes/v1关联的。
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi # 直接对资源进行了限定
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: 172.26.248.150
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: 172.26.248.150
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 8Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: 172.26.248.150
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: 172.26.248.150
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 15Gi
    
    
# 1P 拆分PV。
kubectl get pv

在这里插入图片描述

3、创建PVC

apiVersion: v1
# 使用PVC类型
kind: PersistentVolumeClaim
metadata:
  # 与容器应用PVC相同
  name: my-pvc
spec:
  # 定义读写权限
  accessModes:
    - ReadWriteMany
  # 请求资源
  resources:
    requests:
      # 存储空间 6G, 只要pvc创建出来,自己就得找个pv绑定, 1G,找不到。pvc一致的等待,可用pv出来(管理员自己手动声明一堆pv,或者别的pv释放了。)以后自动绑定。
      storage: 6Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx6-pvc
spec:
  containers:
  - name: nginx6-pvc
    image: nginx
    # 挂在点
    volumeMounts:
    - name: wwwroot
      mountPath: /usr/share/nginx/html
    ports:
    - containerPort: 80
  # 挂载来源
  volumes:
  - name: wwwroot
    # 定义PVC
    persistentVolumeClaim:
      # 定义PVC名称
      claimName: my-pvc
      
      
#作业
pv:回收策略
pvc:回收策略
自己测试pvc,pv各种回收策略下的产生效果。
删了Pod 以后 Pv,PVC都怎么了。。。

4~5全面结束。大家辛苦。

4、测试

kubectl get pvc
kubectl get pv
curl podIp测试数据

5、Storage Classes

https://kubernetes.io/zh/docs/concepts/storage/storage-classes/#%E5%AD%98%E5%82%A8%E5%88%86%E9%85%8D%E5%99%A8

每个 StorageClass 都包含 provisionerparametersreclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。

6、实战-动态提供 PV

基于Storage Class和nfs文件系统,实现存储的动态供给(NFS+PV+PVC)

在这里插入图片描述

1、创建存储类(NFS环境前面已经搭好)

字段名称填入内容备注
名称nfs-storage自定义存储类名称
NFS Server172.26.248.150NFS服务的IP地址
NFS Path/nfs/dataNFS服务所共享的路径
# 先创建授权
# vi nfs-rbac.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
   name: nfs-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: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
#vi nfs-deployment.yaml;创建nfs-client的授权
kind: Deployment
apiVersion: apps/v1
metadata:
   name: nfs-client-provisioner
spec:
   replicas: 1
   strategy:
     type: Recreate
   selector:
     matchLabels:
        app: nfs-client-provisioner
   template:
      metadata:
         labels:
            app: nfs-client-provisioner
      spec:
         serviceAccount: nfs-provisioner
         containers:
            -  name: nfs-client-provisioner
               image: quay.io/external_storage/nfs-client-provisioner:latest
               volumeMounts:
                 -  name: nfs-client-root
                    mountPath:  /persistentvolumes
               env:
                 -  name: PROVISIONER_NAME #供应者的名字
                    value: storage.pri/nfs #名字虽然可以随便起,以后引用要一致
                 -  name: NFS_SERVER
                    value: 172.26.248.150
                 -  name: NFS_PATH
                    value: /nfs/data
         volumes:
           - name: nfs-client-root
             nfs:
               server: 172.26.248.150
               path: /nfs/data
##这个镜像中volume的mountPath默认为/persistentvolumes,不能修改,否则运行时会报错
#创建storageclass
# vi storageclass-nfs.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage-nfs
provisioner: storage.pri/nfs
reclaimPolicy: Delete

#扩展"reclaim policy"有三种方式:Retain、Recycle、Deleted。
Retain
#保护被PVC释放的PV及其上数据,并将PV状态改成"released",不将被其它PVC绑定。集群管理员手动通过如下步骤释放存储资源:
手动删除PV,但与其相关的后端存储资源如(AWS EBS, GCE PD, Azure Disk, or Cinder volume)仍然存在。
手动清空后端存储volume上的数据。
手动删除后端存储volume,或者重复使用后端volume,为其创建新的PV。

Delete
删除被PVC释放的PV及其后端存储volume。对于动态PV其"reclaim policy"继承自其"storage class",
默认是Delete。集群管理员负责将"storage class"的"reclaim policy"设置成用户期望的形式,否则需要用
户手动为创建后的动态PV编辑"reclaim policy"

Recycle
保留PV,但清空其上数据,已废弃


2、改变默认sc

##改变系统默认sc
https://kubernetes.io/zh/docs/tasks/administer-cluster/change-default-storage-class/#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%94%b9%e5%8f%98%e9%bb%98%e8%ae%a4-storage-class

kubectl patch storageclass storage-nfs-hdd -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

3、创建pvc

#vi  pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-claim-01
 # annotations:
 #   volume.beta.kubernetes.io/storage-class: "storage-nfs"
spec:
  storageClassName: storage-nfs  #这个class一定注意要和sc的名字一样
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi

4、使用pvc

#vi testpod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: pvc-claim-01
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-claim-01
 # annotations:
 #   volume.beta.kubernetes.io/storage-class: "storage-nfs"
spec:
  storageClassName: storage-nfs  #这个class一定注意要和sc的名字一样,只要设置了默认,可以省略
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  
# 去nfs服务器中验证
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐