Geo blob 복제
GitLab v19.5요약
업로드, LFS 오브젝트, CI job 아티팩트와 같은 blob은 셀프 서비스 프레임워크를 통해 보조 사이트로 복제됩니다. 아래 다이어그램에서는 blob의 한 예시로 job 아티팩트를 사용합니다. 기본 사이트의 동작은 다음과 같습니다.
업로드, LFS 오브젝트, CI job 아티팩트와 같은 blob은 셀프 서비스 프레임워크를 통해
보조 사이트로 복제됩니다. 동기화 상태를 추적하기 위해 각 모델에는 대응하는 레지스트리 테이블이 있습니다.
예를 들어 Upload에는 PostgreSQL Geo 추적 데이터베이스의 Geo::UploadRegistry가 있습니다.
서비스 간 blob 복제 해피 패스 워크플로#
아래 다이어그램에서는 blob의 한 예시로 job 아티팩트를 사용합니다.
새 job 아티팩트 복제#
기본 사이트의 동작은 다음과 같습니다.
소스 코드 보기
sequenceDiagram
participant R as Runner
participant P as Puma
participant DB as PostgreSQL
participant SsP as Secondary site PostgreSQL
R->>P: Upload artifact
P->>DB: Insert `ci_job_artifacts` row
P->>DB: Insert `geo_events` row
P->>DB: Insert `geo_event_log` row
DB->>SsP: Replicate rows- 러너가 아티팩트를 업로드합니다
- Puma가
ci_job_artifacts행을 삽입합니다 - Puma가 "Job Artifact with ID 123 was updated" 와 같은 데이터를 담아
geo_events행을 삽입합니다 - Puma가
geo_events행을 가리키는geo_event_log행을 삽입합니다(SSF를 기존 레거시 로직 위에 구축했기 때문입니다) - PostgreSQL 스트리밍 복제가 읽기 전용 복제본에 해당 행들을 삽입합니다
PostgreSQL DB 행이 복제된 뒤 보조 사이트의 동작은 다음과 같습니다.
소스 코드 보기
sequenceDiagram
participant DB as PostgreSQL
participant GLC as Geo Log Cursor
participant R as Redis
participant S as Sidekiq
participant TDB as PostgreSQL Tracking DB
participant PP as Primary site Puma
GLC->>DB: Query `geo_event_log`
GLC->>DB: Query `geo_events`
GLC->>R: Enqueue `Geo::EventWorker`
S->>R: Pick up `Geo::EventWorker`
S->>TDB: Insert to `job_artifact_registry`, "starting sync"
S->>PP: GET <primary site internal URL>/geo/retrieve/job_artifact/123
S->>TDB: Update `job_artifact_registry`, "synced"- Geo Log Cursor 루프가 새
geo_event_log행을 찾습니다 - Geo Log Cursor가
geo_events행을 처리합니다- Geo Log Cursor가
geo_events행 데이터를 전달하면서Geo::EventWorkerjob을 큐에 넣습니다
- Geo Log Cursor가
- Sidekiq가
Geo::EventWorkerjob을 가져갑니다job_artifact_registry행이 없으므로 Sidekiq가 PostgreSQL Geo 추적 데이터베이스에 해당 행을 삽입하고 "started sync" 로 표시합니다- Sidekiq가 기본 Geo 사이트의 API 엔드포인트에 GET 요청을 보내 파일을 내려받습니다
- Sidekiq가
job_artifact_registry행을 "synced" 및 "pending verification" 으로 표시합니다
기존 job 아티팩트 백필#
- 시스템 관리자에게 Geo가 없는 기존 GitLab 사이트가 있습니다
- 기존 CI job과 job 아티팩트가 있습니다
- 시스템 관리자가 새 GitLab 사이트를 구축하고 이를 보조 Geo 사이트로 구성합니다
보조 사이트의 동작은 다음과 같습니다.
Geo::Secondary::RegistryConsistencyWorker와 Geo::RegistrySyncWorker라는 두 개의 cronjob 이 1분마다 실행됩니다.
아래 워크플로는 이 두 갈래로 나누어 설명합니다.
소스 코드 보기
sequenceDiagram
participant SC as Sidekiq-cron
participant R as Redis
participant S as Sidekiq
participant DB as PostgreSQL
participant TDB as PostgreSQL Tracking DB
SC->>R: Enqueue `Geo::Secondary::RegistryConsistencyWorker`
S->>R: Pick up `Geo::Secondary::RegistryConsistencyWorker`
S->>DB: Query `ci_job_artifacts`
S->>TDB: Query `job_artifact_registry`
S->>TDB: Insert to `job_artifact_registry`- Sidekiq-cron 이 1분마다
Geo::Secondary::RegistryConsistencyWorkerjob을 큐에 넣습니다. 실제로 작업(행 생성 및 삭제)을 하고 있는 동안에는 이 job 이 스스로를 즉시 다시 큐에 넣습니다. 이 job은 배타적 리스를 사용해 자신의 인스턴스가 동시에 여러 개 실행되지 않도록 합니다. - Sidekiq가
Geo::Secondary::RegistryConsistencyWorkerjob을 가져갑니다- Sidekiq가
ci_job_artifacts테이블에서 최대 10000 행을 조회합니다 - Sidekiq가
job_artifact_registry테이블에서 최대 10000 행을 조회합니다 - Sidekiq가 기존 job 아티팩트에 대응하는
job_artifact_registry행을 PostgreSQL Geo 추적 데이터베이스에 삽입합니다
- Sidekiq가
소스 코드 보기
sequenceDiagram
participant SC as Sidekiq-cron
participant R as Redis
participant S as Sidekiq
participant DB as PostgreSQL
participant TDB as PostgreSQL Tracking DB
participant PP as Primary site Puma
SC->>R: Enqueue `Geo::RegistrySyncWorker`
S->>R: Pick up `Geo::RegistrySyncWorker`
S->>TDB: Query `*_registry` tables
S->>R: Enqueue `Geo::EventWorker`s
S->>R: Pick up `Geo::EventWorker`
S->>TDB: Insert to `job_artifact_registry`, "starting sync"
S->>PP: GET <primary site internal URL>/geo/retrieve/job_artifact/123
S->>TDB: Update `job_artifact_registry`, "synced"- Sidekiq-cron 이 1분마다
Geo::RegistrySyncWorkerjob을 큐에 넣습니다. 실제로 작업을 하고 있는 동안에는 이 job 이 최대 한 시간까지 루프를 돌며 동기화 job을 예약합니다. 이 job은 배타적 리스를 사용해 자신의 인스턴스가 동시에 여러 개 실행되지 않도록 합니다. - Sidekiq가
Geo::RegistrySyncWorkerjob을 가져갑니다- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의 모든
registry테이블에서 "동기화를 한 번도 시도하지 않은" 행을 조회합니다. 각 테이블의 행을 번갈아 배치해 메모리 큐에 추가합니다. - 이전 단계에서 1000 행 미만이 조회되면 Sidekiq가 모든
registry테이블에서 "동기화 실패 후 재시도 가능" 행을 조회해 번갈아 배치한 뒤 메모리 큐에 추가합니다. - Sidekiq가 큐의 각 항목에 대해 "Job Artifact with ID 123 was updated" 와 같은 인수를 담아
Geo::EventWorkerjob을 큐에 넣고, 큐에 넣은 Sidekiq job ID를 추적합니다. - "최대 동시 실행 수" 설정에 도달하면 Sidekiq가
Geo::EventWorkerjob을 큐에 넣는 작업을 중단합니다 - Sidekiq가 더 처리할 것이 없을 때까지 이런 작업을 반복합니다
- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의 모든
- Sidekiq가
Geo::EventWorkerjob을 가져갑니다- Sidekiq가
job_artifact_registry행을 "started sync" 로 표시합니다 - Sidekiq가 기본 Geo 사이트의 API 엔드포인트에 GET 요청을 보내 파일을 내려받습니다
- Sidekiq가
job_artifact_registry행을 "synced" 및 "pending verification" 으로 표시합니다
- Sidekiq가
새 job 아티팩트 검증#
기본 사이트의 동작은 다음과 같습니다.
소스 코드 보기
sequenceDiagram
participant Ru as Runner
participant P as Puma
participant DB as PostgreSQL
participant SC as Sidekiq-cron
participant Rd as Redis
participant S as Sidekiq
participant F as Filesystem
Ru->>P: Upload artifact
P->>DB: Insert `ci_job_artifacts`
P->>DB: Insert `ci_job_artifact_states`
SC->>Rd: Enqueue `Geo::VerificationCronWorker`
S->>Rd: Pick up `Geo::VerificationCronWorker`
S->>DB: Query `ci_job_artifact_states`
S->>Rd: Enqueue `Geo::VerificationBatchWorker`
S->>Rd: Pick up `Geo::VerificationBatchWorker`
S->>DB: Query `ci_job_artifact_states`
S->>DB: Update `ci_job_artifact_states` row, "started"
S->>F: Checksum file
S->>DB: Update `ci_job_artifact_states` row, "succeeded"- 러너가 아티팩트를 업로드합니다
- Puma가
ci_job_artifacts행을 생성합니다 - Puma가 검증 상태를 저장할
ci_job_artifact_states행을 생성합니다.- 해당 행은 "pending verification" 으로 표시됩니다
- Sidekiq-cron 이 1분마다
Geo::VerificationCronWorkerjob을 큐에 넣습니다 - Sidekiq가
Geo::VerificationCronWorkerjob을 가져갑니다- Sidekiq가
ci_job_artifact_states에서 "pending verification" 또는 "검증 실패 후 재시도 가능" 으로 표시된 행의 개수를 조회합니다 - Sidekiq가 "최대 검증 동시 실행 수" 설정 범위 안에서 하나 이상의
Geo::VerificationBatchWorkerjob을 큐에 넣습니다
- Sidekiq가
- Sidekiq가
Geo::VerificationBatchWorkerjob을 가져갑니다- Sidekiq가
ci_job_artifact_states에서 "pending verification" 으로 표시된 행을 조회합니다 - 이전 단계에서 10 행 미만이 조회되면 Sidekiq가
ci_job_artifact_states에서 "검증 실패 후 재시도 가능" 으로 표시된 행을 조회합니다 - 각 행에 대해 다음을 수행합니다
- Sidekiq가 해당 행을 "started verification" 으로 표시합니다
- Sidekiq가 파일의 SHA256 체크섬을 구합니다
- Sidekiq가 체크섬을 행에 저장하고 "succeeded verification" 으로 표시합니다
- 이제 보조 Geo 사이트가 이 체크섬과 대조할 수 있습니다
- Sidekiq가
보조 사이트의 동작은 다음과 같습니다.
소스 코드 보기
sequenceDiagram
participant SC as Sidekiq-cron
participant R as Redis
participant S as Sidekiq
participant TDB as PostgreSQL Tracking DB
participant F as Filesystem
participant DB as PostgreSQL
SC->>R: Enqueue `Geo::VerificationCronWorker`
S->>R: Pick up `Geo::VerificationCronWorker`
S->>TDB: Query `job_artifact_registry`
S->>R: Enqueue `Geo::VerificationBatchWorker`
S->>R: Pick up `Geo::VerificationBatchWorker`
S->>TDB: Query `job_artifact_registry`
S->>TDB: Update `job_artifact_registry` row, "started"
S->>F: Checksum file
S->>DB: Query `ci_job_artifact_states`
S->>TDB: Update `job_artifact_registry` row, "succeeded"- 아티팩트가 정상적으로 동기화되면 "pending verification" 상태가 됩니다
- Sidekiq-cron 이 1분마다
Geo::VerificationCronWorkerjob을 큐에 넣습니다 - Sidekiq가
Geo::VerificationCronWorkerjob을 가져갑니다- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의
job_artifact_registry에서 "pending verification" 또는 "검증 실패 후 재시도 가능" 으로 표시된 행의 개수를 조회합니다- Sidekiq가 "최대 검증 동시 실행 수" 설정 범위 안에서 하나 이상의
Geo::VerificationBatchWorkerjob을 큐에 넣습니다
- Sidekiq가 "최대 검증 동시 실행 수" 설정 범위 안에서 하나 이상의
- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의
- Sidekiq가
Geo::VerificationBatchWorkerjob을 가져갑니다- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의
job_artifact_registry에서 "pending verification" 으로 표시된 행을 조회합니다 - 이전 단계에서 10 행 미만이 조회되면 Sidekiq가
job_artifact_registry에서 "검증 실패 후 재시도 가능" 으로 표시된 행을 조회합니다 - 각 행에 대해 다음을 수행합니다
- Sidekiq가 해당 행을 "started verification" 으로 표시합니다
- Sidekiq가 파일의 SHA256 체크섬을 구합니다
- Sidekiq가 체크섬을 행에 저장합니다
- Sidekiq가 이 체크섬을 PostgreSQL 이 복제한
ci_job_artifact_states행의 체크섬과 비교합니다 - 체크섬이 일치하면 Sidekiq가
job_artifact_registry행을 "succeeded verification" 으로 표시합니다
- Sidekiq가 PostgreSQL Geo 추적 데이터베이스의