kubernetes集群系列资料13--存储机制介绍

一、K8S存储机制介绍  

  k8s的stateful控制组件是为有状态服务而设计的,有状态服务需要对数据进行存储;k8s有4种存储机制,主要为:

  1)configMap:为K8S存储配置文件而设计的,configMap可以用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。
  2)secret:为了解决密码、token、密钥等敏感数据的配置加密而设计,而不需要将这些敏感数据暴露到镜像或pod.spec中,可以volume或环境变量的方式使用。
  3)volume:为容器提供共享存储卷,避免发生容器崩溃重启后容器中文件丢失的问题。当pod不存在时,volume也不复存在;k8s支持多种类型的卷,pod可使用任意数量的卷。
  4)persistentVolume/persistentVolumeClai:

二、configMap介绍

  许多应用程序从配置文件、命令行参数或环境变量中读取配置信息,而configMap API给我们提供了向容器注入配置信息的机制。
  传统生成环境中,配置文件注册中心负责向n个集群n个节点应用程序的提供配置信息,该中心需要自行构建,没有较好的开源方案。应用程序向配置文件注册中心提供本节点的信息(如:IP、hostname),配置文件注册中心根据规则为该节点应用程序更新配置,应用程序按照新配置进行重载后运行。
  k8s集群中,configMap充当了配置文件注册中心的作用。pod向configMap申请配置,configMap为各pod下发不同的配置。
  configMap创建配置有3中方式:使用目录创建、使用文件创建、使用字面值创建。

1、使用目录创建configMap

mkdir configMapFile;cd configMapFile
cat > game.properties <<eof
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
enemies.code.passphrase=UUDDLRLRBABAS
enemies.code.allowed=true
enemies.code.lives=30
eof

cat >ui.properties<<eof
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
eof

kubectl create configmap game-config --from-file=../configMapFile #创建configMap;
kubectl get configmap               #查看configMap;
kubectl get cm game-config -o yaml  #以yaml格式输出game-config配置;
kubectl get cm game-config -o json    #以yaml格式输出game-config配置;

 2、使用文件创建configMap

kubectl create configmap game-config2 --from-file=../configMapFile/game.properties #使用文件创建configMap;
kubectl get cm game-config2 -o yaml

  多次使用文件创建,与在该目录下一次性批量创建效果相同。

3、使用字面量创建configMap

kubectl create configmap game-config3 --from-literal=special.how=very --from-literal=special.type=charm #使用字面量创建configMap;
kubectl get cm game-config3 -o yaml

4、案例:使用configMap向pod注入环境变量

cat >special-config.yaml<<eof
apiVersion: v1
kind: ConfigMap
metadata:
    name: special-config
    namespace: default
data:
    special.how: very
    special.type: charm
eof
kubectl apply -f special-config.yaml #使用yaml文件创建configMap;

cat >env-config.yaml<<eof
apiVersion: v1
kind: ConfigMap
metadata:
    name: env-config
    namespace: default
data:
    log_level: INFO
eof
kubectl apply -f env-config.yaml

cat >pod_configMapTest.yaml<<eof
apiVersion: v1
kind: Pod
metadata:
    name: dapi-test-pod
    namespace: default
spec:
    containers:
        - name: test-container
          image: hub.atguigu.com/library/nginx:latest
          command: ["/bin/sh","-c","env"]
          env:                              #设置pod环境变量;
            - name: SPECIAL_LEVEL_KEY
              valueFrom:                    #向pod环境变量注入special-config配置中某个键的值;
                configMapKeyRef:
                    name: special-config
                    key: special.how
            - name: SPECIAL_TYPE_KEY
              valueFrom:
                configMapKeyRef:
                    name: special-config
                    key: special.type
          envFrom:                          #向pod注入env.config配置中所有键值对;
            - configMapRef:
                name: env-config
    restartPolicy: Never
eof
kubectl apply -f pod_configMapTest.yaml

验证结果显示:环境变量包含导入的变量SPECIAL_LEVEL_KEY、SPECIAL_TYPE_KEY、log_level。

 5、案例:通过volume来使用configMap

cat >pod_configMapTest_1.yaml<<eof
apiVersion: v1
kind: Pod
metadata:
    name: dapi-test-pod-1
    namespace: default
spec:
    containers:
    - name: test-container
      image: hub.atguigu.com/library/nginx:latest
      command: ["/bin/sh","-c","ls /etc/config/"]
      volumeMounts:                     #指定挂载卷;
        - name: config-volume           #指定挂载卷名称;
          mountPath: /etc/config        #指定挂载卷挂载点;
    volumes:
        - name: config-volume
          configMap:
            name: special-config        #将configMap导入pod的volume中,有不同的选型。基本方式为:将文件填入volume,键以文件名显示,值以内容显示;
    restartPolicy: Never
eof
kubectl apply -f pod_configMapTest_1.yaml

5、案例:configMap热更新

cat >config_update_test.yaml<<eof
apiVersion: v1
kind: ConfigMap
metadata:
    name: log-config
    namespace: default
data:
    log_level: INFO
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
    name: my-nginx
    namespace: default
spec:
    replicas: 1
    template:
        metadata:
            labels:
                run: my-nginx
        spec:
            containers:
            - name: my-nginx
              image: hub.atguigu.com/library/nginx:latest
              ports:
              - containerPort: 80
              volumeMounts:                     #指定挂载卷;
                - name: config-volume           #指定挂载卷名称;
                  mountPath: /etc/config        #指定挂载卷挂载点;
            volumes:
                - name: config-volume
                  configMap:
                    name: log-config        #将configMap导入pod的volume中,有不同的选型。基本方式为:将文件填入volume,键以文件名显示,值以内容显示;
            restartPolicy: Always
eof
kubectl apply -f config_update_test.yaml
kubectl exec $(kubectl get pod -l run=my-nginx -o=name |cut -d "/" -f2) -it -- cat /etc/config/log_level #查看导入pod的configMap配置,该值以volume文件存在;

验证结果:配置写入volume的log_level文件。

 

6、案例:configMap热更新

cat >config_update_test.yaml<<eof
apiVersion: v1
kind: ConfigMap
metadata:
    name: log-config
    namespace: default
data:
    log_level: INFO
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
    name: my-nginx
    namespace: default
spec:
    replicas: 1
    template:
        metadata:
            labels:
                run: my-nginx
        spec:
            containers:
            - name: my-nginx
              image: hub.atguigu.com/library/nginx:latest
              ports:
              - containerPort: 80
              volumeMounts:                     #指定挂载卷;
                - name: config-volume           #指定挂载卷名称;
                  mountPath: /etc/config        #指定挂载卷挂载点;
            volumes:
                - name: config-volume
                  configMap:
                    name: log-config        #将configMap导入pod的volume中,有不同的选型。基本方式为:将文件填入volume,键以文件名显示,值以内容显示;
            restartPolicy: Always
eof
kubectl apply -f config_update_test.yaml
kubectl exec $(kubectl get pod -l run=my-nginx -o=name |cut -d "/" -f2) -it -- cat /etc/config/log_level #查看导入pod的configMap配置,该值以volume文件存在;
kubectl edit configmap log-config #修改configMap配置log_level值改为DEBUG;
kubectl patch deployment my-nginx --patch '{"spec":{"template":{"metadata":{"annotations":{"version/config":"20210618 14:53:00"}}}}}' #手动指定20210618 14:53:00重新加载配置文件,以便配置文件生效;
kubectl exec $(kubectl get pod -l run=my-nginx -o=name |cut -d "/" -f2) -it -- cat /etc/config/log_level #查看log_level值是否修改;

验证结果:configMap配置已热更新。

 三、secret介绍 

service Account:用来访问K8S API,由K8S自动创建,并且会自动挂载到pod的/run/secrets/kubernetes.io/serviceaccount目录中;对于有些pod(如coreDNS、flannel)来说,需要与K8S API进行交互,K8S API不是谁都可以访问的,必须通过挂载SA后pod才能访问K8S API;

opaque:base64编码格式的secret,用来存储密码、密钥等;opaque类型的数据是一个map类型,要求value是base64编码格式;
kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息;

1、SA案例

kubectl run nginx --image nginx #创建名为nginx的depoloyment及pod;
kubectl get deployment;kubectl get pods
kubectl exec nginx-7bb7cd8db5-czg6s ls /run/secrets/kubernetes.io/serviceaccount #查看sa的默认挂载的目录;
kubectl get secret -n kube-system #查看集群自动创建的secret;

 2、opaque案例

 

echo -n 'admin' |base64 	#输出以base64加密结果为YWRtaW4=;
echo -n '1qaz@WSX' |base64 	#输出以base64加密结果为MXFhekBXU1g=;
echo -n 'YWRtaW4=' |base64 -d  #输出YWRtaW4=的解密结果为admin;
cat >secret.yml<<eof
apiVersion: v1
kind: Secret
metadata:
    name: mysecret
data:
    username: YWRtaW4=
    password: MXFhekBXU1g=
eof
kubectl apply -f secret.yml
kubectl get secret
#将secret挂载到volume中
cat >secret-pod.yml<<eof
apiVersion: v1
kind: Pod
metadata:
    labels:
        name: secret-test
    name: secret-test
spec:
    volumes:
    - name: secrets
      secret:
        secretName: mysecret
    containers:
    - image: hub.atguigu.com/library/nginx:latest
      name: db
      volumeMounts:
      - name: secrets
        mountPath: '/etc/secrets'
        readOnly: true
eof
kubectl apply -f secret-pod.yml
kubectl get pod
kubectl exec secret-test -it -- cat /etc/secrets/username #验证secret是否导入volume中;

#将secret导出到pod的环境变量中
cat >secret-pod-out.yml<<eof
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
    name: secret-pod-out-deployment
spec:
    replicas: 2
    template:
        metadata:
            labels:
                app: secret-pod-out-deployment
        spec:
            containers:
            - image: hub.atguigu.com/library/nginx:latest
              name: pod-1
              ports:
              - containerPort: 80
              env:
              - name: TEST_USER
                valueFrom:
                    secretKeyRef:
                        name: mysecret
                        key: username
              - name: TEST_PASSWORD
                valueFrom:
                    secretKeyRef:
                        name: mysecret
                        key: password
eof
kubectl apply -f secret-pod-out.yml
kubectl get pod
kubectl exec secret-pod-out-deployment-7b8f585846-2cvj6 -it -- echo $TEST_PASSWORD #验证secret是否导入pod中;

3、kubernetes.io/dockerconfigjson案例

kubectl create secret docker-registry myregistrykey --docker-server=hub.atguigu.com --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@example.com #创建docker registry认证的secret;私有仓库不进行认证就无法下载镜像,因此需要创建该secret来存储私有docker registry的认证信息
cat >myregistry-secret.yml<<eof apiVersion: v1 kind: Pod metadata: name: foo spec: containers: - image: hub.atguigu.com/library/nginx:latest name: foo imagePullSecrets: - name: myregistrykey eof kubectl apply -f myregistry-secret.yml kubectl get pod

 四、volume介绍

docker中,容器崩溃后重启时数据不会丢失;但K8S中,容器崩溃时,该容器的文件会丢失,kubelet重启该容器,容器以镜像最初状态重新启动;POD中同时运行的多个容器需要共享文件。
k8s支持以下类型的卷:emptyDir;hostPath;iscsi;local;nfs;awsElasticBlockStore;azureDisk;azureFile;cephfs;csi;downwardAPI;fc;flocker;gcePersistentDisk;gitRepo;glusterfs;persistentVolumeClaim;projected;portworxVolume;quobyte;rbd;scaleIO;secret;storageos;vsphereVolume;

1、emptyDir介绍  

当pod被分配给节点时,首先创建emptyDir卷,并且只要该pod在该节点上运行,该卷就会存在。该卷最初时空的,pod中容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同的路径上。当处于任何原因从节点中删除pod时,emptyDir中数据将被永久删除。
empty的用法有:
  暂存空间,如:用于基于磁盘的合并排序;
  用作长时间计算崩溃恢复时的检查点;
  web服务器容器提供数据时,保存内容管理器容器提取的文件;

cat >volume-emptyDir.yml<<eof
apiVersion: v1
kind: Pod
metadata:
    name: volume-test-pod
spec:
    containers:
    - image: hub.atguigu.com/library/nginx:latest
      name: volume-test-container
      volumeMounts:
      - mountPath: /cache
        name: cache-volume
    - image: hub.atguigu.com/library/busybox:latest
      name: liveness-exec-container
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","touch /tmp/live;sleep 6000s"]
      volumeMounts:
      - mountPath: /test
        name: cache-volume      
    volumes:
    - name: cache-volume
      emptyDir: {}
eof
kubectl apply -f volume-emptyDir.yml
kubectl get pod
kubectl exec volume-test-pod -c volume-test-container -it -- touch /cache/test.txt
kubectl exec volume-test-pod -c volume-test-container -it -- ls /cache
kubectl exec volume-test-pod -c liveness-exec-container -it -- ls /test

2、hostPath介绍  

hostPath卷:将主机节点的文件系统中文件或目录挂载到集群中;用途如下:
  运行需要访问docker内部的容器;使用/var/lib/docker的hostPath;
  在容器中运行cAdvisor(K8S中一个用于监控docker的组件);使用/dev/cgroups的hostPath;
  允许pod指定给定的hostPath是否应该在pod运行之前存在,是否应该创建,以及它应该以什么形式存在;
hostPath卷属性有path,type;
  type: #type默认值为空,用于向后兼容,意味着在挂载hostPath卷之前不会执行任何检查。
  type:DirectoryOrCreate #如果在给定的路径上没有任何东西存在,则根据需要创建一个空目录,权限为0755,与kubelet具有相同的组和所有权;
  type:Directory #给定的路径上必须存在目录;
  type:FileOrCreate #如果在给定的路径上没有任何东西存在,则根据需要创建一个空文件,权限为0644,与kubelet具有相同的组和所有权;
  type:File #给定的路径上必须存在文件;
  type:Socket #给定的路径上必须存在UNIX套接字;
  type:CharDevice #给定的路径上必须存在字符设备;
  type:BlockDevice #给定的路径上必须存在块设备;
使用hostPath卷注意事项:
  由于每个节点上的文件都不同,具有相同配置的pod在不同节点上的行为可能会有所不同;
  当K8S按照计划添加资源感知调度时,将无法考虑hostPath使用的资源;
  在底层主机上创建的文件或目录只能由root写入。您需要在特权容器中以root身份运行进程,或修改主机上文件权限以便写入hostPath卷。

cat >volume-hostPath.yml<<eof
apiVersion: v1
kind: Pod
metadata:
    name: hostpath-volume-pod
spec:
    containers:
    - image: hub.atguigu.com/library/nginx:latest
      name: hostPath-volume--container
      volumeMounts:
      - mountPath: /cache
        name: cache-volume
    volumes:
    - name: cache-volume
      hostPath: 
        path: /data
        type: Directory
eof
kubectl apply -f volume-hostPath.yml  #确保调度节点存在/data/目录;
kubectl get pod
kubectl exec volume-test-pod -c volume-test-container -it -- touch /cache/test.txt

五、PV及PVC介绍

 PV(persistentVolume)

  是由管理设置的存储,它是集群的一部分。就像节点是集群中的资源一样,PV也是集群中的资源。PV是volume之类的卷插件,但居于哦独立于使用PV的pod的生命周期。此API对象包含存储实现的细节,接NFS,iSCSI或特定于云供应商的存储系统。

PVC(persistentVolumeClaim)
  是用户存储的请求。它与pod相似。pod消耗节点资源,PVC消耗PV资源。pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(如:可以读/写一次或只读多次模式挂载);

静态PV
  集群管理员创建一些PV。他们带有可供集群用户使用的实际存储的细节他们存在于K8S API中,可用于消费;

动态PV(实现方式复杂,价格昂贵,不太成熟,但是是未来的趋势)
  当管理员创建静态PV都不匹配用户的persistentVolumeClaim时,集群可能会尝试动态地为PVC创建卷。此配置基于StorageClasses:PVC必须请求[存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为“”可以有效地金庸其动态配置。
  要启用基于存储级别的动态存储配置,集群管理员需要启用API server上的DefaultStorageClass【准入控制器】。例如,通过确保DefaultStorageClass位于API server组件的--admission-control标志,使用逗号分隔的有序值列表中,可以完成此操作。

绑定
  master中的控制环路监视新的PVC,寻找匹配的PV(如果可能),并将它们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将PV绑定到PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦PV和PVC绑定后,PersistentVolumeClaimbanging是排他性的,不管它们是如何绑定的。PVC跟PV绑定是一对一的映射。一般情况下,PVC规定容量一般小于PV容量,很少情况会出现近似相等。

持久化卷声明的保护
  PVC保护的目的是确保由POD正在使用的PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失。当启用PVC保护alpha功能时,如果用户删除了一个pod正在使用的PVC,则该PVC不会被立即删除。PVC的删除将被推迟,指导PVC不再被任何pod使用。注意:当pod状态为pending并且pod已经分配给节点或pod为running状态时,PVC处于活动状态。

PV类型以插件形式实现。K8S目前支持以下插件类型:
  awsElasticBlockStore;azureDisk;azureFile;FC(fiber channel);
  FlexVolume;Flocker;NFS;iSCSI;RBD(ceph block device);cephFS;
  cinder(openstack block storage);glusterfs;vshpereVolume;quobyte volumes;
  HostPath;VMware Photon;portworx Volumes;scaleIO volumes;storageOS;

PV访问模式:
  persistentVolume可以资源提供者支持的任何方式挂载到主机上。供应商具有不同的功能,每个PV的访问模式都将被设置为怪卷支持的特定模式;如:NFS可支持多个读/写客户端,但特定的NFS PV可能以只读方式导出到服务器。每  个PV都有一套自己的用来描述特定功能的访问模式。一个卷只能使用一种访问模式挂载,即使它支持很多访问模式。
  ReadWriteOnce(RWO)---该卷可以被单个节点以读/写模式挂载;
  ReadOnlyMany(ROX)---该卷可以被多个节点以只读模式挂载;
  ReadWriteMany(RWX)---该卷可以被多个节点以读/写模式挂载;

回收策略:
  retain(保留)---手动回收;PV不再被pod使用,但也不允许其他pod使用,等待管理员去手动释放数据。
  recycle(回收)---基本擦除(rm -rf /thevolume/*);最新版K8S不支持。
  delete(删除)---关联的存储资产(如AWS EBS|GCE PD|AZURE DISK|OPENSTACK CINDER)将被删除;
  当前只有NFS和hostPath支持回收策略。AWS EBS|GCE PD|AZURE DISK|OPENSTACK CINDER支持删除策略。

卷可以处于以下某种状态:
  available(可用)---一块空闲资源还没有被任何声明绑定;
  bound(已绑定)---卷已经被声明绑定;
  released(已释放)---声明被删除,但是资源还未被集群重新声明。
  failed(失败)---该卷的自动回收失败。
命令行会显示绑定到PV的PVC的名称。

创建statefuSet前必须要创建要给SVC;

##安装NFS服务器(选定K8S集群之外的主机部署,IP为192.168.66.100)
yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 777 /nfsdata          #慎用权限;
chown nfsnobody /nfsdata
cat >>/etc/exports<<eof  
/nfsdata *(rw,no_root_squash,no_all_squash,sync) #创建一个nfs文件系统;
eof
systemctl enable rpcbind;systemctl start rpcbind;systemctl status rpcbind
systemctl enable nfs;systemctl start nfs;systemctl status nfs
mkdir /nfs{1..3}            #在nfs服务器创建3个空目录;
chmod 777 /nfs{1..3}         
chown nfsnobody /nfs{1..3} 

cat >>/etc/exports<<eof     #在创建3个nfs文件系统;
/nfs1 *(rw,no_root_squash,no_all_squash,sync) 
/nfs2 *(rw,no_root_squash,no_all_squash,sync) 
/nfs3 *(rw,no_root_squash,no_all_squash,sync) 
eof
systemctl restart rpcbind nfs
##所有K8S集群节点安装工具
yum install -y nfs-utils rpcbind
mkdir /nfs_test/
showmount -e 192.168.66.100
mount -t nfs 192.168.66.100:/nfsdata /nfs_test/ #将nfs服务器192.168.66.100的/nfsdata挂载至本机/nfs_test目录下;
cd /nfs_test/
echo "nfs_test" >test.txt #在nfs服务器192.168.66.100的/nfsdata与本机/nfs_test目录下都可看见创建的test.txt;
umount /nfs_test/ #卸载挂载的nfs服务器192.168.66.100的/nfsdata;

##部署PV
cat >PV.yml<<eof
apiVersion: v1
kind: PersistentVolume
metadata:
    name: nfspv1
spec:
    capacity:
        storage: 10Gi                       #声明卷的容量;
    accessModes:
        - ReadWriteOnce                     #声明访问方式;
    persistentVolumeReclaimPolicy: Retain   #声明回收策略;
    storageClassName: nfs                   #指定要绑定PV的类;非常重要的一个指标;
    nfs:
        path: /nfsdata
        server: 192.168.66.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: nfspv01
spec:
    capacity:
        storage: 5Gi                       #声明卷的容量;
    accessModes:
        - ReadWriteMany                     #声明访问方式;
    persistentVolumeReclaimPolicy: Retain   #声明回收策略;
    storageClassName: slow                   #指定要绑定PV的类;非常重要的一个指标;
    nfs:
        path: /nfs1
        server: 192.168.66.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: nfspv02
spec:
    capacity:
        storage: 5Gi                       #声明卷的容量;
    accessModes:
        - ReadWriteOnce                     #声明访问方式;
    persistentVolumeReclaimPolicy: Retain   #声明回收策略;
    storageClassName: nfs                   #指定要绑定PV的类;非常重要的一个指标;
    nfs:
        path: /nfs2
        server: 192.168.66.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
    name: nfspv03
spec:
    capacity:
        storage: 1Gi                       #声明卷的容量;
    accessModes:
        - ReadWriteOnce                     #声明访问方式;
    persistentVolumeReclaimPolicy: Retain   #声明回收策略;
    storageClassName: nfs                   #指定要绑定PV的类;非常重要的一个指标;
    nfs:
        path: /nfs3
        server: 192.168.66.100
eof
kubectl apply -f PV.yml
kubectl get pv          #此时pv可以直接挂载至pod使用了;但正常情况下,使用PVC来调用PV;
##创建服务并使用PVC
cat >PVC.yml<<eof
apiVersion: v1
kind: Service
metadata:
    name: nginx
    labels:
        app: nginx
spec:
    ports:
    - port: 80
      name: web
    clusterIP: None
    selector:
        app: nginx
---
apiVersion: apps/v1
kind: StatefulSet       #创建statefuSet前必须要创建要给SVC;
metadata:
    name: web
spec:
    selector:
        matchLabels:
            app: nginx
    serviceName: "nginx"  #必须为无头服务(即该服务必须为clusterIP: None)才行;
    replicas: 3
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
            - name: nginx
              image: hub.atguigu.com/library/nginx:latest
              ports:
              - containerPort: 80
                name: web
              volumeMounts:
              - name: www
                mountPath: /usr/share/nginx/html
    volumeClaimTemplates:                           #声明卷的请求;
    - metadata:
        name: www
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: "nfs"
        resources:
            requests:
                storage: 1Gi
eof
kubectl apply -f PVC.yml
kubectl get pv
kubectl get pvc
kubectl get pod
kubectl get statefulset

###测试NFS卷的使用
##在NFS服务器操作
cd /nfs3        #根据实际pv确定目录;
echo "hello world" >index.html
chmod 777 index.html
chown nfsnobody index.html
##在K8S master操作
curl 10.244.2.157           #该IP为名为web-0的pod调度节点的IP;
kubectl delete pod web-0    
kubectl get pod -o wide
curl 10.244.2.159           #访问新pod,其pv内容不会变化。

 1、PV手动回收

 

 

 删除statefulset、pod、pvc后,需要手动释放pv时,需要至NFS服务器删除对应目录下的文件及pv下的claimRef字段内容。

 

 

  

  

  

  

  

  

 

原文地址:https://www.cnblogs.com/chalon/p/14898159.html