k8s卷管理-1

发布时间 2024-01-10 16:07:55作者: FuShudi

卷管理-1

我们之前创建的Pod是没有做存储的,那么这个Pod产生的数据文件都是会随着Pod的删除而删除,不能做到数据持久存储,现在开始看卷管理,通过定义volume,然后pod去挂载pod就可以实现数据存储,共享

k8s的卷从总体上来说,分为3类

  1. 本地存储
  2. 网络存储
  3. 持久化存储

1. 本地存储

1.1 emptyDir

对于emptyDir来说,他会在Pod所在的物理机上创建一个随机目录,Pod里的容器会挂载到这个目录,但是当容器删除之后,这个随机目录也会随着删除,数据不会持久化存储到本地,适用于多个容器之间共享数据。
我们来看看如何去定义以及使用emptyDir

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: volume1
  name: volume1
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: volume1
    resources: {}
# 加上这一段
    volumeMounts:
# 这里的name是已经定义好的名字
    - name: volume1
# 这个是挂载到容器内的哪个目录
      mountPath: /volumes

# 这里是定义卷
  volumes:
  - name: volume1
    emptyDir: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

通过这个yaml文件来创建pod

[root@master k8s]# kubectl apply -f volume.yaml 
pod/volume1 created
[root@master k8s]# kubectl get pods -owide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
volume1   1/1     Running   0          6s    10.244.166.176   node1   <none>           <none>

查看到这个pod是被调度到了node1上,那么我们进入到容器内去创建一个文件,看看在node1上是否会存在

[root@master k8s]# kubectl exec -it volume1 -- /bin/bash
root@volume1:/volumes# echo volume_file > volume_file
root@volume1:/volumes# ls
volume_file
# 现在我们来到node1节点使用find去查找文件volume_file
[root@node1 ~]# find / -name volume_file
/var/lib/kubelet/pods/e7db8b1c-2df5-4b62-b33e-ef1c1e45b60c/volumes/kubernetes.io~empty-dir/volume1/volume_file
# 是可以找得到这个文件的,那么我们来看看这个文件的内容,是否与之前的一致
[root@node1 ~]# cat /var/lib/kubelet/pods/e7db8b1c-2df5-4b62-b33e-ef1c1e45b60c/volumes/kubernetes.io~empty-dir/volume1/volume_file
volume_file

通过这个实验我们发现他确实是将文件存储在了本地,但是emptyDir是会随着pod的删除而去删除物理机上的目录的,我们来到master删除pod

[root@master k8s]# kubectl delete -f volume.yaml 
pod "volume1" deleted
# 再次回到node1查找文件
[root@node1 ~]# find / -name volume_file

再次去node1上查找文件的时候他是已经找不到了,说明pod删除这个目录也删除,所以说这个类型并不适合持久化存储文件。而且在物理机上产生的目录也是随机的,那我们能不能让他不随机产生呢,我们去手动给他指定呢?可以的,继续看

1.2 hostPath

hostPath他是可以让你手动指定存储在物理机的哪个目录上的,并且这个目录并不会随着pod的删除而删除。我们通过实验来看看

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: volume2
  name: volume2
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: volume2
    resources: {}
    volumeMounts:
    - name: hostpath
      mountPath: /volumes
# 定义卷,
  volumes:
  - name: hostpath
    hostPath:
      path: /hostpath
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

通过这个文件来创建pod

[root@master k8s]# kubectl apply -f hostpath.yaml 
pod/volume2 created
[root@master k8s]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
volume2   1/1     Running   0          3s    10.244.166.177   node1   <none>           <none>

我们进入容器来创建文件,然后删除pod,看看node1上的/hostpath是否还存在

[root@master k8s]# kubectl exec -it pods/volume2 -- /bin/bash
root@volume2:/volumes# echo hostpath > hostpath
root@volume2:/volumes# ls
hostpath
root@volume2:/volumes# 
# 退出容器并删除pod
root@volume2:/volumes# exit
exit
[root@master k8s]# kubectl delete -f hostpath.yaml 
pod "volume2" deleted
# 我们来到node1查看
[root@node1 /]# cd hostpath/
[root@node1 hostpath]# ls
hostpath

现在我们可以发现,pod删除之后他的目录并没有删除,那这样岂不是可以做到持久化存储吗?不可以的
因为是这样,他目前只是在node1上创建了这个目录并保存了文件,如果你用deployment控制器,然后给他一个Drain,他开始驱逐pod了,然后pod被调度到node2上了,那么他还能读取到我之前产生的数据文件吗?显然是不可以的

网络存储

网络存储支持非常多的类型,比如NFS,Ceph以及iScsi等等,当然,k8s的更新非常的快,非常的频繁,可能现在能用这些网络存储,但是等到过几个版本他就用不了了也是很正常的
我们就使用master节点来充当nfs服务器吧

搭建NFS服务器

这个相信有Linux的基础的是肯定会搞的

# 1. 安装nfs工具,所有节点都需要做,没有nfs-utils是挂载不上的
[root@master k8s]# yum install nfs* -y
# 2. 创建共享目录,master做就可以了
[root@master k8s]# mkdir /nfs
# 3. 将共享目录导出,master做
[root@master k8s]# echo "/nfs *(rw,no_root_squash)" >> /etc/exports
# 4. 重启服务
[root@master k8s]# systemctl restart nfs-server rpcbind

使用NFS网络存储

好了,现在nfs服务器已经搞好了,现在开始给pod挂载nfs,他的定义其实也是很简单的

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: volume1
  name: volume1
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nfs1
    resources: {}
    volumeMounts:
    - name: nfs1
      mountPath: /volumes
  volumes:
  - name: nfs1
# 将这里的hostPath改成nfs就可以了
    nfs:
      server: master
      path: /nfs
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

我们来创建pod然后进入容器创建文件

[root@master k8s]# kubectl apply -f nfs.yaml
[root@master k8s]# kubectl exec -it pods/volume1 -- /bin/bash
root@volume1:/volumes# echo "this is a nfsfile" > nfsfile
root@volume1:/volumes# ls
nfsfile

我们在master节点的共享目录上查看这个文件

[root@master k8s]# cat /nfs/nfsfile 
this is a nfsfile

是没有任何问题的,那么我们现在再创建一个pod也让他挂载这个nfs,看看这个pod能不能读取到这个文件
yaml文件还是用刚刚那个,你只需要将他的pod名字改一下就可以了

[root@master k8s]# kubectl apply -f nfs.yaml 
pod/volume2 created
[root@master k8s]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
volume1   1/1     Running   0          15m   10.244.166.179   node1   <none>           <none>
volume2   1/1     Running   0          15s   10.244.104.14    node2   <none>           <none>

现在node1和node2上各被调度了一个pod,那我们进入volume2看看文件是否存在

[root@master k8s]# kubectl exec -it volume2 -- /bin/bash
root@volume2:/# cd /volumes/
root@volume2:/volumes# ls
nfsfile
root@volume2:/volumes# cat nfsfile 
this is a nfsfile

我们可以发现,是可以看到文件的,没有任何的问题,那么现在pod之间的数据就可以做到共享,以及持久存储了,这个是NFS,我们再来看一个iSCSI网络存储

搭建iSCSI服务器

我们还是在master上搭建这个服务,首先我们先给master加上一块硬盘,大小随意,然后我们安装iSCSI服务程序

# 1. 查看刚刚添加的磁盘
[root@master ~]# lsblk 
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0   20G  0 disk 
sr0          11:0    1 1024M  0 rom  
nvme0n1     259:0    0   50G  0 disk 
├─nvme0n1p1 259:1    0    1G  0 part /boot
└─nvme0n1p2 259:2    0   49G  0 part 
  ├─cs-root 253:0    0 45.1G  0 lvm  /
  └─cs-swap 253:1    0  3.9G  0 lvm
# sda就是刚刚添加的
# 2. 安装iSCSI
[root@master ~]# yum install  targetcli -y
# 3. 配置iSCSI
# 3.1 创建块设备
/> cd /backstores/block
/backstores/block> create block01 /dev/sda 
Created block storage object block01 using /dev/sda.
# 3.2 创建iqn
/backstores/block> cd /iscsi
/iscsi> create iqn.2024-01.com.fsdstudy:k8s
Created target iqn.2024-01.com.fsdstudy:k8s.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.
# 3.3 创建lun
/iscsi> cd /iscsi/iqn.2024-01.com.fsdstudy:k8s/tpg1/luns
/iscsi/iqn.20...k8s/tpg1/luns> create /backstores/block/block01 
Created LUN 0.
# 3.4 创建acl,只有是这个iqn名字的才能连接成功,相当于口令一样
/iscsi/iqn.20...k8s/tpg1/luns> cd /iscsi/iqn.2024-01.com.fsdstudy:k8s/tpg1/acls
/iscsi/iqn.20...k8s/tpg1/acls> create iqn.2024-01.com.fsdstudy:pod
Created Node ACL for iqn.2024-01.com.fsdstudy:pod
Created mapped LUN 0.
# 3.5 退出即可
/iscsi/iqn.20...k8s/tpg1/acls> exit
# 3.6 node节点安装客户端
[root@node1 ~]# yum install -y iscsi*
[root@node2 ~]# yum install -y iscsi*
# 3.7 将node节点的iqn号修改成之前在master上定义的acl,所有的node节点都要做
[root@node1 ~]# cat /etc/iscsi/initiatorname.iscsi 
InitiatorName=iqn.2024-01.com.fsdstudy:pod

我们现在的iSCSI服务器就已经搭建好了,直接开始使用

使用iSCSI网络存储

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: volume3
  name: iscsi
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: iscsi
    resources: {}
    volumeMounts:
    - name: iscsi
      mountPath: /volumes
  volumes:
  - name: iscsi
    iscsi:
# 这里写要链接的iqn号,并不是写acl
      iqn: iqn.2024-01.com.fsdstudy:k8s
      lun: 0
      targetPortal: 192.168.200.200:3260
# 连接好之后把设备格式化成什么文件系统
      fsType: xfs
      readOnly: false
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

使用yaml文件创建pod

[root@master k8s]# kubectl apply -f iscsi.yaml
# 容器创建过程会相对来说慢一点,稍等片刻
[root@master k8s]# kubectl get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
iscsi     1/1     Running   0          20s    10.244.104.15    node2   <none>           <none>
volume1   1/1     Running   0          88m    10.244.166.179   node1   <none>           <none>
volume2   1/1     Running   0          73m    10.244.104.14    node2   <none>           <none>

后续的操作也就是进入容器查看,但是这个iSCSI是做不到数据互通的,他只能做到将你的数据保存下来
还有pv和pvc下一篇继续写