0
点赞
收藏
分享

微信扫一扫

Xcode Build System

郝春妮 2023-07-13 阅读 71

文章目录

一、Volume

1、什么是Volume

Volume官网:https://kubernetes.io/docs/concepts/storage/volumes/

容器中的磁盘上文件是短暂的,这给在容器中运行的重要应用程序带来了一些问题。首先,当一个容器崩溃时,kubelet会重启它,但是文件会丢失——容器以干净的状态开始。其次,当在一个Pod中一起运行容器时,通常需要在这些容器之间共享文件。Kubernetes的Volume 抽象解决了这两个问题。

2、Host类型volume实战(不推荐)

定义一个Pod,其中包含两个Container,都使用Pod的Volume

创建volume-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: nginx-container # nginx container
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts: # 使用某个volume
    - name: volume-pod # volume名称
      mountPath: /nginx-volume # 对应container中的目录
  - name: busybox-container # busybox的container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    volumeMounts:
    - name: volume-pod
      mountPath: /busybox-volume # 对应container目录
  volumes: # 定义volume
  - name: volume-pod # volume名称
    hostPath: # volume类型
      path: /tmp/volume-pod  # 对应宿主机的位置
# 运行
kubectl apply -f volume-pod.yaml
# 查看pod,发现pod运行在了w1节点
kubectl get pods -o wide
# 进入w1的容器
docker exec -it a2e9dbc52a11 /bin/bash
docker exec -it 27c66caa2b85 sh
# 看容器的/nginx-volume目录中的内容与宿主机的/tmp/volume-pod内容是不是一样,再折腾一下看文件会不会同步,看两个pod中的内容是否会同步

(1)小总结

我们发现,使用volume形式,会与宿主机共享目录,里面数据内容是一致的。

如果pod挂掉了,宿主机的文件仍然不会丢失,可以完美解决数据保存的问题,保证数据不丢失。

但是host的方式,只能保证pod与当前宿主机目录的绑定关系,集群下无法保证(如果下次pod运行在另一台宿主机,文件仍然无法关联)。

或许我们可以使用打标签的方式,指定该pod永远部署在某一台机器,但是如果该机器挂了,就无法使用了。

二、PersistentVolume持久化volume(推荐)

1、什么是PersistentVolume

官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/

# 实例 ,定义一个PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 5Gi    # 存储空间大小
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce     # 只允许一个Pod进行独占式读写操作
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp            # 远端服务器的目录
    server: 172.17.0.2    # 远端的服务器

说白了,PV是K8s中的资源,volume的plugin实现,生命周期独立于Pod,封装了底层存储卷实现的细节。这种资源可以和第三方存储技术绑定,比如DFS。
注意:PV的维护通常是由运维人员、集群管理员进行维护的。

2、什么是PersistentVolumeClaim

官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims

有了PV,那Pod如何使用呢?为了方便使用,我们可以设计出一个PVC(PersistentVolumeClaim)来绑定PV,然后把PVC交给Pod来使用即可。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

说白了,PVC会匹配满足要求的PV[是根据size和访问模式进行匹配的],进行一一绑定,然后它们的状态都会变成Bound。

也就是PVC负责请求PV的大小和访问方式,然后Pod中就可以直接使用PVC咯。

注意:PVC通常由开发小伙伴维护,开发小伙伴无需关注与存储细节,开发小伙伴只需要声明使用的资源大小,由PVC来声明,PVC会去找合适的PV。

3、Pod中如何使用PVC

官网:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim # 指定pvc

三、Pod中使用PVC实战

在这里插入图片描述

NFS(network file system)网络文件系统,是FreeBSD支持的文件系统中的一种,允许网络中的计算机之间通过TCP/IP网络共享资源。

1、搭建NFS

在master节点(192.168.56.100)上搭建一个NFS服务器,目录为/nfs/data

01 选择master节点作为nfs的server,所以在master节点上
	# 安装nfs
	yum install -y nfs-utils
	# 创建nfs目录
	mkdir -p /nfs/data/
	mkdir -p /nfs/data/mysql
	# 授予权限
	chmod -R 777 /nfs/data
	# 编辑export文件,输入下面一行
	vi /etc/exports
	  /nfs/data *(rw,no_root_squash,sync)
	# 使得配置生效
	exportfs -r
	# 查看生效 显示:/nfs/data     	<world>
	exportfs
	# 启动rpcbind、nfs服务
	systemctl restart rpcbind && systemctl enable rpcbind
	systemctl restart nfs && systemctl enable nfs
	# 查看rpc服务的注册情况
	rpcinfo -p localhost
	# showmount测试	showmount -e 192.168.56.100
	showmount -e master-ip
	
02 所有node上安装客户端 
	yum -y install nfs-utils
	systemctl start nfs && systemctl enable nfs

2、创建PV&PVC&Nginx

(1)在nfs服务器创建所需要的目录

mkdir -p /nfs/data/nginx

(2)定义PV,PVC和Nginx的yaml文件

nginx-pv-demo.yaml

# 定义PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv # pv名字
spec:
  accessModes:
    - ReadWriteMany # 多个pod多次访问模式
  capacity:
    storage: 2Gi     # 大小
  nfs:
    path: /nfs/data/nginx     # 服务器path
    server: 192.168.56.100 # 服务器ip  
    
---
# 定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc # pvc名称
spec:
  accessModes:
    - ReadWriteMany # 访问模式,需要与pv对应,会进行匹配
  resources:
    requests:
      storage: 2Gi # 需要的空间大小
  
---
# 定义Pod,指定需要使用的PVC
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels: 
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /usr/share/nginx/html # container共享目录
      volumes:
      - name: nginx-persistent-storage
        persistentVolumeClaim:
          claimName: nginx-pvc # 指定pvc

(3)根据yaml文件创建资源并查看资源

# 启动
[root@m ~]# kubectl apply -f nginx-pv-demo.yaml
persistentvolume/nginx-pv created
persistentvolumeclaim/nginx-pvc created
deployment.apps/nginx created
# 查看pv和pvc
[root@m ~]# kubectl get pv,pvc
NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/nginx-pv   2Gi        RWX            Retain           Bound    default/nginx-pvc                           10s

NAME                              STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/nginx-pvc   Bound    nginx-pv   2Gi        RWX                           9s
# 查看pod
[root@m ~]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE   NOMINATED NODE   READINESS GATES
nginx-77945f44db-8rfhr   1/1     Running   0          53s   192.168.80.207   w2     <none>           <none>

# 删除
kubectl delete -f nginx-pv-demo.yaml

(4)测试持久化存储

01 在nfs服务器的/nfs/data/nginx新建文件1.html,写上内容hello nginx

02 kubectl get pods -o wide 得到nginx-pod的ip地址 :192.168.80.207

03 curl nginx-pod-ip/1.html
curl 192.168.80.207/1.html :打印hello nginx

04 kubectl exec -it nginx-pod bash 进入/usr/share/nginx/html目录查看,发现有了1.html

05 kubectl delete pod nginx-pod
发现原来的pod被删了,又自动启动了一个新的pod,新的pod地址为:192.168.80.208

06 查看新nginx-pod的ip并且访问nginx-pod-ip/1.html
curl 192.168.80.208/1.html 确实仍然能够访问,打印出hello nginx

四、StorageClass

1、什么是StorageClass

上面手动管理PV的方式还是有点low,能不能更加灵活一点呢?
官网:https://kubernetes.io/docs/concepts/storage/storage-classes/
nfs github:github:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs

StorageClass声明存储插件,用于自动创建PV。

说白了就是创建PV的模板,其中有两个重要部分:PV属性和创建此PV所需要的插件。

这样PVC就可以按“Class”来匹配PV。

可以为PV指定storageClassName属性,标识PV归属于哪一个Class。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

01 对于PV或者StorageClass只能对应一种后端存储
02 对于手动的情况,一般我们会创建很多的PV,等有PVC需要使用的时候就可以直接使用了
03 对于自动的情况,那么就由StorageClass来自动管理创建
04 如果Pod想要使用共享存储,一般会在创建PVC,PVC中描述了想要什么类型的后端存储、空间等,K8s从而会匹配对应的PV,如果没有匹配成功,Pod就会处于Pending状态。Pod中使用只需要像使用volumes一样,指定名字就可以使用了
05 一个Pod可以使用多个PVC,一个PVC也可以给多个Pod使用
06 一个PVC只能绑定一个PV,一个PV只能对应一种后端存储

有了StorageClass之后的PVC可以变成这样:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim1
spec:
accessModes:
    - ReadWriteMany
resources:
 requests:
    storage: 1Mi
  storageClassName: nfs

StorageClass之所以能够动态供给PV,是因为Provisioner,也就是Dynamic Provisioning

但是NFS这种类型,K8s中默认是没有Provisioner插件的,需要自己创建。

2、StorageClass实战

github:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs
在这里插入图片描述

(1)准备好NFS服务器[并且确保nfs可以正常工作],创建持久化需要的目录

mkdir -p /nfs/data/cxf
chmod 777 /nfs/data

# server: 192.168.56.100

(2)根据rbac.yaml文件创建资源

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
  - apiGroups: [""]
    resources: ["services", "endpoints"]
    verbs: ["get"]
  - apiGroups: ["extensions"]
    resources: ["podsecuritypolicies"]
    resourceNames: ["nfs-provisioner"]
    verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
     # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-provisioner
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml

(3)根据deployment.yaml文件创建资源

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.56.100 # 指定nfs地址
            - name: NFS_PATH
              value: /nfs/data/cxf # 指定nfs目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.56.100 # 指定nfs地址
            path: /nfs/data/cxf # 指定nfs目录
# 创建
kubectl apply -f deployment.yaml

(4)根据class.yaml创建资源

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: example-nfs
provisioner: example.com/nfs
# 创建
kubectl apply -f class.yaml

(5)根据pvc.yaml创建资源

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi
  # 这个名字要和上面创建的storageclass名称一致
  storageClassName: example-nfs
# 创建
kubectl apply -f pvc.yaml
# 获取pvc,发现状态已经是Bound了
kubectl get pvc
# 获取pv,发现自动创建了pv
kubectl get pv

(6)根据nginx-pod.yaml创建资源

kind: Pod
apiVersion: v1
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
      - name: my-pvc # 指定pvc
        mountPath: "/usr/cxf" # 容器地址
  restartPolicy: "Never"
  volumes:
    - name: my-pvc # 指定pvc
      persistentVolumeClaim:
        claimName: my-pvc
# 创建
kubectl apply -f nginx-pod.yaml
# 查看pod
kubectl get pods -o wide
# 进入nginx
kubectl exec -it nginx bash
cd /usr/cxf
# 进行同步数据测试 

五、PV的状态和回收策略

  • PV的状态

Available:表示当前的pv没有被绑定

Bound:表示已经被pvc挂载

Released:pvc没有在使用pv, 需要管理员手工释放pv

Failed:资源回收失败

  • PV回收策略

Retain:表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理

Recycle:在Kubernetes新版本就不用了,采用动态PV供给来替代

Delete:表示删除PVC的时候,PV也会一起删除,同时也删除PV所指向的实际存储空间

注意:目前只有NFS和HostPath支持Recycle策略。AWS EBS、GCE PD、Azure Disk和Cinder支持Delete策略

举报

相关推荐

0 条评论