• 06K8S之VOLUME


    VOLUME

    volume:持久化存储卷,可以对数据进行持久化存储

    网络存储大体可以分为3类:

    1.传统的SAN或NAS设备构建的网络存储设备(脱离本机节点的存储设备):
      SAN(storage area network:存储区域网络):iSCSI,FC (协议)
      NAS(network additional storage:网络附加存储):nfs,cifs,http (协议)
    2.分布式存储:文件系统级别或者块级别
    	glusterfs,rbd(ceph),cephfs
    3.云存储:
    	EBS,Azure Disk,
    

    查看k8s支持哪些存储

    kubectl explain pods.spec.volumes
    
    k8s支持的后端存储如下:
    awsElasticBlockStore
    azureDisk
    azureFile
    cephfs
    cinder
    configMap
    csi
    downwardAPI
    emptyDir
    fc
    flexVolume
    flocker
    gcePersistentDisk
    gitRepo # 本质也是一个emptyDir类型的存储卷,使用git克隆代码到本地的空目录中,运行pod时将存储卷挂载到容器,之后仓库中代码的变化,不会影响到容器。在pod删除时,emptyDir目录中的数据也不复存在。
    glusterfs
    hostPath
    iscsi
    nfs
    persistentVolumeClaim
    photonPersistentDisk
    portworxVolume
    projected
    quobyte
    rbd
    scaleIO
    secret
    storageos
    vsphereVolume
    
    常用的如下:
    emptyDir
    hostPath
    nfs
    persistentVolumeClaim
    glusterfs
    cephfs
    configMap
    

    如何使用存储卷

    需要经历如下步骤:
    (1)定义pod的volume,这个volume指明它要关联到哪个存储上的
    (2)在容器中要使用volume mounts(挂载存储)
    经过以上两步才能使用存储卷
    

    常用存储卷类型

    1.EmptyDir

    emptyDir类型的Volume在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
    
    kubectl apply -f pod-vol-demo.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
     name: pod-demo
     namespace: default
     labels: # <map[string]string> 映射类型,类似于json
        app: myapp
        tier: frontend
     annotations:
       master01/created-by: cluster admin
    spec:
      containers:
      - name: myapp
        image: nginx:1.20 # 使用镜像启动默认命令
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /data/web/html/
      - name: busybox 
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: html
          mountPath: /data/
        command: # ["/bin/sh","-c","sleep 3600"] # 这里使用自定义的命令,而没使用镜像启动默认的命令,就是为了防止默认命令
    启动之后会退出
        - "/bin/sh"
        - "-c"
        - "sleep 7200"
      volumes:
      - name: html
        emptyDir: {} 
    
    当pod数据卷被pod中的多个容器挂载时,一个容器中产生的数据,会被共享到pod中其他容器挂载在目录中。。。,如下图2
    

    图2:

    kubectl apply -f pod-vol-demo.yaml 
    
    apiVersion: v1
    kind: Pod
    metadata:
     name: pod-demo
     namespace: default
     labels: # <map[string]string> 映射类型,类似于json
        app: myapp
        tier: frontend
     annotations:
       master01/created-by: cluster admin
    spec:
      containers:
      - name: myapp
        image: nginx:1.20 # 使用镜像启动默认命令
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html/
      - name: busybox
        image: busybox:latest  # sidecar 为主容器提供主页文件
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: html
          mountPath: /data/
        command: # ["/bin/sh","-c","sleep 3600"] # 这里使用自定义的命令,而没使用镜像启动默认的命令,就是为了防止默认命令
    启动之后会退出
        - "/bin/sh"
        - "-c"
        - "while true;do echo $(date) >> /data/index.html;sleep 2;done"                
      volumes:
      - name: html
        emptyDir: {}
    
    

    2.hostpath

    hostPath Volume为Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的高速文件系统进行存储;hostpath(宿主机路径):节点级别的存储卷,在pod被删除,这个存储卷还是存在的,不会被删除,所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。
    
    查看hostpath存储卷的使用
    kubectl explain pods.spec.volumes.hostPath
    
    cat pod_volume_host.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-hostpath
    spec:
      containers:
      - image: nginx
        name: test-nginx
        volumeMounts:
        - mountPath: /test-nginx
          name: test-volume
      - image: tomcat
        name: test-tomcat
        volumeMounts:
        - mountPath: /test-tomcat
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /data1
          type: DirectoryOrCreate
    
    kubectl apply -f pod_volume_host.yaml 
    
    
    如果pod处于running状态,那么可以执行如下步骤测试存储卷是否可以被正常使用
    kubectl exec -it test-hostpath -c test-nginx -- /bin/bash 登录到nginx容器
    看是否存在目录 /test-nginx/,如果存在,说明存储卷挂载成功
    
    kubectl exec -it test-hostpath -c test-tomcat-- /bin/bash 登录到tomcat容器
    看是否存在目录 /test-tomcat/,如果存在,说明存储卷挂载成功
    
    看pod被调度到哪个节点,通过kubectl get pods -o wide查看,如下图1,调度到node1
     
    登录到node1上,查看是否有/data1这个目录,如果有,属于正常创建,那么在这个目录下生成一些文件,可以在刚才创建的pod下面的test-nginx和test-tomcat这两个容器里面看到这些文件,说明pod里面的容器挂载同一个存储卷时,它们是共享的
    

    图1:

    hostpath存储卷缺点:

    单节点
    pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失
    nfs,cephfs,glusterfs,pvc,storageclass
    
    

    参考官网:https://kubernetes.io/docs/concepts/storage/volumes/#hostpath

    3.nfs存储卷

    1.创建nfs存储

    以master1节点作为nfs服务端:
    在master1上操作:
    安装nfs:
    yum install nfs-utils -y
    创建共享目录:
    mkdir /data/volumes -pv 
    cat /etc/exports
    /data/volumes 192.168.1.0/24(rw,no_root_squash) 
    
    exportfs -arv
    systemctl start nfs
    
    在node1上手动挂载试试:
    yum install nfs-utils -y
    mount -t nfs 192.168.1.133:/data/volumes /mnt
    df -h 可以看到已经挂载了
    手动卸载:
    umount /mnt
    

    2.再回到master1节点:

    再回到master1节点:
    kubectl explain pod.spec.volumes.nfs
    https://kubernetes.io/docs/concepts/storage/volumes#nfs
    
    cat pod-nfs.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
     name: test-nfs-volume
    spec:
     containers:
     - name: test-nfs
       image: nginx
       ports:
       - containerPort: 80
         protocol: TCP
       volumeMounts:
       - name: nfs-volumes
         mountPath: /usr/share/nginx/html
     volumes:
     - name: nfs-volumes
       nfs:
        path: /data/volumes
        server: 192.168.1.133
    
    
    
    path: /data/volumes #nfs的共享目录
    server: master1 #nfs服务器地址
    默认是读写挂载的
    kubectl apply -f pod-nfs.yaml 
    kubectl get pods -o wide 显示如下:
    
    

    刚才创建的pod在node1节点上
    cd /data/volumes
    创建一个共享的文件
    cat index.html
    <h1> NFS 192.168.1.133<h1>
    curl 10.244.2.46
    显示如下:
     
    上面说明挂载nfs存储卷成功了,nfs支持多个客户端挂载,可以在多创建几个pod,挂载同一个nfs服务器;但是nfs如果宕机了,数据也就丢失了,所以需要使用分布式存储,常见的分布式存储有glusterfs和cephfs
    
    作业:自己在上面pod里,在创建一个容器。这个容器也是使用nfs类型的volume,但是这个volume我们要求大家自己在nfs服务端创建一个共享目录,生成一个volume,然后被新的容器挂载使用。
    

    练习:

    apiVersion: v1
    kind: Pod
    metadata:
     name: test-nfs-volume
    spec:
     containers:
     - name: test-nfs
       image: nginx
       ports:
       - containerPort: 80
         protocol: TCP
       volumeMounts:
       - name: nfs-volumes
         mountPath: /usr/share/nginx/html
     - name: test-tomcat
       image: tomcat
       ports:
       - containerPort: 8080
         protocol: TCP
       volumeMounts:
       - name: nfs-tomcat
         mountPath: /tomcat
     volumes:
     - name: nfs-volumes
       nfs:
        path: /data/volumes
        server: 192.168.1.133
     - name: nfs-tomcat
       nfs:
         path: /data/volumes1
         server: 192.168.1.133
    

    4.pvc存储卷

    1.pv

    PersistentVolume(PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统
    

    2.pvc

    PersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。 Pod可以请求特定级别的资源(CPU和内存)。 pvc在申请pv的时候也可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。
    

    3.pv和pvc

    accessModes:kubectl explain.pvc.spec

    不同的存储卷支持的访问访问模式:

    3.1 pv和pvc的生命周期
    PV是群集中的资源。 PVC是对这些资源的请求,并且还充当对资源的索赔检查。 PV和PVC之间的相互作用遵循以下生命周期:
    (1)pv的供应方式
    可以通过两种方式配置PV:静态或动态。
    静态的
    集群管理员创建了许多PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API中,可供使用。
    动态的
    当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,群集可能会尝试为PVC专门动态配置卷。此配置基于StorageClasses:PVC必须请求存储类,管理员必须已创建并配置该类,以便进行动态配置。
    (2)绑定
    用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态
    (3)使用
    a)需要找一个存储服务器,把它划分成多个存储空间;
    b)k8s管理员可以把这些存储空间定义成多个pv;
    c)在pod中使用pvc类型的存储卷之前需要先创建pvc,通过定义需要使用的pv的大小和对应的访问模式,找到合适的pv;
    d)pvc被创建之后,就可以当成存储卷来使用了,我们在定义pod时就可以使用这个pvc的存储卷
    e)pvc和pv它们是一一对应的关系,pv如果被pvc绑定了,就不能被其他pvc使用了;
    f)我们在创建pvc的时候,应该确保和底下的pv能绑定,如果没有合适的pv,那么pvc就会处于pending状态。
    (4)回收策略
    当我们创建pod时如果使用pvc做为存储卷,那么它会和pv绑定,当删除pod,pvc和pv绑定就会解除,解除之后和pvc绑定的pv卷里的数据需要怎么处理,目前,卷可以保留,回收或删除
    Retain
    Recycle (不推荐使用,1.15可能被废弃了)
    Delete
    
    •	Retain
    当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用,里面的数据还是存在的,当我们下次再使用的时候,数据还是存在的,这个是默认的回收策略,管理员能够通过下面的步骤手工回收存储卷:
    1)删除PV:在PV被删除后,在外部设施中相关的存储资产仍然还在;
    2)手工删除遗留在外部存储中的数据;
    3)手工删除存储资产,如果需要重用这些存储资产,则需要创建新的PV。
    
    
    •	Delete
    删除pvc时即会从Kubernetes中移除PV,也会从相关的外部设施中删除存储资产,例如AWS EBS, 或者Cinder存储卷。
    
    3.2 创建pv
    (1)在nfs中导出多个存储目录,在nfs服务器上操作(这里是k8s的master1节点)
    mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -p 
    cat /etc/exports
    /data/volume_test/v1 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v2 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v3 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v4 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v5 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v6 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v7 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v8 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v9 192.168.0.0/24(rw,no_root_squash)
    /data/volume_test/v10 192.168.0.0/24(rw,no_root_squash)
    exportfs -arv 使配置文件生效
    service nfs restart
    
    (2)把上面的存储目录做成pv
    kubectl explain pv 查看pv的创建方法
    kubectl explain pv.spec.nfs 查看怎么把nfs定义成pv
    
    参考:https://kubernetes.io/docs/concepts/storage/persistent-volumes
    
    (3)创建pv(pv是集群级别的资源,不需要定义namespace)
    cat pv.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v1
    spec:
      capacity:
        storage: 1Gi
      accessModes: ["ReadWriteOnce"]
      nfs:
        path: /data/volume_test/v1
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v2
    spec:
      capacity:
          storage: 2Gi
      accessModes: ["ReadWriteMany"]
      nfs:
        path: /data/volume_test/v2
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v3
    spec:
      capacity:
          storage: 3Gi
      accessModes: ["ReadOnlyMany"]
      nfs:
        path: /data/volume_test/v3
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v4
    spec:
      capacity:
          storage: 4Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v4
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v5
    spec:
      capacity:
          storage: 5Gi #pv的存储空间容量
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v5 #把nfs的存储空间创建成pv
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v6
    spec:
      capacity:
          storage: 6Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v6
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v7
    spec:
      capacity:
          storage: 7Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v7
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v8
    spec:
      capacity:
          storage: 8Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v8
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v9
    spec:
      capacity:
          storage: 9Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v9
        server: master1
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v10
    spec:
      capacity:     #pv的存储空间容量
          storage: 10Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volume_test/v10  #把nfs的存储空间创建成pv
        server: master1
    ---
    kubectl  apply  -f pv.yaml
    kubectl   get pv   显示如下:
    
    (4)创建pvc
    cat pvc.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes: ["ReadWriteMany"]
      resources: # 申请PV资源时,PV满足的最小值
        requests:
          storage: 2Gi
    (5)创建pod
    cat pod-pvc.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-pvc
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim:
          claimName: my-pvc
    kubectl  apply -f pod-pvc.yaml
    
    注:
    (1)我们每次创建pvc的时候,需要事先有划分好的pv,可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的
    (2)pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失.
    

    5.StorageClass

    详见个人本地文档

    6.configmap和 secret

    配置容器化应用的方式:
    1.自定义命令行参数;
    	args:[]
    2.把配置文件直接添加进镜像;
    3.环境变量
      (1) Cloud Native的应用程序一般可直接通过环境变量加载配置;
      (2) 通过entrypoint脚本来预处理变量为配置文件中的配置信息;
    4.存储卷:直接挂载配置文件到容器目录中
    5.configmap
    
    # 1.什么是Configmap?
    Configmap是k8s中的资源对象,用于保存非机密性的配置的,数据可以用key/value键值对的形式保存,也可通过文件的形式保存。
    # 2.Configmap能解决哪些问题?
    我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s中引入了Configmap资源对象,可以当成volume挂载到pod中,实现统一的配置管理。
    
    

    1、Configmap是k8s中的资源, 相当于配置文件,可以有一个或者多个Configmap;
    2、Configmap可以做成Volume,k8s pod启动之后,通过 volume 形式映射到容器内部指定目录上;
    3、容器中应用程序按照原有方式读取容器特定目录上的配置文件。
    4、在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
    
    # 3.Configmap应用场景
    (1)、使用k8s部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap可以将配置信息和docker镜像解耦,以便实现镜像的可移植性和可复用性,因为一个configMap其实就是一系列配置信息的集合,可直接注入到Pod中给容器使用。configmap注入方式有两种,一种将configMap做为存储卷,一种是将configMap通过env中configMapKeyRef注入到容器中。
    (2)、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用configmap可以友好的进行配置共享。
    
    # 4. 局限性
    ConfigMap在设计上不是用来保存大量数据的。在ConfigMap中保存的数据不可超过1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
    
    

    Configmap创建方法

    1.命令行直接创建
    直接在命令行中指定configmap参数创建,通过--from-literal指定参数
    kubectl create configmap tomcat-config --from-literal=tomcat_port=8080 --from-literal=server_name=myapp.tomcat.com
    kubectl describe configmap tomcat-config
    '''
    Name:         tomcat-config
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    Data
    ====
    server_name:
    ----
    myapp.tomcat.com
    tomcat_port:
    ----
    8080
    Events:  <none>
    '''
    
    2.通过文件创建
    通过指定文件创建一个configmap,--from-file=<文件>
    
    vim nginx.conf
    server {
      server_name www.nginx.com;
      listen 80;
      root /home/nginx/www/
    }
    #定义一个key是www,值是nginx.conf中的内容
    kubectl create configmap www-nginx --from-file=www=./nginx.conf
    kubectl describe configmap www-nginx
    '''
    Name:         www-nginx
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Data
    ====
    www:
    ----
    server {
      server_name www.nginx.com;
      listen 80;
      root /home/nginx/www/
    }
    '''*
    
    3.指定目录创建configmap
    mkdir test-a
    cd test-a/
    cat my-server.cnf 
    '''
    server-id=1
    '''
    cat my-slave.cnf 
    '''
    server-id=2
    '''
    #指定目录创建configmap
    kubectl create configmap mysql-config --from-file=/root/test-a/
    #查看configmap详细信息
    kubectl describe configmap mysql-config
    '''
    Name:         mysql-config
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    Data
    ====
    my-server.cnf:
    ----
    server-id=1
    my-slave.cnf:
    ----
    server-id=2
    Events:  <none>
    '''
    
    
    
    4编写configmap资源清单YAML文件
    cat mysql-configmap.yaml 
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql
      labels:
        app: mysql
    data:
      master.cnf: |
        [mysqld]
        log-bin
        log_bin_trust_function_creators=1
        lower_case_table_names=1
      slave.cnf: |
        [mysqld]
        super-read-only
        log_bin_trust_function_creators=1
    

    使用Configmap

    1.通过环境变量引入:使用configMapKeyRef
    #创建一个存储mysql配置的configmap
    kubectl apply -f mysql-configmap.yaml
    cat mysql-configmap.yaml 
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql
      labels:
        app: mysql
    data:
        log: "1"
        lower: "1"
        
        
    #创建pod,引用Configmap中的内容
    kubectl apply -f mysql-pod.yaml
    cat mysql-pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: mysql-pod
    spec:
      containers:
      - name: mysql
        image: busybox
        command: [ "/bin/sh", "-c", "sleep 3600" ]
        env:
        - name: log_bin   #定义环境变量log_bin
          valueFrom: 
            configMapKeyRef:
              name: mysql     #指定configmap的名字
              key: log #指定configmap中的key
        - name: lower   #定义环境变量lower
          valueFrom:
            configMapKeyRef:
              name: mysql
              key: lower
      restartPolicy: Never
    
    
    kubectl exec -it mysql-pod -- /bin/sh
    / # printenv 
    log_bin=1
    lower=1
    
    2.通过环境变量引入:使用envfrom
    kubectl apply -f mysql-pod-envfrom.yaml
    cat mysql-pod-envfrom.yaml 
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: mysql-pod-envfrom
    spec:
      containers:
      - name: mysql
        image: busybox
        imagePullPolicy: IfNotPresent
        command: [ "/bin/sh", "-c", "sleep 3600" ]
        envFrom: 
        - configMapRef:
           name: mysql     #指定configmap的名字
      restartPolicy: Never
    
    kubectl exec -it mysql-pod-envfrom -- /bin/sh
    / # printenv
    lower=1
    log=1
    
    
    3.把configmap做成volume,挂载到pod
    kubectl apply -f mysql-configmap.yaml
    cat mysql-configmap.yaml 
    
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql
      labels:
        app: mysql
    data:
        log: "1"
        lower: "1"
        my.cnf: |
          [mysqld]
          User1=root1
    
    
    kubectl apply -f mysql-pod-volume.yaml
    cat mysql-pod-volume.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: mysql-pod-volume
    spec:
      containers:
      - name: mysql
        image: busybox
        command: [ "/bin/sh","-c","sleep 3600" ]
        volumeMounts:
        - name: mysql-config
          mountPath: /tmp/config
      volumes:
      - name: mysql-config
        configMap:
          name: mysql
      restartPolicy: Never
    
    
     kubectl exec -it mysql-pod-volume -- /bin/sh
     / # cd /tmp/config/
    /tmp/config # ls
    log    lower   my.cnf
    

    Configmap热更新

    kubectl edit configmap mysql
    把logs: “1”变成log: “2”
    保存退出
    

    kubectl exec -it mysql-pod-volume -- /bin/sh
    
    / # cat /tmp/config/log 
    2
    #发现log值变成了2,更新生效了
    注意:
    更新 ConfigMap 后:
    使用该 ConfigMap 挂载的 Env 不会同步更新
    
    使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
    

    secret

    configMap保存数据为明文方式,而对于敏感数据需要加密存放,就要使用secret。保存在secret中的数据也是key/value键值对,只显示键,不显示值,即使显示值,值也是base64编码的加密数据。
    比如:1.私钥和证书需要存放在secret当中;2.连接MySQL的密码可以保存在secret中;3.连接私有镜像的仓库的账户和密码可以使用secret保存。
    kubectl create secret --help 
    # secret 的三种类型:
    docker-registry     Create a secret for use with a Docker registry
    generic             Create a secret from a local file, directory, or literal value
    tls                 Create a TLS secret
    
    generic:通用的,一般保存密码之类的
    tls:保存私钥和类型
    docker-registry:保存docker-registry的认证信息
    	docker运行一个镜像,首先是检查当前节点有没有,如果没有就要去仓库中托,如果我们用的是私有仓库,则必须要输入账号密码才能够访问,那么仓库账号和密码放在哪呢?
        kubectl explain pod.spec
        	imagePullSecrets	<[]Object>  # 配置docker(或kubelet)拉取私有仓库镜像的secret(使用私有仓库账号和密码创建)的对象列表
    	kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL # 给私有仓库创建secret
    '''
    Create a secret based on a file, directory, or specified literal value.
    
     A single secret may package one or more key/value pairs.
    
     When creating a secret based on a file, the key will default to the basename of the file, and the
    value will default to the file content. If the basename is an invalid key or you wish to chose your
    own, you may specify an alternate key.
    
     When creating a secret based on a directory, each file whose basename is a valid key in the
    directory will be packaged into the secret. Any directory entries except regular files are ignored
    (e.g. subdirectories, symlinks, devices, pipes, etc).
    
    Examples:
      # Create a new secret named my-secret with keys for each file in folder bar
      kubectl create secret generic my-secret --from-file=path/to/bar
      
      # Create a new secret named my-secret with specified keys instead of names on disk
      kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa
    --from-file=ssh-publickey=path/to/id_rsa.pub
      
      # Create a new secret named my-secret with key1=supersecret and key2=topsecret
      kubectl create secret generic my-secret --from-literal=key1=supersecret
    --from-literal=key2=topsecret
      
      # Create a new secret named my-secret using a combination of a file and a literal
      kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa
    --from-literal=passphrase=topsecret
      
      # Create a new secret named my-secret from an env file
      kubectl create secret generic my-secret --from-env-file=path/to/bar.env
    '''
    kubectl create secret generic mysql-root-password --from-literal=password=MyP@ss123
    
    [root@master01 volume]# kubectl get secret
    NAME                  TYPE                                  DATA   AGE
    default-token-tqx6z   kubernetes.io/service-account-token   3      26d
    mysql-root-password   Opaque                                1      26s # Opaque 模糊类型
    
    [root@master01 volume]# kubectl describe secret mysql-root-password
    Name:         mysql-root-password
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Type:  Opaque
    
    Data
    ====
    password:  9 bytes  # 只显示密码是9个字节,明文密码被隐藏了
    
    kubectl get secret mysql-root-password -o yaml
    Name:         mysql-root-password
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Type:  Opaque
    
    Data
    ====
    password:  9 bytes
    [root@master01 volume]# kubectl get secret mysql-root-password -o yaml
    apiVersion: v1
    data:
      password: TXlQQHNzMTIz  # 可以查看到加密后的密码,但是这种加密是对称加密,密码可以被解码。
    kind: Secret
    metadata:
      creationTimestamp: "2021-12-21T02:34:48Z"
      name: mysql-root-password
      namespace: default
      resourceVersion: "1668872"
      uid: 25194f0c-5841-4541-b9b6-3112fa39567b
    type: Opaque
    
    echo TXlQQHNzMTIz | base64 -d # 如下图
    

    在容器中引用secret:

    kubectl apply -f pod-secret-1.yaml
    cat pod-secret-1.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-secret-1
      namespace: default
      labels:
        app: myapp
        tier: frontend
      annotations:
        zhang.com/created-by: "cluster admin"
    spec: 
      containers:
      - name: myapp
        image: nginx:1.20
        ports:
        - name: http
          containerPort: 80
        env: 
        - name: MYSQP_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-root-password
              key: password
    
    kubectl exec -it pod-secret-1 -- /bin/sh
    查看容器中的环境变量:
      printenv # 如下图
    

  • 相关阅读:
    animation循环滚动
    <canvas>简单学习
    月末总结
    回顾-总结(2)
    初识正则
    学习中小项目遇到事
    在炎热的夏天学习以提高效率
    前端存储之cookie、localStorage
    总结(1)
    jQuery
  • 原文地址:https://www.cnblogs.com/zccoming/p/15728634.html
Copyright © 2020-2023  润新知