在没有特权的情况下在 K8S pod 中挂载文件系统

在没有特权的情况下在 K8S pod 中挂载文件系统

我有一个 K8S 部署,将卷作为原始块加载(通过volumeDevices):

apiVersion: apps/v1
kind: Deployment
...
spec:
  replicas: 1
...
  containers:
  - name: somepod
    image: ubuntu:latest
    command: ["sh","-c", "--"]
    args: ["mount /dev/block /data && while true; do sleep 1000000; done"]
    securityContext:
      privileged: true
    volumeDevices:
    - devicePath: /dev/block
      name: vol
  volumes:
  - name: vol
    persistentVolumeClaim:
      claimName: vol

这按预期工作。

我想要实现的目标:

我想在容器中挂载 /dev/block ,而不必授予它特权访问权限(因此,无需 root)。

我可以完全控制基础映像,其默认用户是 1001,已添加到非 root 组。

当 k8s 将 /dev/block 添加到容器时,据我所知,它会为其分配一个随机组,例如 993:

brw-rw----. 1 root  993 259,  16 Dec 15 09:00 block

据我了解,这是我无法控制的(例如,我无法告诉 k8s 将其安装在已知组下)。

我尝试过的事情:

  • 将文件系统格式化为 ext4,添加 /etc/fstab 行/dev/block /data ext4 user,uid=1001,auto 0 0
  • 添加securityContext: fsGroup:1001
  • 将文件系统格式化为 ntfs 添加 /etc/fstab 行 /dev/block /data ntfs user,uid=1001,auto 0 0
  • pmount在容器中安装和使用。失败,因为我的用户不属于 /dev/block 组
  • 使用 postStart 挂钩(无用,因为它共享主运行时的相同权限)
  • 使用特权 initContainer 将卷从 /dev/block 挂载到emptyDir /data。根据我的理解,initContainer 和容器应该共享emptyDir,但由于数据存在于已安装的卷上,因此这是行不通的。

我还没有尝试过的事情:

一个可能的失败点可能是我可能不正确的 /etc/fstab 设置,因为每当我尝试以用户身份挂载时,无论如何,我仍然会遇到 /dev/block 上的权限问题。

为什么我使用块卷:

我正在运行 EKS,并且希望在同一可用区的多个 Pod 之间共享“ReadWriteMany”中的数据。我研究过在 io2 中使用 EFS 卷而不是 EBS,但我有价格/延迟问题。

相关问题:

答案1

最终对我来说的解决方案是使用 AWS EC2 函数(由 Karpenter 导出),该函数允许为节点配置给定卷快照的副本。

我的 Karpenter 的 ec2 NodeClass 看起来像:

apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
  name: test
spec:
  amiFamily: AL2
  ...
  blockDeviceMappings:
  - deviceName: /dev/xvda
    ebs:
      deleteOnTermination: true
      volumeSize: 100Gi
      volumeType: gp2
  - deviceName: /dev/xvdc
    ebs:
      deleteOnTermination: true
      snapshotID: snap-ID-NUMBER
      volumeSize: 40Gi
      volumeType: gp2
 ...
  userData: |-
    #!/bin/bash
    set -x
    ...
    mkdir -p /home/ec2-user/data/
    mount -o defaults /dev/nvme2n1 /home/ec2-user/data/
    ...

这里进行了一些尝试和错误,但主要的收获是:

  • AWS 提供从我提供的给定 snapshotID 复制的磁盘;
  • 它被添加到 /dev/xvdc 下;在我的 AMI 中,这等于 /dev/nvme2n1,尽管不能保证所有 AMIS/Arch 都如此
  • 我将文件系统挂载在 EC2 的用户数据中。

此外,为了确保数据更新,我运行 aws s3 同步作为 userData 的一部分。无需 Karpenter,只需使用 AWS EC2 的 api 即可复制相同的行为。

相关内容