在 AWS 上设置 EFS 存储#
ElasticFileSystem (弹性文件系统) 是一种使用 NFS 协议的分布式文件系统。据传,它是 AWS 在幕后使用的 GlusterFS 分支。
缺点
在 Kubernetes 规范中,持久卷的权限设置问题尚未完全解决。这带来了一些我们稍后将讨论的复杂问题。
根据系统设置方式的不同,聪明的用户或许能够直接连接 EFS 服务器并读取其他用户的文件。
步骤
设置 EFS 卷
在 AWS 中通过 EFS 设置向导进行操作(未来这部分可能会脚本化)。新的 EFS 卷必须与您的集群位于同一个 VPC 中。这一点在创建后可以在 AWS 设置中更改。
接下来,为 NFS 流量创建一个新的安全组(目标是该组中的其他实例)。为节点安全组和主节点安全组添加入站 NFS 流量规则。然后,将 EFS 卷更改为使用该安全组。
为了验证您的 EFS 卷是否正常工作,请通过 ssh 登录到其中一个主节点并切换到 root 用户。然后,按照 EFS 控制台页面上的步骤挂载您的 NFS 卷。DNS 条目可能需要几分钟才能生效。
挂载成功后,将其卸载并断开与管理节点的连接。
配置 Kubernetes 以识别您的 EFS 卷
创建 test_efs.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: efs-persist spec: capacity: storage: 123Gi accessModes: - ReadWriteMany nfs: server: fs-${EFS_ID}.efs.us-east-1.amazonaws.com path: "/"
创建 test_efs_claim.yaml
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: efs-persist spec: storageClassName: "" accessModes: - ReadWriteMany resources: requests: storage: 11Gi
这些文件中的大小具有误导性。EFS 不会强制执行配额。未来我们希望将 EFS PersistentVolume 的大小设置为一个极大值,比如 8EiB,而 PersistentVolumeClaim 设置为 10GB。就目前我们所知,这些大小并不重要。
PersistentVolume (持久卷) 定义了一项可以在容器内执行挂载的服务。PersistentVolumeClaim (持久卷声明) 是一种预留 PersistentVolume 的一部分并可能锁定其访问权限的方式。
storageClassName 设置看起来无伤大雅,但它却至关重要。集群中唯一没有 storage class (存储类) 的 PV 就是我们上面定义的那个。未来我们应该为不同的 PV 打上标签,并在 PVC 中使用标签过滤器,而不是依赖于默认的“”。
我们将配置 jupyterhub 在所有容器中使用同一个“静态”声明。这意味着我们所有的用户都将使用同一个 EFS 共享,它应该能够根据我们的需求进行扩展。
这部分与标准指南略有不同。我们需要在我们的应用程序将要运行的命名空间中创建这些 PV 和 PVC。选择一个命名空间(这将与您稍后在 helm install 步骤中使用的命名空间相同)。
运行以下命令来设置您的命名空间和存储
kubectl create namespace <your namespace> kubectl --namespace=<your namespace> apply -f test_efs.yaml kubectl --namespace=<your namespace> apply -f test_efs_claim.yaml
我不确定 PV 是否需要位于命名空间中,但这个参数似乎不会造成任何损害。PVC 必须位于命名空间中,否则会出现各种奇怪的错误。
配置您的应用程序以使用 EFS 作为其后端存储
现在我们将以下内容添加到 config.yaml 中
singleuser: image: name: jupyter/base-notebook tag: latest storage: type: "static" static: pvcName: "efs-persist" subPath: "home/{username}" extraEnv: CHOWN_HOME: "yes" uid: 0 fsGid: 0 cmd: "start-singleuser.sh"
image 设置覆盖了默认固定的 jh 基础镜像,因为该镜像尚未更新以包含 CHOWN_HOME 设置。
type static 告诉 jh 不要使用存储类,而是使用下面定义的 PVC。
pvcName 与我们之前指定的声明名称相匹配。
subPath 告知挂载点应该位于所提供存储的哪个位置。在这种情况下,它将是“$EFS_ROOT/home/{username}”。
事实证明,jupyterhub 中存在一个错误,导致默认的 subPath 不起作用,而将 subPath 设置为“{username}”也会以同样的方式出错。
extraEnv 部分在尝试启动用户容器内的 jupyterhub 之前设置环境变量。需要 CHOWN_HOME 来强制更改主目录的所有权。
Kubernetes 内部对于是否应该传入 uid 和 gid 来改变目录在容器内的挂载方式仍有争议。我们目前采取的办法是在 jupyterhub 启动前自动对目录执行 chown 操作。
UID/fsGID 是必需的,用以强制容器以 root 身份运行 start-singleuser.sh。一旦 start-singleuser.sh 正确更改了目录的所有权,它就会切换到 jupyterhub 用户。