8. k8s持久化存储
·
在k8s中为什么要做数据持久化?
当在Kubernetes中部署应用程序时,数据通常存储在容器内部的文件系统中。然而,
容器的生命周期是临时的,当容器被删除或重新启动时,容器内的数据也会丢失。
为了解决这个问题,需要在Kubernetes中实现数据持久化。数据持久化是将数据保存到持久化存
储介质(如磁盘)上,以便在容器被重新创建或迁移到其他节点时仍然可用。
数据持久化的场景包括:
1、数据存储:许多应用程序需要保存用户生成的数据,如文件、图片、日志等。通过数据持久化,可
以确保这些数据在容器销毁或重启后仍然存在。
2、数据共享:在某些情况下,多个容器或Pod可能需要访问和共享相同的数据。通过将数据存储在
持久化卷中,可以使多个容器之间共享数据,实现数据一致性和共享访问。
3、数据备份和恢复:持久化存储解决方案通常提供数据备份和恢复机制,以防止数据丢失。这对于保
护重要数据、应对故障或恢复到先前的状态非常重要。
4、数据迁移和扩展:在Kubernetes集群中,可能需要扩展应用程序到多个节点或迁移到其他集群。
通过将数据存储在持久化卷中,可以方便地将数据与应用程序一起迁移到新的环境,无需担心数据丢失。
5、数据安全:某些行业或应用程序对数据的安全性有严格的要求。持久化存储解决方案通常提供数据
加密和访问控制功能,以确保数据在传输和存储过程中的安全性。
k8s持久化存储方案-emptyDir
在Kubernetes中,EmptyDir是一种卷(Volume),它提供了一个空目录来供容器使用。EmptyDir
卷在Pod级别上创建,与Pod的生命周期绑定。EmptyDir卷在Pod被删除或重新启动时会被清空,因
此它不是持久化的存储解决方案。
EmptyDir 卷的使用场景包括:
1. 临时文件共享:如果多个容器需要在同一个Pod中进行临时文件共享,EmptyDir卷是一个简便
的解决方案。容器可以将文件写入EmptyDir卷,并且其他容器可以读取和修改这些文件。当Pod
被删除或重启时,EmptyDir卷中的文件会被清空。
2. 共享数据:某些应用程序可能需要在容器之间共享一些中间结果或临时数据。EmptyDir卷可以
作为容器之间的临时数据交换机制。容器可以将数据写入EmptyDir卷,其他容器可以读取和处
理这些数据,从而实现数据共享和协作。
3. 缓存:EmptyDir卷可以用作容器的缓存存储。某些应用程序可能需要将频繁访问的数据缓存到
本地存储中,以提高性能。EmptyDir卷提供了一个临时的、高速的存储介质来存储缓存数据,
提供快速的读取和写入操作。
当在Kubernetes中使用存储卷(Volume),需要经历以下步骤:
1. 定义Pod的Volume:在Pod的配置中定义一个Volume,指定它要关联到哪个存储上。可以
使用不同类型的Volume,如EmptyDir、HostPath、PersistentVolumeClaim等,具体选
择取决于需求。
2. 在容器中使用Volume Mounts:在Pod的配置中,为每个容器定义Volume Mounts,将
Volume 挂载到容器内部的指定路径上。这样容器就能够访问和操作Volume中的数据。
3. 通过Volume实现数据持久化和共享:一旦Volume被挂载到容器中,容器就可以将数据写入
Volume 或从Volume中读取数据。这使得数据能够在容器的生命周期内持久存在,并且可以被
其他容器共享和访问。
root@ubuntu0:~/matedata/volumes# cat emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: xpp
labels:
app: v1
spec:
containers:
- name: pod-xp
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /cache #挂在到容器下的/cache 也就是在这个目录下产生的数据会产生到容器下的 /cache 下 那临时目录需要去对应被调度的机器上找
name: cache-volume
volumes:
- emptyDir: {} #{}表示临时目录,可以不用指定大小
name: cache-volume #卷的名字
如何去对应的机器上找临时目录,他被调度到ubuntu2 上了,那就去ubuntu2 上去找
root@ubuntu0:~/matedata/volumes# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
default-55cdb47c4-zl2x9 1/1 Running 0 12h 10.244.25.164 ubuntu1 <none> <none>
xpp 1/1 Running 0 13s 10.244.152.98 ubuntu2 <none> <none>
root@ubuntu0:~/matedata/volumes#
查看对应的uuid,然后去对应的机器上找
root@ubuntu0:~/matedata/volumes# kubectl get pods xpp -o yaml | grep uid
uid: 6f0ce328-63f5-436d-95f7-2612c8ae750a
root@ubuntu2:~# tree /var/lib/kubelet/pods/6f0ce328-63f5-436d-95f7-2612c8ae750a/
/var/lib/kubelet/pods/6f0ce328-63f5-436d-95f7-2612c8ae750a/
|-- containers
| `-- pod-xp
| `-- 0b0ad86f
|-- etc-hosts
|-- plugins
| `-- kubernetes.io~empty-dir
| |-- cache-volume
| | `-- ready
| `-- wrapped_kube-api-access-m25b5
| `-- ready
`-- volumes
|-- kubernetes.io~empty-dir
| `-- cache-volume #就在这个目录下,在这个目录下创建的数据,容器内对应的/cache也会有数据
`-- kubernetes.io~projected
`-- kube-api-access-m25b5
|-- ca.crt -> ..data/ca.crt
|-- namespace -> ..data/namespace
`-- token -> ..data/token
11 directories, 7 files
hostPath
hostPath 是 Kubernetes 中的一种卷类型,它将主机节点上的文件或目录挂载到容器中。使用
hostPath,可以将主机节点上的文件系统路径直接映射到容器的文件系统中。这种方式在某些情况下非常
有用,但也需要谨慎使用,因为它具有一些潜在的限制和风险。
以下是 hostPath 的一些关键特点和适用场景:
1. 直接访问主机文件系统:hostPath 卷允许容器直接访问主机节点上的文件系统。这对于需要访
问主机节点上的特定文件或目录的应用程序非常有用。例如,某些日志收集器可能需要访问主机
上的日志文件。
2. 主机依赖性:hostPath 卷的挂载是与特定主机节点紧密关联的,因此在调度 Pod 时需要特别
注意。如果 Pod 被调度到另一个主机节点上,它将无法访问之前挂载的主机文件系统。
3. 危险性:hostPath 卷的使用需要谨慎,因为容器可以访问主机节点上的任何文件或目录,包括
敏感的系统文件。此外,如果多个 Pod 使用相同的 hostPath 卷并且并发写入同一个文件,可
能会导致冲突和数据损坏。
4. 开发和测试环境:hostPath 卷特别适用于开发和测试环境,因为它可以方便地将主机节点上的
文件或目录映射到容器中,从而加快开发和测试工作流程。
需要注意的是,hostPath 卷并不适合生产环境中的大多数用例。在生产环境中,建议使用更可靠和
弹性的持久化存储方案,例如网络存储卷(NFS)、云提供商的块存储或对象存储等。
root@ubuntu0:~# kubectl explain pods.spec.volumes.hostPath
KIND: Pod
VERSION: v1
RESOURCE: hostPath <Object>
root@ubuntu0:~/matedata/volumes# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: test-nginx
volumeMounts:
- mountPath: /test-nginx
name: test-volume
- image: nginx
imagePullPolicy: IfNotPresent
name: test-tomcat
volumeMounts:
- mountPath: /test-tomcat
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data1
type: DirectoryOrCreate
# DirectoryOrCreate 表示本地有/data1 目录,就用本地的,本地没有就会在pod调度到的节点自
动创建一个
root@ubuntu0:~/matedata/volumes# mkdir /data1
root@ubuntu0:~/matedata/volumes# kubectl apply -f hostpath.yaml
pod/test-hostpath created
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-hostpath 2/2 Running 3 (28s ago) 52s 10.244.152.101 ubuntu2 <none> <none>
机器是调度到ubuntu2这台机器上,去ubuntu2这台机器上看看有没有创建/data1目录
root@ubuntu2:~# ls /data1/
root@ubuntu2:~#
root@ubuntu2:~# cd /data1/
root@ubuntu2:/data1# mkdir aa
#测试存储卷是否可以正常使用,登录到nginx容器
root@ubuntu0:~/matedata/volumes# kubectl exec -it test-hostpath -c test-nginx -- /bin/bash
root@test-hostpath:/# cd /test-nginx/
root@test-hostpath:/test-nginx# ls
aa
缺点
pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失
NFS
NFS(Network File System)是一种网络文件系统协议,它允许不同计算机之间共享文件和目录。
在 Kubernetes(k8s)中,NFS 是一种常见的持久化存储方案,用于将网络共享的存储卷挂载到容器中。
下面是 NFS 的基本介绍和常见应用场景:
1. 基本原理:NFS 允许将存储资源(文件或目录)通过网络共享给其他计算机。NFS 服务器将存
储资源公开为共享,并将其挂载到客户端计算机上。客户端可以像访问本地文件系统一样访问这
些共享资源。
2. 持久化存储方案:在 Kubernetes 中,NFS 可以作为持久化存储方案使用。它可以提供可靠的
存储,并在容器被重新调度到不同的节点时保持数据的一致性。
3. 分布式访问:NFS 允许多个客户端同时访问共享资源。这使得它非常适合那些需要多个容器或
Pod 共享数据的场景,例如数据库系统或分布式文件共享。
4. 跨平台兼容性:NFS 是一种跨平台的文件系统协议,支持在不同操作系统之间进行文件共享。这
使得它成为在混合操作系统集群中实现持久化存储的理想选择。
5. 灵活性:NFS 提供了对存储资源的灵活访问和管理。管理员可以根据需求创建和配置 NFS 服务
器,设置共享权限以及实施访问控制策略。
6. 备份和恢复:NFS 具备备份和恢复数据的能力。通过使用备份工具和策略,可以对 NFS 共享的
数据进行定期备份,以防止数据丢失或损坏。
常见的应用场景包括:
• 数据库持久化:NFS 可用于挂载数据库文件,确保数据库的持久性和数据一致性,并提供跨多个
数据库节点的共享访问。
• 分布式文件共享:多个容器或 Pod 可以通过挂载相同的 NFS 共享来实现文件共享和协作,如
共享配置文件、日志目录等。
• 文件存储和共享:NFS 可以用作共享存储,供团队成员或应用程序之间共享文件,便于协作和数
据交换。
总结起来,NFS 是一种在 Kubernetes 中常用的持久化存储方案,可以提供可靠的存储和跨多个容
器或 Pod 的文件共享。它具有跨平台兼容性、灵活性和备份恢复能力等
1、搭建nfs服务
以k8s的控制节点作为NFS服务端
root@ubuntu0:~/matedata/volumes# apt install nfs-kernel-server -y
2.在宿主机创建NFS需要的共享目录
root@ubuntu0:~# mkdir /data/volumes -pv
3.配置nfs共享服务器上的/data/volumes目录
root@ubuntu0:~# systemctl restart nfs-server
root@ubuntu0:~# tail -n1 /etc/exports
/data/volumes *(rw,no_root_squash)
#no_root_squash: 用户具有根目录的完全管理访问权限
4.使NFS配置生效
root@ubuntu0:~# exportfs -arv
root@ubuntu0:~# systemctl restart nfs-server
5.在剩下的两台机器上也安装nfs
root@ubuntu2:/data1# apt install nfs-kernel-server -y
root@ubuntu2:/data1# systemctl restart nfs-server
root@ubuntu2:/data1# showmount -e 192.168.23.99
Export list for 192.168.23.99:
/data/volumes *
6.挂载
root@ubuntu2:/data1# mount -t nfs 192.168.23.99:/data/volumes /data1
root@ubuntu2:/data1# df -h /data1
Filesystem Size Used Avail Use% Mounted on
192.168.23.99:/data/volumes 24G 17G 5.8G 75% /data1
root@ubuntu2:/data1#
7.创建Pod,挂载NFS共享出来的目录
root@ubuntu0:~/matedata/volumes# cat nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-nfs-volume
spec:
containers:
- name: test-nfs
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes #名字需要一致
mountPath: /usr/share/nginx/html #挂在到容器的什么路径
volumes:
- name: nfs-volumes #名字需要一致
nfs:
path: /data/volumes #nfs共享的目录
server: 192.168.23.99 #nfs服务端地址
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs.yaml
pod/test-nfs-volume created
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-nfs-volume 1/1 Running 0 8h 10.244.25.168 ubuntu1 <none> <none>
root@ubuntu0:~/matedata/volumes# curl 10.244.25.168
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.17.9</center>
</body>
</html>
root@ubuntu0:~/matedata/volumes# cd /data/volumes
root@ubuntu0:/data/volumes# vim index.html
root@ubuntu0:/data/volumes# cat index.html
hhhh
root@ubuntu0:/data/volumes# curl 10.244.25.168
hhhh
可以把pod给删除,让他调度到另一个机器上,也是能访问的
k8s 持久化存储方案-PVC
1. K8s PV 是什么?
PersistentVolume(PV): PV 是集群中的存储资源,可以是物理存储设备、网络存储或云存储等。
PV独立于Pod存在,它们是集群级别的资源,由集群管理员进行配置和管理。PV具有持久性,即使Pod
被删除,PV中的数据也会保留。PV定义了存储的容量、访问模式和其他属性。
2.K8s PVC 是什么?
PersistentVolumeClaim(PVC):PVC是Pod对PV的申请,它表示Pod需要一定的存储资源来
满足其持久化存储需求。PVC在Pod和PV之间建立了一个抽象层,使得Pod无需关心底层存储的具体
细节。PVC定义了Pod对存储的需求,包括存储容量、访问模式等。
3.K8s PVC和PV工作原理
当创建一个PersistentVolume(PV)和PersistentVolumeClaim(PVC)时,它们之间的相互作
用和工作原理如下:
1. PV的供应方式:
• 静态配置:集群管理员预先创建PV对象,包含了实际存储资源的详细信息。这些PV
存在于Kubernetes API中,供用户使用。
• 动态配置:当静态PV无法匹配用户的PVC时,Kubernetes可以尝试为PVC动态地
配置PV。这基于StorageClasses,PVC必须请求存储类,并且管理员必须创建和配
置该类以进行动态配置。
2. 绑定
• 用户创建PVC并指定所需的存储资源和访问模式。
• 在找到可用的PV之前,PVC保持未绑定状态。
3.使用
• 首先,存储管理员创建PV,并将其划分为多个存储卷。
• 用户在创建Pod之前创建PVC,并指定所需的PV大小和访问模式。
• 创建PVC后,可以将其作为存储卷使用,并在Pod定义中引用该PVC。
• PV和PVC是一对一的关系。一旦PV被某个PVC绑定,其他PVC就不能使用它。
• 如果没有合适的PV可用,PVC将处于挂起状态,直到有一个合适的PV可用为止。
4. 回收策略:
• 当删除使用PVC作为存储卷的Pod时,PVC与PV的绑定将解除。
• PV有不同的回收策略可供选择:
• Retain(保留):删除PVC后,PV保留,并且数据仍然存在。PV不会被绑
定到其他PVC上,可以再次使用。
• Recycle(回收,不推荐):删除PVC后,PV会被清空数据并准备重新使用。
这个回收策略在Kubernetes 1.15版本后被废弃。
• Delete(删除):删除PVC后,PV也会从Kubernetes中移除,并且相关
的存储资源也会被删除。
通过PV和PVC的结合使用,Kubernetes提供了一种灵活的持久化存储管理机制,使得开发者可以
轻松地申请、使用和管理存储资源,同时提供了不同的回收策略以满足不同的需求。
1、创建nfs共享目录
#在宿主机创建NFS需要的共享目录
root@ubuntu0:/data/volumes# mkdir /data/volume_test/v{1,2} -p
2.配置nfs共享宿主机上的/data/volume_test/v1..v2目录
root@ubuntu0:~/matedata/volumes# tail -n2 /etc/exports
/data/volume_test/v1 *(rw,no_root_squash)
/data/volume_test/v2 *(rw,no_root_squash)
root@ubuntu0:~/matedata/volumes# exportfs -arv
3.如何编写pv的资源清单文件
root@ubuntu0:~/matedata/volumes# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: v1
spec:
capacity:
storage: 1Gi #pv的存储空间容量
accessModes: ["ReadWriteOnce"]
nfs:
path: /data/volume_test/v1 #把nfs的存储空间创建成pv
server: 192.168.23.99 #nfs服务器的地址 ---
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: v2
spec:
capacity:
storage: 2Gi
accessModes: ["ReadWriteMany"]
nfs:
path: /data/volume_test/v2
server: 192.168.23.99
root@ubuntu0:~/matedata/volumes# kubectl apply -f pv.yaml
persistentvolume/v1 created
persistentvolume/v2 created
root@ubuntu0:~/matedata/volumes# kubectl get pv -owide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
v1 1Gi RWO Retain Available 5s Filesystem
v2 2Gi RWX Retain Available 5s Filesystem
#STATUS是Available,表示pv是可用的
4.创建pvc,和符合条件的pv绑定
root@ubuntu0:~/matedata/volumes# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
root@ubuntu0:~/matedata/volumes# kubectl apply -f pvc.yaml
persistentvolumeclaim/my-pvc created
查看pv,发现v2已经被绑定了
root@ubuntu0:~/matedata/volumes# kubectl get pv -owide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
v1 1Gi RWO Retain Available 2m8s Filesystem
v2 2Gi RWX Retain Bound default/my-pvc 2m8s Filesystem
#STATUS是Bound,表示这个pv已经被my-pvc绑定了
pvc的名字-绑定到pv-绑定的是v2这个pv-pvc可使用的容量是2G
5、创建pod,挂载pvc
root@ubuntu0:~/matedata/volumes# cat pod_pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nginx-html
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-html
persistentVolumeClaim:
claimName: my-pvc
root@ubuntu0:~/matedata/volumes# kubectl apply -f pod_pvc.yaml
pod/pod-pvc created
root@ubuntu0:~/matedata/volumes# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-pvc 1/1 Running 0 17s 10.244.25.169 ubuntu1 <none> <none>
进入容器内查看是否已经挂载上了
root@ubuntu0:~/matedata/volumes# kubectl exec -it pod-pvc -- bash
root@pod-pvc:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 24G 14G 8.6G 62% /
tmpfs 64M 0 64M 0% /dev
/dev/mapper/ubuntu--vg-ubuntu--lv 24G 14G 8.6G 62% /etc/hosts
shm 64M 0 64M 0% /dev/shm
192.168.23.99:/data/volume_test/v2 24G 23G 0 100% /usr/share/nginx/html
测试pod挂载PVC 是否正常:
在绑定的v2 目录下创建文件,写入测试内容“my-pvc”
root@ubuntu0:~/matedata/volumes# echo "my-pvc" >> /data/volume_test/v2/index.html
root@ubuntu0:~/matedata/volumes# curl 10.244.25.169
my-pvc
测试删除pod,再重新创建pod ,挂载原先的pvc,看数据是否会丢失:
root@ubuntu0:~/matedata/volumes# kubectl delete -f pod_pvc.yaml
pod "pod-pvc" deleted
root@ubuntu0:~/matedata/volumes# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-pvc 1/1 Running 0 4s 10.244.152.102 ubuntu2 <none> <none>
root@ubuntu0:~/matedata/volumes# curl 10.244.152.102
my-pvc
k8s存储类:storageclass
1.Kubernetes提供了StorageClass来自动创建PV,以减轻管理员的维护成本。以下是关于
Kubernetes PV、PVC和StorageClass的更新内容:
2.PV(PersistentVolume)是Kubernetes中的持久化存储资源,而PVC(PersistentVolumeClaim)
是Pod对PV的申请。传统的PV和PVC模式需要管理员预先创建PV,然后将其与PVC进行一对一的
绑定。这种方式在大规模部署中可能导致管理复杂性和维护成本的增加。
3.为了解决这个问题,Kubernetes引入了StorageClass机制。StorageClass是一种动态创建PV的模板。
集群管理员可以创建多个StorageClass,每个StorageClass定义了存储的类型、访问模式和其他属性。
4.当用户创建一个PVC并指定StorageClass时,Kubernetes会自动根据该StorageClass创建一个PV,
并将其与PVC进行绑定。这样,管理员无需手动创建PV,而是根据StorageClass的定义,动态生成PV
来满足用户的存储需求。
StorageClass 提供了以下好处
1. 简化管理:StorageClass 允许管理员创建一组可重用的存储配置模板,而无需为每个 PVC 手动
创建和管理 PV。这降低了管理成本和复杂性。
2. 动态供应:使用 StorageClass,管理员可以根据需求动态创建 PV,从而自动为 PVC 提供存储
资源。这种动态供应的机制使得存储的分配更加灵活和自动化。
3. 可选性和灵活性:StorageClass 允许管理员根据存储的不同特性和需求创建不同的
StorageClass。用户可以根据自己的需求选择合适的 StorageClass,并使用相应的存储资源。
#查看定义的 storageclass 需要的字段
root@ubuntu0:~# kubectl explain storageclass
KIND: StorageClass
VERSION: storage.k8s.io/v1
DESCRIPTION:
StorageClass describes the parameters for a class of storage for which
PersistentVolumes can be dynamically provisioned.
StorageClasses are non-namespaced; the name of the storage class according
to etcd is in ObjectMeta.Name.
provisioner:供应商,storageclass 需要有一个供应者,用来确定我们使用什么样的存储来创建
pv,常见的 provisioner 如下
(https://kubernetes.io/zh/docs/concepts/storage/storage-classes/
provisioner既可以由内部供应商提供,也可以由外部供应商提供,如果是外部供应商可以参考https://github.com/kubernetes-incubator/external-storage/下提供的方法创建
以NFS为例,要想使用NFS,我们需要一个nfs-client的自动装载程序,称之为provisioner,这个程序会使用我们已经配置好的NFS服务器自动创建持久卷,也就是自动帮我们创建PV。
上传镜像,并解压
allowVolumeExpansion:允许卷扩展,PersistentVolume 可以配置成可扩展。将此功能设置为true时,允许用户通过编辑相应的PVC 对象来调整卷大小。当基础存储类的allowVolumeExpansion 字段设置为true 时,以下类型的卷支持卷扩展。
此功能仅用于扩容卷,不能用于缩小卷
安装nfsprovisioner,用于配合存储类动态生成pv
root@ubuntu0:~/matedata/volumes# ansible all -m copy -a "src=/root/nfs-subdir-external-provisioner.tar.gz dest=/root"
root@ubuntu0:~/matedata/volumes# ansible all -m shell -a "ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz"
root@ubuntu0:~/matedata/volumes# ansible all -m shell -a "crictl image ls|grep nfs-subdir-external-provisioner"
ubuntu2 | CHANGED | rc=0 >>
registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner v4.0.0 3beaacba3ff48 45.1MB
ubuntu1 | CHANGED | rc=0 >>
registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner v4.0.0 3beaacba3ff48 45.1MB
1、创建运行 nfs-provisioner 需要的 sa 账号
root@ubuntu0:~/matedata/volumes# cat serviceaccount.yam
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
root@ubuntu0:~/matedata/volumes# kubectl apply -f serviceaccount.yam
serviceaccount/nfs-provisioner created
扩展:什么是 sa?
sa 的全称是 serviceaccount。
serviceaccount 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的。
指定了 serviceaccount 之后,我们把 pod 创建出来了,我们在使用这个 pod 时,这个 pod 就有了我们指定的账户的权限了。
2、对 sa 授权
root@ubuntu0:~/matedata/volumes# kubectl get sa
NAME SECRETS AGE
default 1 43d
nfs-provisioner 1 25s
root@ubuntu0:~/matedata/volumes# kubectl create clusterrolebinding nfs-provisioner --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner created
3、安装 nfs-provisioner 程序
root@ubuntu0:~/matedata/volumes# tail -n1 /etc/exports
/data/nfs_pro *(rw,no_root_squash)
使配置生效
root@ubuntu0:~/matedata/volumes# exportfs -arv
4.创建 storageclass,动态供给 pv
root@ubuntu0:~/matedata/volumes# cat nfs-storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs
provisioner: example.com/nfs # 必须与 Deployment 中的 PROVISIONER_NAME 一致,因为需要有一个对应的 StorageClass 来告诉 Kubernetes 使用哪个 provisioner:
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs-storageclass.yaml
storageclass.storage.k8s.io/nfs created
root@ubuntu0:~/matedata/volumes# kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs example.com/nfs Delete Immediate false 4s
5.安装 nfs-provisioner 程序
root@ubuntu0:~/matedata/volumes# cat nfs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: xpp
labels:
app: v1
spec:
selector:
matchLabels:
app: nfs-provisioner
replicas: 1
strategy: #用于将现有的pod部署成新的pod的部署策略
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes #将 NFS 共享挂载到容器的 /persistentvolumes 路径
env:
- name: PROVISIONER_NAME # provisioner 的标识符
value: example.com/nfs
- name: NFS_SERVER
value: 192.168.23.99
- name: NFS_PATH
value: /data/nfs_pro
volumes:
- name: nfs-client-root
nfs:
server: 192.168.23.99
path: /data/nfs_pro
root@ubuntu0:~/matedata/volumes# kubectl apply -f nfs-deployment.yaml
deployment.apps/xpp created
root@ubuntu0:~/matedata/volumes# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-pvc 1/1 Running 0 54m
xpp-c44d68dcf-fkxkk 1/1 Running 0 2m40s
#显示内容如上,说明 storageclass 创建成功了
注意:provisioner 处写的 example.com/nfs 应该跟安装 nfs provisioner 时候的 env 下的
PROVISIONER_NAME 的 value 值保持一致,如下:
env:
- name: PROVISIONER_NAME
value: example.com/nfs
6.创建 pvc,通过 storageclass 动态生成 pv
root@ubuntu0:~/matedata/volumes# cat claim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim1
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
storageClassName: nfs
root@ubuntu0:~/matedata/volumes# kubectl apply -f claim.yaml
persistentvolumeclaim/test-claim1 created
#查看是否动态生成了 pv,pvc 是否创建成功,并和 pv 绑定
root@ubuntu0:~/matedata/volumes# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-pvc Bound v2 2Gi RWX 11d
test-claim1 Bound pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95 1Gi RWX nfs 29s
#通过上面可以看到 test-claim1 的 pvc 已经成功创建了,绑定的 pv 是
pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95,这个 pv 是由 storageclass 调用 nfs provisioner
自动生成的
root@ubuntu0:~/matedata/volumes# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-81a6a294-de2a-4e44-94d0-35c8a67b3a95 1Gi RWX Delete Bound default/test-claim1 nfs 47s
6.创建 pod,挂载 storageclass 动态生成的 pvc
root@ubuntu0:~/matedata/volumes# cat read-pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: read-pod
spec:
containers:
- name: read-pod
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
restartPolicy: "Never"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim1
root@ubuntu0:~/matedata/volumes# kubectl apply -f read-pod.yaml
pod/read-pod created
root@ubuntu0:~/matedata/volumes# kubectl apply -f read-pod.yaml
pod/read-pod created
root@ubuntu0:~/matedata/volumes# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-pvc 1/1 Running 0 65m
read-pod 1/1 Running 0 23s
xpp-c44d68dcf-fkxkk 1/1 Running 0 13m
root@ubuntu0:~/matedata/volumes# kubectl describe pods read-pod
Volumes:
nfs-pvc:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: test-claim1
ReadOnly: false
kube-api-access-qxkd8:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
storageclass 默认的回收策略是 delete,删除 pvc,会把 pvc 以及 pvc 绑定的 pv 和 pv 对应的后
端存储目录都删除,比较危险。
生产环境回收策略用 retain,这样的话删除 pvc,不会把 pvc 绑定的 pv 和 pv 对应的后端存储目录
都删除。
更多推荐




所有评论(0)