Omnibus GitLab 아키텍처 및 구성 요소

Omnibus GitLab은 Chef의 Omnibus 프로젝트의 맞춤형 포크이며, Chef 구성 요소인 쿠킹북과 레시피를 사용하여 사용자의 컴퓨터에서 GitLab을 구성하는 작업을 수행합니다. GitLab.com의 Omnibus GitLab 저장소는 Omnibus GitLab에 필요한 모든 구성 요소를 호스팅합니다. 여기에는 패키지를 빌드하는 데 필요한 Omnibus의 일부, 즉 구성 및 프로젝트 메타데이터와 설치 후 사용자의 컴퓨터에서 사용되는 Chef 관련 구성 요소가 포함됩니다.

Omnibus-GitLab 구성 요소

이 구성 요소에 대한 심층적인 비디오 워크스루는 YouTube에서 확인할 수 있습니다.

소프트웨어 정의

GitLab 프로젝트 정의 파일

Omnibus 아키텍처의 주요 구성 요소는 프로젝트 세부정보와 외부 소프트웨어 및 라이브러리에 대한 종속 관계를 나열하는 프로젝트 정의 파일입니다.

프로젝트 정의 파일의 주요 구성 요소는 다음과 같습니다:

  • 프로젝트 메타데이터: 프로젝트의 이름과 설명과 같은 속성을 포함합니다.
  • 프로젝트의 라이센스 세부정보.
  • 종속 목록: GitLab을 빌드하거나 실행하는 데 필요한 외부 도구 및 소프트웨어의 목록과 때때로 그 메타데이터입니다.
  • GitLab 설치에 사용되는 전역 구성 변수: 설치 디렉토리, 시스템 사용자 및 시스템 그룹을 포함합니다.

개별 소프트웨어 정의

Omnibus GitLab은 배터리가 포함된 배포 스타일을 따릅니다. GitLab 인스턴스의 적절한 기능에 필요한 모든 소프트웨어, 라이브러리 및 바이너리는 임베디드 형식으로 패키지의 일부로 제공됩니다.

따라서 Omnibus 아키텍처의 또 다른 주요 구성 요소는 소프트웨어 정의 및 구성입니다. 일반적인 소프트웨어 구성은 다음 부분으로 구성됩니다:

  • 필요한 소프트웨어의 버전.
  • 소프트웨어의 라이센스.
  • 소프트웨어가 빌드/실행되는 데 필요한 종속성.
  • 소프트웨어를 빌드하고 패키지 내에 포함시키는 데 필요한 명령.

때때로, 소프트웨어의 소스 코드는 GitLab과 함께 사용하기 위해 패치해야 할 수 있습니다. 이는 보안 취약점을 수정하거나, GitLab에 필요한 기능을 추가하거나, GitLab의 다른 구성 요소와 작동하도록 만들기 위해서입니다. 이를 위해 Omnibus GitLab은 서로 다른 소프트웨어에 대한 패치를 저장하는 패치 디렉터리를 포함합니다.

보다 광범위한 변경의 경우, 필요한 변경 사항을 미러에서 분기하여 추적하는 것이 더 편리할 수 있습니다. 이를 위해 따라야 할 패턴은 업스트림 태그나 sha로부터 분기를 만든 다음 그 분기점의 이름을 참조하는 것입니다. 예를 들어, Omnibus 코드베이스에서 gitlab-omnibus-v5.6.10은 업스트림 프로젝트의 v5.6.10 태그를 기반으로 합니다. 이를 통해 https://gitlab.com/gitlab-org/omnibus/compare/v5.6.10...gitlab-omnibus-v5.6.10와 같은 비교 링크를 생성하여 어떤 로컬 변경 사항이 존재하는지를 확인할 수 있습니다.

전역 GitLab 구성 템플릿

Omnibus GitLab은 사용자의 컴퓨터에 설치될 GitLab 인스턴스의 모든 부분을 구성하는 데 사용할 수 있는 단일 구성 파일을 포함하고 있습니다. 이 구성 파일은 GitLab 인스턴스에 적용될 모든 구성 설정의 표준 출처 역할을 합니다. 이 파일은 GitLab 인스턴스에 대한 일반 설정과 다양한 구성 요소에 대한 다양한 옵션을 나열합니다. 이 파일의 일반적인 구조는 <component>['<setting>'] = <value> 형식으로 지정된 구성을 포함합니다. 사용 가능한 모든 옵션은 구성 템플릿에 나열되어 있지만, GitLab의 기본 작동에 필요한 것 외의 모든 옵션은 기본적으로 주석 처리되어 있습니다. 사용자는 필요에 따라 주석을 제거하고 해당 값을 지정할 수 있습니다.

GitLab 요리책

Omnibus GitLab은 이전에 설명한 바와 같이 cookbooks, attributes, resources와 같은 여러 Chef 구성 요소를 사용합니다. GitLab EE는 GitLab CE가 사용하는 cookbook에서 확장된 별도의 cookbook를 사용하여 EE 전용 구성 요소를 추가합니다. Omnibus GitLab의 Chef 관련 부분에서 주요 역할을 하는 구성 요소는 다음과 같습니다:

기본 속성

기본 속성은 이름에서 알 수 있듯이, 구성 파일에서 제공되는 다양한 설정의 기본 값을 지정합니다. 이러한 값들은 fail-safe 역할을 하며 사용자가 설정에 값을 제공하지 않을 경우 사용되므로 최소한의 사용자 조정으로 작동하는 GitLab 인스턴스를 보장합니다.

레시피

레시피는 Omnibus 패키지를 사용하여 GitLab을 설치하는 동안 대부분의 중대한 작업을 수행합니다. 이들은 사용자의 컴퓨터에서 GitLab 생태계의 각 구성 요소를 설정하는 책임이 있습니다. 이들은 필요에 따라 파일, 디렉터리 및 링크를 생성하고, 해당 위치에 파일을 배치하며, 권한과 소유자를 설정하고, 필요한 서비스를 구성, 시작 및 중지하며, 파일이 변경되면 이러한 서비스에 알림을 보냅니다. default라는 이름의 마스터 레시피는 진입점 역할을 하며 다양한 구성 요소 및 서비스에 필요한 모든 레시피를 호출합니다.

사용자 정의 리소스

사용자 정의 리소스는 레시피 전역에서 사용할 수 있는 매크로로 볼 수 있습니다. 사용자 정의 리소스의 일반적인 용도로는 일반 서비스에 사용되는 포트를 정의하고 다양한 레시피에서 사용될 수 있는 중요한 디렉터리를 나열하는 것이 있습니다. 이들은 다양한 레시피에서 재사용할 수 있는 리소스를 정의합니다.

구성 요소의 구성 템플릿

앞서 언급했듯이, Omnibus GitLab은 GitLab 인스턴스의 모든 구성 요소를 조정하기 위한 단일 구성 파일을 제공합니다. 그러나 다양한 구성 요소의 아키텍처 설계로 인해 특정 위치에 각각의 구성 파일이 필요할 수 있습니다. 이러한 구성 파일은 일반 구성 파일에서 사용자가 지정한 값 또는 지정된 기본 값에서 생성되어야 합니다. 따라서 Omnibus GitLab은 이러한 구성 파일의 템플릿을 함께 제공하며, 기본 값이나 사용자 값으로 채워질 수 있는 자리 표시자를 포함합니다. 레시피는 이러한 템플릿을 채우고 필요에 따라 해당 위치에 배치하는 작업을 수행합니다.

일반 라이브러리 메서드

Omnibus GitLab은 또한 주로 코드 재사용을 목적으로 하는 라이브러리 메서드를 함께 제공합니다. 여기에는 서비스가 실행 중인지 확인하는 방법, 파일이 존재하는지 확인하는 방법 및 다양한 구성 요소와 상호작용하는 도우미 방법이 포함됩니다. 이들은 종종 Chef 레시피에서 사용됩니다.

Omnibus GitLab에서 사용되는 모든 라이브러리 중에는 몇 가지 특별한 라이브러리가 있습니다: 주 GitLab 모듈과 그에 의해 호출되는 모든 구성 요소별 라이브러리입니다. 구성 요소별 라이브러리는 해당 구성 요소에 대해 정의된 설정을 위한 구성 파일을 파싱하는 작업을 수행하는 메서드를 포함합니다. 주 GitLab 모듈은 이를 조정하는 메서드를 포함합니다. 이는 기본 값을 식별하고, 구성 요소별 라이브러리를 호출하며, 기본 값과 사용자 지정 값을 병합하고, 이를 검증하고, 초기 값을 기반으로 추가 구성을 생성하는 역할을 합니다. Omnibus GitLab 패키지에 포함된 모든 최상위 구성 요소는 이 모듈에 추가되어 구성 파일 및 기본 속성에서 언급할 수 있고 올바르게 파싱될 수 있습니다.

runit

GitLab은 runit 레시피를 사용하여

서비스 관리 및 감독을 수행합니다. runit 레시피는 OS에 의해 사용되는 init 시스템을 식별하고 GitLab에 필요한 서비스 파일을 생성하고, 서비스를 활성화하며, 서비스를 다시 로드하는 기본 서비스 관리 작업을 수행합니다. runit은 다른 레시피에서 서비스를 상호작용하는 데 사용할 수 있는 runit_service 정의를 제공합니다. 추가 정보는 /files/gitlab-cookbooks/runit를 참조하세요.

Services

서비스는 runit 프로세스 init/감독을 사용하여 실행하는 소프트웨어 프로세스입니다. 사용자 gitlab-ctl 명령을 사용하여 상태를 확인하고, 시작하고, 중지하며, 다시 시작할 수 있습니다. 레시피는 또한 GitLab 인스턴스에 대해 구성된 프로세스 그룹 및 설정/역할에 따라 이러한 서비스를 비활성화하거나 활성화할 수 있습니다. 서비스와 이와 관련된 서비스 그룹의 목록은 files/gitlab-cookbooks/package/libraries/config/services.rb에서 확인할 수 있습니다.

Additional gitlab-ctl commands

Omnibus는 기본적으로 GitLab 인스턴스를 관리하기 위해 gitlab-ctl reconfiguregitlab-ctl restart와 같은 몇 가지 래퍼 명령을 제공합니다. 특정 사용 사례를 해결하기 위한 추가 래퍼 명령이 있습니다. 이러한 명령은 데이터베이스 마이그레이션 실행 또는 휴면 계정을 제거하는 등의 특정 작업을 수행하기 위해 일반 gitlab-ctl 명령과 함께 사용됩니다.

Tests

Omnibus GitLab 리포지토리는 ChefSpec을 사용하여 요리책과 레시피를 테스트합니다. 일반적인 전략은 레시피를 확인하여 두 가지(또는 그 이상)의 조건에서 올바르게 작동하는지 확인하는 것입니다: 사용자가 해당 구성 사항을 지정하지 않거나(즉, 기본값을 사용하는 경우) 사용자가 지정한 구성을 사용하는 경우입니다. 테스트는 파일이 올바른 위치에 생성되었는지, 서비스가 시작/중지/알림되고 있는지, 올바른 바이너리가 호출되고 있는지 및 메서드 호출에 올바른 매개변수가 전달되고 있는지를 확인하는 것을 포함할 수 있습니다. 레시피 및 라이브러리 메서드는 관련된 테스트를 가지고 있습니다. Omnibus GitLab은 테스트 프로세스를 지원하기 위해 일부 지원 메서드 또는 매크로를 사용합니다. 테스트는 전체 테스트 스위트를 실행하는 데 필요한 시간을 줄이기 위해 가능한 경우 병렬화할 수 있도록 호환되도록 정의됩니다.

따라서 위에서 설명한 구성 요소 중 일부(소프트웨어 정의, 프로젝트 메타데이터 및 테스트와 같은)는 패키지 빌드 중에 사용되며, 일부(셰프 요리책 및 레시피, GitLab 구성 파일, runit 및 gitlab-ctl 명령 등)는 사용자가 설치한 인스턴스를 구성하는 데 사용됩니다.

Work life cycle of Omnibus GitLab

What happens during package building

패키지 빌드의 유형은 빌드 프로세스가 실행되는 OS에 따라 달라집니다. 빌드가 Debian 환경에서 수행되면 .deb 패키지가 생성됩니다. 패키지 빌드 중에 발생하는 일은 다음 단계로 요약할 수 있습니다.

  1. 종속 소프트웨어의 소스 가져오기:
    1. 소프트웨어 정의를 구문 분석하여 해당 버전을 확인합니다.
    2. 원격 또는 캐시에서 소스 코드를 가져옵니다.
  2. 개별 소프트웨어 구성 요소 빌드:
    1. 필요한 환경 변수 및 플래그를 설정합니다.
    2. 해당되는 경우 패치를 적용합니다.
    3. 구성 요소를 빌드하고 설치하는 작업을 수행합니다. 이는 /opt/gitlab 내의 적절한 위치에 설치되는 것입니다.
  3. 번들된 모든 구성 요소의 라이선스 정보를 생성합니다. 외부 소프트웨어, Ruby gems 및 JS 모듈이 포함됩니다. 이는 각 종속 항목의 정의와 구성 요소에 의해 제공된 추가 라이선스 문서(예: GitLab Rails에 의해 제공된 licenses.csv 파일)를 분석하는 것을 포함합니다.

  4. 호환되지 않는 라이선스를 가진 구성 요소를 포함하지 않도록 구성 요소의 라이선스를 확인합니다.

  5. 바이너리가 사용 가능한 라이브러리에 연결되어 있는지 확인하기 위해 패키지에 대한 상태 검사를 실행합니다. 번들된 라이브러리의 경우 바이너리는 전역에서 사용 가능한 라이브러리가 아닌 해당 라이브러리에 연결되어야 합니다.

  6. /opt/gitlab의 내용을 포함하여 패키지를 빌드합니다. 이는 gitlab.rb 파일 내에 제공된 메타데이터를 활용합니다. 여기에는 패키지 이름, 버전, 유지 관리자, 홈페이지, 및 다른 패키지와의 충돌에 대한 정보가 포함됩니다.

캐싱

Omnibus는 빌드 프로세스를 최적화하기 위해 두 가지 유형의 캐시를 사용합니다: 하나는 소프트웨어 아티팩트(종속 소프트웨어의 소스)를 저장하기 위한 것이고, 다른 하나는 각 소프트웨어 구성 요소가 빌드된 후 프로젝트 트리를 저장하기 위한 것입니다.

소프트웨어 아티팩트 캐시 (GitLab Inc 빌드용)

소프트웨어 아티팩트 캐시는 종속 소프트웨어의 소스를 저장하기 위해 Amazon S3 버킷을 사용합니다. 우리의 빌드 프로세스에서 이 캐시는 bin/omnibus cache populate 명령을 사용하여 채워집니다. 이는 Amazon 버킷에서 필요한 모든 소프트웨어 소스를 가져와 필요한 위치에 저장합니다. 소프트웨어의 버전 요구 사항에 변화가 있을 경우, omnibus는 원래의 upstream에서 소스를 가져와 아티팩트 캐시에 추가합니다. 이 과정은 omnibus 내부에서 이루어지며, 우리는 omnibus.rb 파일에서 사용할 Amazon 버킷을 구성합니다. 이 캐시는 원래의 upstream 원격이 다운되더라도 종속 소프트웨어의 가용성을 보장합니다.

빌드 캐시

우리의 빌드 프로세스에서 중요한 역할을 하는 두 번째 유형의 캐시는 빌드 캐시입니다. 빌드 캐시는 각 종속 소프트웨어가 빌드된 후의 프로젝트 트리의 스냅샷으로 설명될 수 있습니다(프로젝트가 빌드되는 위치 - /opt/gitlab). 다섯 개의 종속 소프트웨어 - A, B, C, D, E가 그 순서대로 빌드된다고 가정해 보겠습니다. 우리는 그들의 의존성을 고려하지 않습니다. 빌드 캐시는 Git 태그를 활용하여 스냅샷을 만듭니다. 각 소프트웨어가 빌드된 후, Git 태그가 계산되어 커밋됩니다. 이제 소프트웨어 D의 정의에 몇 가지 변경을 했다고 가정해 보겠습니다. A, B, C 및 E는 동일합니다. 다시 빌드를 시도할 때, omnibus는 이전 빌드에서 D가 빌드되기 전에 만들어졌던 스냅샷을 재사용할 수 있습니다. 따라서 A, B 및 C를 빌드하는 데 소요되는 시간을 절약할 수 있습니다. Omnibus는 캐시를 더럽히는 소프트웨어가 빌드되기 직전의 스냅샷을 사용합니다(더럽히는 것은 소프트웨어 정의의 변화, 이전 구성 요소의 이름/버전 변화, 또는 현재 구성 요소의 버전 변화로 인해 발생할 수 있습니다). 마찬가지로, 만약 빌드 과정에서 소프트웨어 A의 정의에 변경이 생기면 캐시가 더럽혀지고, 따라서 A와 모든 후속 종속성이 처음부터 다시 빌드됩니다. C가 캐시를 더럽히면 A와 B는 재사용되고 C, D 및 E는 처음부터 다시 빌드됩니다.

이 캐시는 빌드 간에 유지될 때만 의미가 있습니다. 이를 위해 우리는 GitLab CI의 캐싱 메커니즘을 사용합니다. 우리는 내부 캐시를 Amazon 버킷에 저장하도록 구성된 전용 러너가 있습니다. 각 빌드 전에 이 캐시를 가져오고(restore_cache_bundle 목표는 우리의 Makefile에 있습니다), 이를 적절한 위치로 이동한 후 빌드를 시작합니다. 빌드 캐시는 더럽혀질 때까지 omnibus에 의해 사용됩니다. 빌드 후, 새로운 캐시를 패킹하고 CI에 이를 Amazon 버킷에 백업하도록 지시합니다(pack_cache_bundle는 우리의 Makefile에 있습니다).

두 가지 유형의 캐시는 GitLab과 외부 요소에 대한 의존성의 전체 빌드 시간을 줄입니다.

캐시 메커니즘은 다음과 같이 요약될 수 있습니다:

  1. 각 소프트웨어 종속성에 대해:
    1. 정의를 파싱하여 버전과 SHA256을 이해합니다.
    2. Amazon 버킷의 아티팩트 캐시에서 소스 파일 tarball이 버전과 SHA256과 일치하면 사용합니다.
    3. 그렇지 않으면, upstream 원격에서 올바른 tarball을 다운로드합니다.
  2. CI 캐시에서 캐시를 가져옵니다.
  3. 각 소프트웨어 종속성에 대해:
    1. 만약 캐시가 더럽혀졌다면, 루프를 종료합니다.
    2. 그렇지 않으면, 스냅샷을 체크아웃합니다.
  4. 남아 있는 종속성이 있다면:
    1. 각 남아 있는 종속성에 대해:
      1. 종속성을 빌드합니다.
      2. 스냅샷을 만들고 커밋합니다.
  5. 새로운 빌드 캐시를 CI 캐시에 푸시합니다.

여러 데이터베이스

이전에 GitLab Rails 애플리케이션은 Omnibus GitLab 데이터베이스에 연결된 유일한 클라이언트였습니다. 시간이 지나면서 이러한 사항이 변경되었습니다:

  • Praefect와 Container Registry는 각각의 데이터베이스를 사용합니다.

  • Rails 애플리케이션은 이제 분해된 데이터베이스를 사용합니다.

추가 데이터베이스가 필요할 수 있으므로:

  • 다중 데이터베이스 청사진에서는 새로운 구성 요소 및 기능에 대해 Omnibus GitLab에 데이터베이스 지원을 추가하는 방법을 설명합니다.

  • 동반 개발 문서에서는 구현 모델에 대한 세부정보를 제공하고 데이터베이스 지원 추가의 예를 제공합니다.