GitLab 복구

Tier: Free, Premium, Ultimate Offering: Self-managed

GitLab은 전체 설치를 복구하기 위한 명령줄 인터페이스를 제공하며, 여러분의 요구에 유연하게 대응할 수 있습니다.

복구 선행 조건 섹션에는 중요한 정보가 포함되어 있습니다. 복구 프로세스를 완전히 읽고 테스트한 후에 본격적인 운영 환경에서 수행하기 전에 반드시 한 번은 확인하십시오.

복구 선행 조건

대상 GitLab 인스턴스는 이미 작동 중이어야 합니다

복구를 수행하기 전에 작동 중인 GitLab 설치가 있어야 합니다. 이는 복구 작업을 수행하는 시스템 사용자(git)가 대상 데이터베이스(gitlabhq_production)를 생성하거나 삭제할 수 없기 때문입니다. 기존 데이터는 삭제되거나 별도의 디렉터리(예: 리포지터리 및 업로드와 같은)로 이동됩니다. SQL 데이터를 복원하는 경우, PostgreSQL 확장에서 소유한 뷰는 건너뛰게 됩니다.

대상 GitLab 인스턴스는 정확히 동일한 버전이어야 합니다

백업을 만든 GitLab의 정확히 동일한 버전 및 유형(CE 또는 EE)으로만 복구할 수 있습니다. 예를 들어, CE 15.1.4와 같이 동일한 버전입니다.

백업이 현재 설치된 버전과 다른 경우 복구하기 전에 반드시 GitLab 설치를 다운그레이드하거나 업그레이드해야 합니다.

GitLab 비밀은 복원되어야 합니다

백업을 복원하려면 GitLab 비밀을 복원해야 합니다. 이에는 데이터베이스 암호화 키, CI/CD 변수, 이중 인증용 변수 등이 포함됩니다. 키가 없으면 여러 문제가 발생합니다. 이중 인증을 사용하는 사용자들은 접근이 차단되며, GitLab 러너는 로그인할 수 없습니다.

복구 사항:

특정 GitLab 구성은 복원해야 할 원래 백업된 환경과 일치해야 합니다

일반적으로 이전의 /etc/gitlab/gitlab.rb(Linux 패키지 설치용) 또는 /home/git/gitlab/config/gitlab.yml(자체 컴파일 설치용) 및 TLS 키, 인증서(/etc/gitlab/ssl, /etc/gitlab/trusted-certs), SSH 호스트 키를 복원하기를 희망할 것입니다.

일부 구성은 PostgreSQL의 데이터와 결합됩니다. 예를 들어:

  • 원래 환경에 리포지터리 스토리지가 세 개인 경우(default, my-storage-1, my-storage-2 등), 대상 환경에도 이러한 리포지터리 이름이 구성에 정의되어 있어야 합니다.
  • 로컬 리포지터리를 사용하는 환경에서 백업을 복원하면, 대상 환경이 객체 리포지터리를 사용하더라도 로컬 리포지터리로 복원됩니다. 객체 리포지터리로의 마이그레이션은 복구 전이나 후에 수행해야 합니다.

마운트 지점으로 복구해야 하는 디렉터리

마운트 지점으로 복구해야 하는 디렉터리가 비어 있는지 확인해야 합니다. 그렇지 않으면 새로운 데이터를 복원하기 전에 GitLab이 이러한 디렉터리를 이동하려고 하기 때문에 오류가 발생할 수 있습니다.

NFS 마운트 구성에 대해 자세히 알아보기를 참조하세요.

Linux 패키지 설치용 복구

이 절차는 다음을 전제로 합니다:

  • 백업이 생성된 GitLab의 정확히 동일한 버전 및 유형(CE/EE)을 설치하였습니다.
  • 적어도 한 번은 sudo gitlab-ctl reconfigure를 실행했습니다.
  • GitLab이 실행 중입니다. 그렇지 않다면 sudo gitlab-ctl start를 사용하여 시작하십시오.

먼저, 백업 tar 파일이 gitlab.rb 구성 gitlab_rails['backup_path']에서 설명한 백업 디렉터리에 있는지 확인합니다. 기본값은 /var/opt/gitlab/backups입니다. 백업 파일의 소유자는 git 사용자여야 합니다.

sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
sudo chown git:git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar

데이터베이스에 연결된 프로세스를 중지하십시오. GitLab의 나머지 부분은 계속 실행된 채로 두십시오.

sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
# 확인
sudo gitlab-ctl status

다음으로, 복구 선행 조건을 완료했는지 확인하고, 원래 설치에서 GitLab 비밀 파일을 복사한 후 gitlab-ctl reconfigure를 실행하십시오.

그 다음으로, 복구를 수행하되, 복원하려는 백업의 ID를 지정하여 실행하십시오:

# 이 명령은 GitLab 데이터베이스 내용을 덮어쓸 것입니다!
# 참고: "_gitlab_backup.tar"은 이름에서 생략되었습니다
sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

백업 tar 파일과 설치된 GitLab 버전 간에 GitLab 버전 불일치가 있는 경우, 복구 명령이 오류 메시지와 함께 중단됩니다:

GitLab 버전 불일치:
  현재 GitLab 버전(16.5.0-ee)이 백업된 GitLab 버전과 다릅니다!
  다음 버전으로 전환한 다음 다시 시도하십시오:
  버전: 16.4.3-ee

올바른 GitLab 버전을 설치한 후에 다시 시도하십시오.

caution
본 복구 명령은 추가 매개변수가 필요합니다. PgBouncer를 사용하는 경우, 성능 상의 이유로 또는 Patroni 클러스터와 함께 사용하는 경우입니다.

다음으로, GitLab을 재시작하고 확인합니다:

sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true

GitLab 13.1 이상의 버전에서는 특히 /etc/gitlab/gitlab-secrets.json이 복원되었거나 다른 서버가 복구 대상인 경우 데이터베이스 값이 현재 비밀을 사용하여 복호화될 수 있는지 확인하십시오.

sudo gitlab-rake gitlab:doctor:secrets

추가적인 확신을 얻기 위해 업로드된 파일의 무결성을 확인할 수 있습니다:

sudo gitlab-rake gitlab:artifacts:check
sudo gitlab-rake gitlab:lfs:check
sudo gitlab-rake gitlab:uploads:check

Docker 이미지 및 GitLab Helm 차트 설치를 위한 복원

Docker 이미지나 Kubernetes 클러스터의 GitLab Helm 차트를 사용하여 GitLab을 설치하는 경우 복원 작업은 복원 디렉터리가 비어 있어야 한다. 그러나 Docker와 Kubernetes 볼륨 마운트를 사용하면 Linux 운영 체제에 있는 lost+found 디렉터리와 같은 시스템 레벨 디렉터리가 볼륨 루트에 생성될 수 있다. 이러한 디렉터리들은 일반적으로 root 소유이며, 복원 Rake 작업은 git 사용자로 실행되기 때문에 액세스 권한 오류가 발생할 수 있다. GitLab 설치를 복원하려면 사용자가 복원 대상 디렉터리가 비어 있는지 확인해야 한다.

이러한 설치 유형 모두에서 백업 tarball은 백업 위치(default location is /var/opt/gitlab/backups)에 있어야 한다.

Helm 차트 설치를 위한 복원

GitLab Helm 차트는 GitLab Helm 차트 설치 복원에 문서화된 프로세스를 사용한다.

Docker 이미지 설치를 위한 복원

Docker Swarm를 사용 중이라면, Puma가 종료되어 컨테이너의 건강 상태 확인이 실패하여 복원 과정 중에 컨테이너가 다시 시작될 수 있다. 이 문제를 해결하기 위해 임시로 건강 상태 확인 메커니즘을 비활성화해야 한다.

  1. docker-compose.yml을 편집하십시오:

    healthcheck:
      disable: true
    
  2. 스택을 배포하십시오:

    docker stack deploy --compose-file docker-compose.yml mystack
    

자세한 정보는 issue 6846를 참조하십시오.

복원 작업은 호스트에서 실행할 수 있다:

# 데이터베이스에 연결된 프로세스를 중지합니다
docker exec -it <컨테이너 이름> gitlab-ctl stop puma
docker exec -it <컨테이너 이름> gitlab-ctl stop sidekiq

# 계속하기 전에 모든 프로세스가 중지되었는지 확인합니다
docker exec -it <컨테이너 이름> gitlab-ctl status

# 복원을 실행합니다. 참고: 백업 이름에 "_gitlab_backup.tar"는 제외됩니다
docker exec -it <컨테이너 이름> gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

# GitLab 컨테이너를 재시작합니다
docker restart <컨테이너 이름>

# GitLab을 확인합니다
docker exec -it <컨테이너 이름> gitlab-rake gitlab:check SANITIZE=true

직접 컴파일한 설치를 위한 복원

먼저, 백업 tar 파일이 gitlab.yml 구성에 설명된 백업 디렉터리에 있는지 확인하십시오:

## 백업 설정
backup:
  path: "tmp/backups"   # 상대적인 경로는 Rails.root를 기준으로 합니다 (기본값: tmp/backups/)

기본값은 /home/git/gitlab/tmp/backups이며, 이것은 git 사용자가 소유해야 합니다. 이제 백업 프로시저를 시작할 수 있습니다:

# 데이터베이스에 연결된 프로세스를 중지합니다
sudo service gitlab stop

sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production

예시 출력:

백업을 푸는 중... [완료]
데이터베이스 테이블 복원 중:
-- create_table("events", {:force=>true})
   -> 0.2231s
[...]
- fixture events를 불러오는 중...[완료]
- fixture issues를 불러오는 중...[완료]
- fixture keys를 불러오는 중...[생략]
- fixture merge_requests를 불러오는 중...[완료]
- fixture milestones를 불러오는 중...[완료]
- fixture namespaces를 불러오는 중...[완료]
- fixture notes를 불러오는 중...[완료]
- fixture projects를 불러오는 중...[완료]
- fixture protected_branches를 불러오는 중...[생략]
- fixture schema_migrations를 불러오는 중...[완료]
- fixture services를 불러오는 중...[생략]
- fixture snippets를 불러오는 중...[생략]
- fixture taggings를 불러오는 중...[생략]
- fixture tags를 불러오는 중...[생략]
- fixture users를 불러오는 중...[완료]
- fixture users_projects를 불러오는 중...[완료]
- fixture web_hooks를 불러오는 중...[생략]
- fixture wikis를 불러오는 중...[생략]
리포지터리를 복원 중:

- 리포지터리 abcd를 복원 중... [완료]
- Object pool 1 ...
임시 디렉터리 삭제 중...[완료]

이제, 이전에 언급된 대로 필요한 경우 /home/git/gitlab/.secret를 복원하십시오.

GitLab을 재시작합니다:

sudo service gitlab restart

백업에서 하나 또는 몇 개의 프로젝트 또는 그룹만 복원

GitLab 인스턴스를 복원하는 데 사용되는 Rake 작업이 단일 프로젝트나 그룹의 복원을 지원하지는 않지만, 복구를 위해 복원된 백업을 분리된 임시 GitLab 인스턴스에 복원한 다음 프로젝트나 그룹을 내보낼 수 있는 대체 방법을 사용할 수 있습니다:

  1. 복원하려는 백업된 인스턴스와 동일한 버전의 새로운 GitLab 인스턴스를 설치합니다.
  2. 이 새 인스턴스에 백업을 복원한 후, 여기서 프로젝트 또는 그룹을 내보냅니다. 내보내는 내용과 내보내지 않는 내용에 대한 자세한 정보는 내보내기 기능의 문서를 참조하십시오.
  3. 내보내기가 완료되면 이를 이전 인스턴스에 가져옵니다.
  4. 원하는 프로젝트나 그룹의 가져오기가 완료되면 새로운 임시 GitLab 인스턴스를 삭제할 수 있습니다.

개별 프로젝트나 그룹의 직접 복원을 제공하기 위한 기능 요청이 issue #17517에서 논의 중입니다.

증분 리포지터리 백업 복원

각 백업 아카이브는 증분 리포지터리 백업 절차를 통해 생성된 것을 포함한 완전한 독립형 백업을 포함합니다. 증분 리포지터리 백업을 복원하려면 다른 일반적인 백업 아카이브를 복원하는 것과 동일한 지침을 사용하십시오.

복원 옵션

GitLab이 제공하는 명령줄 도구는 더 많은 옵션을 허용합니다.

두 개 이상의 백업이 있는 상황에서 복원할 백업 지정

백업 파일은 백업 ID로 시작하는 명명 규칙을 사용합니다. 두 개 이상의 백업이 존재하는 경우, 환경 변수 BACKUP=<backup-id>를 설정하여 복원할 <backup-id>_gitlab_backup.tar 파일을 지정해야 합니다.

복원 중 프롬프트 비활성화

백업 복원 중, 복원 스크립트는 다음과 같은 확인 프롬프트를 나타냅니다.

  • authorized_keys에 쓰기 설정이 활성화되어 있는 경우, 복원 스크립트가 authorized_keys 파일을 삭제하고 다시 작성하기 전에 확인 프롬프트가 표시됩니다.
  • 데이터베이스를 복원하는 경우, 복원 스크립트가 모든 기존 테이블을 삭제하기 전에 확인 프롬프트가 표시됩니다.
  • 데이터베이스를 복원한 후, 스키마 복원 중 오류가 발생한 경우, 추가 문제가 발생할 가능성이 있으므로 계속하기 전에 확인 프롬프트가 표시됩니다.

이러한 프롬프트를 비활성화하려면, GITLAB_ASSUME_YES 환경 변수를 1로 설정합니다.

  • Linux 패키지 설치:

    sudo GITLAB_ASSUME_YES=1 gitlab-backup restore
    
  • 직접 컴파일한 설치:

    sudo -u git -H GITLAB_ASSUME_YES=1 bundle exec rake gitlab:backup:restore RAILS_ENV=production
    

force=yes 환경 변수도 이러한 프롬프트를 비활성화합니다.

복원에서 작업 제외

복원 중 특정 작업을 제외하려면, 환경 변수 SKIP을 추가합니다. SKIP의 값은 다음 옵션들의 쉼표로 구분된 디렉터리입니다:

  • db (데이터베이스)
  • uploads (첨부 파일)
  • builds (CI 작업 출력 로그)
  • artifacts (CI 작업 아티팩트)
  • lfs (LFS 객체)
  • terraform_state (테라폼 상태)
  • registry (컨테이너 레지스트리 이미지)
  • pages (페이지 콘텐츠)
  • repositories (Git 리포지터리 데이터)
  • packages (패키지)

특정 작업을 제외하려면:

  • Linux 패키지 설치:

    sudo gitlab-backup restore BACKUP=<백업-id> SKIP=db,uploads
    
  • 직접 컴파일한 설치:

    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<백업-id> SKIP=db,uploads RAILS_ENV=production
    

특정 리포지터리 스토리지 복원

여러 리포지터리 스토리지를 사용할 때, 특정 리포지터리 스토리지에서 리포지터리를 별도로 복원할 수 있습니다. 이를 위해 REPOSITORIES_STORAGES 옵션을 사용합니다. 이 옵션은 쉼표로 구분된 스토리지 이름 디렉터리을 허용합니다.

예:

  • Linux 패키지 설치:

    sudo gitlab-backup restore BACKUP=<백업-id> REPOSITORIES_STORAGES=리포지터리1,리포지터리2
    
  • 직접 컴파일한 설치:

    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<백업-id> REPOSITORIES_STORAGES=리포지터리1,리포지터리2
    

특정 리포지터리 복원

REPOSITORIES_PATHSSKIP_REPOSITORIES_PATHS 옵션을 사용하여 특정 리포지터리를 복원할 수 있습니다. 두 옵션 모두 프로젝트 및 그룹 경로의 쉼표로 구분된 디렉터리을 허용합니다. 그룹 경로를 지정하는 경우, 해당 그룹 및 하위 그룹에 있는 모든 프로젝트의 리포지터리가 포함되거나 건너뛰어집니다. 프로젝트 및 그룹 리포지터리는 지정된 백업 내에 존재해야 합니다.

예를 들어, Group A(group-a)의 모든 프로젝트에 대한 모든 리포지터리, Group B(group-b)의 Project C에 대한 리포지터리를 복원하고 Group A(group-a)의 Project D를 건너뛰려면:

  • Linux 패키지 설치:

    sudo gitlab-backup restore BACKUP=<백업-id> REPOSITORIES_PATHS=group-a,group-b/project-c SKIP_REPOSITORIES_PATHS=group-a/project-d
    
  • 직접 컴파일한 설치:

    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<백업-id> REPOSITORIES_PATHS=group-a,group-b/project-c SKIP_REPOSITORIES_PATHS=group-a/project-d
    

압축 해제된 백업 복원

만약 압축 해제된 백업 (SKIP=tar로 생성함)을 찾고, BACKUP=<백업-id>로 백업을 선택하지 않으면 압축 해제된 백업이 사용됩니다.

예를 들어:

  • Linux 패키지 설치:

    sudo gitlab-backup restore
    
  • 직접 컴파일한 설치:

    sudo -u git -H bundle exec rake gitlab:backup:restore
    

문제 해결

다음은 가능한 문제들과 그에 대한 해결책입니다.

Linux 패키지 설치에서 출력 경고를 사용하여 데이터베이스 복원

백업 복원 절차를 사용하는 경우, 다음과 같은 경고 메시지가 발생할 수 있습니다.

ERROR: must be owner of extension pg_trgm
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension plpgsql
WARNING:  no privileges could be revoked for "public" (two occurrences)
WARNING:  no privileges were granted for "public" (two occurrences)

이러한 경고 메시지에도 불구하고 백업은 성공적으로 복원됩니다.

Rake 작업은 gitlab 사용자로 실행되며, 이 사용자는 데이터베이스의 슈퍼유저 권한을 가지고 있지 않습니다. 복원이 시작되면, gitlab 사용자로 실행되지만 접근할 수 없는 오브젝트를 변경하려고 시도합니다. 이러한 오브젝트는 데이터베이스 백업이나 복원에 영향을 미치지 않지만, 경고 메시지가 표시됩니다.

자세한 정보는 다음을 참조하세요:

Git 서버 후크로 인한 복원 실패

백업으로부터 복원 중에, 다음 조건들이 해당된 경우 오류가 발생할 수 있습니다:

다음과 같은 오류가 발생합니다:

{"level":"fatal","msg":"restore: pipeline: 1 failures encountered:\n - @hashed/path/to/hashed_repository.git (path/to_project): manager: restore custom hooks, \"@hashed/path/to/hashed_repository/<BackupID>_<GitLabVersion>-ee/001.custom_hooks.tar\": rpc error: code = Internal desc = setting custom hooks: generating prepared vote: walking directory: copying file to hash: read /mnt/gitlab-app/git-data/repositories/+gitaly/tmp/default-repositories.old.<timestamp>.<temporaryfolder>/custom_hooks/compliance-triggers.d: is a directory\n","pid":3256017,"time":"2023-08-10T20:09:44.395Z"}

이를 해결하려면, Git 서버 후크를 GitLab 버전 15.11 이상용으로 업데이트하고 새로운 백업을 만듭니다.

fapolicyd를 사용하여 성공적으로 복원한 후 리포지터리가 비어있는 것으로 표시될 때

보안을 강화하기 위해 fapolicyd를 사용하는 경우, GitLab은 복원이 성공적이었음을 보고하지만 리포지터리가 비어 있는 것으로 표시할 수 있습니다. 더 많은 문제 해결 도움을 위해서는 Gitaly 문제 해결 문서를 참조하세요.