zoukankan      html  css  js  c++  java
  • 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字段内容。

     

     

      

      

      

      

      

      

     

  • 相关阅读:
    Effective Java 第三版——72. 赞成使用标准异常
    Effective Java 第三版——71. 避免不必要地使用检查异常
    Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
    Effective Java 第三版——69. 仅在发生异常的条件下使用异常
    Effective Java 第三版——68. 遵守普遍接受的命名约定
    Effective Java 第三版——67. 明智谨慎地进行优化
    Effective Java 第三版——66. 明智谨慎地使用本地方法
    Effective Java 第三版——65. 接口优于反射
    Effective Java 第三版——64. 通过对象的接口引用对象
    Effective Java 第三版——63. 注意字符串连接的性能
  • 原文地址:https://www.cnblogs.com/chalon/p/14898159.html
Copyright © 2011-2022 走看看