k8s数据管理(八)
volume
我们经常会说:容器和 Pod 是短暂的。
其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。
为了持久化保存容器的数据,可以使用 Kubernetes Volume。
Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。
本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。Kubernetes Volume 也支持多种 backend 类型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可参考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes
Volume 提供了对各种 backend 的抽象,容器在使用 Volume 读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的 Volume 都只是一个目录。
emptyDir
emptyDir 是最基础的 Volume 类型。一个 emptyDir Volume 是 Host 上的一个空目录。
emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。
也就是说:emptyDir Volume 的生命周期与 Pod 一致。
Pod 中的所有容器都可以共享 Volume,它们可以指定各自的 mount 路径。
下面通过例子来实践 emptyDir
第一步:配置文件如下:
这里我们模拟了一个 producer-consumer 场景。Pod 有两个容器 producer和 consumer,它们共享一个 Volume。producer 负责往 Volume中写数据,consumer 则是从 Volume 读取数据。
① 文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-volume。
② producer 容器将 shared-volume mount 到 /producer_dir 目录。
③ producer 通过 echo 将数据写到文件 hello 里。
④ consumer 容器将 shared-volume mount 到 /consumer_dir 目录。
⑤ consumer 通过 cat 从文件 hello 读数据。
第二步:执行如下命令创建 Pod:
[root@ken ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
producer-consumer 2/2 Running 0 2m1s
[root@ken ~]# kubectl logs producer-consumer consumer
hello world
注意:一个pod里面运行多个容器的时候,查看容器日志,需要指定pod名称及容器名
kubectl logs 显示容器 consumer 成功读到了 producer 写入的数据,验证了两个容器共享 emptyDir Volume。
因为 emptyDir 是 Docker Host 文件系统里的目录,其效果相当于执行了 docker run -v /producer_dir 和 docker run -v /consumer_dir。
第三步:通过 docker inspect 查看容器的详细配置信息,我们发现两个容器都 mount 了同一个目录:
这里 /var/lib/kubelet/pods/4dcc0366-245f-11e9-9172-000c292d5bb8/volumes/kubernetes.io~empty-dir/shared-volume 就是 emptyDir在 Host 上的真正路径。
emptyDir 是 Host 上创建的临时目录,其优点是能够方便地为 Pod 中的容器提供共享存储,不需要额外的配置。但它不具备持久性,如果 Pod 不存在了,emptyDir 也就没有了。根据这个特性,emptyDir 特别适合 Pod 中的容器需要临时共享存储空间的场景,比如前面的生产者消费者用例。
hostpath
hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器。大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。
比如 kube-apiserver 和 kube-controller-manager 就是这样的应用,通过
kubectl edit –namespace=kube-system pod kube-apiserver-k8s-master
查看 kube-apiserver Pod 的配置,下面是 Volume 的相关部分:
这里定义了三个 hostPath volume k8s、certs 和 pki,分别对应 Host 目录 /etc/kubernetes、/etc/ssl/certs 和 /etc/pki。
如果 Pod 被销毁了,hostPath 对应的目录也还会被保留,从这点看,hostPath 的持久性比 emptyDir 强。不过一旦 Host 崩溃,hostPath 也就没法访问了。
示例:把节点上的tmp目录挂载到容器中
第一步:编写yml文件
[root@ken-node1 ~]# cat hostpath.yml
apiVersion: v1
kind: Pod
metadata:
name: myhostpath
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: hostpath
mountPath: /usr/share/nginx/html
volumes:
- name: hostpath
hostPath:
path: /tmp
type: Directory
启动nginx,把主机的/tmp目录挂载到nginx容器的网站根目录
这里共享的是tmp目录,如果是挂载其他的目录要确保节点有这个目录
第二步:启动
[root@ken-node1 ~]# kubectl apply -f hostpath.yml
第三步:在tmp目录下编写测试文件
[root@ken-node1 ~]# echo "hostpath" > /tmp/index.html
第四步:查看podIP并尝试访问
[root@ken-node1 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READIN
myhostpath 1/1 Running 0 8m8s 10.244.1.59 ken-node2 <none> <none>
第五步:访问
[root@ken-node1 ~]# curl 10.244.1.59
hostpath
对接NFS
第一步:在控制节点部署NFS
[root@ken-node1 ~]# yum install nfs-utils rpcbind -y
[root@ken-node1 ~]# rm -rf /ken
[root@ken-node1 ~]# mkdir /ken
[root@ken-node1 ~]# chown -R nfsnobody: /ken
[root@ken-node1 ~]# echo "/ken *(rw)" > /etc/exports
[root@ken-node1 ~]# systemctl restart nfs rpcbind
第二步:编写yml文件
[root@ken-node1 ~]# cat nfs.yml
apiVersion: v1
kind: Pod
metadata:
name: nfs
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nfsback
mountPath: /usr/share/nginx/html
volumes:
- name: nfsback
nfs:
path: /ken
server: 192.168.163.132
第三步:节点需要下载nfs-utils去支持nfs文件类型,否则会报错
[root@ken-node2 ~]# yum install nfs-utils -y
第四步:执行yml文件
[root@ken-node1 ~]# kubectl apply -f nfs.yml
第五步:查看pod的IP
[root@ken-node1 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs 1/1 Running 0 3m3s 10.244.2.61 ken-node3 <none> <none>
第六步:编写测试文件在/ken共享目录下
[root@ken-node1 ~]# echo "nfs" > /ken/index.html
第七步: 访问测试
[root@ken-node1 ~]# curl 10.244.2.61
nfs
PV & PVC
PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。
PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。
有了 PersistentVolumeClaim,用户只需要告诉 Kubernetes 需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息。这些 Storage Provider 的底层信息交给管理员来处理,只有管理员才应该关心创建 PersistentVolume 的细节信息。
Kubernetes 支持多种类型的 PersistentVolume,比如 AWS EBS、Ceph、NFS 等,完整列表请参考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes
NFS PV
第一步:需在 k8s-master 节点上搭建了一个 NFS 服务器,目录为 /nfsdata:
要更改目录属主,否则没有写入权限: chown -R nfsnobody.nfsnobody /nfsdata
注意:
- nfs可以安装在任意节点,不一定是在k8s集群当中的一台服务器
- k8s集群内的每台节点必须都要安装nfs-utils否则识别不到nfs类型
[root@ken ~]# showmount -e
Export list for ken:
/nfsdata *
第二步:创建一个 PV mypv1,配置文件 nfs-pv1.yml 如下:
[root@ken ~]# cat nfs-pv1.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /nfsdata/pv1 #需要创建pv1目录,否则pod起不来
server: 172.20.10.2
① capacity 指定 PV 的容量为 1G。
② accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
③ persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有:
Retain – 需要管理员手工回收。
Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。
Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
④ storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
⑤ 指定 PV 在 NFS 服务器上对应的目录。
第三步:创建 mypv1:
[root@ken ~]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 created
第四步:查看pv
[root@ken ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Recycle Available nfs 48s
STATUS 为 Available,表示 mypv1 就绪,可以被 PVC 申请。
第五步:接下来创建 PVC mypvc1,配置文件 nfs-pvc1.yml 如下:
注意:
1. 各个节点都需要下载nfs-utils
[root@ken-node1 ~]# cat pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
volumeName: mypv #pv名字
PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。
[root@ken ~]# kubectl apply -f nfs-pvc1.yml
persistentvolumeclaim/mypvc1 created
第六步:查看pvc
[root@ken ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc1 Bound mypv1 1Gi RWO nfs 112s
[root@ken ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Recycle Bound default/mypvc1 nfs 6m5s
从 kubectl get pvc 和 kubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。
第七步:接下来就可以在 Pod 中使用存储了,Pod 配置文件 pod1.yml 如下:
与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用 mypvc1 申请的 Volume。
第八步:创建 mypod1:
[root@ken ~]# kubectl apply -f pod1.yml
pod/mypod1 created
[root@ken ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypod1 1/1 Running 0 51s 10.244.1.59 host1 <none> <none>
第九步:验证 PV 是否可用:
[root@ken ~]# kubectl exec mypod1 touch /mydata/hello [root@ken ~]# ls /nfsdata/pv1/
hello
可见,在 Pod 中创建的文件 /mydata/hello 确实已经保存到了 NFS 服务器目录 /nfsdata/pv1 中。
回收PV
当 PV 不再需要时,可通过删除 PVC 回收。
当 PVC mypvc1 被删除后,Kubernetes 启动了一个新 Pod recycler-for-mypv1,这个 Pod 的作用就是清除 PV mypv1 的数据。此时 mypv1 的状态为 Released,表示已经解除了与 mypvc1 的 Bound,正在清除数据,不过此时还不可用。
当数据清除完毕,mypv1 的状态重新变为 Available,此时则可以被新的 PVC 申请。
因为 PV 的回收策略设置为 Recycle,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain。
第一步:将策略设置为 Retain。
[root@ken ~]# cat nfs-pv1.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/pv1
server: 172.20.10.2
第二步:通过 kubectl apply 更新 PV:
root@ken ~]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 configured
[root@ken ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Retain Available nfs 65m
回收策略已经变为 Retain,通过下面步骤验证其效果:
① 重新创建 mypvc1
。
② 在 mypv1
中创建文件 hello
。
③ mypv1
状态变为 Released
。
④ Kubernetes 并没有启动 Pod recycler-for-mypv1
。
⑤ PV 中的数据被完整保留。
另外使用retain虽然删除pod后的数据得到了保留,但其 PV 状态会一直处于 Released,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建 PV。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。
新建的 mypv1
状态为 Available
,已经可以被 PVC 申请。
小结
本章我们讨论了 Kubernetes 如何管理存储资源。
emptyDir 和 hostPath 类型的 Volume 很方便,但可持久性不强,Kubernetes 支持多种外部存储系统的 Volume。
PV 和 PVC 分离了管理员和普通用户的职责,更适合生产环境。
k8s数据管理(八)的更多相关文章
- k8s数据管理(八)--技术流ken
volume 我们经常会说:容器和 Pod 是短暂的.其含义是它们的生命周期可能很短,会被频繁地销毁和创建.容器销毁时,保存在容器内部文件系统中的数据都会被清除. 为了持久化保存容器的数据,可以使用 ...
- linux运维、架构之路-K8s数据管理
一.Volume介绍 容器和Pod是短暂的,它们的生命周期可能很短,会被频繁的销毁和创建,存在容器中的数据会被清除,为了持久化保存容器的数据,k8s提供了Volume.Volume的生命周期独立于容器 ...
- ASP.NET Core on K8S深入学习(10)K8S包管理器Helm
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.关于Helm 1.1 为何需要Helm? 虽然K8S能够很好地组织和编排容 ...
- ApacheCN 数据库译文集 20211112 更新
创建你的 Mysql 数据库 零.前言 一.介绍 MySQL 设计 二.数据采集 三.数据命名 四.数据分组 五.数据结构调整 六.补充案例研究 Redis 学习手册 零.序言 一.NoSQL 简介 ...
- ApacheCN Vue 译文集 20211115 更新
使用 GraphQL 构建 VueJS 应用 零.前言 一.数据绑定.事件和计算属性 二.组件.混合器和功能组件 三.设置我们的聊天应用--AWS Amplify 环境和 GraphQL 四.创建自定 ...
- ASP.NET Core on K8S深入学习(8)数据管理
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在Docker中我们知道,要想实现数据的持久化(所谓Docker的数据持久化即 ...
- Kubernetes1.91(K8s)安装部署过程(八)-- kubernetes-dashboard安装
kubernets-dashboard顾名思义是操作面板安装,也就是可视化管理机器,同意我们用镜像结合配置文件部署. 1.下载镜像: docker pull registry.docker-cn.co ...
- kubernetes实战(八):k8s集群安全机制RBAC
1.基本概念 RBAC(Role-Based Access Control,基于角色的访问控制)在k8s v1.5中引入,在v1.6版本时升级为Beta版本,并成为kubeadm安装方式下的默认选项, ...
- Docker笔记(八):数据管理
前面(哪个前面我也忘了)有说过,如果我们需要对数据进行持久化保存,不应使其存储在容器中,因为容器中的数据会随着容器的删除而丢失,而因通过将数据存储于宿主机文件系统的形式来持久化.在Docker容器中管 ...
随机推荐
- Linux非交互方式设置密码
echo "123" | passwd -stdin lamp echo testuser:password|chpasswd 参考:Linux通过Shell脚本命令修改密码不需要 ...
- Storm与SparkStreaming对比
Storm与SparkStreaming对比 ◆ Spark Streaming 批处理的性能比Storm高出几十倍.◆ Streaming采用小批量模式,Storm是一条消息一条消息的计算.◆ St ...
- Keras结合Keras后端搭建个性化神经网络模型(不用原生Tensorflow)
Keras是基于Tensorflow等底层张量处理库的高级API库.它帮我们实现了一系列经典的神经网络层(全连接层.卷积层.循环层等),以及简洁的迭代模型的接口,让我们能在模型层面写代码,从而不用仔细 ...
- Vue生命周期,我奶奶看了都懂了
最近一直在学习Vue,而vue生命周期是我们不可能绕开的一个很核心的知识点,今天来简单的梳理一下大概的内容. 一.钩子函数 在一开始学习的时候,总有钩子函数这个名词冒出来,而且在vue官网文档中也频繁 ...
- WS以及NW小世界网络的生成(MATLAB)
WS小世界网络生成算法,一般小世界网络生成算法速度慢,节点度分布与数学推导不符,在网络仿真中造成不便,这里针对实际网络动力学仿真过程撰写了WS小世界网络的MATLAB生成算法,并考虑了矩阵化,具有较高 ...
- 更改默认Xcode
更改默认 Xcode 的指令: sudo xcode-select -switch /Applications/Xcode.app 如果系统里面有好几个版本的 Xcode,可以用这个命令指定默认的 ...
- 区块链入门到实战(35)之Solidity – 变量作用域
局部变量的作用域仅限于定义它们的函数,但是状态变量可以有三种作用域类型. Public – 公共状态变量可以在内部访问,也可以通过消息访问.对于公共状态变量,将生成一个自动getter函数. Inte ...
- Linux 部署java web 项目,验证码图片不显示文字问题
系统上线后,在获取验证码接口时,获取的验证码图片上没有对应的验证码数字,经过验证后,是由于Linux缺少字体造成的. 正常我们也可以将window的字体直接上传到linux服务器上,window的字体 ...
- 焦大:seo该研究用户需求还是搜索算法
http://www.wocaoseo.com/thread-62-1-1.html 上一篇博客我写了用户需求点是做seo排名最首要关注的东西,其实这个我在以前也一直说的,seo有两大核心,一个是检索 ...
- day03 每日一行
day03 每日一行 问题描述 用列表解释式 .生成器表达式实现 字典列表为: [{'first': 'john', 'last': 'smith', 'email': 'jsmith@exsampl ...