一、引言
在使用K8S时总绕不开的话题就是K8S持久化存储,要实现持久化数据,就要把数据存储到硬盘上。在K8S持久化的过程中会有许多的概念PV、PVC、StorageClass、Provisioner等等。我只想存储一个文件有么有简单的方式呢?答案是有的。
K8S环境下,Container 中的文件在磁盘上是临时存放的,当容器崩溃时文件丢失。kubelet 会重新启动容器, 但容器会以干净的状态重启。所以我们要使用 Volume 来持久化数据。
Docker 也有 卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录 Docker 提供卷驱动程序,但是其功能非常有限。
Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。
临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁 持久卷。对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。
卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放 的内容。
使用卷时,在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 各个卷则挂载在镜像内的指定路径上。 卷不能挂载到其他卷之上,也不能与其他卷有硬链接。Pod 配置中的每个容器必须独立指定各个卷的挂载位置。
二、K8S存储的分类
2.1、Emptydir---临时存储
当pod的存储方案设定为emptydir的时候,pod启动时,就会在pod所在节点的磁盘空间开辟出一块空卷,最开始里面是什么都没有的,pod启动后容器产生的数据会存放到那个空卷中。空卷变成了一个临时卷供pod内的容器读取和写入数据,一旦pod容器消失,节点上开辟出的这个临时卷就会随着pod的销毁而销毁。
Emptydir的用途
emptyDir配置示例
Go
[root@k8s-master emptydir]# cat emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /usr/share/nginx/html
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
创建和验证
Go
[root@k8s-master emptydir]# kubectl apply -f emptydir.yaml
pod/test-pd created
[root@k8s-master emptydir]# kubectl get pod -owide |grep test-pd
test-pd 1/1 Running 0 29s 10.244.2.172 k8s-node2 <none> <none>
#1、在K8S-node2上进行操作
[root@k8s-node2 cache-volume]# docker ps -a|grep test-pd
ec7a0faec6bb nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes k8s_test-container_test-pd_default_0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae_0
#2、查看容器的详细信息
[root@k8s-node2 ~]# docker inspect f87f032bbaf8
....
"Mounts": [
{
"Type": "bind",
"Source": "/home/k8s/kubelet/pods/0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae/volumes/kubernetes.io~empty-dir/cache-volume",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
......
###Source是宿主机的地址
###Destination是挂载到容器的地址
#3、进入宿主机的目录并创建文件
[root@k8s-node2 cache-volume]# ls /home/k8s/kubelet/pods/0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae/volumes/kubernetes.io~empty-dir/cache-volume
[root@k8s-node2 cache-volume]# cd /home/k8s/kubelet/pods/0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae/volumes/kubernetes.io~empty-dir/cache-volume
[root@k8s-node2 cache-volume]# echo date > index.html
[root@k8s-node2 cache-volume]# cat index.html
date
##访问该pod的IP地址
[root@k8s-node2 cache-volume]# curl 10.244.2.173
date
[root@k8s-node2 cache-volume]# date > index.html
[root@k8s-node2 cache-volume]# curl 10.244.2.173
Sun Jun 5 17:02:30 CST 2022
###创建其他的访问文件
[root@k8s-node2 cache-volume]# echo 2022-06-05 > test.html
[root@k8s-node2 cache-volume]# curl 10.244.2.173/test.html
2022-06-05
#4、删除对应的pod清除实验。
[root@k8s-master emptydir]# kubectl delete -f emptydir.yaml
pod "test-pd" deleted
###再次在node2计算节点上查看
[root@k8s-node2 cache-volume]# ls /home/k8s/kubelet/pods/0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae/volumes/kubernetes.io~empty-dir/cache-volume
ls: cannot access /home/k8s/kubelet/pods/0e27bcf4-7ebe-4dc3-b48a-3230cf7641ae/volumes/kubernetes.io~empty-dir/cache-volume: No such file or directory
#emptydir是随pod创建而创建,然后再随pod删除而删除
2.2、hostPath
hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中, 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
hostPath的用途
Type的值
除了必需的path 属性之外,用户可以选择性地为hostPath 卷指定type。
支持的type 值如下:
取值
行为
空
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate
如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory
在给定路径上必须存在的目录。
FileOrCreate
如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File
在给定路径上必须存在的文件。
Socket
在给定路径上必须存在的 UNIX 套接字。
CharDevice
在给定路径上必须存在的字符设备。
BlockDevice
在给定路径上必须存在的块设备。
hostPath配置示例
Go
[root@k8s-master hostpath]# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-hostpath
volumes:
- name: test-hostpath
hostPath:
path: /data
type: DirectoryOrCreate
创建和配置示例
Go
#1、创建pod
[root@k8s-master hostpath]# kubectl apply -f hostpath.yaml
pod/test-pd created
[root@k8s-master hostpath]# kubectl get pod -owide|grep test-pd
test-pd 1/1 Running 0 6m54s 10.244.2.174 k8s-node2 <none> <none>
#2、在K8S-node2节点上查看内部
[root@k8s-node2 data]# docker ps -a|grep test-container
b4ff1de7e371 nginx "/docker-entrypoint.…" 8 minutes ago Up 8 minutes k8s_test-container_test-pd_default_e48b2791-54d6-40d6-bc77-56328ca4c038_0
[root@k8s-node2 data]# docker inspect b4ff1de7e371
[
....
"Mounts": [
{
"Type": "bind",
"Source": "/data",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
....
]
##"Source": "/data", # 宿主机的目录
## "Destination": "/usr/share/nginx/html", # 容器中的目录
#3、在master节点上进入pod
[root@k8s-master hostpath]# kubectl exec -it pod/test-pd /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@test-pd:/# cd /usr/share/nginx/html
root@test-pd:/usr/share/nginx/html# ls
index.html
root@test-pd:/usr/share/nginx/html# echo date >> index.html
root@test-pd:/usr/share/nginx/html# cat index.html
Sun Jun 5 17:23:17 CST 2022 test hostpath
date
[root@k8s-master hostpath]# curl 10.244.2.174
Sun Jun 5 17:23:17 CST 2022 test hostpath
date
#4、删除pod
[root@k8s-master hostpath]# kubectl delete -f hostpath.yaml
pod "test-pd" deleted
[root@k8s-master hostpath]# kubectl delete -f hostpath.yaml
Error from server (NotFound): error when deleting "hostpath.yaml": pods "test-pd" not found
#5、重启创建pod
[root@k8s-master hostpath]# kubectl apply -f hostpath.yaml
pod/test-pd created
[root@k8s-master hostpath]# kubectl get pod -owide|grep test-pd
test-pd 1/1 Running 0 63s 10.244.2.175 k8s-node2 <none> <none>
[root@k8s-master hostpath]# curl 10.244.2.175
Sun Jun 5 17:23:17 CST 2022 test hostpath
date
###这种方式如果宿主机一直在的话,或者该pod一直被调度到该节点的话,可以实现pod的存储,如果该node停机维护或其他
问题,该数据就无法保持了。
2.3、pv、pvc
既然Host类型的持久化存储无法解决节点宕机或者pod在另外的机器上拉起导致数据无法恢复的Bug,那我们就应该思考一个问题:既然我无法在宿主机持久化,那我在集群之外的服务器上存储数据,让我的Pod关联到这个数据存储服务器上,同时我对这个数据存储服务器做高可用,岂不美哉? 想法很好,那我们来介绍一下K8S给我们的解决方案: PersistentVolumes 简称PV
hostpath创建pv、pvc
Go
#1、创建pv
[root@k8s-master volumes]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-pv-volume
labels:
type: local
spec:
storageClassName: manual-nginx
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/home/nfs"
[root@k8s-master volumes]# kubectl apply -f pv.yaml
persistentvolume/nginx-pv-volume created
[root@k8s-master ~]# kubectl get pv -owide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
nginx-pv-volume 5Gi RWO Retain Available manual-nginx 10s Filesystem
##可以看到这个PV为10G,访问模式为RWO,卸载后保留,目前的STATUS为可用状态。
#2、创建pvc
[root@k8s-master volumes]# kubectl apply -f pvc.yaml
persistentvolumeclaim/nginx-pv-claim created
[root@k8s-master volumes]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-pv-claim
spec:
storageClassName: manual-nginx
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
[root@k8s-master volumes]# kubectl get pv,pvc -owide|grep pv-claim
persistentvolume/nginx-pv-volume 5Gi RWO Retain Bound default/nginx-pv-claim manual-nginx 5m54s Filesystem
persistentvolumeclaim/nginx-pv-claim Bound nginx-pv-volume 5Gi RWO manual-nginx 97s Filesystem
3、创建pod
[root@k8s-master volumes]# cat pvc-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: nginx-pv-volume
persistentVolumeClaim:
claimName: nginx-pv-claim
containers:
- name: task-pv-container
image: nginx:1.7.9
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-pv-volume
nodeSelector:
kubernetes.io/hostname: k8s-node6
[root@k8s-master volumes]# kubectl apply -f pvc-pod.yaml
pod/task-pv-pod created
[root@k8s-master volumes]# kubectl get pod -owide|grep task-pv-pod
task-pv-pod 1/1 Running 0 20s 10.244.4.117 k8s-node6 <none> <none>
#3、在k8s-node3中执行
[root@k8s-node6 ~]# hostname > /home/nfs/index.html
[root@k8s-node6 ~]# curl 10.244.4.117
k8s-node6
NFS创建pv pvc
大多数情况下,持久化 Volume 的实现,往往依赖于一个远程存储服务,比如:远程文件存储(比如,NFS、GlusterFS)、远程块存储(比如,公有云提供的远程磁盘)等等。
Go
1、搭建nfs服务器
yum -y install nfs-utils rpcbind
[root@k8s-master ~]# vim /etc/exports
/data/k8s *(rw,sync,no_root_squash)
[root@k8s-master ~]# systemctl enable rpcbind
[root@k8s-master ~]# systemctl start rpcbind
[root@k8s-master ~]# systemctl status rpcbind
####在启动nfs
[root@k8s-master ~]# systemctl enable nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
[root@k8s-master ~]# systemctl start nfs
[root@k8s-master ~]# systemctl status nfs
客户端挂在
[root@k8s-node1 ~]# mkdir /data/k8s/ -p
[root@k8s-node1 ~]# mount -t nfs 172.16.4.169:/data/k8s /data/k8s
2、创建pv和pvc
[root@k8s-master volumes]# kubectl apply -f nfs-pv.yaml
persistentvolume/nginx-nfs-pv created
[root@k8s-master volumes]# cat nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume # 类型为PV
metadata:
name: nginx-nfs-pv # pv的名称
spec:
accessModes: # 访问模式
- ReadWriteMany # PV以read-write挂载到多个节点
capacity: # 容量
storage: 2Gi # pv可用的大小
nfs:
path: /home/k8s/nfs # NFS的路径
server: 172.16.4.169 # NFS服务器地址
##创建pvc
[root@k8s-master volumes]# cat nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim # 类型
metadata:
name: nginx-nfs-pvc # PVC的名称
spec:
accessModes: # 访问模式
- ReadWriteMany # PVC以read-write挂载到多个节点
resources:
requests:
storage: 2Gi # PVC允许申请的大小
[root@k8s-master volumes]# kubectl apply -f nfs-pvc.yaml
persistentvolumeclaim/nginx-nfs-pvc created
[root@k8s-master ~]# kubectl get pv,pvc -owide|grep nfs
persistentvolume/nginx-nfs-pv 2Gi RWX Retain Bound default/nginx-nfs-pvc 4m37s Filesystem
persistentvolumeclaim/nginx-nfs-pvc Bound nginx-nfs-pv 2Gi RWX 53s Filesystem
##c创建pod
[root@k8s-master volumes]# cat nfs-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-nfs-pvc
spec:
selector:
matchLabels:
app: nginx-pvc
template:
metadata:
labels:
app: nginx-pvc
spec:
containers:
- name: nginx-test-pvc
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: web-port
containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx-persistent-storage # 取个名字,与下面的volumes的名字要一致
mountPath: /usr/share/nginx/html # 容器中的路径
volumes:
- name: nginx-persistent-storage
persistentVolumeClaim:
claimName: nginx-nfs-pvc # 引用前面声明的PVC
[root@k8s-master volumes]# kubectl apply -f nfs-pod.yaml
deployment.apps/nginx-nfs-pvc created
[root@k8s-master volumes]# kubectl get pod -owide|grep nfs
nginx-nfs-pvc-577dbd6d5-jsjqf 1/1 Running 0 2m32s 10.244.2.183 k8s-node2 <none> <none>
[root@k8s-master volumes]# curl 10.244.2.183
Thu May 12 19:26:48 CST 2022
this is mater
4、回收的顺序为:先删除pod,在删除pvc,查看pv的时候pv的状态为:Released ,如果变为avaiable,
则需要删除claimRef:字段下的所有配置。
2.4、StorageClass
创建PV有两种方式:一种是人工管理 PV 的方式就叫作 Static Provisioning;另一种是Dynamic Provisioning动态创建存储卷,动态供给的关键就是StorageClass,它的作用就是创建PV模板,Provision意为”提供者。
创建StorageClass里面需要定义PV属性比如存储类型、大小等;另外创建这种PV需要用到存储插件。最终效果是,用户提交PVC,里面指定存储类型,如果符合我们定义的StorageClass,则会为其自动创建PV并进行绑定。
什么是StorageClass
StorageClass 为管理员提供了描述存储 "class(类)" 的方法。 不同的 class 可能会映射到不同的服务质量等级或备份策略,或由群集管理员确定的任意策略。
Kubernetes提供了一套可以自动创建PV的机制,即:Dynamic Provisioning。而这个机制的核心在于StorageClass这个API对象。
StorageClass对象会定义下面两部分内容:
有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV。
StorageClass 为管理员提供了描述存储 “类” 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 “配置文件”。
StorageClass的功能
StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。StorageClass 的另一个重要作用,是指定 PV 的 Provisioner(存储插件)。这时候,如果你的存储插件支持 Dynamic Provisioning 的话,Kubernetes 就可以自动为你创建 PV 了。
通过StorageClass创建pv和pvc例子
Go
1、创建pvc和storageclass的yaml文件
[root@k8s-master storageclass]# cat storageclass-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: storageclass-claim1
spec:
accessModes:
- ReadWriteOnce
# 指定所使用的存储类,此存储类将会自动创建符合要求的 PV
storageClassName: fast
resources:
requests:
storage: 30Gi
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
[root@k8s-master storageclass]# kubectl apply -f storageclass-pvc.yaml
persistentvolumeclaim/storageclass-claim1 created
storageclass.storage.k8s.io/fast created
2、查看该pvc处于pending原因,由于没有没有gce插件
[root@k8s-master storageclass]# kubectl describe persistentvolumeclaim/storageclass-claim1
Name: storageclass-claim1
Namespace: default
StorageClass: fast
Status: Pending
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/gce-pd
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ProvisioningFailed 14m persistentvolume-controller storageclass.storage.k8s.io "fast" not found
Warning ProvisioningFailed 68s (x10 over 13m) persistentvolume-controller Failed to provision volume with StorageClass "fast": failed to get GCE GCECloudProvider with error <nil>
StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。StorageClass 的另一个重要作用,是指定 PV 的 Provisioner(存储插件)。这时候,如果你的存储插件支持 Dynamic Provisioning 的话,Kubernetes 就可以自动为你创建 PV 了。
2.5、Local PV(local-volume-provisioner)
Kubernetes 依靠 PV、PVC 实现了一个新的特性,这个特性的名字叫作:Local Persistent Volume,也就是 Local PV。
Local PV 实现的功能就非常类似于 hostPath 加上 nodeAffinity,比如,一个 Pod 可以声明使用类型为 Local 的 PV,而这个 PV 其实就是一个 hostPath 类型的 Volume。如果这个 hostPath 对应的目录,已经在节点 A 上被事先创建好了,那么,我只需要再给这个 Pod 加上一个 nodeAffinity=nodeA,不就可以使用这个 Volume 了吗?理论上确实是可行的,但是事实上,我们绝不应该把一个宿主机上的目录当作 PV 来使用,因为本地目录的存储行为是完全不可控,它所在的磁盘随时都可能被应用写满,甚至造成整个宿主机宕机。所以,一般来说 Local PV 对应的存储介质是一块额外在挂载在宿主机的磁盘或者块设备,我们可以认为就是“一个 PV 一块盘”。
local-volume-provisioner创建local PV
3.1、准备本地存储
Go
##依次在K8S的各个计算节点依次执行
1、创建对应的目录
mkdir /home/data/{data1,data2,data3}
2、依次挂载对应的节点
mount --bind /home/data/data1/ /home/data/data1/
mount --bind /home/data/data2/ /home/data/data2/
mount --bind /home/data/data3/ /home/data/data3/
3、把相关的配置信息写道/etc/fstab
echo UUID=`sudo blkid -s UUID -o value /dev/sda2` /home/data/data1 ext4 defaults 0 2 | sudo tee -a /etc/fstab
echo UUID=`sudo blkid -s UUID -o value /dev/sda2` /home/data/data2 ext4 defaults 0 2 | sudo tee -a /etc/fstab
echo UUID=`sudo blkid -s UUID -o value /dev/sda2` /home/data/data3 ext4 defaults 0 2 | sudo tee -a /etc/fstab
###
上述的/home/data/data1、/home/data/data2、/home/data/data13是 local-volume-provisioner
使用的发现目录(discovery directory),local-volume-provisioner 会为发现目录下的每一个
子目录创建对应的 PV
3.2、下载和配置 local-volume-provisioner
Go
1、下载
wget https://raw.githubusercontent.com/pingcap/tidb-operator/master/examples/local-pv/local-volume-provisioner.yaml
2、修改不同的路径。如果你使用与上一步中不同路径的发现目录,需要修改 ConfigMap 和 DaemonSet 定义。
#cat local-volume-provisioner.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: "local-storage"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: local-provisioner-config
namespace: kube-system
data:
setPVOwnerRef: "true"
nodeLabelsForPV: |
- kubernetes.io/hostname
storageClassMap: |
local-storage:
hostDir: /home/data
mountDir: /data
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: local-volume-provisioner
namespace: kube-system
labels:
app: local-volume-provisioner
spec:
selector:
matchLabels:
app: local-volume-provisioner
template:
metadata:
labels:
app: local-volume-provisioner
spec:
serviceAccountName: local-storage-admin
containers:
- image: "quay.io/external_storage/local-volume-provisioner:v2.3.4"
name: provisioner
securityContext:
privileged: true
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: MY_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: JOB_CONTAINER_IMAGE
value: "quay.io/external_storage/local-volume-provisioner:v2.3.4"
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /etc/provisioner/config
name: provisioner-config
readOnly: true
- mountPath: /data
name: local-disks
mountPropagation: "HostToContainer"
volumes:
- name: provisioner-config
configMap:
name: local-provisioner-config
- name: local-disks
hostPath:
path: /home/data
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: local-storage-admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: local-storage-provisioner-pv-binding
namespace: kube-system
subjects:
- kind: ServiceAccount
name: local-storage-admin
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:persistent-volume-provisioner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: local-storage-provisioner-node-clusterrole
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: local-storage-provisioner-node-binding
namespace: kube-system
subjects:
- kind: ServiceAccount
name: local-storage-admin
namespace: kube-system
roleRef:
kind: ClusterRole
name: local-storage-provisioner-node-clusterrole
apiGroup: rbac.authorization.k8s.io
如果你使用与上一步中不同路径的发现目录,需要修改 ConfigMap 和 DaemonSet 定义。
3.3、部署和检查 local-volume-provisioner 程序
Go
1、部署
[root@k8s-master tidb]# kubectl apply -f local-volume-provisioner.yaml
storageclass.storage.k8s.io/local-storage unchanged
configmap/local-provisioner-config unchanged
daemonset.apps/local-volume-provisioner unchanged
serviceaccount/local-storage-admin unchanged
clusterrolebinding.rbac.authorization.k8s.io/local-storage-provisioner-pv-binding unchanged
clusterrole.rbac.authorization.k8s.io/local-storage-provisioner-node-clusterrole unchanged
clusterrolebinding.rbac.authorization.k8s.io/local-storage-provisioner-node-binding unchanged
2、检查pv和pod状态
[root@k8s-master tidb]# kubectl get po -n kube-system -l app=local-volume-provisioner && kubectl get pv
NAME READY STATUS RESTARTS AGE
local-volume-provisioner-9gp9x 1/1 Running 0 29h
local-volume-provisioner-kghc7 1/1 Running 0 29h
local-volume-provisioner-v2vvt 1/1 Running 0 29h
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
local-pv-264b0ff0 446Gi RWO Delete Available local-storage 62m
local-pv-27bc7b00 446Gi RWO Delete Available local-storage 62m
local-pv-4653df42 446Gi RWO Delete Available local-storage 62m
local-pv-993f4e47 446Gi RWO Delete Available local-storage 62m
local-pv-ad7b1fa4 446Gi RWO Delete Available local-storage 62m
local-pv-b9e5d531 446Gi RWO Delete Available local-storage 62m
local-pv-bfe87b7 446Gi RWO Delete Available local-storage 62m
local-pv-dc8fa7ee 446Gi RWO Delete Available local-storage 62m
local-pv-f12d96bb 446Gi RWO Delete Available local-storage 62m
三、总结
本文讨论了 k8s 存储的几种常见的存储类型类型,有临时存储如:hostPath、emptyDir。也有真正的持久化存储,还讨论了相关的概念,如:PVC、PV、StorageClass等,下图是对这些概念的一个概括: