zoukankan      html  css  js  c++  java
  • K8S 的 Volume

    K8S 有很多 Volume 类型

    • awsElasticBlockStore
    • azureDisk
    • azureFile
    • cephfs
    • cinder
    • configMap
    • csi
    • downwardAPI
    • emptyDir
    • fc (fibre channel)
    • flexVolume
    • flocker
    • gcePersistentDisk
    • gitRepo (deprecated)
    • glusterfs
    • hostPath
    • iscsi
    • local
    • nfs
    • persistentVolumeClaim
    • projected
    • portworxVolume
    • quobyte
    • rbd
    • scaleIO
    • secret
    • storageos
    • vsphereVolume

    详细信息可以查看官网
    https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

    这里只介绍几种:emptyDir,local,hostPath,nfs,secret,configMap

    emptyDir

    初始化为空目录,只在 Pod 运行时存在,当 Pod 停止或死掉后,目录下的所有数据都会被删除(如果只是 Container 死掉数据不会被删除),可以被同一个 Pod 下的不同 Container 使用

    emptyDir 主要用于某些应用程序无需永久保存的临时目录,在多个容器之间共享数据等场景

    下面是一个简单的例子,将 emptyDir 的 volume 给 mount 到 /cache 目录

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
    

    缺省情况下,emptyDir 是在 Pod 运行的主机的文件系统上创建临时目录

    此外也可以通过将 emptyDir.medium 设定为 "Memory" 从而使用内存作为文件系统,这种情况速度会比较快,但空间会比较小,而且如果主机重启数据会丢失

    local

    使 Volume 和 Pod 被分配到同一个 Node,实现数据的本地化,适合一些对读写磁盘数据要求比较高的,比如数据库

    这种做法的风险是 Volume 和 Pod 都被绑定到固定的一个 Node (暂时不支持动态配置),一但这个 Node 出问题,会影响 Volume 和 Pod,可用性会降低

    先创建一个 StorageClass

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: local-storage
    provisioner: kubernetes.io/no-provisioner
    volumeBindingMode: WaitForFirstConsumer
    

    这里 WaitForFirstConsumer 表示不要立即绑定 Volume,而是等到 Pod 调度的时候再绑定

    创建 PV

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: example-pv
    spec:
      capacity:
        storage: 100Gi
      volumeMode: Filesystem
      accessModes:
      - ReadWriteOnce
      persistentVolumeReclaimPolicy: Delete
      storageClassName: local-storage
      local:
        path: /mnt/disks/ssd1
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
              - example-node
    

    这个 PV 使用 example-node 节点的 /mnt/disks/ssd1 目录,并且指定 StorageClass 为前面创建的 local-storage

    创建 PVC

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: example-pvc
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
      storageClassName: local-storage
    

    通过指定 storageClass 为前面创建的 local-storage,这样会等到 Pod 调度的时候再绑定 PVC 和 PV,确保能找到合适的 PV 使得 Volume 和 Pod 在同一个 Node 上

    创建 Pod

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - cache-volume
        persistentVolumeClaim:
          claimName: example-pvc
    

    等这个 Pod 创建的时候 example-pvc 再去绑定合适的 pv 使得 Pod 和 Volume 跑在同一个 Node

    hostPath

    把 Volume 挂到 host 主机的路径,这和 local 很像,但有区别

    host 模式下 Pod 的运行节点是随机的,假设 Pod 第一次起来的时候是在 Node-A,这时会在 Node-A 创建目录挂到 Pod,如果后来 Pod crash 然后重启,可能会被分配到 Node-B,这时会在 Node-B 创建目录挂到 Pod,但是之前保存在 Node-A 的数据就丢失了

    local 模式下 Pod 和创建的目录一直是在同一台主机上

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /test-pd
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          # directory location on host
          path: /data
          # this field is optional
          type: Directory
    

    适用场景的例子,比如如果需要读取主机的系统路径 /sys,读取主机的 docker 信息 /var/lib/docker,这些都是固定路径,每台机都有,而且只关心本机的信息

    nfs

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: k8s.gcr.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /test-pd
          name: test-volume
      volumes:
      - name: test-volume
        nfs:
          path: /data
          server: 192.168.1.10
    

    或者

    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs
    spec:
      capacity:
        storage: 1Mi
      accessModes:
        - ReadWriteMany
      nfs:
        server: nfs-server.default.svc.cluster.local
        path: "/data/volumes"
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nfs
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: ""
      resources:
        requests:
          storage: 1Mi
    ---
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: nfs-busybox
    spec:
      replicas: 2
      selector:
        name: nfs-busybox
      template:
        metadata:
          labels:
            name: nfs-busybox
        spec:
          containers:
          - image: busybox
            command:
              - sh
              - -c
              - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'
            imagePullPolicy: IfNotPresent
            name: busybox
            volumeMounts:
              # name must match the volume name below
              - name: nfs
                mountPath: "/mnt"
          volumes:
          - name: nfs
            persistentVolumeClaim:
              claimName: nfs
    

    最终相当于执行

    mount -t nfs nfs-server.default.svc.cluster.local:/data/volumes /mnt
    

    注意需要保证目标主机的 nfs 是配置好的,相应的路径是可以 mount 的

    secret

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    data:
      username: YWRtaW4=
      password: MWYyZDFlMmU2N2Rm
    type: Opaque
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: redis
        volumeMounts:
        - name: foo
          mountPath: "/etc/foo"
          readOnly: true
      volumes:
      - name: foo
        secret:
          secretName: mysecret
    

    secret 里面定义的 username 和 password 是 base64 编码的
    可以看到启动的容器里面的 /etc/foo 目录下会有两个文件,名字分别是 username 和 password,里面的内容被自动按 base64 解码了

    secret 安全性

    • 实际上 secret 通过 kubectl get secret mysecret -o yaml 同样可以看到 username 和 password 的值,当然这应该可以配置权限,使得只有相应的帐号可以查询使用
    • secret 是写在容器的内存文件系统而不是磁盘文件系统,不会落盘增加安全性
    • secret 的内容通过 base64 编码存在 etcd 中,挂到容器时会被自动解码为明文

    可以看到实际上比起 ConfigMap 安全性似乎没多大提升,base64 实际上很容易解码,或许以后会改进

    真正要求安全性的话可以考虑用 Vault

    ConfigMap

    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: test-cfg
    data:
      redis_host: "192.168.1.100"
      redis_port: "6379"
      config.json: |-
        {
            "Postgres": {
                "Host": "192.168.1.200",
                "Port": "5432"
            },
            "Kafka": {
                "Host": "192.168.1.10:9092",
                "From": "smallest"
            }
        }
      config.properties: |
        username = admin
        password = admin
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: configmap-pod
    spec:
      containers:
        - name: test
          image: busybox
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config
      volumes:
        - name: config-vol
          configMap:
            name: test-cfg
    

    启动后可以看到 config map 定义的所有配置项都变成 /etc/config 目录下的文件

    也可以只挂载 config map 定义的部分配置项

    apiVersion: v1
    kind: Pod
    metadata:
      name: configmap-pod
    spec:
      containers:
        - name: test
          image: busybox
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config
          env:
            - name: MY_REDIS_HOST
              valueFrom:
                configMapKeyRef:
                  name: test-cfg
                  key: redis_host
      volumes:
        - name: config-vol
          configMap:
            name: test-cfg
            items:
               - key: config.properties
                 path: path/to/my-config.properties
               - key: config.json
                 path: config.json
    

    启动后可以看到 /etc/config 目录下只有 config.json 文件
    而 config.properties 被重命名并放到 /etc/config/path/to/my-config.properties
    另外 redis_host 被作为环境变量配置了进去

    通过 subPath 选取 config map 的配置

    apiVersion: v1
    kind: Pod
    metadata:
      name: configmap-pod
    spec:
      containers:
        - name: test
          image: busybox
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config/my-config.json
              subPath: config.json
      volumes:
        - name: config-vol
          configMap:
            name: test-cfg
    

    这样会自动到 test-cfg 这个 config map 寻找 config.json 配置项,将其重命名并挂载到 /etc/config/my-config.json



  • 相关阅读:
    cocos2d-x C++的do...while(0)另类使用方法
    C++ Virtual详解
    xcode5向APP store上传应用的时候注意点
    IOS7学习之路九(ios7自定义UIAlertView)
    IOS7学习之路八(iOS 禁止屏幕旋转的方法)
    Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy8 cannot be cast to XXX-------动态代理(proxy-target-class属性的意义)
    Maven支持第三方库大全
    EOS page问题
    EOS页面流参数传值问题
    XML中转义字符及使用
  • 原文地址:https://www.cnblogs.com/moonlight-lin/p/13715817.html
Copyright © 2011-2022 走看看