跳转到内容

自托管

Tuist 缓存服务可以自托管,为你的团队提供私有二进制缓存。这对于拥有大型产物和频繁构建的组织最有用,将缓存放置在更靠近 CI 基础设施的地方可以减少延迟并提高缓存效率。通过最小化构建代理和缓存之间的距离,你可以确保网络开销不会抵消缓存的速度优势。

::: info

自托管缓存节点需要 Enterprise 计划

你可以将自托管缓存节点连接到托管的 Tuist 服务器 (https://tuist.dev) 或自托管的 Tuist 服务器。自托管 Tuist 服务器本身需要单独的服务器许可证。请参阅 服务器自托管指南

:::

  • Docker 和 Docker Compose
  • S3 兼容存储桶
  • 运行的 Tuist 服务器实例(托管或自托管)

缓存服务以 Docker 镜像形式分发,地址为 ghcr.io/tuist/cache。我们在 cache 目录中提供参考配置文件。

::: tip

我们提供 Docker Compose 设置,因为它是一种方便的评估和小规模部署基线。你可以将其作为参考并根据你喜欢的部署模型(Kubernetes、原始 Docker 等)进行调整。

:::

Terminal window
curl -O https://raw.githubusercontent.com/tuist/tuist/main/cache/docker-compose.yml
mkdir -p docker
curl -o docker/nginx.conf https://raw.githubusercontent.com/tuist/tuist/main/cache/docker/nginx.conf

使用你的配置创建 .env 文件。

::: tip

该服务使用 Elixir/Phoenix 构建,因此某些变量使用 PHX_ 前缀。你可以将这些视为标准服务配置。

:::

# 用于签名和加密数据的密钥。最少 64 个字符。
# 生成方式:openssl rand -base64 64
SECRET_KEY_BASE=YOUR_SECRET_KEY_BASE
# 你的缓存服务可访问的公共主机名或 IP 地址。
PUBLIC_HOST=cache.example.com
# 用于身份验证的 Tuist 服务器 URL(必需)。
# - 托管:https://tuist.dev
# - 自托管:https://your-tuist-server.example.com
SERVER_URL=https://tuist.dev
# S3 存储配置
S3_BUCKET=your-cache-bucket
S3_HOST=s3.us-east-1.amazonaws.com
S3_REGION=us-east-1
# 可选:专用的 Xcode 缓存桶。
# 当你想为 Xcode 缓存与模块/Gradle 缓存产物使用不同的保留策略、存储类别或成本跟踪时很有用。
# S3_XCODE_CACHE_BUCKET=your-xcode-cache-bucket
# S3 身份验证(选项 1:静态凭据)
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
# S3 身份验证(选项 2:IAM 角色 / IRSA)
# 省略 S3_ACCESS_KEY_ID 和 S3_SECRET_ACCESS_KEY,
# 而是设置 AWS_WEB_IDENTITY_TOKEN_FILE 和 AWS_ROLE_ARN。
# 这些通常由 EKS 或类似平台自动注入。
# CAS 存储(非 compose 部署必需)
STORAGE_DIR=/storage
# 可选的专用 KV SQLite 数据库路径。
# 默认为 /data/key_value.sqlite。
KEY_VALUE_DATABASE_PATH=/data/key_value.sqlite
变量必需默认描述
SECRET_KEY_BASE用于签名和加密数据的密钥(最少 64 个字符)。
PUBLIC_HOST你的缓存服务的公共主机名或 IP 地址。用于生成绝对 URL。
SERVER_URLhttps://tuist.dev用于身份验证的 Tuist 服务器 URL。
STORAGE_DIRCAS 产物存储在磁盘上的目录。提供的 Docker Compose 设置使用 /storage
KEY_VALUE_DATABASE_PATH/data/key_value.sqlite键值存储使用的专用 SQLite 数据库路径。
POOL_SIZE2主元数据 SQLite 数据库的连接池大小。
KEY_VALUE_POOL_SIZEPOOL_SIZE专用键值 SQLite 数据库的连接池大小。
S3_BUCKET模块和 Gradle 缓存产物的 S3 桶。当未设置 S3_XCODE_CACHE_BUCKET 时,也用于 Xcode 缓存产物。
S3_XCODE_CACHE_BUCKETS3_BUCKETXcode 缓存产物的可选专用桶。设置后,Xcode 缓存读写直接使用此桶。当你想为 Xcode 缓存产物使用不同的保留策略、存储类别或成本跟踪时很有用。
S3_HOSTS3 端点主机名(例如 s3.us-east-1.amazonaws.com)。
S3_REGIONS3 区域。也接受为 AWS_REGION
S3_ACCESS_KEY_ID条件性S3 access key。使用静态凭据时必需。也接受为 AWS_ACCESS_KEY_ID。请参阅 S3 身份验证
S3_SECRET_ACCESS_KEY条件性S3 secret key。使用静态凭据时必需。也接受为 AWS_SECRET_ACCESS_KEY。请参阅 S3 身份验证
S3_ENDPOINT完整 S3 端点 URL。设置后,使用解析的主机和方案覆盖 S3_HOST。适用于 S3 兼容提供商。
AWS_WEB_IDENTITY_TOKEN_FILEIAM 角色身份验证的 Web 身份令牌文件路径。请参阅 S3 身份验证
AWS_ROLE_ARN使用 Web 身份令牌身份验证时要承担的 IAM 角色 ARN。
DISK_HIGH_WATERMARK_PERCENT85触发 LRU 驱逐的磁盘使用百分比。
DISK_TARGET_PERCENT70驱逐后的目标磁盘使用量。
KEY_VALUE_MAX_DB_SIZE_BYTES26843545600基于大小的 KV 驱逐开始前专用键值 SQLite 数据库的最大大小。
KEY_VALUE_EVICTION_MIN_RETENTION_DAYS1键值条目在被基于大小的 KV 驱逐移除之前必须达到的最小年龄。
KEY_VALUE_EVICTION_MAX_DURATION_MS300000单次 KV 驱逐运行的最大运行时间。
KEY_VALUE_EVICTION_HYSTERESIS_RELEASE_BYTES24696061952KV 驱逐完成后的目标大小,提供迟滞以防止工作线程在限制附近振荡。
KEY_VALUE_READ_BUSY_TIMEOUT_MS2000KV 穿透请求的 SQLite 忙超时(毫秒)。如果数据库锁定时间超过此值,则将读取视为缓存未命中并从 S3 获取值。
KEY_VALUE_MAINTENANCE_BUSY_TIMEOUT_MS50后台维护操作(PRAGMA 查询、增量 vacuum)的 SQLite 忙超时(毫秒)。低值可防止维护阻塞读取流量。
PHX_SOCKET_PATH/run/cache/cache.sock服务创建其 Unix socket 的路径(启用时)。
PHX_SOCKET_LINK/run/cache/current.sockNginx 用于连接服务的符号链接路径。
OTEL_EXPORTER_OTLP_ENDPOINT用于分布式追踪的 OpenTelemetry Collector gRPC 端点。
LOKI_URL用于日志转发的 Loki 兼容端点的基础 URL。
DEPLOY_ENVproduction在追踪和日志标签中使用的环境标签(例如 productionstaging)。

缓存服务支持多种与 S3 身份验证的方法。方法根据设置的环境变量自动确定。

设置 S3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEY(或 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)。这是最简单的方法,适用于任何 S3 兼容提供商。

S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
S3_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

IAM 角色与 Web 身份(IRSA) {#iam-role-irsa}

Section titled “IAM 角色与 Web 身份(IRSA) {#iam-role-irsa}”

如果你在 Kubernetes 上使用 EKS 运行缓存服务,可以使用 IAM Roles for Service Accounts (IRSA)EKS Pod Identity 进行身份验证。省略 S3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEY,并确保以下环境变量可用于容器:

  • AWS_WEB_IDENTITY_TOKEN_FILE — 投影服务账户令牌的路径(由 EKS 注入)
  • AWS_ROLE_ARN — 要承担的 IAM 角色

当服务账户使用 IAM 角色注解时,EKS 会自动注入这些变量。

EC2 实例配置文件 {#instance-profile}

Section titled “EC2 实例配置文件 {#instance-profile}”

当不存在静态凭据或 Web 身份令牌文件时,服务会回退到默认 AWS 凭据链。这意味着它可以使用 EC2 实例配置文件ECS 任务角色 进行身份验证,无需任何额外配置——只需确保实例或任务具有 S3 访问权限的 IAM 角色。

Terminal window
docker compose up -d
Terminal window
curl http://localhost/up

部署缓存服务后,将其注册到你的 Tuist 服务器:

  • 托管 Tuist 服务器 (https://tuist.dev):

    1. 导航到你的组织的 设置 页面。
    2. 找到 自定义缓存端点 部分。
    3. 添加你的缓存服务 URL(例如 https://cache.example.com)。
  • 自托管 Tuist 服务器

    1. TUIST_CACHE_ENDPOINTS 设置为逗号分隔的缓存节点 URL 列表(例如 https://cache-1.example.com,https://cache-2.example.com)。
    2. 重启 Tuist 服务器以应用配置。
graph TD
A[部署缓存服务] --> B[注册缓存端点]
B --> C[Tuist CLI 使用你的端点]

配置后,Tuist CLI 将使用你的自托管缓存。

Docker Compose 配置使用三个卷:

用途
storage二进制产物存储
sqlite_dataSQLite 元数据存储。默认情况下包含 /data/repo.sqlite(产物元数据、孤立清理状态、Oban)和 /data/key_value.sqlite(KV 元数据)。
cache_socketNginx-服务通信的 Unix socket

缓存服务运行多个后台维护循环,将磁盘和数据库使用量保持在一定范围内。你可以通过上面配置表中列出的环境变量调整它们的行为。

  • CAS 磁盘驱逐 — 当磁盘使用量超过 DISK_HIGH_WATERMARK_PERCENT(默认 85%)时,服务会删除最近最少使用的本地产物,直到使用量降至 DISK_TARGET_PERCENT(默认 70%)。被驱逐的产物仍保留在 S3 中。
  • KV 驱逐 — 30 天内未访问的条目无论数据库大小如何都会被删除。此外,当 KV 数据库超过 KEY_VALUE_MAX_DB_SIZE_BYTES(默认 25 GiB)时,服务会删除超过 KEY_VALUE_EVICTION_MIN_RETENTION_DAYS 的条目,直到数据库收缩到 KEY_VALUE_EVICTION_HYSTERESIS_RELEASE_BYTES。每次运行上限为 KEY_VALUE_EVICTION_MAX_DURATION_MS
  • 孤立清理 — 扫描磁盘存储树中与 cache_artifacts 行不匹配的文件并删除它们。这取决于主元数据数据库,而不是 KV 数据库。

有关每个流程如何在内部工作的详细说明,请参阅 架构指南

  • GET /up — 健康时返回 200
  • GET /metrics — Prometheus 指标

缓存在 /metrics 公开 Prometheus 兼容指标。

如果你使用 Grafana,可以导入参考仪表板

设置 OTEL_EXPORTER_OTLP_ENDPOINT 以启用 OpenTelemetry 追踪。缓存服务检测 Bandit(HTTP 服务器)、Phoenix(请求生命周期)、Ecto(数据库查询)、Finch(传出 HTTP)和 Broadway(消息处理)。追踪通过 gRPC 导出到配置的收集器。

设置 LOKI_URL 以将应用日志转发到 Loki 兼容端点。日志通过 Loki HTTP API 推送,带有 app=tuist-cacheenvlevel 标签。

Terminal window
docker compose pull
docker compose up -d

服务在启动时自动运行数据库迁移。升级后,KV 缓存从新流量重新填充时会有一个短暂的热身期。

缓存未被使用 {#troubleshooting-caching}

Section titled “缓存未被使用 {#troubleshooting-caching}”

如果你预期有缓存但看到持续的缓存未命中(例如,CLI 重复上传相同的产物,或者下载从未发生),请按以下步骤操作:

  1. 验证在你的组织设置中正确配置了自定义缓存端点。
  2. 确保你的 Tuist CLI 已通过运行 tuist auth login 进行身份验证。
  3. 检查缓存服务日志中是否有任何错误:docker compose logs cache

我需要 repo.sqlite 文件吗? {#troubleshooting-repo-sqlite}

Section titled “我需要 repo.sqlite 文件吗? {#troubleshooting-repo-sqlite}”

repo.sqlite 是主元数据数据库。它存储产物元数据、孤立清理状态和后台作业数据。正常运行需要它。

如果你从也存储 KV 元数据的旧版本升级,KV 数据已移至专用的 key_value.sqlite 文件。repo.sqlite 中的旧 KV 表(key_value_entrieskey_value_entry_hashes)不再使用,可以在维护窗口期间删除以回收空间。

Socket 路径不匹配 {#troubleshooting-socket}

Section titled “Socket 路径不匹配 {#troubleshooting-socket}”

如果你看到连接被拒绝错误:

  • 确保 PHX_SOCKET_LINK 指向 nginx.conf 中配置的 socket 路径(默认:/run/cache/current.sock
  • 验证 PHX_SOCKET_PATHPHX_SOCKET_LINK 都在 docker-compose.yml 中正确设置
  • 验证 cache_socket 卷已挂载到两个容器中