Kubernetes的故事之持久化存储(十)
一、Storage
1.1、Volume
官网网址:https://kubernetes.io/docs/concepts/storage/volumes/
通过官网说明大致总结下就是这个volumes在docker中的理解就是我仅仅是通过一个volumes技术可以声名一个变量,然后可以通过这个变量将物理主机的路径和虚拟路径进行一个绑定;简单来说这就是一个持久化技术;在k8s中就可以理解是跟pod的绑定持久化;这块内容的实践在前面的yaml文件中有应用到,有兴趣的可以看前面文章。但这玩意还是有问题的,例如,我应用现在在A节点上,数据持久化也持久化在A节点上,但是,服务迁移后我服务到了B节点上,这时问题就来了。
1.2、Host类型volume实战
定义一个Pod,其中包含两个Container,都使用Pod的Volume;pod命名是volume-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: volume-pod
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: volume-pod
mountPath: /nginx-volume
- name: busybox-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
volumeMounts:
- name: volume-pod
mountPath: /busybox-volume
volumes:
- name: volume-pod
hostPath:
path: /tmp/volume-pod
(1)创建资源
kubectl apply -f volume-pod.yaml
(2)查看pod的运行情况
kubectl get pods -o wide
(3)来到运行的worker节点
用命令查看容器是否存在
docker ps | grep volume
进入docker目录看创建的目录是否存在,会发现nginx-volume和busybox-volume目录是存在的
docker exec -it containerid sh
(4)查看pod中的容器里面的hosts文件,是否一样。(将上面两个文件夹里面的东西和宿主机的volume-pod内容对比下就可以了)
(5)所以一般container中的存储或者网络的内容,不要在container层面修改,而是在pod中修改
1.3 PersistentVolume
官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/
这个方案是生产环境推荐的方式;
前面说的volumes技术是将虚拟盘映射到物理机上,我也说过会有一个问题,那就是系统迁移到另一台服务器上时,虚拟盘和持久盘不在同一个物理主机上,那怎么解决这个问题呢,其实也很简单,我在持久化时不是持久化到物理主机上,而是持久化到一个固定的主机上,然后将固定的主机物理盘做高可用,这样,你虚拟盘怎么浪都可以找到固定的持久化盘位置了。yaml文件如下
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi # 存储空间大小
volumeMode: Filesystem
accessModes:
- ReadWriteOnce # 只允许一个Pod进行独占式读写操作
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp # 远端服务器的目录
server: 172.17.0.2 # 远端的服务器
说白了,PV是K8s中的资源,volume的plugin实现,生命周期独立于Pod,封装了底层存储卷实现的细节。
1.4、PersistentVolumeClaim
官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims
有了PV,那Pod如何使用呢?为了方便使用,我们可以设计出一个PVC来绑定PV,然后把PVC交给Pod来使用即可
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
说白了,PVC会匹配满足要求的PV[**是根据size和访问模式进行匹配的**],进行一一绑定,然后它们的状态都会变成Bound。也就是PVC负责请求PV的大小和访问方式,然后Pod中就可以直接使用PVC咯。
1.5、Pod中如何使用PVC
官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
1.6、Pod中使用PVC实战
场景背景:使用nginx持久化存储演示
- 共享存储使用nfs,比如选择在m节点
- 创建pv和pvc
- nginx pod中使用pvc
1.6.1 master节点搭建nfs
在master节点上搭建一个NFS服务器,目录为/nfs/data
1)选择master节点作为nfs的server,所以在master节点上安装nfs
yum install -y nfs-utils
创建nfs目录
mkdir -p /nfs/data/
mkdir -p /nfs/data/mysql
授予权限
chmod -R 777 /nfs/data
编辑export文件
vi /etc/exports
/nfs/data *(rw,no_root_squash,sync)
使得配置生效
exportfs -r
查看生效
exportfs
启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs
查看rpc服务的注册情况
rpcinfo -p localhost
showmount测试
showmount -e master-ip
2)所有node上安装客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs
1.6.2 创建PV&PVC&Nginx
(1)在nfs服务器创建所需要的目录
mkdir -p /nfs/data/nginx
(2)定义PV,PVC和Nginx的yaml文件;我取名为nginx-pv-demo.yaml
# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 2Gi
nfs:
path: /nfs/data/nginx
server: 121.41.10.13 ---
# 定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi ---
# 定义Pod,指定需要使用的PVC
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: mysql
ports:
- containerPort: 80
volumeMounts:
- name: nginx-persistent-storage
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-persistent-storage
persistentVolumeClaim:
claimName: nginx-pvc
(3)根据yaml文件创建资源并查看资源
kubectl apply -f nginx-pv-demo.yaml
kubectl get pv,pvc
kubectl get pods -o wide
(4)测试持久化存储
- 在/nfs/data/nginx新建文件1.html,写上内容
- kubectl get pods -o wide 得到nginx-pod的ip地址
- curl nginx-pod-ip/1.html
- kubectl exec -it nginx-pod bash 进入/usr/share/nginx/html目录查看
- kubectl delete pod nginx-pod
- 查看新nginx-pod的ip并且访问nginx-pod-ip/1.html
1.7、 StorageClass
上面手动管理PV的方式还是有点low,下面来个更方便的
官网:https://kubernetes.io/docs/concepts/storage/storage-classes/
github:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs
官网的话简述下意思就是说StorageClass是声明存储插件,用于自动创建PV的。说白了就是创建PV的模板,其中有两个重要部分:PV属性和创建此PV所需要的插件。这样PVC就可以按“Class”来匹配PV。可以为PV指定storageClassName属性,标识PV归属于哪一个Class。
下面是官网上提供的模板文件
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
- debug
volumeBindingMode: Immediate
官网太长我不一一解读,可以自己看,但官网的文档说明了一个很重要的信息,那就是StorageClass之所以能够动态供给PV,是因为Provisioner,也就是Dynamic Provisioning,但是NFS这种类型,K8s中默认是没有Provisioner插件的,需要自己创建;但我们现在用的就是NFS这种模式,如果NFS不能支持,那我们当面玩的一切的一切就是白玩的,其实我觉得不用太担心,为什么呢,针对开发这种事,总有人愿意挑战,把不可能的事变成可能;下面我在实战中我结合github中大佬提供的NFS插件支持的做法实现上面的理论。
1.8 StorageClass实战
github:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs
(1)准备好NFS服务器[并且确保nfs可以正常工作],创建持久化需要的目录
cd /nfs/data/ghy
(2)由于创建资源需要APIServer的认证,所以要创建一个帐户跟APIServer交互,所以根据rbac.yaml文件创建资源
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: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get"]
- 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
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-provisioner
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-provisioner
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
(3)根据deployment.yaml文件创建资源,里面会有我们要访问的服务器,大家把里面配置的ip和服务器文件名改成自己的;看这个配置大家也很容易清楚这玩意就是跟NFS服务器进行交互的玩意
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: nfs-provisioner
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: example.com/nfs
- name: NFS_SERVER
value: 192.168.0.21
- name: NFS_PATH
value: /nfs/data/ghy
volumes:
- name: nfs-client-root
nfs:
server: 192.168.0.21
path: /nfs/data/ghy
kubectl apply -f deployment.yaml
(4)根据class.yaml创建资源
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: example-nfs
provisioner: example.com/nfs
kubectl apply -f class.yaml
(5)经过前面的步骤,以前我们要创建PV的动作就可以不用了。因为有了storage自动帮我们生成了,接下来我们就应该创建PVC了,但现在又有个问题,那就是PVC不能自动绑定PV,原因就是因为我们现在的方式是不用创建Pv了,pv创建的这个动作由,storage自动帮我们创建,现在我们创建一个PVC然后根据my-pvc.yaml创建资源;
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
# 这个名字要和上面创建的storageclass名称一致,之所以要一至是因为我们要通过storageclass创建PV,所以要匹配storageclass然后让他动态帮我们创建PV
storageClassName: example-nfs
kubectl apply -f my-pvc.yaml
kubectl get pvc
(6)经过上面PV和PVC都有了,按照以前的方式就差个Pod了,下面根据nginx-pod.yaml创建资源
kind: Pod
apiVersion: v1
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: my-pvc
mountPath: "/usr/ghy"
restartPolicy: "Never"
volumes:
- name: my-pvc
persistentVolumeClaim:
claimName: my-pvc
kubectl apply -f nginx-pod.yaml
kubectl exec -it nginx bash
然后用下面命令修改文件进行验证文件同步问题
cd /usr/ghy
上面流程其实总结下可以用下面这张图片总结
1.9 PV的状态和回收策略
PV的状态
- Available:表示当前的pv没有被绑定
- Bound:表示已经被pvc挂载
- Released:pvc没有在使用pv, 需要管理员手工释放pv
- Failed:资源回收失败
PV回收策略
- Retain:表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理
- Recycle:在Kubernetes新版本就不用了,采用动态PV供给来替代
- Delete:表示删除PVC的时候,PV也会一起删除,同时也删除PV所指向的实际存储空间
注意:目前只有NFS和HostPath支持Recycle策略。AWS EBS、GCE PD、Azure Disk和Cinder支持Delete策略
Kubernetes的故事之持久化存储(十)的更多相关文章
- Kubernetes 学习(十)Kubernetes 容器持久化存储
0. 前言 最近在学习张磊老师的 深入剖析Kubernetes 系列课程,最近学到了 Kubernetes 容器持久化存储部分 现对这一部分的相关学习和体会做一下整理,内容参考 深入剖析Kuberne ...
- Kubernetes持久化存储2——探究实验
目录贴:Kubernetes学习系列 一.简介 本文在“创建PV,创建PVC挂载PV,创建POD挂载PVC”这个环境的基础上,进行各种删除实验,并记录.分析各资源的状态. 二.实验脚本 实验创建了一个 ...
- kubernetes学习 做持久化存储
本节演示如何为 MySQL 数据库提供持久化存储,步骤: 1.创建 PV 和 PVC 2.部署 MySQL 3.向 MySQL 添加数据 4.模拟节点宕机故障,Kubernetes 将 MySQL 自 ...
- 使用Ceph集群作为Kubernetes的动态分配持久化存储(转)
使用Docker快速部署Ceph集群 , 然后使用这个Ceph集群作为Kubernetes的动态分配持久化存储. Kubernetes集群要使用Ceph集群需要在每个Kubernetes节点上安装ce ...
- Kubernetes 系列(六):持久化存储 PV与PVC
在使用容器之后,我们需要考虑的另外一个问题就是持久化存储,怎么保证容器内的数据存储到我们的服务器硬盘上.这样容器在重建后,依然可以使用之前的数据.但是显然存储资源和 CPU 资源以及内存资源有很大不同 ...
- Kubernetes 持久化存储是个难题,解决方案有哪些?\n
像Kubernetes 这样的容器编排工具正在彻底改变应用程序的开发和部署方式.随着微服务架构的兴起,以及基础架构与应用程序逻辑从开发人员的角度解耦,开发人员越来越关注构建软件和交付价值. Kuber ...
- Kubernetes 使用 ceph-csi 消费 RBD 作为持久化存储
原文链接:https://fuckcloudnative.io/posts/kubernetes-storage-using-ceph-rbd/ 本文详细介绍了如何在 Kubernetes 集群中部署 ...
- Kubernetes之持久化存储
转载自 https://blog.csdn.net/dkfajsldfsdfsd/article/details/81319735 ConfigMap.Secret.emptyDir.hostPath ...
- Vue-admin工作整理(十二):Vuex-插件(持久化存储)
Vuex可以支持插件形式,来处理指定业务,比如:持久化存储的插件(当每次刷新浏览器的时候store里面的参数都会被清除,因为它是存在内存中的,而不是存在本地的,有时候我们希望将一些东西存在本地) 插件 ...
随机推荐
- 【LeetCode】188. Best Time to Buy and Sell Stock IV 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【LeetCode】155. Min Stack 最小栈 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 栈同时保存当前值和最小值 辅助栈 同步栈 不同步栈 日期 题目地 ...
- 【LeetCode】560. Subarray Sum Equals K 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【LeetCode】473. Matchsticks to Square 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 日期 题目地址:https://leetco ...
- FAT
目录 概 主要内容 代码 Zhang J., Xu X., Han B., Niu G., Cui L., Sugiyama M., Kankanhalli M. Attacks which do n ...
- 详解Kalman Filter
中心思想 现有: 已知上一刻状态,预测下一刻状态的方法,能得到一个"预测值".(当然这个估计值是有误差的) 某种测量方法,可以测量出系统状态的"测量值".(当然 ...
- 网站迁移纪实:从Web Form 到 Asp.Net Core (Abp vNext 自定义开发)
问题和需求 从2004年上线,ZLDNN.COM运行已经超过16年了,一直使用DotNetNuke平台(现在叫DNN Platform),从最初的DotNetNuke 2.1到现在使用的7.4.先是在 ...
- 初遇NFT-IPFS
初遇NFT-IPFS 本次学习如何使用Hardhat框架制作可预售的NFT并利用IPFS存储元数据. NFT简介 NFT全称Non-fungible Token(即非同质化通证).不可分割性(目前有碎 ...
- Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...
- 使用sudo执行命令提示command not found
笔记: 使用源码部署nginx的时候,使用sudo nginx提示command not found,但是直接使用nginx会导致权限问题: 这种情况应该是环境变量导致的,使用 env |grep P ...