1. 本地存储
1.1. emptyDir
对于emptyDir来说,会在pod所在的物理机上生成一个随机目录。pod的容器会挂载到这个随机目录上。当pod容器删除后,随机目录也会随之删除。适用于多个容器临时共享数据。在pod删除后,该目录也会随之删除。
yaml文件
apiVersion: v1
kind: Pod
metadata:
name: emptydirpod
labels:
name: enptydirpod10
spec:
volumes:
- name: v1
emptyDir: {}
containers:
- name: enptydirpod10
image: nginx
volumeMounts:
- name: v1
mountPath: /abc
resources:
limits:
memory: "128Mi"
cpu: "500m"
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
emptydirpod 1/1 Running 0 24h 10.244.69.226 knode2 <none> <none>
# 可以在knode2 上查看具体时挂在那个临时目录
crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
2f18c27e13ffa c20060033e06f 7 hours ago Running nfspod 0 9db51a9ea7ccb nfspod
b0a0211723a6a c20060033e06f 25 hours ago Running enptydirpod10 0 6ef3e4bce7ea5 emptydirpod
ad94cf343599b 7b60c7012b1c9 35 hours ago Running calico-typha 0 2f01766ac16fe calico-typha-85568b8955-js254
1153efb242afb c14671fdda128 5 days ago Running csi-node-driver-registrar 2 139ccac6c83dc csi-node-driver-l2hmk
843067cc582ac f37eacbb9a295 5 days ago Running calico-csi 2 139ccac6c83dc csi-node-driver-l2hmk
e25fd796f2735 08616d26b8e74 5 days ago Running calico-node 2 e039f3f2d6053 calico-node-qwb8n
b056bbe270c17 556768f31eb1d 5 days ago Running kube-proxy 2 255cf55426cc0 kube-proxy-hp5ts
crictl inspect b0a0211723a6a
"mounts": [
{
"containerPath": "/abc",
"hostPath": "/var/lib/kubelet/pods/b08bb846-9199-41bf-8423-4dbd0db88ee0/volumes/kubernetes.io~empty-dir/v1",
"propagation": "PROPAGATION_PRIVATE",
"readonly": false,
"selinuxRelabel": false
1.2. hostPath
挂载卷的方式和emptyDir是一样的,只不过不是随机的,是我们自定义的目录,把自定义的目录挂载到容器里面。
yaml文件
apiVersion: v1
kind: Pod
metadata:
name: emptydirpod
labels:
name: enptydirpod10
spec:
volumes:
- name: v1
hostPath:
path: /data
containers:
- name: enptydirpod10
image: nginx
volumeMounts:
- name: v1
mountPath: /abc
resources:
limits:
memory: "128Mi"
cpu: "500m"
这样自定义的目录,可以永久保留。如果上面的pod是在knode2上运行的,目录也是在knode2上的永久目录,但是未来该pod万一调度到了knode1上面了,就找不到数据了。保存的记录就没有了。没有办法各个节点之间进行同步。
2. 网络存储
网络存储支持很多种类型 nfs/ceph/iscsi等都可以作为后端存储来使用。
2.1. 挂载NFS网络存储
在NFS服务端上的配置
yum install -y yum-utils vim bash-completion net-tools wget nfs-utils
mkdir /nfsdata
systemctl start nfs-server.servic
systemctl enable nfs-server.service
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service.
systemctl stop firewalld.service
systemctl disable firewalld.service
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
setenforce 0
vim /etc/selinux/config
vim /etc/exports
/nfsdata *(rw,async,no_root_squash)
exportfs -arv # 不用重启nfs服务,配置文件就会生效
# no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!这个项目『极不安全』,不建议使用。以root身份写。
# exportfs命令
# -a 全部挂载或者全部卸载
# -r 重新挂载
# -u 卸载某一个目录
# -v 显示共享目录
在kubernetes集群knode节点上的配置
yum install -y nfs-utils
# 虽然未来的pod要连接nfs,但是真正连接nfs的是pod所在的物理主机。所以作为物理主机(客户端)也要安装nfs客户端。
yaml文件
apiVersion: v1
kind: Pod
metadata:
name: nfspod
labels:
name: nfspod
spec:
volumes:
- name: nfsv1
nfs:
server: 172.16.100.183
path: /nfsdate
containers:
- name: nfspod
image: nginx
volumeMounts:
- name: nfsv1
mountPath: /nfsvolumes
resources:
limits:
memory: "128Mi"
cpu: "500m
在kubernetes集群kmaster节点上的配置
kubectl apply -f nfspod.yaml
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfspod 1/1 Running 0 7h 10.244.69.227 knode2 <none> <none>
kubectl exec -ti nfspod -- bash
root@nfspod:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 64G 4.8G 60G 8% /
tmpfs 64M 0 64M 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
172.16.100.183:/nfsdate 64G 2.3G 62G 4% /nfsvolumes
/dev/mapper/cs-root 64G 4.8G 60G 8% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 128M 12K 128M 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
在knode2上查看物理节点是否有挂载
df -h | grep nfs
172.16.100.183:/nfsdate 64G 2.3G 62G 4% /var/lib/kubelet/pods/e227f191-21d8-455f-a6e9-d6ce0024f0f3/volumes/kubernetes.io~nfs/nfsv1
3. 持久化存储
持久化存储有两个类型:PersistentVolume/PersistentVolumeClaim
master上有很多命名空间 N1和N2,不同用户连接到不同的命名空间里面。用户管理pod,而专员管理存储,分开管理。
下面是一个存储服务器,共享多个目录,由专门的管理员管理。管理员会在集群中创建 PersistentVolume(PV),这个PV是全局可见的。该PV会和存储服务器中的某个目录关联。
用户要做的就是创建自己的 PVC,PVC是基于命名空间进行隔离的。而PV是全局可见的。之后把PVC和PV关联在一起。
创建pv yaml文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
storageClassName: test
nfs:
path: /nfsdate
server: 172.16.100.183
kubectl apply -f pv.yml
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 5Gi RWO Recycle Available slow 12s
创建pvc yaml文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc01
spec:
resources:
requests:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
storageClassName: test
kubectl apply -f pvc.yml
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv01 5Gi RWO test 7m11s
注意:pv和pvc的yaml文件
storageClassName
参数要么不写自动绑定,要么都写并且要保持一直,要不然pv和pvc会绑定不成功,pvc会一直处于Pending
状态。
挂载pod的yaml文件
apiVersion: v1
kind: Pod
metadata:
name: pvpod
labels:
name: pvpod
spec:
containers:
- name: pvpod
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypv01
resources:
limits:
memory: "128Mi"
cpu: "500m"
volumes:
- name: mypv01
persistentVolumeClaim:
claimName: pvc01
kubectl apply -f pvpod.yml
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pvpod 1/1 Running 0 6s 10.244.195.166 knode1 <none> <none>
kubectl exec -it pvpod -- bash # 进入到pod进行查看
df -h
Filesystem Size Used Avail Use% Mounted on
overlay 64G 4.8G 60G 8% /
tmpfs 64M 0 64M 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/cs-root 64G 4.8G 60G 8% /etc/hosts
shm 64M 0 64M 0% /dev/shm
172.16.100.183:/nfsdate 64G 2.3G 62G 4% /var/www/html
tmpfs 128M 12K 128M 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
回收策略
回收策略:默认retain(NFS支持recycle,理论上recycle删除pvc,也会删除nfs数据,同时pv状态变为available)
reclaimPolicy
两种常用取值:Delete
、Retain
;
Delete
:表示删除PVC的时候,PV也会一起删除,同时也删除PV所指向的实际存储空间;
Retain
:表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理;retain是不回收数据,删除pvc后,pv不可用,并长期保持released状态。
Delete的优缺点:
优点:实现数据卷的全生命周期管理,应用删除PVC会自动删除后端云盘。能有效避免出现大量闲置云盘没有删除的情况。
缺点:删除PVC时候一起把后端云盘一起删除,如果不小心误删pvc,会出现后端数据丢失;
Retain的优缺点:
优点:后端云盘需要手动清理,所以出现误删的可能性比较小;
缺点:没有实现数据卷全生命周期管理,常常会造成pvc、pv删除后,后端云盘闲置往清理,长此以往导致大量磁盘浪费。
4. 利用nfs配置动态卷供应流程
利用nfs配置动态卷供应流程:(整个过程是不需要创建pv的)
- 配置 NFS 服务器
- 获取 NFS Subdir External Provisioner 文件,地址:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/tree/master/deploy
- 如果集群启用了 RBAC,设置授权。
- 配置 NFS subdir external provisioner
- 创建 Storage Class
- 创建 PVC 和 Pod 进行测试
- 配置 NFS 服务器
mkdir /nfsdate
vim /etc/exports
exportfs -arv
exporting *:/vdisk
cat /etc/exports
/vdisk *(rw,async,no_root_squash)
# 获取 NFS Subdir External Provisioner 文件
yum install -y git
git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git
- 如果集群启用了 RBAC,设置授权。
# 上传到master,解压
ls
class.yaml deployment.yaml kustomization.yaml objects rbac.yaml test-claim.yaml test-pod.yaml
vim rbac.yaml
vim rbac.yaml
sed -i 's/namespace: default/namespace: vol/g' rbac.yaml # 更换命名空间
kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
- 配置 NFS subdir external provisioner
cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: vol
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/cloudcs/nfs-subdir-external-provisioner:v4.0.2
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 192.168.100.143
- name: NFS_PATH
value: /vdisk
volumes:
- name: nfs-client-root
nfs:
server: 192.168.100.143
path: /vdisk
# 更换image镜像源,nfs的server IP和path路径
# 还有一个镜像,也是通过华为云香港主机下载,直接push到阿里云
# image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
# 所有节点提前下载该镜像
crictl pull registry.cn-hangzhou.aliyuncs.com/cloudcs/nfs-subdir-external-provisioner:v4.0.2
# 注意修改deployment.yaml 里面的image路径为 registry.cn-hangzhou.aliyuncs.com/cloudcs/nfs-subdir-external-provisioner:v4.0.2
kubectl apply -f deployment.yaml
deployment.apps/nfs-client-provisioner created
- 创建 Storage Class
class yaml文件
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "false"
kubectl apply -f class.yml
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 30s
创建pvc的yaml文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvctest
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-client
resources:
requests:
storage: 5Gi
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvctest Bound pvc-58dfcbc5-acc9-4c52-8b8b-8d917ae37403 5Gi RWO nfs-client 4s
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-58dfcbc5-acc9-4c52-8b8b-8d917ae37403 5Gi RWO Delete Bound volumes/pvctest nfs-client 8s
这里只需要创建pvc,pv由
StorageClass
类来创建,因此storageClassName
需要和class类yaml文件中metadata.name
一致。