• 容器卷挂载的秘密


    什么是容器卷

    数据卷 (Data Volumes )是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于 Linux 中的 mount 行为。

    容器挂载原理


    containerd创建的容器里的数据存储在下面的目录中

    [root@master01 httpbin]#ls /run/containerd/io.containerd.runtime.v2.task/k8s.io/{podid}/rootfs/
    
    • 1

    所以我们可以这样思考一下

    1. docker挂载也使用了命名空间的机制,一个容器(也就是一个进程)单独记录一套挂载信息。
    2. 每个容器中的数据目录都存储在上面的目录中。我们进入容器ls 获取的信息就是上面的信息,只是在进入容器的时候使用了CLONE_NEWNS机制也就是chroot 功能。
    3. 所以容器挂载卷,使用了两个机制,第一 CLONE_NEWNS 命名空间机制,让你以为你是在一台新的系统上,其实是原始系统的一个目录中,第二使用挂载命名空间,这样可以使这个新的系统只能看到它自己的挂载信息。
    4. 这样来完成容器挂载的操作。
    5. 对于k8s来说,远程挂载也可以实现,所以可以使用类似于AWS等存储系统。

    k8s中容器挂载的方式

    让我们先重温一下,k8s如何将volumes挂载到容器内部,下面是一段nginx,静态文件挂载到node上的yaml配置。

    spec: #期望Pod实现的功能(即在pod中部署)
      containers: #生成container,与docker中的container是同一种
      - name: ssx-nginx-c
        image: nginx:latest #使用镜像nginx: 创建container,该container默认80端口可访问
        ports:
        - containerPort: 80  # 开启本容器的80端口可访问
        volumeMounts:  #挂载持久存储卷
        - name: volume #挂载设备的名字,与volumes[*].name 需要对应 
        mountPath: /usr/share/nginx/html #挂载到容器的某个路径下  
      volumes:
      - name: volume #和上面保持一致 这是本地的文件路径,上面是容器内部的路径
        hostPath:
        path: /opt/web/dist #此路径需要实现创建
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • volumeMounts: 下可配置 指定挂载卷挂载到容器内部指定目录中。
    • volumes: 配置了当前挂载卷的类型,名称,以及挂载类型的一些属性等

    对于存储来说,我们需要确定使用那些挂载类型可以满足当前容器的需求,所以我们需要对挂载类型进行一一列举分析。

    挂载类型

    下面只列举几个常用的类型,至于全部支持的类型请查看源码staging/src/k8s.io/api/core/v1/types.go:VolumeSource{}

    hostPath

    直接挂载到node节点上的目录中
    容器删除时,挂载的内容不会消失

    type HostPathVolumeSource struct {
        // node路径
        Path string `json:"path" protobuf:"bytes,1,opt,name=path"`
        // 挂载类型
        Type *HostPathType `json:"type,omitempty" protobuf:"bytes,2,opt,name=type"`
    }
    // +enum
    type HostPathType string
    const (
        //对于向后兼容,如果未设置,则将其留空
        HostPathUnset HostPathType=“”
        //如果给定路径上不存在任何内容,将在那里创建一个空目录
        //如文件模式0755所需,具有与Kubelet相同的组和所有权。
        HostPathDirectoryOrCreate HostPathType=“DirectoryOr创建”
        //给定路径上必须存在目录
        HostPathDirectory HostPathType=“Directory”
        //如果给定路径上不存在任何内容,将在那里创建一个空文件
        //如文件模式0644所需,具有与Kubelet相同的组和所有权。
        HostPathFileOrCreate HostPathType=“FileOrCreate”
        //文件必须存在于给定路径
        HostPathFile HostPathType=“File”
        //给定路径上必须存在UNIX套接字
        HostPathSocket HostPathType=“Socket”
        //给定路径上必须存在字符设备
        HostPathCharDev HostPathType=“CharDevice”
        //给定路径上必须存在块设备
        HostPathBlockDev HostPathType=“BlockDevice”
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    使用此类卷时要小心,因为:

    • HostPaths 可以公开特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
    • 由于节点上的文件不同,具有相同配置(例如从 PodTemplate 创建)的 Pod 在不同节点上的行为可能不同
    • 在底层主机上创建的文件或目录只能由 root 写入。您要么需要在 特权容器中以 root 身份运行您的进程,要么修改主机上的文件权限以便能够写入hostPath卷

    emptyDir

    secret

    spec:
      volumes:
      - name: secret-volume
        secret:
        secretName: test-db-secret
      containers:
      - name: db-client-container
        image: myClientImage
        volumeMounts:
        - name: secret-volume
          readOnly: true
          mountPath: "/etc/secret-volume"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    secret是指定目录,而里面的key就是文件名,value是文件内容,configmap也一致。

    configmap

    spec:
      containers:
        - name: test
          image: busybox:1.28
          volumeMounts:
            - name: config-vol
              mountPath: /etc/config
      volumes:
        - name: config-vol
          configMap:
            name: log-config
            items:
              - key: log_level
                path: log_level
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    cephfs

    apiVersion: v1
    kind: Pod
    metadata:
      name: cephfs
    spec:
      containers:
      - name: cephfs-rw
        image: kubernetes/pause
        volumeMounts:
        - mountPath: "/mnt/cephfs"
          name: cephfs
      volumes:
      - name: cephfs
        cephfs:
          monitors:
          - 10.16.154.78:6789
          - 10.16.154.82:6789
          - 10.16.154.83:6789
          # by default the path is /, but you can override and mount a specific path of the filesystem by using the path attribute
          # path: /some/path/in/side/cephfs
          user: admin
          secretFile: "/etc/ceph/admin.secret"
          readOnly: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    nfs

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd
    spec:
      containers:
      - image: registry.k8s.io/test-webserver
        name: test-container
        volumeMounts:
        - mountPath: /my-nfs-data
          name: test-volume
      volumes:
      - name: test-volume
        nfs:
          server: my-nfs-server.example.com
          path: /my-nfs-volume
          readOnly: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    PVC

    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
            readOnly: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    参考文献

    https://kubernetes.io/docs/concepts/storage/volumes/ (讲解volumes每个类型的用途)
    https://github.com/kubernetes/examples/blob/master/volumes/cephfs/cephfs.yaml (ceph例子)
    https://blog.csdn.net/hwruirui/article/details/119566635(pid命名空间讲解)

  • 相关阅读:
    【SpringBoot】请求参数处理 —— Rest使用与原理
    Nacos服务注册中心
    MySQL | 行锁——记录锁、间隙锁 、临键锁、插入意向锁
    低能量电子束曝光技术
    day36
    Java Web 7 JavaScript 7.5 BOM
    关于iframe的页面加载出现滚动条的问题
    Docker build创建指定容器镜像
    Vue中事件修饰符与键盘事件
    Web 安全:PKI 扫盲
  • 原文地址:https://blog.csdn.net/a1023934860/article/details/128039746