在Kubernetes上安装Alluxio

本文档展示了如何通过 Operator(Kubernetes 管理应用程序的扩展)在 Kubernetes 上安装 Alluxio。

系统要求

  • Kubernetes

    • 至少1.19版本的 Kubernetes 集群,支持特性门控

    • 确保集群的 Kubernetes 网络策略允许应用程序(Alluxio 客户端)与定义端口上的 Alluxio Pods 之间建立连接

    • Kubernetes 集群已安装至少3.6.0版本的 Helm 3

    • 用于存储和管理容器镜像的镜像仓库

  • 硬件

    • 每个节点至少 8个 CPU 和 32GB 内存

    • 每个节点至少100GB 的存储空间

  • 权限。参考:使用 RBAC 授权

    • 创建 CRD(自定义资源定义)的权限

    • 为 Operator Pod 创建 ServiceAccount、ClusterRole 和 ClusterRoleBinding 的权限

    • 创建 operator 所在命名空间的权限

准备

下载 Alluxio operator 和 Alluxio 集群的安装包

请进入 Alluxio下载页面,选择 Alluxio Enterprise AI 进行下载,下载完成后解压文件。

$ tar zxf alluxio-enterprise-k8s-ai-trial.tar.gz

解压后可以得到以下文件:

  • alluxio-operator-{{site.ALLUXIO_OPERATOR_VERSION_STRING}}-helmchart.tgz 是部署 Alluxio operator 的 helm chart

  • alluxio-operator-{{site.ALLUXIO_OPERATOR_VERSION_STRING}}-docker.tar 是 Alluxio operator 的 docker 镜像

  • alluxio-enterprise-{{site.ALLUXIO_VERSION_STRING}}-docker.tar 是 Alluxio 的 docker 镜像

将镜像上传到镜像仓库

镜像仓库是存储和共享容器镜像的中心化位置。镜像仓库可以是公共的,也可以是私有的。云服务提供商会提供容器镜像仓库服务作为其云服务的一部分, 包括 Amazon Elastic Container Registry(ECR)Azure Container Registry(ACR)Google Container Registry(GCR)。 您甚至可以在本地系统或组织内部运行私有镜像仓库。

以下示例展示了如何上传 Alluxio operator 镜像。

# 加载镜像到本地
$ docker load -i alluxio-operator-{{site.ALLUXIO_OPERATOR_VERSION_STRING}}-docker.tar
$ docker load -i alluxio-enterprise-{{site.ALLUXIO_VERSION_STRING}}-docker.tar

# 将镜像更改为私有镜像仓库
$ docker tag alluxio/operator:{{site.ALLUXIO_OPERATOR_VERSION_STRING}} <PRIVATE_REGISTRY>/alluxio-operator:{{site.ALLUXIO_OPERATOR_VERSION_STRING}}
$ docker tag alluxio/alluxio-enterprise:{{site.ALLUXIO_VERSION_STRING}} <PRIVATE_REGISTRY>/alluxio-enterprise:{{site.ALLUXIO_VERSION_STRING}}

# 上传镜像到私有镜像仓库
$ docker push <PRIVATE_REGISTRY>/alluxio-operator:{{site.ALLUXIO_OPERATOR_VERSION_STRING}}
$ docker push <PRIVATE_REGISTRY>/alluxio-enterprise:{{site.ALLUXIO_VERSION_STRING}}

为 operator 解压 helm chart

# 将文件解压到目录 alluxio-operator
$ tar zxf alluxio-operator-{{site.ALLUXIO_OPERATOR_VERSION_STRING}}-helmchart.tgz

解压后生成的 alluxio-operator 就是负责部署 operator 的 helm chart 文件

部署

部署 Alluxio operator

创建 alluxio-operator/alluxio-operator.yaml 文件指定镜像和版本,用于部署 operator。 以下示例展示了如何指定 operator 镜像和版本:

global:
  image: <PRIVATE_REGISTRY>/alluxio-operator
  imageTag: {{site.ALLUXIO_OPERATOR_VERSION_STRING}}

进入到 alluxio-operator 目录,执行以下命令部署 operator:

$ cd alluxio-operator
# 最后一个参数表示是 helm chart 文件的路径,"." 表示当前目录
$ helm install operator -f alluxio-operator.yaml .
NAME: operator
LAST DEPLOYED: Wed May 15 17:32:34 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

# 确认 operator 是否正常运行
$ kubectl get pod -n alluxio-operator
NAME                                              READY   STATUS    RESTARTS   AGE
alluxio-cluster-controller-5647cc664d-lrx84       1/1     Running   0          14s
alluxio-collectinfo-controller-667b746fd6-hfzqk   1/1     Running   0          14s
alluxio-csi-controller-7bd66df6cf-7kh6k           2/2     Running   0          14s
alluxio-csi-nodeplugin-9cc9v                      2/2     Running   0          14s
alluxio-csi-nodeplugin-fgs5z                      2/2     Running   0          14s
alluxio-csi-nodeplugin-v22q6                      2/2     Running   0          14s
alluxio-ufs-controller-5f6d7c4d66-drjgm           1/1     Running   0          14s

部署 alluxio operator 需要从公共镜像仓库拉取依赖镜像, 如果您因为网络环境无法访问公共镜像仓库导致部署 alluxio-operator 失败, 请参考配置 alluxio-operator 镜像

部署 Alluxio

创建 alluxio-operator/alluxio-cluster.yaml , 用于部署 Alluxio 集群。下面的文件展示了最简配置。

要获取资源规划建议,请参阅资源需求和兼容性

operator 已经默认设置了推荐的配置,这些配置足以启动一个 Alluxio 集群。如需修改配置, 可编辑 alluxio-cluster.yaml 文件中的 .spec.properties 字段。常见用例章节介绍了一些需修改这些属性的通用场景。

.spec.properties 字段下的配置项将会被附加到 alluxio-site.properties 配置文件中, Alluxio 进程会读取该文件。您可以在 Alluxio 的 coordinator 和 worker pod 中, 通过查看 /opt/alluxio/conf/alluxio-site.properties 找到您的配置。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  properties:

  worker:
    count: 2
    pagestore:
      size: 100Gi
      reservedSize: 10Gi

请注意,默认情况下 page store 的缓存目录位于主机的 /mnt/alluxio/pagestore 路径下。缓存的大小可以通过 .spec.worker.pagestore.size 属性设置。预留空间的大小可以通过 .spec.worker.pagestore.reservedSize 属性设置,通常建议将预留空间的大小设置为缓存空间大小的 5% 至 10%。请根据主机的存储设备大小合理设置缓存和预留空间的大小。

上面提供了最简配置,可帮助您快速部署 alluxio 集群用于测试验证。在实际的生产环境中,我们推荐通过 label 和 selector 的方式来部署 alluxio 集群, 通过为节点打 label,可以确保在 Pod 重启之后,任何持久化的信息仍然可用。 持久化的信息包括 coordinator 的 job 元数据 和 worker 的缓存数据。

首先,选定一批 kubernetes 节点用于运行 alluxio 集群,可以通过label的方式指定节点:

kubectl label nodes <node-name> alluxio-role=coordinator
kubectl label nodes <node-name> alluxio-role=worker

然后,在alluxio-cluster.yaml中指定nodeSelector,下面是一个配置示例:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  properties:

  coordinator:
    nodeSelector:
      alluxio-role: coordinator
    
  worker:
    nodeSelector:
      alluxio-role: worker
    count: 2
    pagestore:
      size: 100Gi

此外,对于 coordinator 我们提供了另一种方式,也可以通过 PVC 将 coordinator 的元数据持久化,下面是一个配置示例:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  properties:

  coordinator:
    metastore:
      type: persistentVolumeClaim
      storageClass: "gp2"
      size: 4Gi
    
  worker:
    nodeSelector:
      alluxio-role: worker
    count: 2
    pagestore:
      size: 100Gi
  • 如果您的训练数据存储在 S3,OSS 等存储中,训练程序可以通过 s3:// 或者 oss:// 的方式访问到训练数据, 您可以在启动 Alluxio 集群之后通过创建 UFS 资源,实现将底层存储挂载到 Alluxio 中,从而对训练加速。

  • 如果您的训练程序是通过 PVC 或者 NAS 的方式访问训练数据, 那么需要在创建 Alluxio 集群时将训练数据的 PVC 或者 NAS 挂载到 Alluxio pod 中, 请参考将底层存储挂载到 Alluxio中的 PVC 或者 NAS/hostPath, 修改 alluxio-operator/alluxio-cluster.yaml

进入alluxio-operator 目录,执行以下命令创建 Alluxio 集群:

$ cd alluxio-operator
$ kubectl create -f alluxio-cluster.yaml
alluxiocluster.k8s-operator.alluxio.com/alluxio created

# 集群即将启动
$ kubectl get pod
NAME                                  READY   STATUS              RESTARTS   AGE
alluxio-coordinator-0                 0/1     Init:0/1            0          7s
alluxio-etcd-0                        0/1     ContainerCreating   0          7s
alluxio-etcd-1                        0/1     ContainerCreating   0          7s
alluxio-etcd-2                        0/1     ContainerCreating   0          7s
alluxio-grafana-847fd46f4b-84wgg      0/1     Running             0          7s
alluxio-prometheus-778547fd75-rh6r6   1/1     Running             0          7s
alluxio-worker-76c846bfb6-2jkmr       0/1     Init:0/2            0          7s
alluxio-worker-76c846bfb6-nqldm       0/1     Init:0/2            0          7s

# 检查集群的状态
$ kubectl get alluxiocluster
NAME      CLUSTERPHASE   AGE
alluxio   Ready          2m18s

# 集群准备就绪后,可以查看集群中的 pod
$ kubectl get pod
NAME                                  READY   STATUS    RESTARTS   AGE
alluxio-coordinator-0                 1/1     Running   0          2m3s
alluxio-etcd-0                        1/1     Running   0          2m3s
alluxio-etcd-1                        1/1     Running   0          2m3s
alluxio-etcd-2                        1/1     Running   0          2m3s
alluxio-grafana-7b9477d66-mmcc5       1/1     Running   0          2m3s
alluxio-prometheus-78dbb89994-xxr4c   1/1     Running   0          2m3s
alluxio-worker-85fd45db46-c7n9p       1/1     Running   0          2m3s
alluxio-worker-85fd45db46-sqv2c       1/1     Running   0          2m3s

在 Alluxio 3.x 中,coordinator 是一个无状态的控制组件,用于托管如分布式加载这样的任务,以及作为 operator 调用 API 的 gateway。

如果集群中的有些组件状态无法达到 Running 状态,可以通过kubectl describe pod查看详细信息,找到问题所在。 部署过程中遇到的具体问题,可以参考常见问题

启动 Alluxio 集群还包括 etcd 和监控组件,如果无法从公共镜像仓库拉取镜像导致 etcd 和监控启动失败,请参考配置 Alluxio 集群镜像

将底层存储挂载到 Alluxio

Alluxio 支持对接多种底层存储,包括 S3HDFSOSSCOSTOS 等。

通过 operator 我们可以通过创建 UnderFileSystem 资源来挂载底层存储。一个 UnderFileSystem 资源对应 Alluxio 中的一个挂载点。 关于 Alluxio 以及底层存储命名空间, 请参考Alluxio 命名空间和底层文件系统命名空间

下面我们提供了几种常用的底层存储挂载示例。

S3

创建 alluxio-operator/ufs.yaml,示例将挂载现有的 S3 bucket到 Alluxio。

apiVersion: k8s-operator.alluxio.com/v1
kind: UnderFileSystem
metadata:
  name: alluxio-s3
spec:
  alluxioCluster: alluxio
  path: s3://<S3_BUCKET>/<S3_DIRECTORY>
  mountPath: /s3
  mountOptions:
    s3a.accessKeyId: <S3_ACCESS_KEY_ID>
    s3a.secretKey: <S3_SECRET_KEY>
    alluxio.underfs.s3.region: <S3_REGION>

将 S3 挂载到 Alluxio 的详细信息请参考Amazon AWS S3.

OSS

创建 alluxio-operator/ufs.yaml文件,以进行UFS 配置。以下示例展示如何将现有的 OSS 路径挂载至 Alluxio。

apiVersion: k8s-operator.alluxio.com/v1
kind: UnderFileSystem
metadata:
  name: alluxio-oss
spec:
  alluxioCluster: alluxio
  path: oss://<OSS_BUCKET>/<OSS_DIRECTORY>
  mountPath: /oss
  mountOptions:
    fs.oss.accessKeyId: <OSS_ACCESS_KEY>
    fs.oss.accessKeySecret: <OSS_ACCESS_KEY_SECRET>
    fs.oss.endpoint: <OSS_ENDPOINT>

将阿里云 OSS 挂载到 Alluxio 的详细信息请参考阿里云 OSS.

COS

创建 alluxio-operator/ufs.yaml文件,以进行UFS 配置,以下示例展示如何将现有的 COS bucket 挂载至 Alluxio。

apiVersion: k8s-operator.alluxio.com/v1
kind: UnderFileSystem
metadata:
  name: alluxio-cos
spec:
  alluxioCluster: alluxio
  path: cos://<COS_BUCKET>/<COS_DIRECTORY>
  mountPath: /cos
  mountOptions:
    fs.cos.access.key: <COS_ACCESS_KEY>
    fs.cos.secret.key: <COS_ACCESS_KEY_SECRET>
    fs.cos.region: <COS_REGION>
    fs.cos.app.id: <COS_APP_ID>

注意: COS bucket 的完整名称为 <COS_BUCKET>-<COS_APP_ID>path 的值应仅包含 <COS_BUCKET> 部分,省略 <COS_APP_ID> 部分, 所以 path 设置为 cos://<COS_BUCKET>/<COS_DIRECTORY>。同时,请确保将 fs.cos.app.id 设置为 <COS_APP_ID>

将 COS 挂载到 Alluxio 的详细信息请参考腾讯云对象存储.

NAS

为了让 Alluxio pod 可以访问到 NAS 存储,您需要先将 NAS 挂载到节点的路径上。 Alluxio operator 支持将节点本地路径挂载到 Alluxio pod 中。 首先需要在创建 Alluxio 集群之前,在 alluxio-operator/alluxio-cluster.yaml 中增加挂载路径, 启动 Alluxio 集群时,会将这些路径挂载到 Alluxio 组件中。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  
  hostPaths:
    coordinator:
      /mnt/nas: /ufs/data
    worker:
      /mnt/nas: /ufs/data
    fuse:
      /mnt/nas: /ufs/data
    
  properties:

  worker:
    count: 2
    pagestore:
      size: 100Gi
  • 键是节点上的主机路径,值是容器中的挂载路径。

  • 如果使用 NAS 作为 UFS,则 coordinator, worker 和 FUSE 进程都需要挂载相同的路径,以便在发生任何错误时 FUSE 可以回退

创建 alluxio-operator/ufs.yaml 文件,以进行UFS 配置。以下示例展示如何将现有的 NAS 或主机路径挂载至Alluxio。

apiVersion: k8s-operator.alluxio.com/v1
kind: UnderFileSystem
metadata:
  name: alluxio-nfs
spec:
  alluxioCluster: alluxio
  path: file:///ufs/data
  mountPath: /nfs
PVC

原先,用户的训练任务通过挂载 PVC 到容器内的特定路径,从而可以读取任务数据。 具体而言,训练任务容器内的路径与 PVC 绑定,任务可以通过这个挂载路径访问数据。

现在,我们使用 Alluxio 来优化这一过程。部署 Alluxio 集群时,需要将之前用于存储训练数据的 PVC 挂载到 Alluxio 组件的容器内路径。 然后,再将 Alluxio 组件的容器内路径挂载到 Alluxio 集群中。通过这种方式,训练数据的 PVC 就被成功挂载到 Alluxio 集群中, 使得数据可以通过 Alluxio 的接口进行访问和处理。

首先在创建 Alluxio 集群之前,在 alluxio-cluster.yaml 中增加挂载路径,将原来训练数据的 PVC 挂载到 Alluxio 组件中的路径:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  
  pvcMounts:
    coordinator:
      training-data-ufs-pvc: /ufs/data
    worker:
      training-data-ufs-pvc: /ufs/data
    fuse:
      training-data-ufs-pvc: /ufs/data

  properties:

  worker:
    count: 2
    pagestore:
      size: 100Gi
  • 键是 PVC,值是容器中的挂载路径。

  • 如果使用 PVC 作为 UFS,则 coordinator, worker 和 FUSE 进程都需要挂载相同的路径,以便在发生任何错误时 FUSE 可以回退

创建 alluxio-operator/ufs.yaml文件,以进行UFS 配置。以下示例展示如何将现有的 PVC 挂载至 Alluxio。

apiVersion: k8s-operator.alluxio.com/v1
kind: UnderFileSystem
metadata:
  name: alluxio-pvc
spec:
  alluxioCluster: alluxio
  path: file:///ufs/data
  mountPath: /pvc

挂载操作

首先需要确认 Alluxio 集群已经启动,状态为 Ready。(或者状态为 WaitingForReady 也可以挂载 UFS)

# 检查集群的状态
$ kubectl get alluxiocluster
NAME      CLUSTERPHASE   AGE
alluxio   Ready          2m18s

执行以下命令创建 UnderFileSystem 资源,并将其挂载到 Alluxio 命名空间:

$ cd alluxio-operator
$ kubectl create -f ufs.yaml
underfilesystem.k8s-operator.alluxio.com/alluxio-s3 created

# 确认存储的状态
$ kubectl get ufs
NAME         PHASE   AGE
alluxio-s3   Ready   46s

# 同时通过Alluxio 命令行来查看挂载表
$ kubectl exec -it alluxio-coordinator-0 -- alluxio mount list 2>/dev/null
Listing all mount points
s3://my-bucket/path/to/mount  on  /s3/ properties={s3a.secretKey=xxx, alluxio.underfs.s3.region=us-east-1, s3a.accessKeyId=xxx}

监控

部署 Alluxio 集群默认开启监控,通过 Grafana 可以直观地查看 Alluxio 各种指标, 请参考监控和指标中的 Kubernetes Operator 章节。

数据访问加速

上述步骤中,您部署了 Alluxio 集群,并将底层存储挂载到 Alluxio 中。训练任务通过 Alluxio 读取数据,可以提升训练速度和 GPU 利用率。 Alluxio 提供了3种数据访问方式:

常见用例

更改资源限制

对于每个组件,如 worker、coordinator 和 FUSE,我们都可以通过以下配置更改资源的使用量:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  worker:
    count: 2
    resources:
      limits:
        cpu: "12"
        memory: "36Gi"
      requests:
        cpu: "1"
        memory: "32Gi"
    jvmOptions:
      - "-Xmx22g"
      - "-Xms22g"
      - "-XX:MaxDirectMemorySize=10g"
  coordinator:
    resources:
      limits:
        cpu: "12"
        memory: "36Gi"
      requests:
        cpu: "1"
        memory: "32Gi"
    jvmOptions:
      - "-Xmx4g"
      - "-Xms1g"
  • 容器将永远无法访问超过限制的资源,这个请求限制会在调度过程中生效。如需了解更多信息,请参阅 为 Pod 和容器管理资源

  • 内存限制应略大于堆内存(-Xmx)和直接内存(-XX:MaxDirectMemorySize=10g)的大小之和,以避免内存不足。

将 PVC 用于 page store

这里的page store 指的是Alluxio 使用的缓存。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  worker:
    pagestore:
      type: persistentVolumeClaim
      storageClass: ""
      size: 100Gi
      reservedSize: 10Gi
  • PVC 由 operator 创建

  • storageClass 默认为 standard,但可以指定为空字符串进行静态绑定

  • size 属性设置了缓存空间的大小,reservedSize 属性设置了预留空间的大小。预留空间是用于临时存放数据的内部缓冲空间。底层存储空间的总大小是缓存空间和预留空间大小之和。我们建议预留空间占缓存空间大小 的 5% 至 10%。

挂载自定义映射配置

可以使用自定义 ConfigMap 在 Pod 上提供配置文件。虽然它也可以用于其他用途,例如环境变量,但以下示例主要针对配置文件。

从本地文件创建一个新的 config map

kubectl create configmap my-configmap --from-file=/path/to/my-configmap

声明 ConfigMap 及其挂载点。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  configMaps:
    worker:
      custom-config-map: /etc/custom
    coordiantor:
      custom-config-map: /etc/custom
  • 键是 ConfigMap 的名称,值是容器中的挂载路径

  • 默认情况下,/opt/alluxio/conf 已被挂载。自定义配置映射需要挂载到其他路径。

    • 以缓存过滤器 son文件为例,将其挂载到/opt/alluxio/conf/cachefilter/cache_filter.json ,并将该路径设置为alluxio.user.client.cache.filter.config.file 的值,供 Alluxio 读取。

将文件作为 Secret 添加到 Pod 上

此机制可用于在 Pod 上提供凭证文件。

从本地文件创建一个新的 secret

kubectl create secret my-file --from-file=/path/to/my-file

指定要加载的 Secret 以及在 Pod 上的文件路径。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  secrets:
    worker:
      my-file: /home/alluxio/my-file
    coordinator:
      my-file: /home/alluxio/my-file

使用 root 用户

FUSE pod 将始终使用 root 用户。其他进程默认使用 uid 为1000的用户。在容器中,用户名为 alluxio。 要将其更改为 root 用户,请使用此配置:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  user: 0
  group: 0
  fsGroup: 0
  • 如果文件可由 root 用户组访问,指定 .spec.fsGroup = 0 即可。

  • 如果将挂载主机路径(如page store 路径和 log 路径)的所有权更改为 root 用户,则其所有权将转移到 root。

使用外部 ETCD 集群

如果使用外部 ETCD 集群,可以指定 Alluxio 使用的 ETCD 端点。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  etcd:
    enabled: false
  properties:
    alluxio.etcd.endpoints: http://external-etcd:2379

当使用 HTTPS进行客户端与服务器的传输安全时,需要使用证书将 SSL/TLS 连接到 ETCD。因此,需要准备CA证书(ca.crt)和一个已签名的密钥对(client.crt, pkcs8_key_encrypted.pem)。 注意:pkcs8_key_encrypted.pem 需要是 PKCS8 格式的密钥,可以通过以下命令转换密钥:

$ openssl pkcs8 -topk8 -v2 aes256 -in server.key -out pkcs8_key_encrypted.pem

注意:如果使用命令 openssl pkcs8 -topk8 -nocrypt -in client.key -out pkcs8_key.pem 生成的未加密key file,无需配置alluxio.etcd.tls.client.key.password

在 Kubernetes 中使用创建的 ca.crt, client.crtpkcs8_key_encrypted.pem 创建 secrets。例如,

$ kubectl create secret generic etcd-certs --from-file=/path/to/ca.crt  --from-file=/path/to/client.crt --from-file=/path/to/pkcs8_key_encrypted.pem

然后在 alluxio-cluster.yaml 文件中配置 etcd 属性,并指定 coordinator、worker 和 FUSE 的 secrets:

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  etcd:
    enabled: false
  properties:
    alluxio.etcd.endpoints: https://external-etcd:2379
    alluxio.etcd.tls.enabled: "true"
    alluxio.etcd.tls.ca.cert: /secrets/etcd-certs/ca.crt
    alluxio.etcd.tls.client.cert: /secrets/etcd-certs/client.crt
    alluxio.etcd.tls.client.key: /secrets/etcd-certs/pkcs8_key_encrypted.pem
    alluxio.etcd.tls.client.key.password: <your key password>
  secrets:
    coordinator:
      etcd-certs: /secrets/etcd-certs
    worker:
      etcd-certs: /secrets/etcd-certs
    fuse:
      etcd-certs: /secrets/etcd-certs

在具有不同磁盘规格的节点上部署 Worker

Operator 支持 Worker 的异构配置,特别是配置不同的磁盘规格。 通常,Worker 配置中的不一致可能会导致严重的意外错误,除以下使用场景外,我们不支持其他情况。

  1. 根据磁盘规格对节点进行分类。例如:我们有 10 个 配备1块1TB 磁盘的节点, 以及12 个配备 2 块 800GB 磁盘的节点。

  2. 给节点打 label,对不同的 Worker 组进行唯一标识,每个组的配置需保持一致。

# label nodes with one disk
kubectl label nodes <node name> apps.alluxio.com/disks=1
# label nodes with two disks
kubectl label nodes <node name> apps.alluxio.com/disks=2
  1. 使用 .workerGroups 列出 Worker 配置,定义通过 nodeSelector 进行过滤的label及其对应的配置。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  # you can still specify common configurations with .worker
  worker:
    # the resources and the jvmOptions will affect all worker groups
    resources:
      limits:
        memory: 40Gi
      requests:
        memory: 36Gi
    jvmOptions: ["-Xmx20g", "-Xms20g", "-XX:MaxDirectMemorySize=16g"]
  # configuration here will override the one in worker
  workerGroups:
  - worker:
      count: 10
      nodeSelector:
        apps.alluxio.com/disks: 1
      pagestore:
        hostPath: /mnt/disk1/alluxio/pagestore
        size: 1Ti
  - worker:
      count: 12
      nodeSelector:
        apps.alluxio.com/disks: 2
      pagestore:
        hostPath: /mnt/disk1/alluxio/pagestore,/mnt/disk2/alluxio/pagestore
        size: 800Gi,800Gi

在运行中的集群中动态更新 Alluxio 配置

  1. 获取 ConfigMap

$ kubectl get configmap
NAME                      DATA   AGE
alluxio-alluxio-conf      4      7m48s
  1. 编辑 ConfigMap 以更新 Alluxio 配置

$ kubectl edit configmap alluxio-alluxio-conf

ConfigMap 中应包含以下四个文件:alluxio-env.shalluxio-site.propertieslog4j2.xmlmetrics.properties。根据需要进行编辑后,保存 ConfigMap。

configmap/alluxio-alluxio-conf edited
  1. 根据需要重启 Alluxio 组件 假设集群名称为 alluxio,该名称已在 alluxio-cluster.yaml中指定。

  • coordinator: kubectl rollout restart statefulset alluxio-coordinator

  • worker: kubectl rollout restart deployment alluxio-worker

  • daemonset fuse (fuse.type = daemonSet): kubectl rollout restart daemonset alluxio-fuse

  • csi fuse (fuse.type = csi): csi fuse pod 没有 rollout restart 命令,您可以等待用户 pod 退出并且当前 csi fuse pod 退出 ,新启动的 csi fuse pod 将使用最新配置。 或者也可以手动删除 csi fuse pod:kubectl delete pod alluxio-fuse-xxx,重启后的 pod 将使用最新配置。

常见问题

etcd pod 一直处于 Pending 状态

比如三个 etcd pod 一直处于 Pending 状态,可以通过 kubectl describe pod 查看详细信息:

# 查看 pod 状态
kubectl get pod

NAME                                  READY   STATUS     RESTARTS   AGE
alluxio-coordinator-0                 0/1     Init:1/2   0          73s
alluxio-etcd-0                        0/1     Pending    0          73s
alluxio-etcd-1                        0/1     Pending    0          73s
alluxio-etcd-2                        0/1     Pending    0          73s
alluxio-grafana-79db8c7dd9-lsq2l      1/1     Running    0          73s
alluxio-prometheus-7c6cbc4b4c-9nk25   1/1     Running    0          73s
alluxio-worker-8c79d5fd4-2c994        0/1     Init:1/2   0          73s
alluxio-worker-8c79d5fd4-jrchj        0/1     Init:1/2   0          73s

# 查看 etcd pod 的详细信息
kubectl describe pod alluxio-etcd-0

Events:
  Type     Reason            Age    From               Message
  ----     ------            ----   ----               -------
  Warning  FailedScheduling  3m57s  default-scheduler  0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling., .

# 查看集群中的 pvc 状态
# 如果发现 etcd 的 pvc 一直处于 Pending 状态(alluxio-fuse 处于 Pending 状态是正常现象),可进一步查看情况
kubectl get pvc

NAME                  STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS           AGE
alluxio-fuse          Pending                                      default-alluxio-fuse   5m31s
data-alluxio-etcd-0   Pending                                                             3h41m
data-alluxio-etcd-1   Pending                                                             3h41m
data-alluxio-etcd-2   Pending                                                             3h41m

# 查看 PVC 描述
kubectl describe pvc data-alluxio-etcd-0

Events:
  Type    Reason         Age                      From                         Message
  ----    ------         ----                     ----                         -------
  Normal  FailedBinding  4m16s (x889 over 3h44m)  persistentvolume-controller  no persistent volumes available for this claim and no storage class is set

根据错误信息可知,etcd Pod 处于 Pending 状态的原因是未设置 storage class。可通过在 alluxio-operator/alluxio-cluster.yaml 文件中指定 etcd 的storage class 来解决。

  etcd:
    persistence:
      storageClass: <STORAGE_CLASS>
      size: 

我们需要先删除 Alluxio 集群, 并且删除 etcd 的 pvc,然后重新创建 Alluxio 集群:

# 删除 Alluxio 集群
$ kubectl delete -f alluxio-operator/alluxio-cluster.yaml

# 删除 etcd 的 pvc
$ kubectl delete pvc data-alluxio-etcd-0
$ kubectl delete pvc data-alluxio-etcd-1
$ kubectl delete pvc data-alluxio-etcd-2

# 重新创建 Alluxio 集群
$ kubectl create -f alluxio-operator/alluxio-cluster.yaml

另外一种情况是 etcd pvc 指定了 storage class,但是 etcd pod 和 pvc 依然是 pending 状态。例如下面的 pvc 详细信息中所展示, etcd pvc 指定的 storage class 不支持动态制备,存储卷需要由集群管理员手动创建。

# 查看 etcd pvc 的详细信息
kubectl describe pvc data-alluxio-etcd-0

Events:
  Type    Reason                Age               From                         Message
  ----    ------                ----              ----                         -------
  Normal  WaitForFirstConsumer  25s               persistentvolume-controller  waiting for first consumer to be created before binding
  Normal  ExternalProvisioning  8s (x3 over 25s)  persistentvolume-controller  Waiting for a volume to be created either by the external provisioner 'none' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.

类似的 etcd pod 一直处于 Pending 状态的问题,可以通过上述方法进行排查。

alluxio-fuse PVC 一直处于 Pending 状态

当我们创建集群之后,发现 alluxio-fuse 一直处于 Pending 状态, 这是正常现象,当 alluxio-fuse 被业务 pod 使用时,pvc 会自动绑定 pv,pvc 的状态会变为 Bound。

无法访问公共镜像仓库

配置 alluxio-operator 镜像

部署 alluxio operator 需要从公共镜像仓库拉取依赖镜像,如果您的网络环境无法访问公共镜像仓库,将会出现拉取镜像出现超时错误:

# 确认 operator 是否正常运行
$ kubectl get pod -n alluxio-operator
NAME                                              READY   STATUS              RESTARTS   AGE
alluxio-cluster-controller-65b59f65b4-5d667       1/1     Running             0          22s
alluxio-collectinfo-controller-667b746fd6-hfzqk   1/1     Running             0          22s
alluxio-csi-controller-c85f8f759-sqc56            0/2     ContainerCreating   0          22s
alluxio-csi-nodeplugin-5pgmg                      0/2     ContainerCreating   0          22s
alluxio-csi-nodeplugin-fpkcq                      0/2     ContainerCreating   0          22s
alluxio-csi-nodeplugin-j9wll                      0/2     ContainerCreating   0          22s
alluxio-ufs-controller-5f69bbb878-7km58           1/1     Running             0          22s

可以发现 cluster controllerufs controllercollectinfo controller 启动成功, 但是 csi controllercsi nodeplugin 一直在 ContainerCreating 状态, 这是因为拉取依赖镜像超时导致的。通过 kubectl describe pod 查看详细信息,可以看到类似如下的错误信息:

$ kubectl -n alluxio-operator describe pod -l app.kubernetes.io/component=csi-controller

Events:
  Type     Reason          Age                    From               Message
  ----     ------          ----                   ----               -------
  Normal   Scheduled       10m                    default-scheduler  Successfully assigned alluxio-operator/alluxio-csi-controller-c85f8f759-sqc56 to cn-beijing.10.0.0.252
  Normal   AllocIPSucceed  10m                    terway-daemon      Alloc IP 10.0.0.27/24 took 28.443992ms
  Normal   Pulling         10m                    kubelet            Pulling image "registry.xxx.com/alluxio/operator:2.0.0"
  Normal   Pulled          10m                    kubelet            Successfully pulled image "registry.xxx.com/alluxio/operator:2.0.0" in 5.55s (5.55s including waiting)
  Normal   Created         10m                    kubelet            Created container csi-controller
  Normal   Started         10m                    kubelet            Started container csi-controller
  Warning  Failed          8m20s (x2 over 10m)    kubelet            Failed to pull image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": failed to pull and unpack image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": failed to resolve reference "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": failed to do request: Head "https://us-west2-docker.pkg.dev/v2/k8s-artifacts-prod/images/sig-storage/csi-provisioner/manifests/v2.0.5": dial tcp 142.251.8.82:443: i/o timeout
  Warning  Failed          8m20s (x3 over 10m)    kubelet            Error: ErrImagePull
  Warning  Failed          7m40s (x5 over 10m)    kubelet            Error: ImagePullBackOff
  Warning  Failed          6m56s (x2 over 9m19s)  kubelet            Failed to pull image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": rpc error: code = DeadlineExceeded desc = failed to pull and unpack image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": failed to resolve reference "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5": failed to do request: Head "https://us-west2-docker.pkg.dev/v2/k8s-artifacts-prod/images/sig-storage/csi-provisioner/manifests/v2.0.5": dial tcp 64.233.187.82:443: i/o timeout
  Normal   Pulling         5m29s (x5 over 10m)    kubelet            Pulling image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5"
  Normal   BackOff         30s (x28 over 10m)     kubelet            Back-off pulling image "registry.k8s.io/sig-storage/csi-provisioner:v2.0.5"

您可以将依赖镜像下载到本地,上传到您的私有镜像仓库,然后修改 alluxio-operator.yaml 文件中的镜像地址,再重新部署 operator。

组件
镜像名
版本
用途

operator 的 csi

registry.k8s.io/sig-storage/csi-node-driver-registrar

v2.0.0

csi driver registrar 依赖

operator 的 csi

registry.k8s.io/sig-storage/csi-provisioner

v2.0.5

csi provisioner 依赖

集群的 etcd

docker.io/bitnami/etcd

3.5.9-debian-11-r24

etcd 依赖

集群的 etcd

docker.io/bitnami/os-shell

11-debian-11-r2

os-shell 依赖

集群的监控

grafana/grafana

10.4.5

监控展示

集群的监控

prom/prometheus

v2.52.0

指标采集

拉取 docker 镜像并且上传到私有镜像仓库的命令如下:

# 拉取镜像到本地
$ docker pull registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.0.0
$ docker pull registry.k8s.io/sig-storage/csi-provisioner:v2.0.5
$ docker pull docker.io/bitnami/etcd:3.5.9-debian-11-r24
$ docker pull docker.io/bitnami/os-shell:11-debian-11-r2
$ docker pull grafana/grafana:10.4.5
$ docker pull prom/prometheus:v2.52.0

# 将镜像更改为私有镜像仓库
$ docker tag registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.0.0 <PRIVATE_REGISTRY>/csi-node-driver-registrar:v2.0.0
$ docker tag registry.k8s.io/sig-storage/csi-provisioner:v2.0.5 <PRIVATE_REGISTRY>/csi-provisioner:v2.0.5
$ docker tag docker.io/bitnami/etcd:3.5.9-debian-11-r24 <PRIVATE_REGISTRY>/etcd:3.5.9-debian-11-r24
$ docker tag docker.io/bitnami/os-shell:11-debian-11-r2 <PRIVATE_REGISTRY>/os-shell:11-debian-11-r2
$ docker tag grafana/grafana:10.4.5 <PRIVATE_REGISTRY>/grafana:10.4.5
$ docker tag prom/prometheus:v2.52.0 <PRIVATE_REGISTRY>/prometheus:v2.52.0

# 上传镜像到私有镜像仓库
$ docker push <PRIVATE_REGISTRY>/csi-node-driver-registrar:v2.0.0
$ docker push <PRIVATE_REGISTRY>/csi-provisioner:v2.0.5
$ docker push <PRIVATE_REGISTRY>/etcd:3.5.9-debian-11-r24
$ docker push <PRIVATE_REGISTRY>/os-shell:11-debian-11-r2
$ docker push <PRIVATE_REGISTRY>/grafana:10.4.5
$ docker push <PRIVATE_REGISTRY>/prometheus:v2.52.0

更改 alluxio-operator/alliuxio-operator.yaml 文件中的镜像地址,增加 provisionerdriverRegistrar 的镜像地址:

global:
  image: <PRIVATE_REGISTRY>/alluxio-operator
  imageTag: {{site.ALLUXIO_OPERATOR_VERSION_STRING}}

alluxio-csi:
  controllerPlugin: 
    provisioner: 
      image: <PRIVATE_REGISTRY>/csi-provisioner:v2.0.5
  nodePlugin: 
    driverRegistrar: 
        image: <PRIVATE_REGISTRY>/csi-node-driver-registrar:v2.0.0

进入到 alluxio-operator 目录,执行以下命令部署 operator:

$ cd alluxio-operator
# 最后一个参数表示是 helm chart 文件的路径,"." 表示当前目录
$ helm install operator -f alluxio-operator.yaml .
NAME: operator
LAST DEPLOYED: Wed May 15 17:32:34 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

# 确认 operator 是否正常运行
$ kubectl get pod -n alluxio-operator
NAME                                              READY   STATUS    RESTARTS   AGE
alluxio-cluster-controller-5647cc664d-lrx84       1/1     Running   0          14s
alluxio-collectinfo-controller-667b746fd6-hfzqk   1/1     Running   0          14s
alluxio-csi-controller-7bd66df6cf-7kh6k           2/2     Running   0          14s
alluxio-csi-nodeplugin-9cc9v                      2/2     Running   0          14s
alluxio-csi-nodeplugin-fgs5z                      2/2     Running   0          14s
alluxio-csi-nodeplugin-v22q6                      2/2     Running   0          14s
alluxio-ufs-controller-5f6d7c4d66-drjgm           1/1     Running   0          14s

配置 Alluxio 集群镜像

启动 Alluxio 集群还包括 etcd 和监控组件,如果无法访问公共镜像仓库,需要将 etcd 和监控组件的镜像地址替换成私有镜像仓库,修改alluxio-operator/alluxio-cluster.yaml文件中的镜像地址。

apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: {{site.ALLUXIO_VERSION_STRING}}
  properties:
  worker:
    count: 2
    pagestore:
      size: 100Gi
  etcd:
    image:
      registry: <PRIVATE_REGISTRY>
      repository: <PRIVATE_REPOSITORY>/etcd
      tag: 3.5.9-debian-11-r24
    volumePermissions:
      image:
        registry: <PRIVATE_REGISTRY>
        repository: <PRIVATE_REPOSITORY>/os-shell
        tag: 11-debian-11-r2
    persistence:
      storageClass: <STORAGE_CLASS>
      size: 
  prometheus:
    image: <PRIVATE_REGISTRY>/prometheus
    imageTag: v2.52.0
  grafana:
    image: <PRIVATE_REGISTRY>/grafana
    imageTag: 10.4.5

Last updated