objstore:Go 模块提供统一接口与高效客户端,适配多种对象存储

为各类对象存储提供统一接口和高效客户端,支持常见操作,注重分布式数据库所需的效率与可靠性,含 YAML 配置和 Prometheus 指标,已在 Thanos 等大规模项目中应用。【此简介由AI生成】

Branch4Tags0

Thanos Logo

最新版本 加入Slack

Go 报告卡 Go 代码参考

测试

Thanos 对象存储客户端

objstore 是一个 Go 模块,提供了统一的接口和高效客户端,以便与各种对象存储服务提供商协同工作。

功能特点:

  • 支持对大多数流行对象存储执行常见操作,并具备明确的契约。
  • 高效且可靠的性能,适用于分布式数据库在对象存储上的需求。
  • 可选的内置基于 YAML 的配置定义,以保持配置的一致性。
  • 可选的 Prometheus 指标仪器化,用于桶操作。

本模块经过实战检验,并被 Thanos、Loki、Cortex、Mimir、Tempo、Parca 等项目在高规模生产环境中使用。

贡献指南

我们非常欢迎贡献!详情请参考我们的 CONTRIBUTING.md

社区

Thanos 是一个开源项目,我们重视并欢迎新的贡献者和社区成员。以下是与社区取得联系的方式:

采用者

查看 采用者列表

背景

这个库最初作为 Thanos 的 objstore 被开发。Thanos 将对象存储作为指标及相关元数据的主要存储。最终,这个包被 Cortex、Loki、Mimir、Tempo、Parca 等其他项目所使用。

鉴于其可重用性,Thanos 社区将这个包提升为一个独立的 Go 模块,并减少了依赖。

维护者

查看 MAINTAINERS.md

如何使用 objstore

本模块的核心是 Bucket 接口

// Bucket provides read and write access to an object storage bucket.
// NOTE: We assume strong consistency for write-read flow.
type Bucket interface {
	io.Closer
	BucketReader

	// Upload the contents of the reader as an object into the bucket.
	// Upload should be idempotent.
	Upload(ctx context.Context, name string, r io.Reader) error

	// Delete removes the object with the given name.
	// If object does not exists in the moment of deletion, Delete should throw error.
	Delete(ctx context.Context, name string) error

所有提供者实现都必须实现 Bucket 接口,该接口允许进行所有对象存储提供者所支持的通用读取和写入操作。如果您希望限制执行存储桶操作代码仅为读取权限(这是一个明智的主意,可以限制访问权限),您可以使用 BucketReader 接口


// BucketReader provides read access to an object storage bucket.
type BucketReader interface {
	// Iter calls f for each entry in the given directory (not recursive.). The argument to f is the full
	// object name including the prefix of the inspected directory.
	// Entries are passed to function in sorted order.
	Iter(ctx context.Context, dir string, f func(string) error, options ...IterOption) error

	// Get returns a reader for the given object name.
	Get(ctx context.Context, name string) (io.ReadCloser, error)

	// GetRange returns a new range reader for the given object name and range.
	GetRange(ctx context.Context, name string, off, length int64) (io.ReadCloser, error)

	// Exists checks if the given object exists in the bucket.
	Exists(ctx context.Context, name string) (bool, error)

	// IsObjNotFoundErr returns true if error means that object is not found. Relevant to Get operations.
	IsObjNotFoundErr(err error) bool

	// Attributes returns information about the specified object.

以下接口表示您的代码可以使用 objstore 客户端执行的对象存储操作。

工厂方法

通常,您有两种使用 objstore 模块的方式:

第一种是导入您需要的提供者,例如 github.com/thanos-io/objstore/providers/s3,并使用可用的构造函数(例如 NewBucket)来实例化。

第二种选项是使用工厂方法 NewBucket(logger log.Logger, confContentYaml []byte, reg prometheus.Registerer, component string) 来根据提供的 YAML 文件实例化对象存储客户端。该 YAML 文件通常具有以下格式:

type: <PROVIDER_TYPE>
config:
  <PROVIDER_TYPE specific options>

具体选项取决于服务提供商,相关内容在以下各节中说明。

注意:所有代码片段均自动生成于代码,并保持最新。

查看Thanos 文档,了解 Thanos 如何使用此模块。

支持的提供商(客户端)

当前对象存储客户端实现:

提供商 成熟度 适用场景 在 CI 中自动测试 维护者
Google Cloud Storage 稳定 生产环境使用 @bwplotka
AWS/S3(以及所有 S3 兼容存储,例如基于磁盘的 Minio 稳定 生产环境使用 @bwplotka
Azure Storage Account 稳定 生产环境使用 @vglafirov,@phillebaba
OpenStack Swift 贝塔(工作原型) 生产环境使用 @FUSAKLA
Tencent COS 贝塔 生产环境使用 @jojohappy,@hanjm
AliYun OSS 贝塔 生产环境使用 @shaulboozhiao,@wujinhu
Baidu BOS 贝塔 生产环境使用 @yahaa
本地文件系统 稳定 测试和演示使用 @bwplotka
Oracle Cloud Infrastructure Object Storage 贝塔 生产环境使用 @aarontams,@gaurav-05,@ericrrath

某些对象存储不支持? 查看如何添加新客户端部分添加新客户端到 Thanos

注意:当前 Thanos 需要对象存储实现具备强一致性(写-读)以满足单例压缩的需求。

S3

Thanos 使用 minio 客户端 库将 Prometheus 数据上传到 AWS S3。

注意:S3 客户端是为 AWS S3 设计的,但可以配置为使用其他 S3 兼容的对象存储,例如 Ceph

S# 对象存储的 yaml 配置定义:

type: S3
config:
  bucket: ""
  endpoint: ""
  region: ""
  aws_sdk_auth: false
  access_key: ""
  insecure: false
  signature_version2: false
  secret_key: ""
  put_user_metadata: {}
  http_config:
    idle_conn_timeout: 1m30s
    response_header_timeout: 2m
    insecure_skip_verify: false
    tls_handshake_timeout: 10s
    expect_continue_timeout: 1s
    max_idle_conns: 100
    max_idle_conns_per_host: 100
    max_conns_per_host: 0
    tls_config:
      ca_file: ""
      cert_file: ""
      key_file: ""
      server_name: ""
      insecure_skip_verify: false
    disable_compression: false
  trace:
    enable: false
  list_objects_version: ""
  bucket_lookup_type: auto
  part_size: 67108864
  sse_config:
    type: ""
    kms_key_id: ""
    kms_encryption_context: {}
    encryption_key: ""
  sts_endpoint: ""
prefix: ""

至少,您需要为 bucketendpointaccess_keysecret_key 键提供值。其余的键是可选的。

然而,如果设置 aws_sdk_auth: true,Thanos 将使用基于 已知环境变量 (AWS_PROFILEAWS_WEB_IDENTITY_TOKEN_FILE 等) 和已知的 AWS 配置文件 (~/.aws/config) 的 AWS SDK for go 默认认证方法。如果启用此选项,则 bucketendpoint 是必需的配置键。

prefix 字段可用于在您的 S3 存储桶中透明地使用前缀。这使得您能够将来自不同来源的区块分离到具有不同前缀的路径中,从而更容易理解发生了什么(例如,您无需使用 Thanos 工具即可知道哪些区块来自哪里)。

AWS 区域与端点的映射可在 这个链接 中找到。

请确保使用正确的签名版本。目前 AWS 需要 v4 签名,所以需要设置 signature_version2: false。如果您不指定它,将会收到 Access Denied 错误。另一方面,一些兼容 S3 的 API 使用 signature_version2: true

您可以通过设置 http_config.idle_conn_timeouthttp_config.response_header_timeout 键来配置 HTTP 客户端的超时设置。一般来说,如果您的日志中出现 timeout awaiting response headers 类似错误,您可能想要增加 http_config.response_header_timeout 的值。

请参阅 net/http 包中 Transport 类型 的文档,以获取关于每个选项具体作用的详细信息。

part_size 以字节为单位指定,指的是用于多部分上传的最小文件大小,因为某些自定义 S3 实现可能有不同的要求。值为 0 表示使用默认的 128 MiB 大小。

对于不支持 ListObjectsV2 的 S3 兼容 API(例如某些版本的 Ceph),请设置 list_objects_version: "v1"。默认值("")等同于 "v2"

http_config.tls_config 允许配置 TLS 连接。请参阅 tls_config 文档,以获取关于每个选项具体作用的详细信息。

bucket_lookup_type 可以是 autovirtual-hostedpath。关于它的更多信息,请阅读 这里

出于调试和测试目的,您可以设置:

  • insecure: true 来切换到不安全的 HTTP 而不是 HTTPS

  • http_config.insecure_skip_verify: true 来禁用 TLS 证书验证(例如,如果您的基于 S3 的存储使用自签名证书)

  • trace.enable: true 来启用 minio 客户端详细日志记录。每个请求和响应都将被记录到调试日志中,因此必须启用调试级别的日志记录才能使用此功能。

S3 服务器端加密

SSE 可以通过 sse_config 进行配置。SSE-S3SSE-KMSSSE-C 均受支持。

  • 如果类型设置为 SSE-S3,则无需配置其他选项。

  • 如果类型设置为 SSE-KMS,则必须设置 kms_key_idkms_encryption_context 是可选的,因为 AWS 提供了默认的加密环境

  • 如果类型设置为 SSE-C,则必须使用 encryption_key 提供加密密钥的路径。

如果设置了 SSE 配置块但 type 不是 SSE-S3SSE-KMSSSE-C 之一,将引发错误。

您还需要为用户应用以下 AWS IAM 策略来访问 KMS 密钥:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "KMSAccess",
            "Effect": "Allow",
            "Action": [
                "kms:GenerateDataKey",
                "kms:Encrypt",
                "kms:Decrypt"
            ],
            "Resource": "arn:aws:kms:<region>:<account>:key/<KMS key id>"
        }
    ]
}

凭据

默认情况下,Thanos 会尝试从以下来源检索凭据:

  1. 如果配置文件中同时存在 access_keysecret_key,则从配置文件中获取。
  2. 从标准的 AWS 环境变量中获取 - AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY
  3. ~/.aws/credentials 文件中获取。
  4. 从实例配置文件中检索 IAM 凭据。

注意:不支持从配置文件中获取访问密钥,而通过其他方法获取密钥(反之亦然)。

AWS 策略

适用于用户的示例 AWS IAM 策略:

  • 对于部署(Thanos 服务的策略):
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::<bucket>/*",
                "arn:aws:s3:::<bucket>"
            ]
        }
    ]
}

(无桶策略)

为了测试策略,为 空置、未使用 的桶设置 S3 访问环境变量以及:

THANOS_TEST_OBJSTORE_SKIP=GCS,AZURE,SWIFT,COS,ALIYUNOSS,OCI
THANOS_ALLOW_EXISTING_BUCKET_USE=true

并运行以下命令:GOCACHE=off go test -v -run TestObjStore_AcceptanceTest_e2e ./pkg/...

  • 关于测试(执行端到端测试的策略):

我们需要访问创建桶(CreateBucket)和删除桶(DeleteBucket)的功能,以及访问所有桶的权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject",
                "s3:CreateBucket",
                "s3:DeleteBucket"
            ],
            "Resource": [
                "arn:aws:s3:::<bucket>/*",
                "arn:aws:s3:::<bucket>"
            ]
        }
    ]
}

遵循此策略,您应能够设置环境变量 THANOS_TEST_OBJSTORE_SKIP=GCS,AZURE,SWIFT,COS,ALIYUNOSS,OCI 并取消设置 S3_BUCKET,然后使用 make test 命令运行所有测试。

关于 AWS 策略的详细信息,请参考:https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html

STS 终端

如果您想使用从实例配置文件中检索到的 IAM 凭证,Thanos 需要通过 AWS STS 进行身份验证。为此,您可以指定自己的 STS 终端。

默认情况下,Thanos 将使用终端:https://sts.amazonaws.com 以及与 AWS 区域对应的终端。

GCS

要将 Google Cloud Storage 存储桶配置为对象存储,您需要设置 bucket 环境变量,使用 GCS 存储桶名称,并配置 Google 应用凭证。

例如:

type: GCS
config:
  bucket: ""
  service_account: ""
prefix: ""

使用 GOOGLE_APPLICATION_CREDENTIALS

应用凭证是通过 JSON 文件配置的,只需要指定存储桶,客户端会查找以下内容:

  1. 由环境变量 GOOGLE_APPLICATION_CREDENTIALS 指定的 JSON 文件路径。
  2. gcloud 命令行工具所知的某个位置中的 JSON 文件。在 Windows 系统中,这是 %APPDATA%/gcloud/application_default_credentials.json。在其他系统中,这是 $HOME/.config/gcloud/application_default_credentials.json
  3. 在 Google App Engine 中,它使用 appengine.AccessToken 函数。
  4. 在 Google Compute Engine 和 Google App Engine 管理的虚拟机中,它从元数据服务器获取凭证。(在这种情况下,提供的作用域将被忽略。)

您可以在 https://cloud.google.com/docs/authentication/production 了解如何获取应用凭证的 JSON 文件。

内联使用服务账户

另一种可能的方法是将服务账户直接内联到 Thanos 配置中,只需维护一个文件。此功能被添加,以便 Prometheus Operator 只需要处理一个密钥文件。

type: GCS
config:
  bucket: "thanos"
  service_account: |-
    {
      "type": "service_account",
      "project_id": "project",
      "private_key_id": "abcdefghijklmnopqrstuvwxyz12345678906666",
      "private_key": "-----BEGIN PRIVATE KEY-----\...\n-----END PRIVATE KEY-----\n",
      "client_email": "project@thanos.iam.gserviceaccount.com",
      "client_id": "123456789012345678901",
      "auth_uri": "https://accounts.google.com/o/oauth2/auth",
      "token_uri": "https://oauth2.googleapis.com/token",
      "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
      "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/thanos%40gitpods.iam.gserviceaccount.com"
    }
GCS 策略

注意: GCS 策略应应用于项目级别,而非存储桶级别。

部署时:

  • Storage Object CreatorStorage Object Viewer

测试时:

  • Storage Object Admin 以具备创建和删除临时存储桶的能力。

为了测试策略是否按预期工作,请执行进入侧车容器的命令,例如:

kubectl exec -it -n <namespace> <prometheus with sidecar pod name> -c <sidecar container name> -- /bin/sh

然后测试您是否至少能够列出存储桶中的对象,例如:

thanos tools bucket ls --objstore.config="${OBJSTORE_CONFIG}"

Azure

若要在Thanos对象存储中使用Azure存储,您需要先通过Azure门户或使用Azure CLI创建存储账户。请遵循Azure存储文档中的指导:https://docs.microsoft.com/en-us/azure/storage/common/storage-quickstart-create-account

配置文件的格式如下:

type: AZURE
config:
  storage_account: ""
  storage_account_key: ""
  container: ""
  endpoint: ""
  user_assigned_id: ""
  max_retries: 0
  reader_config:
    max_retry_requests: 0
  pipeline_config:
    max_tries: 0
    try_timeout: 0s
    retry_delay: 0s
    max_retry_delay: 0s
  http_config:
    idle_conn_timeout: 0s
    response_header_timeout: 0s
    insecure_skip_verify: false
    tls_handshake_timeout: 0s
    expect_continue_timeout: 0s
    max_idle_conns: 0
    max_idle_conns_per_host: 0
    max_conns_per_host: 0
    tls_config:
      ca_file: ""
      cert_file: ""
      key_file: ""
      server_name: ""
      insecure_skip_verify: false
    disable_compression: false
  msi_resource: ""
prefix: ""

若使用 msi_resource,身份验证将通过系统分配的管理身份进行。对于 Azure 而言,其值应为 https://<storage-account-name>.blob.core.windows.net

若使用 user_assigned_id,身份验证将通过用户分配的管理身份进行。在采用 user_assigned_id 时,msi_resource 默认为 https://<storage_account>.<endpoint>

通用的 max_retries 将被用作 pipeline_configmax_triesreader_configmax_retry_requests 的值。为了实现更精细的控制,可以忽略 max_retries(设为 0),并设置特定的重试值。

OpenStack Swift

Thanos 使用 ncw/swift 客户端将 Prometheus 数据上传至 OpenStack Swift

以下是示例配置文件,用于指导 Thanos 使用 OpenStack swift 容器作为对象存储。注意,如果使用了用户、项目或租户的 name,则还必须指定其通过 ID 或名称指定的域。在 官方文档 中可以找到各种 OpenStack 身份验证的示例。

默认情况下,OpenStack Swift 对文件大小有 5 GiB 的限制。Thanos 索引文件通常大于此限制。为了解决这个问题,Thanos 使用 静态大对象(SLO),将其作为段上传。默认情况下,这些段被放置在相同容器的 segments 目录下。使用 SLO 的默认限制为 1 GiB,这也是段的最大大小。如果您不想为段使用相同的容器(最佳实践是使用 <container_name>_segments 以避免污染容器对象列表),可以使用 large_file_segments_container_name 选项覆盖默认值,将段放入其他容器。在极少数情况下,您可以通过将 use_dynamic_large_objects 设为 true 来切换到 动态大对象(DLO),但请谨慎使用,因为它更依赖于最终一致性。

type: SWIFT
config:
  auth_version: 0
  auth_url: ""
  username: ""
  user_domain_name: ""
  user_domain_id: ""
  user_id: ""
  password: ""
  domain_id: ""
  domain_name: ""
  application_credential_id: ""
  application_credential_name: ""
  application_credential_secret: ""
  project_id: ""
  project_name: ""
  project_domain_id: ""
  project_domain_name: ""
  region_name: ""
  container_name: ""
  large_object_chunk_size: 1073741824
  large_object_segments_container_name: ""
  retries: 3
  connect_timeout: 10s
  timeout: 5m
  use_dynamic_large_objects: false
prefix: ""

腾讯云对象存储(COS)

若要使用腾讯云对象存储(COS)作为存储仓库,首先需要申请一个腾讯账号并创建一个对象存储桶。请注意,详细步骤请参考腾讯云文档:https://cloud.tencent.com/document/product/436

为了配置腾讯账号使用COS作为存储仓库,您需要在文件中以YAML格式设置以下参数:

type: COS
config:
  bucket: ""
  region: ""
  app_id: ""
  endpoint: ""
  secret_key: ""
  secret_id: ""
  http_config:
    idle_conn_timeout: 1m30s
    response_header_timeout: 2m
    insecure_skip_verify: false
    tls_handshake_timeout: 10s
    expect_continue_timeout: 1s
    max_idle_conns: 100
    max_idle_conns_per_host: 100
    max_conns_per_host: 0
    tls_config:
      ca_file: ""
      cert_file: ""
      key_file: ""
      server_name: ""
      insecure_skip_verify: false
    disable_compression: false
prefix: ""

secret_keysecret_id 字段是必须的。http_config 字段是可选的,用于优化 HTTP 传输设置。配置必需的存储桶信息有两种方式:

  1. 提供关键字 bucketregionapp_id 的值。
  2. 当您想指定 VPC 内部端点时,提供 endpoint 关键字的 URL 格式。更多关于端点的详细信息,请参考 endpoint 文档
阿里云 OSS

为了使用阿里云 OSS 对象存储,您首先需要在阿里云上创建一个存储桶,并设置适当的存储类别、访问控制列表(ACLs),并获取访问密钥。详情请访问 https://www.alibabacloud.com/product/oss

阿里云 OSS 对象存储的 YAML 配置定义:

type: ALIYUNOSS
config:
  endpoint: ""
  bucket: ""
  access_key_id: ""
  access_key_secret: ""
prefix: ""
百度BOS

为了使用百度BOS对象存储,您需要先申请一个百度账号并创建一个对象存储桶。更多详细内容,请参考百度云文档。百度BOS对象存储的yaml配置定义如下:

type: BOS
config:
  bucket: ""
  endpoint: ""
  access_key: ""
  secret_key: ""
prefix: ""

文件系统

当用户希望在本地的文件系统中存储和访问存储桶时,会使用这种存储类型。我们将文件系统视为与对象存储相同的方式,因此即便是我们可能在本地拥有文件,所有针对远程存储桶的优化同样适用。

注意: 这种存储类型是实验性的,并且可能效率不高。不建议在生产环境中将其作为指标的主要存储。特别是目前没有计划支持类似NFS的分布式文件系统。这主要适用于测试和演示。

文件系统“对象存储”的YAML配置定义:

type: FILESYSTEM
config:
  directory: ""
prefix: ""

Oracle 云基础设施对象存储

要将 Oracle 云基础设施(OCI)对象存储配置为 Thanos 对象存储,您需要为 OCI 租户提供适当的认证凭证。Thanos 的 OCI 对象存储客户端实现支持使用默认密钥对或实例主体认证。

API 签名密钥

默认的 API 签名密钥认证提供程序利用与 OCI 命令行界面(CLI)相同的配置,通常存储在 $HOME/.oci/config 或通过以字符串 OCI_CLI 开头的变量名。您还可以使用以 TF_VAR 开头的环境变量。如果多处找到了相同的配置,提供程序将优先选择第一个。

以下示例配置提供程序以查找用于认证的现有 API 签名密钥:

type: OCI
config:
  provider: "default"
  bucket: ""
  compartment_ocid: ""
  part_size: ""                   // Optional part size to override the OCI default of 128 MiB, value is in bytes.
  max_request_retries: ""         // Optional maximum number of retries for a request.
  request_retry_interval: ""      // Optional sleep duration in seconds between retry requests.
  http_config:
    idle_conn_timeout: 1m30s      // Optional maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit.
    response_header_timeout: 2m   // Optional amount of time to wait for a server's response headers after fully writing the request.
    tls_handshake_timeout: 10s    // Optional maximum amount of time waiting to wait for a TLS handshake. Zero means no timeout.
    expect_continue_timeout: 1s   // Optional amount of time to wait for a server's first response headers. Zero means no timeout and causes the body to be sent immediately.
    insecure_skip_verify: false   // Optional. If true, crypto/tls accepts any certificate presented by the server and any host name in that certificate.
    max_idle_conns: 100           // Optional maximum number of idle (keep-alive) connections across all hosts. Zero means no limit.
    max_idle_conns_per_host: 100  // Optional maximum idle (keep-alive) connections to keep per-host. If zero, DefaultMaxIdleConnsPerHost=2 is used.
    max_conns_per_host: 0         // Optional maximum total number of connections per host.
    disable_compression: false    // Optional. If true, prevents the Transport from requesting compression.
    client_timeout: 90s           // Optional time limit for requests made by the HTTP Client.

实例主体提供者

例如:

type: OCI
config:
  provider: "instance-principal"
  bucket: ""
  compartment_ocid: ""

您也可以像在 Default Provider 示例中一样,包含任何可选配置。

原始提供者

例如:

type: OCI
config:
  provider: "raw"
  bucket: ""
  compartment_ocid: ""
  tenancy_ocid: ""
  user_ocid: ""
  region: ""
  fingerprint: ""
  privatekey: ""
  passphrase: ""         // Optional passphrase to encrypt the private API Signing key

您还可以像 Default Provider 示例中那样,包含任何可选配置。

如何向 Thanos 添加新的客户端?

以下清单可以帮助您将新的 Go 代码客户端添加到支持的提供程序:

  1. ./providers/<provider> 下创建新目录
  2. 实现 objstore.Bucket 接口
  3. 为测试目的添加 NewTestBucket 构造函数,用于创建和删除临时存储桶。
  4. ForeachStore 方法 中使用创建的 NewTestBucket,以确保我们可以在新提供程序上运行测试。(在 PR 中)
  5. 对您的提供程序运行 TestObjStoreAcceptanceTest 以确保其符合要求。修复发现的任何错误,直到测试通过。(在 PR 中)
  6. 将客户端实现添加到 factory 代码中的工厂中。(在每个命令中使用尽可能少的标志)
  7. 将客户端结构配置添加到 cfggen 中,以允许配置自动生成。

至此,任何人都可以通过规范使用您的提供程序。

Introduction

为各类对象存储提供统一接口和高效客户端,支持常见操作,注重分布式数据库所需的效率与可靠性,含 YAML 配置和 Prometheus 指标,已在 Thanos 等大规模项目中应用。【此简介由AI生成】

Customize my domain