언리얼 클라우드 DDC(Unreal Cloud DDC) 는 분산 스토리지 서비스로, 주로 클라우드 기반 파생 데이터 캐시(Derived Data Cache, DDC) 로 사용됩니다.
언리얼 클라우드 DDC는 전 세계에서 리플리케이트할 수 있는 콘텐츠 어드레서블 스토어에 컴팩트 바이너리 오브젝트를 저장합니다. 컴팩트 바이너리 오브젝트는 JSON과 비슷한 직관적인 키-값 오브젝트로서 우수한 바이너리 시리얼라이제이션 및 광범위한 타입 시스템을 갖추고 있습니다.
주요 타입 중 하나는 어태치먼트(Attachment) 타입으로, 대형 블롭을 포함하지 않고 참조하는 오브젝트를 지원합니다. 블롭은 이미지, 오디오 파일 또는 기타 멀티미디어 콘텐츠 같은 바이너리 데이터 파일입니다. 이러한 어태치된 페이로드는 콘텐츠 어드레싱되는데, 이는 페이로드의 해시가 식별자로 사용된다는 뜻입니다. 콘텐츠 어드레싱은 분산 스토리지 시스템, 특히 git에서 일반적으로 사용되는 방식입니다. 콘텐츠 어드레싱은 페이로드의 변경 불가 식별자를 생성하여 캐시에서 이미 사용할 수 있는지 및 다른 곳에 리플리케이트해야 하는지를 신속하게 확인하는 기능을 제공합니다.
언리얼 클라우드 DDC를 사용하면 사용자가 원격지에 있는 등의 이유로 준비된 로컬(또는 파일 공유) 캐시에 액세스할 수 없는 경우, 팀이 언리얼 엔진에서 쿠킹 프로세스 속도를 크게 높일 수 있습니다.
라이선스
언리얼 클라우드 DDC의 소스는 일반 언리얼 엔진 소스 라이선스의 적용을 받습니다.
에픽은 GitHub에서 컨테이너 이미지를 제공합니다. 이러한 컨테이너는 MIT 라이선스에 따라 제공됩니다.
디렉터리
- Jupiter - 언리얼 클라우드 DDC 기능 대부분입니다.
- Jupiter.Common - Lib - 언리얼 클라우드 DDC 외부에서 사용할 수 있는 기능이 포함된 레거시 라이브러리입니다.
- Helm - 모든 컴포넌트에 대한 Helm 차트입니다.
- Benchmark - 간단한 HTTP 벤치마킹 사용자 SuperBenchmark(sb)를 수행하는 데 유용한 템플릿과 Vegeta를 사용하여 벤치마크를 실행하는 데 사용할 수 있는 Docker 컨테이너입니다.
- Composes - 로컬 디플로이 및 테스트를 더 쉽게 하기 위한 다양한 Docker Compose 파일 컬렉션입니다.
종속성
- DotNet Core 6 (및 Visual Studio 2022 또는 VS Code)
- Docker
- Scylla
- 블롭 스토리지(S3, Azure Blob Storage 또는 로컬 파일시스템)
기타 유용한 툴
- MongoDB
- Minio
- Docker Compose
기능 테스트 요건
테스트를 시작하기 전에 다음 명령줄을 사용하여 필수 서비스를 시작합니다.
명령줄
docker-compose -f Composes\docker-compose-tests.yml -p jupiter-test up
로컬에서 실행하기
언리얼 클라우드 DDC를 사용해 보고 싶다면, docker-compose 를 사용하여 시작하세요. 참고로, 언리얼 클라우드 DDC는 여러 다양한 백엔드를 지원하므로 에픽에서는 사용 사례마다 다른 구성을 제공합니다.
시작하려면 다음 명령을 실행합니다.
명령줄
docker-compose -f Composes\docker-compose.yml -f Composes\docker-compose-aws.yml up --build
Azure에서 사용할 수 있는 서비스에 더 밀접한 서비스로 실행하려면 AWS 컴포즈 파일을 docker-compose-azure.yml 로 대체할 수 있습니다.
Docker Compose 구성은 빠르게 시작할 수 있도록 인증을 비활성화합니다. 일반적으로 디플로이하기 전에 언리얼 클라우드 DDC를 OIDC 제공자에 연결하는 것이 좋습니다.
디플로이
현재 언리얼 클라우드 DDC는 AWS의 프로덕션에서만 실행되지만, 스토리지 및 데이터베이스 요건은 일반적이며 추상적입니다.
에픽은 Azure 서비스에 대해 테스트하지 않은 기본 지원을 제공합니다.
/Helm 아래에서 Kubernetes에 대한 에픽 내부 디플로이에 사용하는 helm 값을 제공하지만, Kubernetes가 필수는 아닙니다.
Docker 이미지는 에픽게임즈 GitHub 조직에 퍼블리싱됩니다.
Scylla
언리얼 클라우드 DDC와 통신할 Scylla 클러스터를 구성해야 합니다.
언리얼 클라우드 DDC는 Scylla 오픈 소스(무료) 실행 또는 유료 오퍼링 실행을 지원합니다. 유료 오퍼링은 Scylla 매니저가 유지보수 작업을 지원하므로 클러스터 관리에 들어가는 수고를 줄이는 데 도움이 될 수 있습니다.
다중 지역 클러스터 구성 방법은 Scylla 문서에서 ScyllaDB 클러스터 생성 - 다중 데이터 센터(DC)를 참조하세요.
Scylla 오픈 소스 버전은 여기에서 다운로드할 수 있습니다.
Scylla는 클라우드 환경에서 사용할 수 있는 머신 이미지를 제공합니다.
AWS
에픽에서 운영하는 방식이기 때문에 가장 많은 테스트를 거친 디플로이 형식입니다. 각 지역의 Kubernetes 클러스터에 설치하는 helm 차트가 이 저장소에 제공됩니다.
온프레미스
언리얼 클라우드 DDC는 클라우드 리소스를 사용하지 않고 온프레미스에 디플로이할 수 있습니다. 단일 지역에서만 실행하려는 경우 MongoDB 데이터베이스를 구성하면 되고, 여러 지역에서 실행하되 여전히 온프레미스에서 실행하려는 경우 Scylla를 구성하면 됩니다.
한 지역에서 시작하지만 향후 확장할 수 있는 경우, Scylla를 사용하는 것이 좋습니다. 왜냐하면 MongoDB를 사용하면 모든 기존 상태를 드롭해야 하지만, Scylla를 사용하면 직접 확장할 수 있기 때문입니다.
Azure
AWS에서 디플로이하려면 Azure를 클라우드 제공자로 설정하고 Azure Blob Storage에 대한 연결 스트링으로 Azure.ConnectionString 세팅을 지정해야 합니다.
디플로이 테스트하기
디플로이를 실행한 다음에는 머신에 연결하고 curl 명령을 실행하여 정상적으로 작동하는지 검증할 수 있습니다.
먼저 상태 확인을 사용해 볼 수 있습니다. 그러면 Health 스트링이 반환되어야 합니다.
명령줄
curl http://localhost/health/live
다음으로, 네임스페이스에 콘텐츠를 추가 및 가져오기해 볼 수 있습니다. 이 경우 테스트 스트링(test)을 test-namespace 에 삽입하게 됩니다. 구성에 따라 다른 네임스페이스를 사용해야 할 수도 있습니다. 이 테스트에서도 인증이 비활성화되어 있다고 가정합니다. 비어 있는 'needs' 목록과 함께 200 상태 코드가 반환되어야 합니다.
명령줄
curl http://localhost/api/v1/refs/test-namespace/default/00000000000000000000000000000000000000aa -X PUT --data 'test' -H 'content-type: application/octet-stream' -H 'X-Jupiter-IoHash: 4878CA0425C739FA427F7EDA20FE845F6B2E46BA' -i
그런 다음에는 이 오브젝트 얻기를 시도해 볼 수 있습니다. 그러면 'test' 스트링과 200 상태 코드가 인쇄되어야 합니다.
명령줄
curl http://localhost/api/v1/refs/test-namespace/default/00000000000000000000000000000000000000aa.raw -i
모니터링
에픽은 Datadog을 사용하여 서비스를 모니터링합니다. 따라서 언리얼 클라우드 DDC는 Datadog과 함께 잘 작동하도록 구성되어 있습니다. 그렇지만, 모든 로그는 구조화된 로그로 stdout에 전달되므로, 구조화된 로그를 이해하는 모든 모니터링 서비스는 이를 잘 모니터링할 수 있어야 합니다.
상태 확인
모든 언리얼 클라우드 DDC 서비스는 상태 확인을 사용하여 자체 서비스와 실행할 수 있는 모든 백그라운드 서비스, DB나 블롭 스토리지 등의 종속 서비스를 모니터링합니다.
/health/live 및 /health/ready 에서 각각 라이브 상태 및 준비 상태를 확인할 수 있습니다. 준비 상태 확인은 서비스가 작동하는지 검증하는 데 사용됩니다. 준비 상태 확인이 false를 반환하면 앱에 트래픽이 발생하지 않습니다. 즉, 로드 밸런서가 트래픽을 무시합니다. 라이브 상태 확인은 해당 POD가 정상적으로 작동하는지 확인하는 데 사용됩니다. 라이브 상태 확인이 false를 반환하면 전체 POD가 종료됩니다. 이는 Kubernetes 클러스터에서 실행할 때만 적용됩니다.
인증
언리얼 클라우드 DDC는 인증을 위해 JWT 검증을 수행하는 모든 OIDC 제공자 사용을 지원합니다. 에픽에서는 Okta를 사용하므로 Okta는 테스트 완료되었지만, 다른 OIDC도 호환될 것입니다.
인증을 환경설정하려면 다음을 수행합니다. IdentityProvider(IdP)를 구성한 다음 각 네임스페이스에 대한 인증을 구성합니다.
IdentityProvider 구성
auth 세팅에서 인증 스키마를 지정합니다.
Auth 세팅
auth:
defaultScheme: Bearer
schemes:
Bearer:
implementation: "JWTBearer"
jwtAudience: "api://unreal"
jwtAuthority: "<idp URL>
첫 번째이자 유일한 스키마인 경우 스키마의 이름을 Bearer 로 명명하는 것이 좋습니다. 여러 스키마를 사용하여 여러 IdP를 연결할 수 있습니다. 이는 주로 마이그레이션 중에 유용합니다.
구현 필드는 보통 JWTBearer 지만, 커스텀 인증 서버로 Okta를 사용하는 경우 에픽에서는 Okta 필드를 제공합니다. 조직의 인증 서버를 사용하는 Okta의 경우, JWTBearer 도 사용해야 합니다.
네임스페이스 액세스
언리얼 클라우드 DDC 내의 작업에 대한 액세스는 다음과 같은 액션 세트를 사용하여 제어합니다.
- ReadObject
- WriteObject
- DeleteObject
- DeleteBucket
- DeleteNamespace
- ReadTransactionLog
- WriteTransactionLog
- AdminAction
이러한 액션은 각 네임스페이스 정책에서 ACL을 사용하여 네임스페이스별로 할당할 수도 있고 인증 세팅에서 ACL에 할당할 수도 있습니다(모든 네임스페이스에 적용하고 네임스페이스와 연관되지 않은 작업에 적용).
다음은 액세스 권한이 있는 사용자에 대한 트랜잭션 로그 액세스 권한, 관리자에 대한 관리자 액세스 권한, 그리고 네임스페이스별 액세스 권한을 설정하는 환경설정 예시입니다.
auth:
acls:
- claims:
- groups=app-ddc-storage-transactionlog
actions:
- ReadTransactionLog
- WriteTransactionLog
- claims:
- groups=app-ddc-storage-admin
actions:
- ReadObject
- WriteObject
- DeleteObject
- DeleteBucket
- DeleteNamespace
- AdminAction
namespace:
policies:
example-namespace:
acls:
- actions:
- ReadObject
- WriteObject
claims:
- ExampleClaim
- actions:
- ReadObject
- WriteObject
claims:
- AnotherClaim
open-namespace:
acls:
- actions:
- ReadObject
- WriteObject
claims:
- "*"
클레임 배열에 여러 클레임을 지정하면 모두 함께 AND 처리되는데, 이는 모든 클레임이 true로 평가되어야 한다는 뜻입니다. A=B 같은 클레임 구문은 클레임 A 에 값 B 가 있어야 합니다. 배열의 경우에는 값 B 가 포함되어야 합니다.
또한, 어떤 클레임이 있든 상관없이 유효한 토큰에 대해 액세스 권한을 부여하는 * 클레임을 지정할 수도 있습니다. 이러한 클레임은 주로 디버그 및 테스트 시나리오용이며 프로덕션 데이터용으로 사용하면 안 됩니다.
네트워킹 구성
언리얼 클라우드 DDC는 VPN 터널에 의존하지 않고 일반 인터넷 연결을 사용하여 많은 퍼포먼스를 발휘합니다. 따라서, 공용 인터넷 엔드포인트에 언리얼 클라우드 DDC를 노출하는 것을 강력히 권장합니다. HTTPS를 사용하고 이 페이지에 설명된 대로 인증을 구성하여 다른 사람이 이 데이터에 액세스하지 못하도록 하세요.
또한, 언리얼 클라우드 DDC는 API의 액세스 레벨을 제어하는 데 사용할 수 있는 여러 개의 포트를 제공합니다.
공용 포트
공용 인터넷에 노출되어야 하는 포트로, 대부분의 사용자가 서비스 액세스에 사용해야 하는 포트입니다. 이 포트는 모든 콘텐츠 열거형 같은 더 민감한 일부 API는 노출하지 않습니다. 포트 80 에서 노출되며, Kubernetes 내에서는 http 로 노출됩니다. 단일 지역만 운영하는 경우 이 포트만 노출하면 됩니다.
비공개 포트
기업 포트라고도 합니다. 인트라넷에 노출된 경로가 있는 경우 비공개 포트를 사용하세요. 이 포트의 목적은 인트라넷의 사용자에게만 노출되는 민감한 특정 네임스페이스를 갖는 것입니다. 활성화하려면 네임스페이스 정책에서 IsPublicNamespace 를 false로 설정합니다.
DDC용으로는 사용하지 않는 것이 좋습니다. 왜냐하면 재택근무 사용자(Working From Home, WFH)는 VPN을 통해서만 네임스페이스에 액세스할 수 있는데, 대체로 DDC 사용 사례에는 VPN이 너무 느리기 때문입니다.
일반적으로 포트 8008 에서 노출되며, Kubernetes 내에서는 corp-http 로 노출됩니다.
"PublicApiPorts": [ 80, 8081 ],
"CorpApiPorts": [ 8008, 8082 ],
"InternalApiPorts": [ 8080, 8083 ]
내부 포트
내부 포트는 다른 언리얼 클라우드 DDC 인스턴스에서만 연결할 수 있어야 합니다. 내부 포트는 비공개 포트가 노출하는 모든 것은 물론 민감한 것으로 간주되는 특정 API(주로 리플리케이션 로그를 통한 콘텐츠 열거)도 노출합니다.
포트 8080 에서 노출되며, Kubernetes 내에서는 internal-http 로 노출됩니다.
프라이빗 VPC를 통해서나 IP 범위 허용 목록 등을 사용하여 다른 언리얼 클라우드 DDC 인스턴스에 대해서만 이 접근권을 유지하는 것이 좋습니다.
이 포트는 주로 추측 블롭 리플리케이션에 사용됩니다. 이 페이지의 블롭 리플리케이션 구성을 참조하세요.
일반적인 작업
로컬 인스턴스에 대해 로컬 쿠킹 실행하기
로컬 인스턴스를 실행하는 경우, -UE-CloudDataCacheHost=http://localhost 옵션을 전달하여 로컬 인스턴스에 대한 로컬 쿠킹을 실행할 수 있습니다. 이 경우 프로젝트가 이미 클라우드 DDC를 사용하도록 구성되어 있으며 UE-CloudDataCacheHost=None 을 호스트 오버라이드로 사용(프로젝트마다 다를 수 있음)한다고 가정합니다.
로컬 쿠킹이 의도대로 작동하면 쿠커에 다음과 같이 출력될 것입니다.
콘솔 출력
DerivedDataCache http://localhost: HTTP DDC: Healthy
새로운 지역 추가하기
새로운 지역에는 다음이 포함되어야 합니다.
-
S3 스토리지
-
컴퓨팅(Kubernetes 클러스터 또는 VM)
-
Scylla 디플로이
새 지역을 추가하도록 언리얼 클라우드 DDC를 환경설정하려면 새 지역의 DNS를 포함하도록 모든 노드의 클러스터 세팅을 업데이트해야 합니다.
또한 새 지역에 대해 LocalKeyspaceReplicationStrategy 가 설정되어 있는지도 확인해야 합니다.
Scylla 환경설정의 경우, 기존 ScyllaDB 클러스터에 새 데이터 센터 추가하기 문서를 참조하세요.
특히 중요한 부분은 키스페이스 업데이트입니다.
ALTER KEYSPACE jupiter WITH replication = { 'class' : 'NetworkTopologyStrategy', '<exiting_dc>' : 3, <new_dc> : 3};
ALTER KEYSPACE system_auth WITH replication = { 'class' : 'NetworkTopologyStrategy', '<exiting_dc>' : 3, <new_dc> : 3};
ALTER KEYSPACE system_distributed WITH replication = { 'class' : 'NetworkTopologyStrategy', '<exiting_dc>' : 3, <new_dc> : 3};
ALTER KEYSPACE system_traces WITH replication = { 'class' : 'NetworkTopologyStrategy', '<exiting_dc>' : 3, <new_dc> : 3};
에픽은 모든 곳에서 리플리케이션 인수 3을 사용하므로 새 지역(DC) 이름을 추가합니다.
또한 새 지역에 대한 리플리케이션 인수를 0으로 설정하려면 각 local 키스페이스도 변경해야 합니다(이 섹션의 LocalKeyspaceReplicationStrategy 관련 지침 참조).
ALTER KEYSPACE jupiter_local_regionA WITH replication = { 'class' : 'NetworkTopologyStrategy', 'regionA' : 2, 'regionB' : 0}
ALTER KEYSPACE jupiter_local_regionB WITH replication = { 'class' : 'NetworkTopologyStrategy', 'regionA' : 0, 'regionB' : 2}
이렇게 하면 로컬 키스페이스는 로컬 지역에만 기록됩니다. 키스페이스 업데이트가 굉장히 중대한 것을 아니지만, 이 데이터는 해당 지역 내에서만 요청되므로 Scylla 클러스터 내에서 많은 대역폭과 스토리지를 절약할 수 있습니다.
또한 이 새 지역으로부터 리플리케이트되도록 언리얼 클라우드 DDC 워커 환경설정의 리플리케이터도 업데이트하는 것이 좋을 수 있습니다.
블롭 리플리케이션 구성하기
언리얼 클라우드 DDC에는 두 개의 리플리케이션 메서드가 있습니다.
-
온디맨드 리플리케이션(On-demand replication)
-
추측 리플리케이션(Speculative replication)
온디맨드 리플리케이션 은 필수 블롭이 없는 지역 B에서 요청이 발생하면 지역 A에서 지역 B로 블롭을 복사합니다. 이 리플리케이션 타입은 네임스페이스 정책에서 OnDemandReplication 을 true로 설정하여 네임스페이스별로 선택할 수 있습니다.
응답 시간이 매우 달라질 수 있으므로 DDC 네임스페이스에 대해서는 이 리플리케이션을 설정하지 않는 것이 좋습니다. 이런 경우 DDC에서는 캐시 누락을 수용하고 콘텐츠를 리빌드하는 것이 더 좋지만, 일반적으로 지연시간 추가 없이 모든 곳에서 사용할 수 있도록 추측 리플리케이션에 의존하여 블롭을 전송합니다.
추측 리플리케이션 은 레퍼런스가 추가되면서 각 지역에 보관된 저널을 사용하여 리플리케이트할 콘텐츠를 파악합니다. 추측 리플리케이션은 네임스페이스에서 발생하는 변경사항을 따라가며 이러한 새 레퍼런스가 참조하는 모든 블롭을 복사합니다. 결국에는 로컬 지역에서 실제로 절대 사용되지 않거나 필요하지 않을 수 있는 콘텐츠를 포함한 모든 콘텐츠를 복사하지만, 레퍼런스가 해석되면 로컬 블롭을 사용할 수 있는 경우가 많다는 장점이 있습니다.
DDC의 경우 응답 시간을 짧게 유지하는 것이 매우 중요하므로 추측 리플리케이션에 의존하는 것이 좋습니다.
추측 리플리케이션을 구성하려면 워커 환경설정에 다음과 같은 섹션을 추가합니다(example-values-ABC.yaml 참조).
example-values-ABC.yaml
worker:
config:
Replication:
Enabled: true
Replicators:
- ReplicatorName: DEF-to-ABC-test-namespace
Namespace: test-namespace
ConnectionString: http://url-to-region-DEF.com
이 리플리케이터를 고유하게 식별할 수 있는 어떤 스트링이든 리플리케이터 이름으로 지정할 수 있으며, 이러한 이름은 리플리케이터가 도달한 상태 저장 및 로깅에 사용됩니다.
Namespace 는 리플리케이트할 네임스페이스입니다.
ConnectionString 은 언리얼 클라우드 DDC 디플로이의 다른 지역에 연결하는 데 사용하는 URL입니다.
이는 내부 포트를 사용하여 노출해야 합니다('네트워킹 구성' 참조). 또한 ServiceCredentials 섹션에서 언리얼 클라우드 DDC에 사용할 크리덴셜도 구성해야 하며, 해당 크리덴셜에는 ReadTransactionLog 액세스 권한이 있어야 합니다.