参考文档:https://kubernetes.io/docs/concepts/storage/volumes/

  • Kubernetes中的Volume提供了在容器中挂载外部存储的能力

  • Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume

本地卷:hostPath,emptyDir网络卷:nfs,ceph(cephfs,rbd),glusterfs公有云:aws,azurek8s资源:downwardAPI,configMap,secret

3.1 emptyDir

emptyDir == docker中的volume

创建一个空卷,挂载到Pod中的容器。Pod删除该卷也会被删除。

应用场景:Pod中容器之间数据共享

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: write
image: centos
command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
volumeMounts:
- name: data
mountPath: /data - name: read
image: centos
command: ["bash","-c","tail -f /data/hello"]
volumeMounts:
- name: data
mountPath: /data volumes:
- name: data
emptyDir: {}
# 查看pod中read容器日志

# kubectl logs my-pod -c read
# kubectl get pod -o wide
NAME                     READY   STATUS   RESTARTS   AGE   IP           NODE       
my-pod                   2/2     Running   5         15m   10.244.2.11   k8s-node2

# 查看卷目录(pod在哪个node节点上,emptydir卷就在哪里)
# docker ps 查看容器名,找到对应POD ID
# /var/lib/kubelet/pods/<POD ID>/volumes/kubernetes.io~empty-dir/data

[root@k8s-node2 ~]# docker ps | grep "my-pod"

[root@k8s-node2 ~]# cat /var/lib/kubelet/pods/7c521ebc-dec6-4487-a698-af4cc006cf57/volumes/kubernetes.io~empty-dir/data/hello

3.2 hostPath

hostPath == docker中的bindmount 日志采集agent、监控agent /proc

挂载Node文件系统上文件或者目录到Pod中的容器。每个node上需要有相应的挂载目录,删除pod,挂载的卷不会被删除。

应用场景:Pod中容器需要访问宿主机文件

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 36000
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
hostPath:
path: /tmp
type: Directory
 

验证:进入Pod中的/data目录内容与当前运行Pod的节点内容一样:

# kubectl get pod -o wide

NAME                     READY   STATUS   RESTARTS   AGE   IP           NODE
my-pod                   1/1     Running   0         17s   10.244.2.13   k8s-node2
# kubectl exec -it my-pod sh
/ # ls /data/

[root@k8s-node2 ~]# ls /tmp/

3.3 网络存储

在172.16.1.72节点上安装nfs:

# yum install nfs-utils -y

# mkdir -p /ifs/kubernetes/
# vim /etc/exports
/ifs/kubernetes *(rw,no_root_squash,sync)

# systemctl start rpcbind.service
# systemctl enable rpcbind.service

# systemctl start nfs-server.service
# systemctl enable nfs-server.service
# rpcinfo -p

# 挂载测试
# mkdir -p /mntdata/
# mount -t nfs 172.16.1.72:/ifs/kubernetes /mntdata/
# df -hT

172.16.1.72:/ifs/kubernetes nfs4       58G  3.0G   55G   6% /mntdata
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
volumes:
- name: wwwroot
nfs:
server: 172.16.1.72
path: /ifs/kubernetes
 

在nfs的家目录中创建index.html首页访问并访问:

# kubectl get pod -o wide

NAME                     READY   STATUS   RESTARTS   AGE     IP           NODE       
web-856c696878-678lq     1/1     Running   0         6m19s   10.244.2.14   k8s-node2
web-856c696878-lbq4z     1/1     Running   0         6m19s   10.244.2.15   k8s-node2
web-856c696878-wvwn8     1/1     Running   0         6m19s   10.244.1.8   k8s-node1

# kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
# kubectl get svc/web
NAME   TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)       AGE
web   NodePort   10.96.174.135   <none>       80:30449/TCP   31s

[root@k8s-node2 ~]# echo "hello" >/ifs/kubernetes/index.html

# 访问nginx

http://NodeIP:30449/

3.4 PV&PVC

PersistentVolume(PV:持久卷):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理

PV供给分为:

  • 静态

  • 动态

PersistentVolumeClaim(PVC:持久卷声明):让用户不需要关心具体的Volume实现细节

3.5 PV静态供给

静态供给是指提前创建好很多个PV,以供使用。

先准备一台NFS服务器作为测试(以172.16.1.72节点作为测试)。

[root@k8s-node2 ~]# yum install nfs-utils -y

[root@k8s-node2 ~]# vim /etc/exports
/ifs/kubernetes *(rw,no_root_squash,sync)
[root@k8s-node2 ~]# mkdir -p /ifs/kubernetes
[root@k8s-node2 ~]# systemctl start nfs

[root@k8s-node2 ~]# systemctl enable nfs

示例:先准备三个PV,分别是5G,10G,20G,修改下面对应值分别创建。

[root@k8s-node2 ~]# mkdir -p /ifs/kubernetes/{pv001,pv002,pv003}

[root@k8s-node2 ~]# ls /ifs/kubernetes/
pv001 pv002 pv003

[root@k8s-admin ~]# vim my-pv.yaml

---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001 # 修改PV名称
spec:
capacity:
storage: 5Gi # 修改大小
accessModes:
- ReadWriteMany
nfs:
path: /ifs/kubernetes/pv001 # 修改目录名
server: 172.16.1.72
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002 # 修改PV名称
spec:
capacity:
storage: 10Gi # 修改大小
accessModes:
- ReadWriteMany
nfs:
path: /ifs/kubernetes/pv002 # 修改目录名
server: 172.16.1.72
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003 # 修改PV名称
spec:
capacity:
storage: 20Gi # 修改大小
accessModes:
- ReadWriteMany
nfs:
path: /ifs/kubernetes/pv003 # 修改目录名
server: 172.16.1.72

应用并查看pv:

[root@k8s-admin ~]# kubectl apply -f my-pv.yaml

persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created

[root@k8s-admin ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM   STORAGECLASS   REASON   AGE
pv001   5Gi       RWX           Retain           Available                                   2m31s
pv002   10Gi       RWX           Retain           Available                                   2m31s

pv003   20Gi       RWX           Retain           Available                                   2m31s

创建一个Pod使用PV:

[root@k8s-admin ~]# vim static-pv.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: my-pvc ---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
# 访问模式
accessModes:
- ReadWriteMany
# 请求容量大小
resources:
requests:
storage: 5Gi

创建并查看PV与PVC状态:

[root@k8s-admin ~]# kubectl apply -f pod-pv.yaml

pod/my-pod created
persistentvolumeclaim/my-pvc created

[root@k8s-admin ~]# kubectl get pv,pvc

会发现该 PVC 会与 5G PV 进行绑定成功。

然后进入到容器中/usr/share/nginx/html(PV挂载目录)目录下创建一个文件测试:

[root@k8s-admin ~]# kubectl exec -it my-pod bash

root@my-pod:/# cd /usr/share/nginx/html
root@my-pod:/usr/share/nginx/html# echo "hello" >index.html

# 再切换到NFS服务器,会发现也有刚在容器创建的文件,说明工作正常。
[root@k8s-node2 ~]# ls -l /ifs/kubernetes/pv001
total 4

-rw-r--r-- 1 root root 6 May 12 22:47 index.html

注意:(1) 容量并不是必须对应(pv!=pvc),根据就近选择合适pv扩容。 (2) 1.11版本支持 pv 动态扩容(k8s层面),具体还要根据后端存储支持。 (3) pv设置的容量并不是最终的限制值,pv的容量只是一个参考值。 (4)pv静态供给下依次删除deployment/pod,pvc,pv后不会删除pv所对应的nfs共享卷 (5)删除pvc后,pv不会自动被删除 (6)Deployment无状态服务PV静态供给,多个pod公用一个pvc和pv (7)kubectl delete -f static-pv.yaml 方式删除deployment/pod时对应的pvc会被删除,pv不会被删除,kubectl apply -f static-pv.yaml再次 创建deployment/pod时会创建新的pvc,之前的静态pv不再被使用,会使用新的静态pv。 (8)静态供给需要提前在nfs家目录中创建pv卷目录。

# kubectl delete pod/my-pod

# kubectl delete persistentvolumeclaim/my-pvc

# kubectl delete persistentvolume/pv001

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

3.6 PV动态供给

我们前面说了 PV 和 PVC 的使用方法,但是前面的 PV 都是静态的,就是我要使用的一个 PVC 的话就必须手动去创建一个 PV,这种方式在很大程度上并不能满足我们的需求,比如我们有一个应用需要对存储的并发度要求比较高,这时使用静态的 PV 就很不合适了,这种情况下我们就需要用到动态 PV,StorageClass。

Dynamic Provisioning机制工作的核心在于StorageClass的API对象。

StorageClass声明存储插件,用于自动创建PV。

Kubernetes支持动态供给的存储插件:

https://kubernetes.io/docs/concepts/storage/storage-classes/

https://github.com/kubernetes-retired/external-storage/

3.7 PV动态供给实践(NFS)

工作流程

由于K8S不支持NFS动态供给,还需要先安装上图中的nfs-client-provisioner插件(nfs-client-provisioner会在nfs服务器上自动创建共享目录):

1 下载nfs-client-provisioner相关的yaml文件

https://github.com/kubernetes-retired/external-storage/tree/master/nfs-client/deploy
   class.yaml   deployment.yaml   rbac.yaml

2 修改连接nfs服务器的地址及共享目录
[root@k8s-admin ~]# vim deployment.yaml

......
spec:
serviceAccountName: nfs-client-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: fuseim.pri/ifs
- name: NFS_SERVER
value: 172.16.1.72 # 修改为nfs服务器地址
- name: NFS_PATH
value: /ifs/kubernetes # 修改为nfs共享目录
volumes:
- name: nfs-client-root
nfs:
server: 172.16.1.72 # 修改为nfs服务器地址
path: /ifs/kubernetes # 修改为nfs共享目录
......


3 查看pvc动态供给配置文件
[root@k8s-admin ~]# cat class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage # pv 动态供给插件名称
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "true"   # 修改删除pv后,自动创建的nfs共享目录不被删除。默认false,即删除

4 应用yaml
[root@k8s-admin ~]# kubectl apply -f .

5 查看

[root@k8s-admin ~]# kubectl get sc,pod -o wide

6 测试动态供给

[root@k8s-admin ~]# vim dynamic-pv.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: my-pvc ---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
storageClassName: "managed-nfs-storage"
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

这次会自动创建 5G PV 并与 PVC 绑定。

[root@k8s-admin ~]# kubectl apply -f dynamic-pv.yaml
[root@k8s-admin ~]# kubectl get pv,pvc

测试方法同上,进入到容器中/usr/share/nginx/html(PV挂载目录)目录下创建一个文件测试。

再切换到NFS服务器,会发现下面目录,该目录是自动创建的PV挂载点。进入到目录会发现刚在容器创建的文件。

[root@k8s-admin ~]# kubectl exec -it my-pod bash

root@my-pod:/# cd /usr/share/nginx/html
root@my-pod:/usr/share/nginx/html# echo "hello" >index.html

# 再切换到NFS服务器,会发现也有刚在容器创建的文件,说明工作正常。
[root@k8s-node2 ~]# ls /ifs/kubernetes/default-my-pvc-pvc-75be2f82-623e-4906-9137-211893ca1731/

index.html

说明:

(1) pv自动供给下依次删除deployment/pod,pvc,pv后默认会删除pv所对应的nfs共享卷 (2) 删除pvc后,pv会自动被删除。 (3) class.yaml文件中archiveOnDelete参数改为‘true’(archiveOnDelete: "true")后,删除pod,pvc,pv后不会删除pv所对应的nfs共享卷,但会在对应的nfs目录加archived字段前缀标识。 (4) Deployment无状态服务PV自动供给,多个pod公用一个pvc和pv。 (5) kubectl delete -f dynamic-pv.yaml 方式删除deployment/pod时对应的pvc和pv也会被删除。kubectl apply -f dynamic-pv.yaml再次创建 deployment/pod时会自动创建新的pvc和pv。 (6)自动供会自动在nfs家目录中创建pv卷目录。

1 查看相关信息
[root@k8s-admin ~]# kubectl get deployment,pod,sc,pvc,pv

2 删除 pod、pvc、pv

[root@k8s-admin ~]# kubectl delete pod/my-pod
[root@k8s-admin ~]# kubectl delete persistentvolumeclaim/my-pvc
# 因为是动态供给所以在删除pvc的时候,pv也会被删除。因为class.yaml文件中
# archiveOnDelete参数改为了‘true’(archiveOnDelete: "true"),pv所
# 对应的nfs共享卷不会被删除。

[root@k8s-node2 ~]# ls /ifs/kubernetes/
archived-default-my-pvc-pvc-d99326d2-26f3-471c-819d-c72f2ddcca56

[root@k8s-admin ~]# kubectl get deployment,pod,sc,pvc,pv

3 删除nfs-client-provisioner控制器

[root@k8s-admin ~]# kubectl delete deployment.apps/nfs-client-provisioner
# 删除deployment的同时相应的pod也会被删除

[root@k8s-admin ~]# kubectl delete storageclass.storage.k8s.io/managed-nfs-storage

第11章:Pod数据持久化的更多相关文章

  1. Java EE数据持久化框架 • 【第1章 MyBatis入门】

    全部章节   >>>> 本章目录 1.1 初识MyBatis 1.1.1 持久化技术介绍 1.1.2 MyBatis简介 1.1.2 Mybatis优点 1.1.3 利用Mav ...

  2. $《第一行代码:Android》读书笔记——第6章 数据持久化

    主要讲述了Android数据持久化的三种方式:文件存储.SharedPreference存储.SQLite数据库存储. (一)文件存储 其实Android中文件存储方式和Java的文件操作类似,就是用 ...

  3. [Xcode 实际操作]七、文件与数据-(11)数据持久化存储框架CoreData的使用:创建CoreData实体并插入数据

    目录:[Swift]Xcode实际操作 本文将演示[CoreData]数据持久化存储框架的使用. 点击[Create a new Xcode project]创建一个新的项目 ->[Single ...

  4. 探索Redis设计与实现11:使用快照和AOF将Redis数据持久化到硬盘中

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  5. iOS数据持久化-OC

    沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...

  6. MySQL性能调优与架构设计——第11章 常用存储引擎优化

    第11章 常用存储引擎优化 前言: MySQL 提供的非常丰富的存储引擎种类供大家选择,有多种选择固然是好事,但是需要我们理解掌握的知识也会增加很多.每一种存储引擎都有各自的特长,也都存在一定的短处. ...

  7. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  8. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  9. 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

随机推荐

  1. 『动善时』JMeter基础 — 23、JMeter中使用“用户自定义变量”实现参数化

    目录 1.用户自定义变量介绍 2.使用"用户自定义变量"实现参数化 (1)测试计划内包含的元件 (2)数据文件内容 (3)测试计划界面内容 (4)线程组元件内容 (5)CSV数据文 ...

  2. C# 技术体系简介

    C# 语言 .Net Framwork .NET Core winform界面编程 WPF开发经验,熟悉C/S架构产品开发及架构和设计 DevExpress界面框架(其实就是基于微软的 Winform ...

  3. 按时按登录IP记录Linux所有用户操作日志的方法

    背景:Linux用户操作记录一般通过命令history来查看历史记录,但是如果因为某人误操作了删除了重要的数据,这种情况下history命令就不会有什么作用了.以下方法可以实现通过记录登陆IP地址和所 ...

  4. linux(centos 7)下安装JDK,Tomcat,mysql 运行Maven 项目

    一.在Linux中安装JDK 1. 将JDK上传到root下(任何位置均可以). 如图: 2. 用解压命令解压JDK tar -xvf (此处为jdk文件名) 如果是rpm包,执行rpm -i jdk ...

  5. 并发王者课-青铜7:顺藤摸瓜-如何从synchronized中的锁认识Monitor

    在前面的文章中,我们已经体验过synchronized的用法,并对锁的概念和原理做了简单的介绍.然而,你可能已经察觉到,有一个概念似乎总是和synchronized.锁这两个概念如影相随,很多人也比较 ...

  6. unity项目字符串转为Vector3和Quaternion

    运用环境:一般在读取csv表格的数据时是string类型转为Vector3或者Quaternion类型 字符串格式:x,x,x /x,x,x,x (英文逗号) 方法: /// <summary& ...

  7. 性能调优必备:NIO的优化实现原理

    前言 我们就从底层的网络 I/O 模型优化出发,再到内存拷贝优化和线程模型优化,深入分析下 Tomcat.Netty 等通信框架是如何通过优化 I/O 来提高系统性能的. 网络 I/O 模型优化 网络 ...

  8. 华为计算平台MDC810发布量产

    华为计算平台MDC810发布量产 塞力斯的发布会刚刚结束,会上塞力斯SF5自由远征版也确实让人眼前一亮. 全球首款4S级加速能力.1000+km续航新能源作为这款车的卖点. 续航1000+km成了最近 ...

  9. pytorch空间变换网络

    pytorch空间变换网络 本文将学习如何使用称为空间变换器网络的视觉注意机制来扩充网络.可以在DeepMind paper 阅读更多有关空间变换器网络的内容. 空间变换器网络是对任何空间变换的差异化 ...

  10. Docker App应用

    Docker App应用 这是一个实验特性. 实验性功能提供了对未来产品功能的早期访问.这些特性仅用于测试和反馈,因为它们可能在没有警告的情况下在不同版本之间更改,或者可以从将来的版本中完全删除.在生 ...