技术标签: kubernetes python java 数据库 大数据
Kubernetes 项目引入了一组叫作 Persistent Volume Claim(PVC)和 Persistent Volume(PV)的 API 对象用于管理存储卷。
简单的说PersistentVolume (PV) 是集群中已由管理员配置的一段网络存储,是持久化存储数据卷;Persistent Volume Claim(PVC)描述的,则是 Pod 所希望使用的持久化存储的属性,比如,Volume 存储的大小、可读写权限等等。
上面的这段文字说明可能过于模糊,下面举个例子看看:
我们定义一个PVC,声明需要的Volume属性:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: manual
resources:
requests:
storage: 1Gi
yaml文件中定义了一个1 GiB的PVC,Access Modes表示需要的volume存储类型,ReadWriteOnce表示只能在一个node节点上进行读写操作,其他的Access Modes详见:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes。
然后再定义一个PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 10.244.1.4
path: "/"
这个 PV 对象中会详细定义存储的类型是NFS,以及大小是1 GiB。
PVC和PV相当于“接口”和“实现”,所以我们需要将PVC和PV绑定起来才可以使用,而PVC和PV绑定的时候需要满足:
做好PVC的声明之后,并建立好PV,然后就可以使用这个PVC了:
apiVersion: v1
kind: Pod
metadata:
labels:
role: web-frontend
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs
在Pod中只需要声明PVC的名字,等Pod创建后kubelet 就会把这个 PVC 所对应的 PV,也就是一个 NFS 类型的 Volume,挂载在这个 Pod 容器内的目录上。
PersistentVolumeController会不断地查看当前每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与这个“单身”的 PVC 进行绑定。所以如果出现没有PV可以和PVC绑定,那么Pod 的启动就会报错。
这个时候就需要用到StorageClass了,在上面我们说的PV和PVC绑定的过程称为Static Provisioning,需要手动的创建PV;StorageClass还提供了Dynamic Provisioning机制,可以根据模板创建PV。
StorageClass 对象会定义如下两个部分内容:
这样k8s就能够根据用户提交的 PVC,找到一个对应的 StorageClass ,然后调用该 StorageClass 声明的存储插件,创建出需要的 PV。
例如声明如下StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: block-service
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
这里定义了名叫 block-service 的 StorageClass,provisioner 字段的值是:kubernetes.io/gce-pd,这是k8s内置的存储插件,type字段也是跟着provisioner定义的,官方默认支持 Dynamic Provisioning 的内置存储插件:https://kubernetes.io/docs/concepts/storage/storage-classes/。
然后就可以在PVC中声明storageClassName为block-service,当创建好PVC 对象之后,k8s就会调用相应的存储插件API创建一个PV对象。
如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
storageClassName: block-service
resources:
requests:
storage: 30Gi
这种自动创建PV的机制就是Dynamic Provisioning,Kubernetes 就能够根据用户提交的 PVC,找到一个对应的 StorageClass ,然后会调用StorageClass 声明的存储插件,创建出需要的 PV。
需要注意的是,如果没有声明StorageClassName在PVC中,PVC 的 storageClassName 的值就是"",这也意味着它只能够跟 storageClassName 也是""的 PV 进行绑定。
PV和PVC之间的相互作用遵循这个生命周期:
Provisioning —>Binding —>Using —>Reclaiming
Provisioning
k8s提供了两种PV生成方式: statically or dynamically
statically:由管理员创建PV,它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费。
dynamically:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses,PVC必须请求一个StorageClasses,并且管理员必须已创建并配置该类才能进行动态配置。
Binding
由用户创建好PersistentVolumeClaim 后,PersistentVolumeController会不断地查看当前每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与这个“单身”的 PVC 进行绑定。
Using
Pods声明并使用PVC作为volume后,集群会找到该PVC,如果该PVC已经绑定了PV,那么会将该volume挂载到Pod中。
Reclaiming
当用户已经不再使用该volume,可以将该PVC删除,以便让资源得以回收。相应的在PVC删除后,PV的回收策略可以是Retained, Recycled, or Deleted,这个策略可以在字段spec.persistentVolumeReclaimPolicy中设置。
删除流程
一般的情况下,我们遵循这个删除流程:
Local Persistent Volume适用于类似分布式数据存储比如 MongoDB、Cassandra等需要在多个不同节点上存储数据,并且对I/O 较为敏感的应用。但是相比于正常的 PV,一旦这些节点宕机且不能恢复时,Local Persistent Volume 的数据就可能丢失。
在我们的实验环境中,在宿主机上挂载几个 RAM Disk(内存盘)来模拟本地磁盘。例如:
我们在node1节点上挂载几个磁盘
$ mkdir /mnt/disks
$ for vol in vol1 vol2 vol3; do
mkdir /mnt/disks/$vol
mount -t tmpfs $vol /mnt/disks/$vol
done
然后创建相应的PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 512Mi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/vol1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node1
这个 PV 的定义里:local 字段指定了它是一个 Local Persistent Volume;而 path 字段,指定的正是这个 PV 对应的本地磁盘的路径,即:/mnt/disks/vol1。并且用nodeAffinity指定这个PV必须运行在node1节点上。
运行上面的PV:
$ kubectl create -f local-pv.yaml
persistentvolume/example-pv created
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
example-pv 512Mi RWO Delete Available local-storage 16s
然后创建一个StorageClass 来描述这个 PV:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
这个 StorageClass叫local-storage,provisioner为no-provisioner表示不需要自动创建PV。
volumeBindingMode=WaitForFirstConsumer表示需要等到Pod运行之后才让PVC和PV绑定。因为在使用Local Persistent Volume的时候PV和对应的PVC必须要跟随Pod在同一node下面,否则会调度失败。
然后我们运行StorageClass:
$ kubectl create -f local-sc.yaml
storageclass.storage.k8s.io/local-storage created
再创建一个PVC:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 512Mi
storageClassName: local-storage
这里注意声明storageClassName需要是我们上面创建的StorageClass。
然后创建PVC:
$ kubectl create -f local-pvc.yaml
persistentvolumeclaim/example-local-claim created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-local-claim Pending local-storage 7s
这个时候因为还没创建Pod,所以状态还是Pending。
创建一个pod:
kind: Pod
apiVersion: v1
metadata:
name: example-pv-pod
spec:
volumes:
- name: example-pv-storage
persistentVolumeClaim:
claimName: example-local-claim
containers:
- name: example-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: example-pv-storage
然后我们创建pod后再看看PVC绑定状态:
$ kubectl create -f local-pod.yaml
pod/example-pv-pod created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-local-claim Bound example-pv 512Mi RWO local-storage 6h
然后我们试着写入一个文件到/usr/share/nginx/html中:
$ kubectl exec -it example-pv-pod -- /bin/sh
# cd /usr/share/nginx/html
# touch test.txt
# 在node1上
$ ls /mnt/disks/vol1
test.txt
文章浏览阅读5.7k次。最近在coding的过程遇到一个问题: public class HashMapDemo { public static void main(String[] args) { testGo(); } public static void testGo() { Map badGodMap = new HashMap<>(_containskey有问题
文章浏览阅读4.7k次。提到collectionview,很多人都会想到用他作为图片的显示。到时如何让collectionview显示为一行的数据,并可以横向的滚动,在xcode的中,我们很容易的想到使用故事版修改属性,将ScrollDirection 修改为Horizontal,如图所示:_swift 实现横向滑动collectionview,左右显示一部分cell,有间距
文章浏览阅读1.5k次。第一:笔画替代法笔画替换,.以原来文字为基础,用其中的一个笔画或者多个笔画通过其他的方式来进行替换,可以是另字体笔画的嫁接,也可以接触其他的图形的创意表达。第二:细节添加根据设计要表达的内容进行针对性的设计改动.常常是笔画的笔画端点处进行锚点增改.通过增加细节,让文字变得不同。第三:删..._字体修改方法
文章浏览阅读297次。TensorBoardX是基于tensorboard的思想用来写tensorboard events的工具,可以实现对传统的tensorboard中scalar,image,figure,histogram,audio,text,graph,onnx_graph等事件进行编写。1 导入SummaryWriter并创建SummaryWriter实例from tensorboardX impo..._pytorch特征在二维平面显示
文章浏览阅读1.3k次。原文链接 https://www.cnblogs.com/coryxie/p/3956211.html 本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com。 本章列出并定义本规范通篇将使用的术语及缩略语。 术语/略缩语定义ACK(确认包)表示积极肯定的握手包。ACK Tx Header Sequence Number(ACK Tx 头包序..._usb中的receptacle tongue是指什么
文章浏览阅读154次。例子:配置Tomcat JNDI数据源-将数据库jar文件拷贝到tomcat\common\lib下-在Tomcat的server.xml配置文件中添加(其中path是工程的名字 docBase也是工程的名字)
文章浏览阅读9.4k次,点赞3次,收藏6次。今天做完项目提交,产品给我提了一个问题,说我这个第一次打开的时候总是获取不到数据,得第二次才可以。我测试了下,点第一次走了接口,结果一闪而过,然后啥都没了,我还打印了下,结果闪了一下就没了,经过仔细查找,才发现我的路径地址是 http://localhost:8080/?#/warship,莫名其妙的多了个 “?”,然后百度了一下说是页面..._vue中第一次点击按钮无数据,第二次点击有数据
文章浏览阅读815次。vue 使用webpack插件打包时候报错,错误如图所示:因为安装的时候是直接使用如下指令:npm install compression-webpack-plugin此时安装的即为该插件的最新版本,现在是2021.7.16,最新版本为经过查找已经自行尝试,实现解决该问题。方案如下:使用低版本该插件具体步骤如下:卸载当前版本npm uninstall compression-webpack-plugin安装低版本npm install compression-webpa_typeerror: cannot read property 'tappromise' of undefined
文章浏览阅读6.3k次,点赞4次,收藏14次。今日工作中有要求需要对.Tar类型文件进行压缩和解压处理。按照常规处理之后出现了压缩文件乱码,以及压缩文件不能对之进行正常解压的现场。经过一番调整,发现问题在与文件解压与压缩时的编码设置。以下代码基于ant-1.9.2.jar_tar 怎么设置编码方式 java
文章浏览阅读362次。当前位置:我的异常网» Oracle管理»oracle 11g em重建,提醒口令无效。口令用pl/SQL都oracle 11g em重建,提醒口令无效。口令用pl/SQL都能登录,就EMCA说无效www.myexceptions.net网友分享于:2015-08-26浏览:1264次oracle 11g em重建,提示口令无效。口令用pl/SQL都能登录,就EMCA说无效!安装ora...
文章浏览阅读155次。Linux服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户。提供这些服务的程序是由运行在后台的守护进程(daemons)来执行的。守护进程是生存期长的一..._unix把进城转为守护进程
文章浏览阅读2.2k次。1.使用yum安装virt-install和virt-viewer工具。2.将centos镜像上传至虚拟机,使用qemu-img创建虚拟机硬盘,然后创建虚拟机3.#virt-install --connect qemu:///system --name-centos7 --os-type=linux --cdrom=/opt/mirror/centos72003.iso --os-variant=rhel7 --ram 1024 --vcpus 2 --vnc --vncport=5909 --vnc_fhviewer