S3 API

Alluxio 提供与 Amazon S3 API 兼容的 RESTful API,允许为 S3 构建的应用程序与 Alluxio 管理的数据进行交互。这使您能够利用 Alluxio 的数据缓存、共享和存储抽象功能,而无需修改现有的基于 S3 的应用程序。

入门指南

先决条件

首先,通过将以下属性添加到您的 conf/alluxio-site.properties 文件中,在所有 Alluxio worker 上启用 S3 API:

alluxio.worker.s3.api.enabled=true

连接到 S3 端点

S3 API 在每个 Alluxio worker 上公开。强烈建议设置一个负载均衡器(例如 Nginx、LVS 或 DNS 轮询)以在所有 worker 之间分发 API 请求。您的负载均衡器的地址将作为客户端的 S3 端点。

  • HTTP 端口29998(默认)

  • HTTPS 端口29996(默认)

要启用 HTTPS,请参阅 TLS 配置指南。您可以通过设置 alluxio.worker.s3.only.https.access=true 来强制仅使用 HTTPS 访问。

配置您的 S3 客户端

配置您的 S3 客户端涉及设置端点、身份验证凭据和寻址样式。

身份验证方法

Alluxio 的 S3 API 支持两种身份验证方法:SIMPLE(默认)和基于令牌的 OIDC

SIMPLE 身份验证(默认)

默认情况下,Alluxio 使用 SIMPLE 身份验证方案,而不是标准的 AWS 凭据验证。

  • 工作原理:为了兼容性,客户端仍应生成根据 AWS Signature Version 4 格式化的 Authorization 标头。Alluxio 解析此标头以提取用户,但验证加密签名。

  • 访问密钥:您希望执行操作的 Alluxio 用户名。这是 Authorization 标头的 Credential 部分。如果您不提供访问密钥,操作将以启动 Alluxio worker 进程的用户身份执行。

  • 秘密密钥:可以是任何虚拟值。客户端需要它来生成签名,但 Alluxio 会忽略它。

基于 OIDC 令牌的身份验证

为了更安全、集中的身份管理,您可以将 S3 API 配置为使用 OIDC (OpenID Connect) 令牌。有关更多详细信息,请参阅完整的身份验证指南。

寻址样式

  • 客户端必须使用路径样式请求(例如,http://<endpoint>/<bucket>/<object>)。

  • 支持虚拟托管样式请求(http://<bucket>.<endpoint>/<object>)。

高级配置

性能和 HTTP 重定向

默认情况下,Alluxio 的 S3 API 使用 HTTP 重定向来实现零拷贝读取。当客户端请求一个对象时,它会被重定向到持有该数据的特定 worker。

但是,某些 S3 客户端,如 Python 的 boto3 和 PyTorch S3 连接器,无法正确处理这些重定向。如果您正在使用此类客户端,则必须通过设置以下属性来禁用重定向:

alluxio.worker.s3.redirect.enabled=false

禁用重定向后,数据将通过最初接收请求的 worker 进行代理,这会引入额外的网络跳数,并可能影响性能。

标签和元数据

  • 启用标签:要使用 S3 对象标签,您必须为您的 UFS 启用扩展属性 (xattr) 支持。

    alluxio.underfs.xattr.change.enabled=true
  • 标签限制:默认情况下,存储桶和对象上的用户定义标签限制为 10 个,并遵守 S3 标签限制。您可以使用 alluxio.proxy.s3.tagging.restrictions.enabled=false 禁用此功能。

  • 元数据大小:根据 S3 对象元数据限制,PUT 请求中用户定义元数据的最大大小默认为 2KB。您可以使用 alluxio.proxy.s3.header.metadata.max.size 更改此设置。

HTTP 持久连接(Keep-Alive)

HTTP 持久连接(也称为 HTTP keep-alive)是使用单个 TCP 连接发送和接收多个 HTTP 请求/响应的想法,而不是为每个请求/响应对打开一个新连接。

持久连接的主要优点包括:

  • 减少延迟:最大限度地减少频繁请求引起的延迟。

  • 节省资源:通过更少的连接和更少的重复请求来减少服务器和客户端的资源消耗。

  • 实时能力:能够快速传输最新数据。

但是,长连接也有一些缺点,例如:

  • 增加服务器压力:许多打开的连接会增加服务器的内存和 CPU 负担。

  • 超时问题:需要处理连接长时间无响应的情况,以确保超时机制的有效性。

要为 S3 API 启用 HTTP 长连接 keep-alive,您需要修改 conf/alluxio-site.properties 文件以包含以下内容:

# Enable keep-alive
alluxio.worker.s3.connection.keep.alive.enabled=true

# Set an idle timeout. The connection will be closed if idle for this duration.
# A value of 0 means to turn off this function.
alluxio.worker.s3.connection.idle.max.time=0sec

限制

  • 存储桶:只有 Alluxio 命名空间中的顶级目录被视为 S3 存储桶。根目录 (/) 不是存储桶,并且无法通过 S3 API 访问根目录下的对象。

  • 对象覆盖:Alluxio 不提供对象锁定或版本控制。如果多个客户端同时写入同一个对象,则最后一次写入将获胜。

  • 不支持的字符:不要在对象键中使用 ?\./../。在路径中使用 // 可能会导致未定义的行为。

  • 文件夹对象:子目录在 ListObjects(V2) 响应中作为 0 字节的文件夹对象返回,与 AWS S3 控制台的行为相匹配。

支持的 S3 操作

下表列出了支持的 S3 API 操作。有关详细用法,请参阅官方 S3 API 文档

S3 API 操作
支持的标头
支持的查询参数

不适用

不适用

不适用

不适用

Content-Type, x-amz-copy-source, x-amz-metadata-directive, x-amz-tagging-directive, x-amz-tagging

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

Range

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

不适用

delimiter, encoding-type, marker, max-keys, prefix

不适用

continuation-token, delimiter, encoding-type, max-keys, prefix, start-after

不适用

不适用

不适用

不适用

Content-Length, Content-MD5, Content-Type, x-amz-tagging

不适用

不适用

不适用

Content-Length, Content-MD5

不适用

用法示例

boto3 客户端

由于 boto3 客户端无法处理重定向响应,因此通过配置显式禁用重定向

alluxio.worker.s3.redirect.enabled=false

以下示例 python 脚本显示了如何初始化 boto3 客户端并使用列出存储桶请求对其进行测试。

import boto3
from botocore.exceptions import ClientError

ALLUXIO_S3_ENDPOINT = "http://<LOAD_BALANCER_ADDRESS>"  # Alluxio's S3 API endpoint when using a load balancer to distribute requests to all workers
# ALLUXIO_S3_ENDPOINT = "http://<ALLUXIO_WORKER>:29998"  # an alternative to a load balancer is to directly connect to a worker
ACCESS_KEY = "placeholder"  # Alluxio does not validate credentials
SECRET_KEY = "placeholder"
REGION = "us-east-1"

FOLDER_PREFIX_TO_LIST = "/"

def main():
    try:
        s3 = boto3.client(
            "s3",
            aws_access_key_id=ACCESS_KEY,
            aws_secret_access_key=SECRET_KEY,
            region_name=REGION,
            endpoint_url=ALLUXIO_S3_ENDPOINT
        )
        print("Client initialized successfully.")

        # Example: list objects with prefix
        response = s3.list_buckets()
        print("Buckets (Alluxio mount points):")
        for bucket in response.get("Buckets", []):
            print(f" - {bucket['Name']}")
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    main()

这假定 boto3 是通过 pip install -r requirements.txt 安装的,其中 boto3requirements.txt 中的唯一条目。

Pytorch

由于 Pytorch 客户端无法处理重定向响应,因此通过配置显式禁用重定向

alluxio.worker.s3.redirect.enabled=false

以下示例 python 脚本使用 Pytorch 的 S3 连接器读取数据。它假定 UFS 已沿路径 /s3-mount 挂载。

# ref https://github.com/awslabs/s3-connector-for-pytorch/tree/main?tab=readme-ov-file#sample-examples

from s3torchconnector import S3MapDataset, S3IterableDataset, S3ClientConfig
import random

S3_ENDPOINT_URL = "http://<LOAD_BALANCER_ADDRESS>"  # Alluxio's S3 API endpoint when using a load balancer to distribute requests to all workers
# S3_ENDPOINT_URL = "http://<ALLUXIO_WORKER>:29998"  # an alternative to a load balancer is to directly connect to a worker
DATASET_URI="s3://s3-mount"
REGION = "us-east-1"

s3_client_config = S3ClientConfig(
  force_path_style=True,
)

iterable_dataset = S3IterableDataset.from_prefix(DATASET_URI,
  region=REGION,
  endpoint=S3_ENDPOINT_URL,
  s3client_config=s3_client_config,
)

for item in iterable_dataset:
  content = item.read()
  print(f"{item.key}:{len(content)}")

map_dataset = S3MapDataset.from_prefix(DATASET_URI,
  region=REGION,
  endpoint=S3_ENDPOINT_URL,
  s3client_config=s3_client_config,
)

# Randomly access to an item in map_dataset.
item = random.choice(map_dataset)
# # Learn about bucket, key, and content of the object
bucket = item.bucket
key = item.key
content = item.read()
print(f"{bucket} {key} {len(content)}")
This assumes Pytorch and related libraries are installed with pip.
$ pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
$ pip install --upgrade pip
$ pip install s3torchconnector

这假定 Pytorch 和相关库是使用 pip 安装的。

$ pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
$ pip install --upgrade pip
$ pip install s3torchconnector

Nvidia Triton 推理服务器

以下步骤显示了如何准备 Triton 模型存储库、服务器和客户端。它假定为 Alluxio 进行了以下准备:

  • Alluxio 部署在 K8s 中

  • Alluxio S3 端点在 <LOAD_BALANCER_ADDRESS> 可用

  • 一个名为 <MY_BUCKET> 的 S3 存储桶在 Alluxio 的挂载点 /s3-mount 处挂载

准备模型存储库并上传到挂载的 S3 存储桶。

$ kubectl run -it --rm debug-shell --image=ubuntu:22.04 --restart=Never -- sh
$ apt update -y
$ apt install -y awscli git python3 python3.10-venv wget
$ git clone -b r25.06 https://github.com/triton-inference-server/server.git
$ cd server/docs/examples
$ ./fetch_models.sh

# upload to s3. note that "/triton_model_repo" it will be used for the triton server
$ aws s3 sync model_repository s3://<MY_BUCKET>/triton_model_repo

创建 triton-server.yaml 并使用 kubectl create -f triton-server.yaml 部署它。

apiVersion: v1
kind: Pod
metadata:
  name: triton-inference-server-s3
  labels:
    app: triton-s3
spec:
  hostNetwork: true
  containers:
    - name: triton-s3-server
      image: nvcr.io/nvidia/tritonserver:24.05-py3
      imagePullPolicy: IfNotPresent
      ports:
        - name: http
          containerPort: 8000
          protocol: TCP
        - name: grpc
          containerPort: 8001
          protocol: TCP
        - name: metrics
          containerPort: 8002
          protocol: TCP
      command: ["/opt/tritonserver/bin/tritonserver"]
      args:
        - "--model-repository=s3://<LOAD_BALANCER_ADDRESS>/s3-mount/triton_model_repo"
        - "--log-verbose=1"
        - "--log-info=true"
      readinessProbe:
        httpGet:
          path: /v2/health/ready
          port: 8000
        initialDelaySeconds: 30
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      livenessProbe:
        httpGet:
          path: /v2/health/live
          port: 8000
        initialDelaySeconds: 60
        periodSeconds: 30
        timeoutSeconds: 5
        failureThreshold: 3

作为启动服务器的一部分,模型数据将被读取,因此会缓存在 Alluxio 中。

创建 triton-client.yaml 并使用 kubectl create -f triton-client.yaml 部署它。

apiVersion: v1
kind: Pod
metadata:
  name: triton-client
  labels:
    app: triton-s3
spec:
  hostNetwork: true
  containers:
    - image: nvcr.io/nvidia/tritonserver:24.05-py3-sdk
      imagePullPolicy: IfNotPresent
      name: tritonserver-client-test
      command: ["sleep", "infinity"]

从客户端内部发送请求

$ kubectl exec -it triton-client -- /workspace/install/bin/image_client -u $(kubectl get pod triton-inference-server-s3 -o jsonpath='{.status.podIP}'):8000 -m densenet_onnx -c 3 -s INCEPTION /workspace/images/mug.jpg
Request 0, batch size 1
Image '/workspace/images/mug.jpg':
    15.349564 (504) = COFFEE MUG
    13.227464 (968) = CUP
    10.424892 (505) = COFFEEPOT

Last updated