Cloud DDC(Jupiter)
Cloud DDC(Jupiter)
这篇记 Unreal Cloud DDC 的概念、本地部署的前提条件,以及自己用 Docker 跑本地实例时踩的一堆坑(主要是 SSL 证书和 Scylla 配置)。官方文档:How to Set Up a Cloud DDC。
介绍
Unreal Cloud DDC 是一个分布式存储服务,主要用作基于云的派生数据缓存(DDC)。对于拿不到现成本地缓存(或文件共享缓存)的团队,比如远程办公的用户,它能明显加快 cook。它的服务端代号叫 Jupiter,后面命令里和 zen_config 里的上游配置都会看到这个名字。
它的前身是 S3DDC(从 AWS S3 下载 zip)。换成 Cloud DDC 之后(UE5.4 处于 Beta),整个分布式组织里任何人构建过的东西,你本地都不必再生成一遍。
部署形态
- AWS 是测试最充分的部署形态,因为 Epic 自己就是这么跑的。每个区域的 Kubernetes 集群里装的 helm chart 在官方仓库里提供。
- Cloud DDC 也可以本地(on-premise)部署,不依赖任何云资源。
- Azure:从 2024 年 3 月 31 日起,Unreal Cloud DDC 已从 Azure Marketplace 下架。
下面记的是本地 Docker 部署的过程。
前提条件
硬件
一台 Linux 机器即可。我用的是 Ubuntu 22.04.4 LTS(jammy):
$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy
SSH 连上去操作(<ddc-vm-ip> 22 <user>)。
软件
Docker:
sudo apt-get update
sudo apt-get install docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo systemctl status docker
Docker Compose(注意公司网络下要跳过 SSL 校验,见下文证书排错):
sudo curl -L --insecure "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
P4(从 Perforce 同步 Cloud DDC 源码):
# 添加 Perforce 的 APT key
wget -qO - https://package.perforce.com/perforce.pubkey | gpg --dearmor | sudo tee /usr/share/keyrings/perforce.gpg
# 添加仓库
sudo nano /etc/apt/sources.list.d/perforce.list
# deb [signed-by=/usr/share/keyrings/perforce.gpg] https://package.perforce.com/apt/ubuntu jammy release
sudo apt-get update
sudo apt-get install helix-cli
# 登录
export P4PORT=<p4-server>:1666
export P4USER=<user>
p4 login
# 建 workspace
p4 client UCDDC_workspace
Workspace 里 UnrealCloudDDC 和 Shared 这两个目录是部署必需的,View 大致是:
View:
//depot/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/... //UCDDC_workspace/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/...
//depot/Release-5.4/Engine/Source/Programs/Shared/... //UCDDC_workspace/Release-5.4/Engine/Source/Programs/Shared/...
p4 sync 拉下来即可。
安装与运行
先起前置服务(minio / azure_storage / mongo / scylla):
cd UCDDC_workspace/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/
sudo docker-compose -f Composes/docker-compose-tests.yml -p jupiter-test up -d
正常输出是四个容器都 done(jupiter-test_minio_1 / azure_storage_1 / mongo_1 / scylla_1)。看日志、停服务:
sudo docker-compose -f Composes/docker-compose-tests.yml -p jupiter-test logs
sudo docker-compose -f Composes/docker-compose-tests.yml -p jupiter-test stop
起主服务:
sudo docker-compose -f Composes/docker-compose.yml -f Composes/docker-compose-aws.yml up --build -d
sudo docker ps
测试部署
健康检查:
curl http://<ddc-vm-ip>/health/live
本地 cook 跑本地实例:
- 环境变量:
withEnv(["UE-CloudDataCacheAccessToken=..."]) - cook 参数:
-UE-CloudDataCacheHost=http://<ddc-vm-ip> - 在项目
DefaultEngine.ini加覆盖:
[StorageServers]
Cloud=(Host="http://<ddc-vm-ip>", Namespace="test-namespace")
Troubleshooting
本地用 Docker 跑 Cloud DDC 时,在公司网络环境下基本每一步都会撞墙,这里把遇到的几类问题和解法记全。
目录层级要对
docker-compose.yml 里 unreal_cloud_ddc 服务的 build context 是 ../../../:
unreal_cloud_ddc:
build:
context: "../../../"
dockerfile: Programs/UnrealCloudDDC/dockerfile
从 docker-compose.yml 所在位置往上三级会回退到 //depot/Release-5.4/Engine/Source/。所以 P4 同步时目录结构至少要保证三级一致,否则 build context 指向错误。
SSL 证书:dotnet restore 拉不到 nuget
公司网络做了 SSL 中间人,容器里 dotnet restore 连 api.nuget.org 会报 NU1301: Unable to load the service index。解法是把公司证书链加进系统信任和 Docker 镜像。
先从系统层面信任:
# 手动看证书链,通常会有两张(服务端 + 公司网关)
openssl s_client -showcerts -connect api.nuget.org:443
# 分别把两张证书粘进文件
cd ~
nano server.crt
nano fortinet.crt
# 加进系统信任列表
sudo cp server.crt /usr/local/share/ca-certificates/
sudo cp fortinet.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
再让 Docker 镜像也信任(注意 Docker 只能访问 build context 目录及其子目录,证书得放进去):
cp server.crt UCDDC_workspace/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/
cp fortinet.crt UCDDC_workspace/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/
编辑 dockerfile,加上:
COPY Programs/UnrealCloudDDC/server.crt /usr/local/share/ca-certificates/server.crt
COPY Programs/UnrealCloudDDC/fortinet.crt /usr/local/share/ca-certificates/fortinet.crt
RUN update-ca-certificates
curl 拉 DataDog 包失败:加 -k
dockerfile 里有一行 curl 下载 DataDog 包,在 SSL 拦截下会报 returned a non-zero code: 60。给那条 curl 加 -k 跳过校验:
RUN curl -k -LO https://github.com/DataDog/dd-trace-dotnet/releases/download/v2.46.0/datadog-dotnet-apm_2.46.0_amd64.deb
包安全告警被当成错误
dotnet restore 报 NU1902: Warning As Error,几个包(Azure.Identity 1.10.4、OpenTelemetry.Instrumentation.* 1.7.0)有已知中危漏洞,而工程把警告当错误。两个解法。
升级 NuGet 包(改 Jupiter.Common/Jupiter.Common.csproj):
<PackageReference Include="Azure.Identity" Version="1.12.0" />
<PackageReference Include="OpenTelemetry" Version="1.9.0" />
或者直接关掉"警告当错误":
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
端口已被占用
scylla 容器启动报 port is already allocated,9042 被 jupiter-test_scylla_1(前置测试服务那套)占了。改 docker-compose.yml 里 scylla 的端口映射:
scylla:
...
ports:
- "9043:9042"
Scylla 配置缺失:LocalDatacenterName / LocalKeyspaceSuffix
unreal_cloud_ddc 容器启动后立刻退出,日志里 OptionsValidationException 说 ScyllaSettings 缺 LocalDatacenterName 和 LocalKeyspaceSuffix。这两个值在 Composes/appsettings.Local.yaml 的 Scylla 段:
Scylla:
ContactPoints:
- scylla
LocalDatacenterName: datacenter1
LocalKeyspaceSuffix: dc1
docker-compose.yml 里原本通过 configs 段引用这个文件:
configs:
cloud_ddc_config:
file: appsettings.Local.yaml
但 configs 是 Docker Swarm 专有功能。sudo docker info 里如果看到 Swarm: inactive,说明是单节点标准模式,configs 不会按预期工作,配置根本没被读进容器。验证一下:
sudo docker logs composes_unreal_cloud_ddc_1
sudo docker ps -a # 能看到容器没起来
# 让容器先挂着不退,方便进去看
nano Composes/docker-compose.yml
# unreal_cloud_ddc:
# entrypoint: "tail -f /dev/null"
sudo docker-compose -f Composes/docker-compose.yml -f Composes/docker-compose-aws.yml up --build -d
sudo docker exec -it composes_unreal_cloud_ddc_1 bash
ls /config
cat /config/appsettings.Local.yaml
exit
两个解法。
解法一,改用 volumes 把本地文件映射进容器(单节点环境推荐):
unreal_cloud_ddc:
...
volumes:
- ./appsettings.Local.yaml:/config/appsettings.Local.yaml
解法二,真的跑 Swarm,换 docker stack deploy:
sudo docker swarm init
sudo docker stack deploy -c Composes/docker-compose-tests.yml jupiter-test
sudo docker stack deploy -c Composes/docker-compose.yml -c Composes/docker-compose-aws.yml jupiter-aws
docker stack services jupiter-test
加 HTTPS 和 DNS
给实例配域名(<cloud-ddc-host>)和 HTTPS。
先从 IT 拿证书文件,放进 loadbalancer 的 ssl 目录:
cd UCDDC_workspace/Release-5.4/Engine/Source/Programs/UnrealCloudDDC/Composes/
mkdir ssl
cp /home/<user>/wildcard_2024.pem ./ssl/
cp /home/<user>/wildcard_2024.key ./ssl/
改 docker-compose.yml 的 loadbalancer,挂上 443 和 ssl 目录:
loadbalancer:
...
ports:
- "443:443"
volumes:
- ./ssl:/etc/nginx/ssl:ro
改 Composes/nginx.conf,配 443 server:
server {
listen 443 ssl http2;
server_name <cloud-ddc-host> <ddc-vm-ip>;
ssl_certificate /etc/nginx/ssl/wildcard_2024.pem;
ssl_certificate_key /etc/nginx/ssl/wildcard_2024.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location /api {
proxy_set_header X-Jupiter-XAccel-Supported true;
proxy_set_header X-Jupiter-Port Public;
proxy_set_header Connection "";
proxy_pass http://jupiter_backend;
proxy_next_upstream error timeout http_500;
}
location /health {
proxy_set_header X-Jupiter-XAccel-Supported true;
proxy_set_header X-Jupiter-Port Public;
proxy_set_header Connection "";
proxy_pass http://jupiter_backend;
proxy_next_upstream error timeout http_500;
}
location /oidc-token {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://jupiter_backend/oidc-token;
}
location /nginx-blobs {
internal;
alias /data/blob-store;
add_header X-Jupiter-IoHash $upstream_http_x_jupiter_iohash;
add_header X-Jupiter-LastAccess $upstream_http_x_jupiter_lastaccess;
add_header X-Jupiter-InlinePayloadHash $upstream_http_x_jupiter_inlinepayloadhash;
add_header Server-Timing $upstream_http_server_timing;
}
location / {
return 404;
}
error_page 404 502 504 @error_page;
location @error_page {
default_type "application/json";
return 200 '{"error_code": "$status"}';
}
}
改完重新 build:
sudo docker-compose -f Composes/docker-compose.yml -f Composes/docker-compose-aws.yml up --build -d
sudo docker exec -it composes_loadbalancer_1 ls /etc/nginx/ssl
延伸阅读:DDC(派生数据缓存)总览。其中 zen_config.lua 的 upstream.jupiter 段就是把 Local/Shared Zen 接到这里部署的 Cloud DDC(Jupiter)的配置。