容器卷挂载的秘密

什么是容器卷

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

容器挂载原理


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

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

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

  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 #此路径需要实现创建
  • 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”
)

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

  • 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"

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

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

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

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

参考文献

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命名空间讲解)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值