GitLab 클러스터 구성

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

다음 방법 중 하나를 사용하여 GitLab 클러스터를 구성하세요:

소규모 GitLab 설치의 경우 Gitaly 자체만 필요할 수 있습니다.

note
GitLab 클러스터는 아직 Kubernetes, Amazon ECS 또는 유사한 컨테이너 환경을 지원하지 않습니다. 자세한 내용은 epic 6127를 참조하세요.

요구 사항

Gitaly 클러스터에 대한 최소 권장 구성은 다음을 요구합니다:

  • 로드 밸런서 1개
  • PostgreSQL 서버 1개 (PostgreSQL 11 이상)
  • Praefect 노드 3개
  • Gitaly 노드 3개 (1개 기본, 2개 보조)

트랜잭션이 하나의 Gitaly 노드가 실패할 경우에 대비해 중재자를 가질 수 있도록 홀수 개의 Gitaly 노드를 구성해야 합니다.

구현 세부정보는 설계 문서를 참조하세요.

note
GitLab에서 설정되지 않은 경우, 기능 플래그는 콘솔에서 false로 읽혀지고 Praefect는 기본 값을 사용합니다. 기본 값은 GitLab 버전에 따라 다릅니다.

네트워크 지연 및 연결성

Gitaly 클러스터를 위한 네트워크 지연은 이상적으로 1자리 수 밀리초로 측정할 수 있어야 합니다. 지연은 특히 다음에 중요합니다:

  • Gitaly 노드 상태 점검. 노드는 1초 이내에 응답할 수 있어야 합니다.
  • 강한 일관성을 enforcing하는 참조 트랜잭션. 낮은 지연 시간은 Gitaly 노드가 변경 사항에 대해 더 빠르게 합의할 수 있음을 의미합니다.

Gitaly 노드 간의 수용 가능한 지연 시간을 달성하기:

  • 물리적 네트워크에서는 일반적으로 높은 대역폭, 단일 위치 연결을 의미합니다.
  • 클라우드에서는 일반적으로 같은 지역에서, 교차 가용성 영역 복제를 허용하는 것을 의미합니다. 이러한 링크는 이러한 유형의 동기화에 적합하도록 설계되었습니다. Gitaly 클러스터에는 2ms 미만의 지연 시간이 충분해야 합니다.

복제를 위한 낮은 네트워크 지연을 제공할 수 없는 경우(예를 들어, 먼 위치 간), Geo를 고려하세요. 자세한 내용은 Geo와의 비교를 참조하세요.

Gitaly 클러스터의 구성 요소는 여러 경로를 통해 서로 통신합니다. Gitaly 클러스터가 제대로 작동하려면 방화벽 규칙이 다음을 허용해야 합니다:

From To Default port TLS port
GitLab Praefect load balancer 2305 3305
Praefect load balancer Praefect 2305 3305
Praefect Gitaly 8075 9999
Praefect GitLab (internal API) 80 443
Gitaly GitLab (internal API) 80 443
Gitaly Praefect load balancer 2305 3305
Gitaly Praefect 2305 3305
Gitaly Gitaly 8075 9999
note
Gitaly는 Praefect에 직접 연결되지 않습니다. 그러나 Gitaly에서 Praefect 로드 밸런서로의 요청은 Gitaly 노드에서 트래픽을 허용하지 않는 한 차단될 수 있습니다.

Praefect 데이터베이스 저장소

요구 사항은 상대적으로 낮습니다. 데이터베이스에는 다음의 메타데이터만 포함되어 있습니다:

  • 저장소가 위치한 곳.
  • 일부 대기 작업.

저장소의 수에 따라 다르지만, 최소 5-10 GB가 적절하며, 이는 주요 GitLab 애플리케이션 데이터베이스와 유사합니다.

설정 지침

Linux 패키지를 사용하여 GitLab을 설치한 경우(강력히 권장), 아래 단계를 따르세요:

  1. 준비
  2. Praefect 데이터베이스 구성
  3. Praefect 프록시/라우터 구성
  4. 각 Gitaly 노드 구성 (각 Gitaly 노드당 한 번)
  5. 로드 밸런서 구성
  6. GitLab 서버 구성 업데이트
  7. Grafana 구성

준비

시작하기 전에 작동하는 GitLab 인스턴스가 있어야 합니다.

GitLab 설치 방법을 알아보세요.

PostgreSQL 서버를 준비하십시오. Linux 패키지와 함께 제공되는 PostgreSQL을 사용하고 이를 통해 PostgreSQL 데이터베이스를 구성해야 합니다. 외부 PostgreSQL 서버(버전 11 이상)를 사용할 수 있지만 수동으로 설정해야 합니다.

새로운 노드를 모두 준비하려면 GitLab을 설치하십시오. 필요한 사항은:

  • 1 PostgreSQL 노드
  • 1 PgBouncer 노드 (선택 사항)
  • 최소 1 Praefect 노드 (필요한 최소 저장소)
  • 3 Gitaly 노드 (고 CPU, 고 메모리, 빠른 저장소)
  • 1 GitLab 서버

각 노드의 IP/호스트 주소도 필요합니다:

  1. PRAEFECT_LOADBALANCER_HOST: Praefect 로드 밸런서의 IP/호스트 주소
  2. POSTGRESQL_HOST: PostgreSQL 서버의 IP/호스트 주소
  3. PGBOUNCER_HOST: PostgreSQL 서버의 IP/호스트 주소
  4. PRAEFECT_HOST: Praefect 서버의 IP/호스트 주소
  5. GITALY_HOST_*: 각 Gitaly 서버의 IP 또는 호스트 주소
  6. GITLAB_HOST: GitLab 서버의 IP/호스트 주소

Google Cloud Platform, SoftLayer 또는 다른 벤더를 사용하는 경우, 각 클라우드 인스턴스에 대한 사설 주소( Google Cloud Platform의 경우 “내부 주소”에 해당)를 사용할 수 있습니다. PRAEFECT_HOST, GITALY_HOST_*, 및 GITLAB_HOST에 대해.

비밀

구성 요소 간의 통신은 다양한 비밀로 안전하게 보호되며, 아래에 설명되어 있습니다. 시작하기 전에 각 비밀에 대해 고유한 비밀을 생성하고 기록해 두십시오. 이렇게 하면 설치 프로세스를 완료할 때 이러한 자리 표시자 토큰을 안전한 토큰으로 교체할 수 있습니다.

  1. GITLAB_SHELL_SECRET_TOKEN: Git 푸시를 수락할 때 GitLab에 HTTP API 요청을 하도록 Git 훅이 사용합니다. 이 비밀은 전통적인 이유로 GitLab Shell과 공유됩니다.
  2. PRAEFECT_EXTERNAL_TOKEN: Praefect 클러스터에 호스팅된 저장소에는 이 토큰을 가진 Gitaly 클라이언트만 액세스할 수 있습니다.
  3. PRAEFECT_INTERNAL_TOKEN: 이 토큰은 Praefect 클러스터 내에서 복제 트래픽에 사용됩니다. 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 구별되며, Gitaly 클라이언트가 Praefect 클러스터의 내부 노드에 직접 액세스해서는 안 됩니다. 그렇지 않으면 데이터 손실이 발생할 수 있습니다.
  4. PRAEFECT_SQL_PASSWORD: 이 비밀번호는 Praefect가 PostgreSQL에 연결하는 데 사용됩니다.
  5. PRAEFECT_SQL_PASSWORD_HASH: Praefect 사용자의 비밀번호 해시입니다. gitlab-ctl pg-password-md5 praefect를 사용하여 해시를 생성합니다. 이 명령은 praefect 사용자에 대한 비밀번호를 요청합니다. PRAEFECT_SQL_PASSWORD 평문 비밀번호를 입력하십시오. 기본적으로 Praefect는 praefect 사용자를 사용하지만 변경할 수 있습니다.
  6. PGBOUNCER_SQL_PASSWORD_HASH: PgBouncer 사용자의 비밀번호 해시입니다. PgBouncer는 PostgreSQL에 연결하기 위해 이 비밀번호를 사용합니다. 자세한 내용은 번들 PgBouncer 문서를 참조하십시오.

아래 지침에서 이러한 비밀이 필요한 위치를 주목합니다.

참고: Linux 패키지 설치는 GITLAB_SHELL_SECRET_TOKEN에 대해 gitlab-secrets.json을 사용할 수 있습니다.

시간 서버 설정 사용자 정의

기본적으로 Gitaly와 Praefect 노드는 시간 동기화 확인을 위해 pool.ntp.org의 시간 서버를 사용합니다. 이 설정은 각 노드의 gitlab.rb에 다음을 추가하여 사용자 정의할 수 있습니다:

  • Gitaly 노드의 경우: gitaly['env'] = { "NTP_HOST" => "ntp.example.com" }
  • Praefect 노드의 경우: praefect['env'] = { "NTP_HOST" => "ntp.example.com" }

PostgreSQL

참고: Geo를 사용하는 경우 GitLab 애플리케이션 데이터베이스와 Praefect 데이터베이스를 동일한 PostgreSQL 서버에 저장하지 마십시오.

복제 상태는 각 GitLab 인스턴스 내부에 있으며 복제해서는 안 됩니다.

이 지침은 단일 PostgreSQL 데이터베이스를 설정하는 데 도움이 되며, 이는 단일 실패 지점을 만듭니다. 이를 피하기 위해 클러스터형 PostgreSQL을 구성할 수 있습니다. Linux 패키지를 사용한 PostgreSQL 복제 및 장애 조치에 대한 지원은 에픽 7814에서 제안되고 있습니다.

다른 데이터베이스(예: Praefect 및 Geo 데이터베이스)에 대한 클러스터형 데이터베이스 지원은 이슈 7292에서 제안되고 있습니다.

사용 가능한 옵션은 다음과 같습니다:

  • 비-Geo 설치의 경우, 다음 중 하나를 선택하십시오:
    • 문서화된 PostgreSQL 설정 중 하나를 사용합니다.
    • 자체 타사 데이터베이스 설정을 사용합니다. 이는 수동 설정이 필요합니다.
  • Geo 인스턴스의 경우, 다음 중 하나를 선택하십시오:

PostgreSQL 설정 시 빈 Praefect 테이블이 생성됩니다. 자세한 정보는 관련 문제 해결 섹션을 참조하세요.

GitLab 및 Praefect 데이터베이스를 동일한 서버에서 실행

GitLab 애플리케이션 데이터베이스와 Praefect 데이터베이스를 동일한 서버에서 실행할 수 있습니다. 그러나 PostgreSQL을 Linux 패키지에서 사용하는 경우 Praefect는 자체 데이터베이스 서버를 가져야 합니다. 장애 조치가 발생하면 Praefect는 인식하지 못하고 사용하려는 데이터베이스가 다음과 같이 되어 실패하기 시작합니다:

  • 사용 불가능.
  • 읽기 전용 모드.

수동 데이터베이스 설정

이 섹션을 완료하려면 다음이 필요합니다:

  • 하나의 Praefect 노드
  • 하나의 PostgreSQL 노드 (버전 11 이상)
    • 데이터베이스 서버를 관리할 수 있는 권한을 가진 PostgreSQL 사용자

이 섹션에서는 PostgreSQL 데이터베이스를 구성합니다. 이는 외부 및 Linux 패키지 제공 PostgreSQL 서버 모두에 사용할 수 있습니다.

다음 지침을 수행하려면 Praefect 노드를 사용할 수 있으며, 이곳에는 Linux 패키지로 설치된 psql이 있습니다 (/opt/gitlab/embedded/bin/psql). Linux 패키지 제공 PostgreSQL을 사용하는 경우 PostgreSQL 노드에서 gitlab-psql을 사용할 수 있습니다:

  1. Praefect에서 사용할 새 사용자 praefect를 생성합니다:

    CREATE ROLE praefect WITH LOGIN PASSWORD 'PRAEFECT_SQL_PASSWORD';
    

    PRAEFECT_SQL_PASSWORD를 준비 단계에서 생성한 강력한 비밀번호로 교체하십시오.

  2. praefect 사용자가 소유하는 새로운 데이터베이스 praefect_production을 생성합니다.

    CREATE DATABASE praefect_production WITH OWNER praefect ENCODING UTF8;
    

Linux 패키지 제공 PgBouncer를 사용할 때는 다음 추가 단계를 수행해야 합니다. 우리는 Linux 패키지와 함께 제공되는 PostgreSQL을 백엔드로 사용하는 것을 강력히 권장합니다. 다음 지침은 Linux 패키지 제공 PostgreSQL에서만 작동합니다:

  1. Linux 패키지 제공 PgBouncer의 경우, 실제 비밀번호 대신 praefect 비밀번호의 해시를 사용해야 합니다:

    ALTER ROLE praefect WITH PASSWORD 'md5<PRAEFECT_SQL_PASSWORD_HASH>';
    

    <PRAEFECT_SQL_PASSWORD_HASH>를 준비 단계에서 생성한 비밀번호의 해시로 교체하십시오. 해시 앞에는 md5 리터럴이 접두어로 붙습니다.

  2. Linux 패키지와 함께 제공되는 PgBouncer는 auth_query를 사용하도록 구성되어 있으며 pg_shadow_lookup 함수를 사용합니다. 이 함수를 praefect_production 데이터베이스에 생성해야 합니다:

    CREATE OR REPLACE FUNCTION public.pg_shadow_lookup(in i_username text, out username text, out password text) RETURNS record AS $$
    BEGIN
        SELECT usename, passwd FROM pg_catalog.pg_shadow
        WHERE usename = i_username INTO username, password;
        RETURN;
    END;
    $$ LANGUAGE plpgsql SECURITY DEFINER;
    
    REVOKE ALL ON FUNCTION public.pg_shadow_lookup(text) FROM public, pgbouncer;
    GRANT EXECUTE ON FUNCTION public.pg_shadow_lookup(text) TO pgbouncer;
    

Praefect에서 사용하는 데이터베이스가 이제 구성되었습니다.

이제 Praefect가 데이터베이스를 사용하도록 구성할 수 있습니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: POSTGRESQL_HOST,
      user: 'praefect',
      port: 5432,
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
   }
}

PostgreSQL을 구성한 후 Praefect 데이터베이스 오류가 발생하면 문제 해결 단계를 참조하십시오.

읽기 배포 캐싱

Praefect 성능은 session_pooled 설정을 추가로 구성하여 개선할 수 있습니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      session_pooled: {
         # ...
         host: POSTGRESQL_HOST,
         port: 5432

         # 직접 데이터베이스 연결의 매개변수를 재정의하려면 아래를 사용하십시오.
         # 두 연결의 매개변수가 동일한 경우 주석 처리하십시오.
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      }
   }
}

구성하면 이 연결은 자동으로 SQL LISTEN 기능에 사용되며 Praefect가 캐시 무효화에 대한 PostgreSQL의 알림을 수신할 수 있게 합니다.

이 기능이 작동하는지 확인하려면 Praefect 로그에서 다음 로그 항목을 찾으십시오:

reads distribution caching is enabled by configuration

PgBouncer 사용

PostgreSQL 리소스 소비를 줄이기 위해 PostgreSQL 인스턴스 앞에 PgBouncer를 설정하고 구성해야 합니다. 그러나 Praefect는 연결 수가 적기 때문에 PgBouncer가 필요하지 않습니다. PgBouncer를 사용하기로 선택하면 GitLab 애플리케이션 데이터베이스와 Praefect 데이터베이스 모두에 대해 동일한 PgBouncer 인스턴스를 사용할 수 있습니다.

PgBouncer를 PostgreSQL 인스턴스 앞에 구성하려면 Praefect의 데이터베이스 매개변수를 설정하여 Praefect를 PgBouncer에 지정해야 합니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: PGBOUNCER_HOST,
      port: 6432,
      user: 'praefect',
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      # sslmode: '...',
      # sslcert: '...',
      # sslkey: '...',
      # sslrootcert: '...',
   }
}

Praefect는 LISTEN 기능을 지원하는 PostgreSQL에 추가 연결이 필요합니다. PgBouncer와 함께 이 기능은 session 풀 모드 (pool_mode = session)에서만 사용할 수 있습니다. transaction 풀 모드 (pool_mode = transaction)에서는 지원되지 않습니다.

추가 연결을 구성하려면 다음 중 하나를 수행해야 합니다:

  • 동일한 PostgreSQL 데이터베이스 엔드포인트를 사용하는 새 PgBouncer 데이터베이스를 구성하되, 다른 풀 모드 (pool_mode = session)를 설정합니다.
  • Praefect를 PostgreSQL에 직접 연결하고 PgBouncer를 우회합니다.

pool_mode = session으로 새 PgBouncer 데이터베이스 구성

session 풀 모드로 PgBouncer를 사용해야 합니다. 번들 PgBouncer를 사용하거나 외부 PgBouncer를 사용하여 수동으로 구성할 수 있습니다.

다음 예제는 번들 PgBouncer를 사용하고 PostgreSQL 호스트에서 두 개의 별도 연결 풀을 설정합니다. 하나는 session 풀 모드이고 다른 하나는 transaction 풀 모드입니다. 이 예제가 작동하려면 설치 지침에 설명된 대로 PostgreSQL 서버를 준비해야 합니다:

pgbouncer['databases'] = {
  # gitlabhq_production을 포함한 다른 데이터베이스 구성
  ...

  praefect_production: {
    host: POSTGRESQL_HOST,
    # 데이터베이스 백엔드에 연결하려면 `pgbouncer` 사용자를 사용합니다.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    pool_mode: 'transaction'
  },
  praefect_production_direct: {
    host: POSTGRESQL_HOST,
    # 데이터베이스 백엔드에 연결하려면 `pgbouncer` 사용자를 사용합니다.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    dbname: 'praefect_production',
    pool_mode: 'session'
  },

  ...
}

# praefect 사용자가 PgBouncer에 연결할 수 있도록 허용
pgbouncer['users'] = {
  'praefect': {
    'password': PRAEFECT_SQL_PASSWORD_HASH,
  }
}

praefect_productionpraefect_production_direct는 동일한 데이터베이스 엔드포인트 (praefect_production)를 사용하지만 서로 다른 풀 모드를 사용합니다. 이는 PgBouncer의 다음 databases 섹션으로 변환됩니다:

[databases]
praefect_production = host=POSTGRESQL_HOST auth_user=pgbouncer pool_mode=transaction
praefect_production_direct = host=POSTGRESQL_HOST auth_user=pgbouncer dbname=praefect_production pool_mode=session

이제 두 연결 모두를 위해 PgBouncer를 사용하도록 Praefect를 구성할 수 있습니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      host: PGBOUNCER_HOST,
      port: 6432,
      user: 'praefect',
      # `PRAEFECT_SQL_PASSWORD`는 Praefect 사용자의 일반 텍스트 비밀번호입니다.
      # `PRAEFECT_SQL_PASSWORD_HASH`와 혼동하지 마십시오.
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      session_pooled: {
         # ...
         dbname: 'praefect_production_direct',
         # 다음 항목을 반복할 필요는 없습니다. 직접 데이터베이스 연결의 
         # 매개변수는 위의 값으로 돌아갑니다.
         #
         # host: PGBOUNCER_HOST,
         # port: 6432,
         # user: 'praefect',
         # password: PRAEFECT_SQL_PASSWORD,
      },
   },
}

이 구성을 통해 Praefect는 두 연결 유형 모두에 대해 PgBouncer를 사용합니다.

참고:

리눅스 패키지 설치는 인증 요구 사항을 처리합니다( auth_query 사용), 하지만 데이터베이스를 수동으로 준비하고 외부 PgBouncer를 구성하는 경우 PgBouncer에서 사용되는 파일에 praefect 사용자와 그 비밀번호를 포함해야 합니다. 예를 들어, auth_file 구성 옵션이 설정된 경우 userlist.txt에 포함해야 합니다. 더 많은 자세한 내용은 PgBouncer 문서를 참조하세요.

Praefect를 PostgreSQL에 직접 연결하도록 구성하기

session 풀 모드로 PgBouncer를 구성하는 대신, Praefect는 PostgreSQL에 직접 접근하기 위한 다양한 연결 매개변수를 사용할 수 있습니다. 이 연결은 LISTEN 기능을 지원합니다.

PgBouncer를 우회하고 PostgreSQL에 직접 연결하는 Praefect 구성의 예:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      session_pooled: {
         # ...
         host: POSTGRESQL_HOST,
         port: 5432,

         # 직접 데이터베이스 연결의 매개변수를 재정의하려면 다음을 사용합니다.
         # 두 연결 모두에 대해 매개변수가 동일한 경우 주석 처리하세요.
         #
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      },
   },
}

Praefect

여러 개의 Praefect 노드가 있는 경우:

  1. 한 노드를 배포 노드로 지정하고 다음 단계에 따라 구성합니다.
  2. 추가 노드마다 다음 단계를 완료합니다.

이 섹션을 완료하려면 구성된 PostgreSQL 서버가 필요합니다:

경고: Praefect는 전용 노드에서 실행해야 합니다. Praefect를 애플리케이션 서버나 Gitaly 노드에서 실행하지 마십시오.

Praefect 노드에서:

  1. /etc/gitlab/gitlab.rb를 수정하여 모든 다른 서비스를 비활성화합니다:
   # Praefect 서버에서 불필요한 서비스가 실행되지 않도록 합니다.
   gitaly['enable'] = false
   postgresql['enable'] = false
   redis['enable'] = false
   nginx['enable'] = false
   puma['enable'] = false
   sidekiq['enable'] = false
   gitlab_workhorse['enable'] = false
   prometheus['enable'] = false
   alertmanager['enable'] = false
   gitlab_exporter['enable'] = false
   gitlab_kas['enable'] = false

   # 오직 Praefect 서비스만 활성화합니다.
   praefect['enable'] = true

   # 업그레이드 시 데이터베이스 마이그레이션이 자동으로 실행되지 않도록 방지합니다.
   praefect['auto_migrate'] = false
   gitlab_rails['auto_migrate'] = false
  1. /etc/gitlab/gitlab.rb를 수정하여 Praefect가 네트워크 인터페이스에서 수신 대기하도록 구성합니다:

    praefect['configuration'] = {
       # ...
       listen_addr: '0.0.0.0:2305',
    }
    
  2. /etc/gitlab/gitlab.rb를 수정하여 Prometheus 메트릭을 구성합니다:

    praefect['configuration'] = {
       # ...
       #
       # Praefect에 대한 Prometheus 메트릭 접근을 활성화합니다. 이 주소/포트에 대한 접근을 제한하려면 방화벽을 사용해야 합니다.
       # 기본 메트릭 엔드포인트는 /metrics입니다.
       prometheus_listen_addr: '0.0.0.0:9652',
       # 일부 메트릭은 데이터베이스에 대한 쿼리를 실행합니다. 별도의 데이터베이스 메트릭을 활성화하면
       # 메트릭이 별도의 /db_metrics 엔드포인트에서 수집될 수 있습니다.
       prometheus_exclude_database_from_default_metrics: true,
    }
    
  3. 클러스터 외부의 클라이언트(예: GitLab Shell)가 Praefect 클러스터와 통신하는 데 필요한 강력한 인증 토큰을 /etc/gitlab/gitlab.rb에서 구성합니다:

    praefect['configuration'] = {
       # ...
       auth: {
          # ...
          token: 'PRAEFECT_EXTERNAL_TOKEN',
       },
    }
    
  4. PraefectPostgreSQL 데이터베이스에 연결하도록 구성합니다. 우리는 또한 PgBouncer를 사용하는 것을 강력히 추천합니다.

    TLS 클라이언트 인증서를 사용하려면, 아래의 옵션을 사용할 수 있습니다:

    praefect['configuration'] = {
       # ...
       database: {
          # ...
          #
          # TLS 클라이언트 인증서를 사용하여 PostgreSQL에 연결합니다.
          # sslcert: '/path/to/client-cert',
          # sslkey: '/path/to/client-key',
          #
          # 커스텀 인증 기관을 신뢰합니다.
          # sslrootcert: '/path/to/rootcert',
       },
    }
    

    기본적으로 Praefect는 PostgreSQL에 연결하기 위해 기회주의적 TLS를 사용합니다. 이는 Praefect가 sslmodeprefer로 설정된 PostgreSQL에 연결을 시도함을 의미합니다. 다음 줄의 주석을 해제하면 이 설정을 재정의 할 수 있습니다:

    praefect['configuration'] = {
       # ...
       database: {
          # ...
          # sslmode: 'disable',
       },
    }
    
  5. /etc/gitlab/gitlab.rb를 수정하여 Praefect 클러스터가 클러스터의 각 Gitaly 노드에 연결하도록 구성합니다.

    가상의 스토리지 이름은 GitLab 구성에서 설정된 스토리지 이름과 일치해야 합니다. 나중의 단계에서 스토리지 이름을 default로 설정하므로 여기에서도 default를 사용합니다. 이 클러스터에는 서로의 복제본이 되도록 설계된 세 개의 Gitaly 노드 gitaly-1, gitaly-2, gitaly-3이 있습니다.

    경고: 이미 default라는 이름의 기존 스토리지가 있는 경우, 가상 스토리를 다른 이름으로 구성하고 Gitaly 클러스터 스토리지로 데이터를 마이그레이션해야 합니다.

    PRAEFECT_INTERNAL_TOKEN을 강력한 비밀로 교체합니다. 이 토큰은 클러스터 내에서 Gitaly 노드와 통신할 때 Praefect가 사용합니다. 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 다릅니다.

    GITALY_HOST_*를 각 Gitaly 노드의 IP 또는 호스트 주소로 교체합니다.

    더 많은 Gitaly 노드를 클러스터에 추가하여 복제본 수를 늘릴 수 있습니다. 매우 큰 GitLab 인스턴스에 대해 더 많은 클러스터를 추가할 수도 있습니다.

    참고: 가상 스토리지에 추가 Gitaly 노드를 추가할 때, 해당 가상 스토리지의 모든 스토리지 이름은 고유해야 합니다. 또한, Praefect 구성에서 참조되는 모든 Gitaly 노드 주소는 고유해야 합니다.

    # 스토리지 해시의 이름은 GitLab 서버의 git_data_dirs('default') 및
    # Gitaly 노드의 gitaly['configuration'][:storage][INDEX][:name]의 이름과
    # 일치해야 합니다('gitaly-1').
    praefect['configuration'] = {
       # ...
       virtual_storage: [
          {
             # ...
             name: 'default',
             node: [
                {
                   storage: 'gitaly-1',
                   address: 'tcp://GITALY_HOST_1:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
                {
                   storage: 'gitaly-2',
                   address: 'tcp://GITALY_HOST_2:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
                {
                   storage: 'gitaly-3',
                   address: 'tcp://GITALY_HOST_3:8075',
                   token: 'PRAEFECT_INTERNAL_TOKEN'
                },
             ],
          },
       ],
    }
    
  6. /etc/gitlab/gitlab.rb에 대한 변경 사항을 저장하고 Praefect를 재구성합니다:

    gitlab-ctl reconfigure
    
  7. 다음을 위한 “배포 노드”:
    1. /etc/gitlab/gitlab.rb에서 praefect['auto_migrate'] = true로 설정하여 Praefect 데이터베이스 자동 마이그레이션을 다시 활성화합니다.
    2. 데이터베이스 마이그레이션이 재구성 중에만 실행되고 업그레이드 중에 자동으로 실행되지 않도록 하려면 다음을 실행합니다:
    sudo touch /etc/gitlab/skip-auto-reconfigure
    
    • 다른 노드는 설정을 그대로 두어도 됩니다. /etc/gitlab/skip-auto-reconfigure는 필수는 아니지만, GitLab이 apt-get update와 같은 명령을 실행할 때 자동으로 재구성을 실행하지 않도록 설정할 수 있습니다. 이렇게 하면 추가 구성 변경을 수행하고 재구성을 수동으로 실행할 수 있습니다.
  8. /etc/gitlab/gitlab.rb에 대한 변경 사항을 저장하고 Praefect를 재구성합니다:

    gitlab-ctl reconfigure
    
  9. Praefect가 Prometheus 수신 주소를 업데이트했는지 확인합니다 , Praefect를 다시 시작합니다:

    gitlab-ctl restart praefect
    
  10. Praefect가 PostgreSQL에 접근할 수 있는지 확인합니다:

    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-ping
    

    체크에 실패하면, 단계를 올바르게 따랐는지 확인하십시오. /etc/gitlab/gitlab.rb를 수정한 경우, sql-ping 명령을 시도하기 전에 sudo gitlab-ctl reconfigure를 다시 실행해야 합니다.

TLS 지원 활성화

Praefect는 TLS 암호화를 지원합니다. 보안 연결을 수신 대기하는 Praefect 인스턴스와 통신하려면 다음을 수행해야 합니다:

  • Gitaly가 TLS로 구성되어 있는지 확인하고, GitLab 구성의 해당 스토리지 항목에서 gitaly_addresstls:// URL 스킴을 사용합니다.

  • 자동으로 제공되지 않기 때문에 자신의 인증서를 준비해야 합니다. 각 Praefect 서버에 해당하는 인증서는 해당 Praefect 서버에 설치되어야 합니다.

또한 인증서 또는 인증서의 인증기관은 다음 절차에 따라 모든 Gitaly 서버와 이를 통신하는 모든 Praefect 클라이언트에 설치되어야 합니다:

GitLab 사용자 지정 인증서 구성 (아래에 반복됨).

다음 사항에 유의하세요:

  • 인증서는 Praefect 서버에 액세스하는 데 사용하는 주소를 지정해야 합니다. 인증서에 주제 대체 이름(Subject Alternative Name)으로 호스트 이름이나 IP 주소를 추가해야 합니다.

  • Gitaly TLS 사용으로 명령줄에서 dial-nodeslist-untracked-repositories와 같은 Praefect 하위 명령을 실행할 때는 Gitaly 인증서가 신뢰되도록 SSL_CERT_DIR 또는 SSL_CERT_FILE 환경 변수를 설정해야 합니다. 예를 들어:

     SSL_CERT_DIR=/etc/gitlab/trusted-certs sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
    
  • Praefect 서버를 비암호화 수신 주소 listen_addr와 암호화 수신 주소 tls_listen_addr를 동시에 구성할 수 있습니다.

    이를 통해 필요시 비암호화 트래픽에서 암호화 트래픽으로의 점진적 전환이 가능합니다.

    비암호화 리스너를 비활성화하려면 아래와 같이 설정합니다:

    praefect['configuration'] = {
      # ...
      listen_addr: nil,
    }
    

TLS로 Praefect 구성하기.

Linux 패키지 설치의 경우:

  1. Praefect 서버에 대한 인증서를 생성합니다.

  2. Praefect 서버에서 /etc/gitlab/ssl 디렉토리를 생성하고 거기에 키와 인증서를 복사합니다:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo cp key.pem cert.pem /etc/gitlab/ssl/
    sudo chmod 644 key.pem cert.pem
    
  3. /etc/gitlab/gitlab.rb를 편집하고 다음을 추가합니다:

    praefect['configuration'] = {
       # ...
       tls_listen_addr: '0.0.0.0:3305',
       tls: {
          # ...
          certificate_path: '/etc/gitlab/ssl/cert.pem',
          key_path: '/etc/gitlab/ssl/key.pem',
       },
    }
    
  4. 파일을 저장하고 재구성을 수행합니다.

  5. Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서를 /etc/gitlab/trusted-certs로 복사합니다:

    sudo cp cert.pem /etc/gitlab/trusted-certs/
    
  6. Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgit_data_dirs를 다음과 같이 편집합니다:

    git_data_dirs({
      "default" => {
        "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:3305',
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  7. 파일을 저장하고 GitLab을 재구성합니다.

자체 컴파일 설치의 경우:

  1. Praefect 서버에 대한 인증서를 생성합니다.

  2. Praefect 서버에서 /etc/gitlab/ssl 디렉토리를 생성하고 거기에 키와 인증서를 복사합니다:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo cp key.pem cert.pem /etc/gitlab/ssl/
    sudo chmod 644 key.pem cert.pem
    
  3. Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서를 시스템 신뢰 인증서로 복사합니다:

    sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
    sudo update-ca-certificates
    
  4. Praefect 클라이언트(각 Gitaly 서버 제외)에서 /home/git/gitlab/config/gitlab.ymlstorages를 다음과 같이 편집합니다:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tls://PRAEFECT_LOADBALANCER_HOST:3305
    
  5. 파일을 저장하고 GitLab을 재시작합니다.

  6. 모든 Praefect 서버 인증서 또는 인증서 권한을 각 Gitaly 서버의 시스템 신뢰 인증서에 복사하여 Gitaly 서버가 호출할 때 Praefect 서버가 인증서를 신뢰하도록 합니다:

    sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
    sudo update-ca-certificates
    
  7. /home/git/praefect/config.toml을 편집하고 다음을 추가합니다:

    tls_listen_addr = '0.0.0.0:3305'
    
    [tls]
    certificate_path = '/etc/gitlab/ssl/cert.pem'
    key_path = '/etc/gitlab/ssl/key.pem'
    
  8. 파일을 저장하고 GitLab을 재시작합니다.

서비스 검색

전제 조건:

  • DNS 서버.

GitLab은 서비스 검색을 사용하여 Praefect 호스트 목록을 검색합니다. 서비스 검색은 DNS A 또는 AAAA 레코드를 주기적으로 확인하는 것을 포함하며, 레코드에서 가져온 IP 주소는 대상 노드의 주소로 사용됩니다. Praefect는 SRV 레코드에 의한 서비스 검색을 지원하지 않습니다.

기본적으로, 확인 간 최소 시간은 5분입니다. 레코드의 TTL과 관계없이 적용됩니다. Praefect는 이 간격을 사용자 정의하는 것을 지원하지 않습니다. 클라이언트가 업데이트를 수신하면:

  • 새로운 IP 주소에 대한 새로운 연결을 설정합니다.

  • 변경되지 않은 IP 주소에 대한 기존 연결을 유지합니다.

  • 제거된 IP 주소에 대한 연결을 끊습니다.

제거될 연결의 진행 중인 요청은 완료될 때까지 여전히 처리됩니다. Workhorse는 10분 제한이 있으며, 다른 클라이언트는 우아한 제한을 지정하지 않습니다.

DNS 서버는 부하 분산 대신 모든 IP 주소를 반환해야 합니다. 클라이언트는 라운드 로빈 방식으로 IP 주소에 요청을 분산할 수 있습니다.

클라이언트 구성을 업데이트하기 전에 DNS 서비스 검색이 올바르게 작동하는지 확인하십시오. 올바른 IP 주소 목록을 반환해야 합니다. dig는 이를 확인하는 데 유용한 도구입니다.

❯ dig A praefect.service.consul @127.0.0.1

; <<>> DiG 9.10.6 <<>> A praefect.service.consul @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29210
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;praefect.service.consul.                     IN      A

;; ANSWER SECTION:
praefect.service.consul.              0       IN      A       10.0.0.3
praefect.service.consul.              0       IN      A       10.0.0.2
praefect.service.consul.              0       IN      A       10.0.0.1

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Wed Dec 14 12:53:58 +07 2022
;; MSG SIZE  rcvd: 86
서비스 검색 구성

기본적으로 Praefect는 DNS 확인을 운영 체제에 위임합니다. 이러한 경우, Gitaly 주소는 다음 형식 중 하나로 설정될 수 있습니다:

  • dns:[host]:[port]

  • dns:///[host]:[port] (슬래시 세 개에 유의)

권한 있는 이름 서버를 설정하여 이 형식으로 지정할 수도 있습니다:

  • dns://[authority_host]:[authority_port]/[host]:[port]
리눅스 패키지 (Omnibus)
  1. 각 Praefect 노드에 대한 IP 주소를 DNS 서비스 검색 주소에 추가합니다.

  2. Praefect 클라이언트(감시 서버 제외)에서 /etc/gitlab/gitlab.rbgit_data_dirs를 다음과 같이 편집합니다. PRAEFECT_SERVICE_DISCOVERY_ADDRESSpraefect.service.consul과 같은 Praefect 서비스 검색 주소로 교체합니다.

    git_data_dirs({
      "default" => {
        "gitaly_address" => 'dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305',
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  3. 파일을 저장하고 GitLab 재구성을 수행합니다.

소스에서 컴파일된 (Self-compiled)
  1. DNS 서비스 검색 서비스를 설치합니다. 모든 Praefect 노드를 서비스에 등록합니다.

  2. Praefect 클라이언트(감시 서버 제외)에서 /home/git/gitlab/config/gitlab.ymlstorages를 다음과 같이 편집합니다:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305
    
  3. 파일을 저장하고 GitLab 재시작을 수행합니다.

Consul로 서비스 발견 구성하기

아키텍처에 이미 Consul 서버가 있는 경우 각 Praefect 노드에 Consul 에이전트를 추가하고 praefect 서비스를 등록할 수 있습니다.

이를 통해 각 노드의 IP 주소가 praefect.service.consul에 등록되어 서비스 발견을 통해 찾을 수 있습니다.

사전 요구 사항:

  • Consul 에이전트를 추적할 하나 이상의 Consul 서버.
  1. 각 Praefect 서버에서 /etc/gitlab/gitlab.rb에 다음을 추가합니다:

    consul['enable'] = true
    praefect['consul_service_name'] = 'praefect'
    
    # 이 문제를 해결할 때까지 다음도 추가해야 합니다:
    # https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/8321
    consul['monitoring_service_discovery'] = true
    praefect['configuration'] = {
      # ...
      #
      prometheus_listen_addr: '0.0.0.0:9652',
    }
    
  2. 파일을 저장하고 GitLab 재구성을 수행합니다.

  3. 서비스 발견에 사용하기 위해 각 Praefect 서버에서 위의 단계를 반복합니다.

  4. Praefect 클라이언트(일반 Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgit_data_dirs를 다음과 같이 편집합니다. CONSUL_SERVER를 Consul 서버의 IP 또는 주소로 바꿉니다. 기본 Consul DNS 포트는 8600입니다.

    git_data_dirs({
      "default" => {
        "gitaly_address" => 'dns://CONSUL_SERVER:8600/praefect.service.consul:2305',
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  5. Praefect 클라이언트에서 dig를 사용하여 각 IP 주소가 praefect.service.consul에 등록되었는지 확인합니다. dig A praefect.service.consul @CONSUL_SERVER -p 8600을 입력합니다. CONSUL_SERVER를 위에서 구성한 값으로 바꾸고 모든 Praefect 노드 IP 주소가 출력에 나타나야 합니다.

  6. 파일을 저장하고 GitLab 재구성을 수행합니다.

Gitaly

참고: 각 Gitaly 노드에 대해 이 단계를 완료해야 합니다.

이 섹션을 완료하려면:

  • 구성된 Praefect 노드
  • GitLab이 설치된 3개(또는 그 이상의) 서버를 Gitaly 노드로 구성해야 합니다. 이러한 노드는 전용 노드여야 하며 다른 서비스는 실행하지 않아야 합니다.

Praefect 클러스터에 할당된 모든 Gitaly 서버는 구성되어야 합니다.

구성은 일반 독립 실행형 Gitaly 서버와 같지만 다음과 같은 점이 다릅니다:

  • 저장소 이름은 GitLab이 아니라 Praefect에 노출됩니다.
  • 비밀 토큰은 GitLab이 아니라 Praefect와 공유됩니다.

Praefect 클러스터의 모든 Gitaly 노드는 동일한 구성을 가질 수 있습니다.

Praefect가 작업을 올바르게 라우팅하기 때문입니다.

특히 주의해야 할 점은:

  • 이 섹션에 구성된 gitaly['configuration'][:auth][:token] 값은 Praefect 노드의 praefect['configuration'][:virtual_storage][<index>][:node][<index>][:token] 아래의 token 값과 일치해야 합니다. 이 값은 이전 섹션에서 설정했습니다. 이 문서에서는 PRAEFECT_INTERNAL_TOKEN이라는 자리를 사용합니다.
  • 이 섹션에 구성된 gitaly['configuration'][:storage]의 물리적 저장소 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage] 아래의 물리적 저장소 이름과 일치해야 합니다. 이는 이전 섹션에서 설정되었습니다. 이 문서에서는 물리적 저장소 이름으로 gitaly-1, gitaly-2, gitaly-3를 사용합니다.

Gitaly 서버 구성에 대한 자세한 내용은 Gitaly 문서를 참조하세요.

  1. Gitaly 노드에 SSH로 접속하고 루트 사용자로 로그인합니다:

    sudo -i
    
  2. /etc/gitlab/gitlab.rb를 편집하여 모든 다른 서비스를 비활성화합니다:

    # Gitaly 노드에서 모든 다른 서비스를 비활성화합니다
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    prometheus_monitoring['enable'] = false
    gitlab_kas['enable'] = false
    
    # Gitaly 서비스만 활성화합니다
    gitaly['enable'] = true
    
    # 필요시 Prometheus를 활성화합니다
    prometheus['enable'] = true
    
    # 'gitlab-ctl reconfigure' 중 데이터베이스 연결을 방지하기 위해 데이터베이스 마이그레이션을 비활성화합니다
    gitlab_rails['auto_migrate'] = false
    
  3. /etc/gitlab/gitlab.rb를 편집하여 Gitaly가 네트워크 인터페이스에서 수신하도록 구성합니다:

    gitaly['configuration'] = {
       # ...
       #
       # Gitaly에서 모든 네트워크 인터페이스에서 연결을 수락하도록 합니다.
       # 이 주소/포트에 대한 접근을 제한하려면 방화벽을 사용해야 합니다.
       listen_addr: '0.0.0.0:8075',
       # Gitaly에 대한 Prometheus 메트릭스 접근을 활성화합니다. 
       # 이 주소/포트에 대한 접근을 제한하려면 방화벽을 사용해야 합니다.
       prometheus_listen_addr: '0.0.0.0:9236',
    }
    
  4. 클라이언트가 이 Gitaly 노드와 통신하는 데 필요한 강력한 auth_tokenGitaly에 대해 구성합니다. 일반적으로, 이 토큰은 모든 Gitaly 노드에서 동일합니다.

    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: 'PRAEFECT_INTERNAL_TOKEN',
       },
    }
    
  5. git push 작업에 필요한 GitLab Shell 비밀 토큰을 구성합니다. 방법은 두 가지입니다:

    • 방법 1:

      1. Gitaly 클라이언트의 /etc/gitlab/gitlab-secrets.json을 Gitaly 서버와 다른 Gitaly 클라이언트의 동일한 경로로 복사합니다.
      2. Gitaly 서버에서 GitLab 재구성을 수행합니다.
    • 방법 2:

      1. /etc/gitlab/gitlab.rb를 편집합니다.
      2. GITLAB_SHELL_SECRET_TOKEN을 실제 비밀로 바꿉니다.

        gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
        
  6. git push 작업에 필요할 internal_api_url을 구성합니다:

    # gitlab-shell API 콜백 URL을 구성합니다. 
    # 이를 설정하지 않으면 `git push`가 실패합니다.
    # 이 URL은 GitLab의 프론트도어일 수도 있고 내부 로드 밸런서일 수도 있습니다.
    # 예: 'https://gitlab.example.com', 'http://10.0.2.2'
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
  7. /etc/gitlab/gitlab.rb에서 gitaly['configuration'][:storage]를 설정하여 Git 데이터의 저장 위치를 구성합니다. 각 Gitaly 노드는 고유한 저장소 이름(unique name)을 가져야 합니다 (예: gitaly-1).

    gitaly['configuration'] = {
       # ...
       storage: [
         # 각 Gitaly 노드에 대해 적절한 이름으로 교체합니다.
         {
           name: 'gitaly-1',
           path: '/var/opt/gitlab/git-data/repositories',
         },
       ],
    }
    
  8. /etc/gitlab/gitlab.rb에 대한 변경 사항을 저장하고 Gitaly 재구성을 수행합니다:

    gitlab-ctl reconfigure
    
  9. Gitaly 가 Prometheus 수신 주소를 업데이트했는지 확인하려면, Gitaly를 재시작합니다:

    gitlab-ctl restart gitaly
    

위의 단계는 각 Gitaly 노드에 대해 완료해야 합니다!

모든 Gitaly 노드가 구성되면 Praefect 연결 확인기를 실행하여 Praefect가 Praefect 구성의 모든 Gitaly 서버에 연결할 수 있는지 확인합니다.

  1. Praefect 노드에 SSH로 접속하고 Praefect 연결 확인기를 실행합니다:

    sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
    

로드 밸런서

장애 조치가 가능한 Gitaly 구성에서는 GitLab 애플리케이션에서 Praefect 노드로 내부 트래픽을 라우팅하기 위해 로드 밸런서가 필요합니다. 사용할 로드 밸런서에 대한 세부사항이나 정확한 구성은 GitLab 문서의 범위를 넘어섭니다.

참고: 로드 밸런서는 GitLab 노드 외에도 Gitaly 노드에서 트래픽을 수신하도록 구성되어야 합니다.

우리는 GitLab과 같은 장애 조치 시스템을 관리하는 경우 이미 선택한 로드 밸런서가 있기를 바랍니다. 몇 가지 예로는 HAProxy (오픈 소스), Google Internal Load Balancer, AWS Elastic Load Balancer, F5 Big-IP LTM, Citrix Net Scaler가 있습니다. 이 문서는 구성해야 할 포트와 프로토콜을 설명합니다.

참고: 장기 실행 작업(예: 복제)이 일부 연결을 오랜 시간 동안 열어 두기 때문에 HAProxy leastconn 로드 밸런싱 전략의 동등한 것을 사용해야 합니다.

LB 포트 백엔드 포트 프로토콜
2305 2305 TCP

GitLab

이 섹션을 완료하려면 다음이 필요합니다:

Praefect 클러스터는 GitLab 애플리케이션에 저장 위치로 노출되어야 하며, 이는 git_data_dirs를 업데이트하여 수행됩니다.

특별한 주의가 필요합니다:

  • 이 섹션에 추가된 git_data_dirs의 저장소 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage] 아래의 저장소 이름과 일치해야 합니다. 이는 이 가이드의 Praefect 섹션에서 설정되었습니다. 이 문서에서는 Praefect 저장소 이름으로 default를 사용합니다.
  1. GitLab 노드에 SSH로 접속하여 root로 로그인합니다:

    sudo -i
    
  2. GitLab이 파일을 제공할 수 있도록 external_url을 구성합니다. /etc/gitlab/gitlab.rb를 편집하여 올바른 엔드포인트 접근을 설정합니다:

    현재 GitLab 인스턴스가 제공되고 있는 실제 외부-facing URL로 GITLAB_SERVER_URL을 교체해야 합니다:

    external_url 'GITLAB_SERVER_URL'
    
  3. GitLab 호스트에서 실행 중인 기본 Gitaly 서비스를 비활성화합니다. GitLab이 구성된 클러스터에 연결되므로 필요하지 않습니다.

    경고: 기본 Gitaly 저장소에 기존 데이터가 저장되어 있는 경우, 먼저 Gitaly 클러스터 저장소로 데이터 마이그레이션을 해야 합니다.

    gitaly['enable'] = false
    
  4. /etc/gitlab/gitlab.rb를 편집하여 Praefect 클러스터를 저장 위치로 추가합니다.

    아래를 교체해야 합니다:

    • PRAEFECT_LOADBALANCER_HOST를 로드 밸런서의 IP 주소 또는 호스트 이름으로
    • PRAEFECT_EXTERNAL_TOKEN을 실제 비밀로

    TLS를 사용하는 경우:

    • gitaly_address는 대신 tls://로 시작해야 합니다.
    • 포트는 3305로 변경해야 합니다.
    git_data_dirs({
      "default" => {
        "gitaly_address" => "tcp://PRAEFECT_LOADBALANCER_HOST:2305",
        "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
      }
    })
    
  5. git push 중 Gitaly 노드에서의 콜백이 적절히 인증되도록 GitLab Shell 비밀 토큰을 구성합니다. 방법 중 하나를 선택합니다:

    • 방법 1:

      1. Gitaly 클라이언트의 /etc/gitlab/gitlab-secrets.json을 Gitaly 서버 및 기타 Gitaly 클라이언트의 동일한 경로로 복사합니다.
      2. Gitaly 서버에서 GitLab 재구성을 진행합니다.
    • 방법 2:

      1. /etc/gitlab/gitlab.rb를 편집합니다.
      2. GITLAB_SHELL_SECRET_TOKEN을 실제 비밀로 교체합니다.

        gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
        
  6. /etc/gitlab/gitlab.rb를 편집하여 Prometheus 모니터링 설정을 추가합니다. Prometheus가 다른 노드에서 활성화된 경우 해당 노드에서 편집합니다.

    아래를 교체해야 합니다:

    • PRAEFECT_HOST를 Praefect 노드의 IP 주소 또는 호스트 이름으로
    • GITALY_HOST_*를 각 Gitaly 노드의 IP 주소 또는 호스트 이름으로
    prometheus['scrape_configs'] = [
      {
        'job_name' => 'praefect',
        'static_configs' => [
          'targets' => [
            'PRAEFECT_HOST:9652', # praefect-1
            'PRAEFECT_HOST:9652', # praefect-2
            'PRAEFECT_HOST:9652', # praefect-3
          ]
        ]
      },
      {
        'job_name' => 'praefect-gitaly',
        'static_configs' => [
          'targets' => [
            'GITALY_HOST_1:9236', # gitaly-1
            'GITALY_HOST_2:9236', # gitaly-2
            'GITALY_HOST_3:9236', # gitaly-3
          ]
        ]
      }
    ]
    
  7. /etc/gitlab/gitlab.rb에 대한 변경 사항을 저장하고 GitLab 재구성을 진행합니다:

    gitlab-ctl reconfigure
    
  8. 각 Gitaly 노드에서 Git Hooks가 GitLab에 도달할 수 있는지 확인합니다. 각 Gitaly 노드에서 다음을 실행합니다:
    • GitLab 15.3 이상에서는 sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml를 실행합니다.
    • GitLab 15.2 이하에서는 sudo -u git -- /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml를 실행합니다.
  9. GitLab이 Praefect에 도달할 수 있는지 확인합니다:

    gitlab-rake gitlab:gitaly:check
    
  10. Praefect 저장소가 새로운 저장소를 저장하도록 구성되었는지 확인합니다:

    1. 왼쪽 사이드바에서 아래쪽에 있는 Admin을 선택합니다.
    2. 왼쪽 사이드바에서 Settings > Repository를 선택합니다.
    3. Repository storage 섹션을 확장합니다.

    이 가이드를 따르면 default 저장소는 모든 새로운 저장소를 저장하기 위해 가중치 100을 가져야 합니다.

  11. 새로운 프로젝트를 생성하여 모든 것이 작동하는지 확인합니다. “README로 저장소 초기화” 박스를 선택하여 저장소에 내용을 추가합니다. 프로젝트가 생성되고 README 파일이 보인다면, 작동합니다!

기존 GitLab 인스턴스에 TCP 사용

기존 Gitaly 인스턴스에 Gitaly 클러스터를 추가할 때, 기존 Gitaly 스토리지가 TCP/TLS에서 수신 대기해야 합니다. gitaly_address가 지정되지 않으면 Unix 소켓을 사용하게 되어 클러스터와의 통신이 차단됩니다.

예를 들어:

git_data_dirs({
  'default' => { 'gitaly_address' => 'tcp://old-gitaly.internal:8075' },
  'cluster' => {
    'gitaly_address' => 'tls://<PRAEFECT_LOADBALANCER_HOST>:3305',
    'gitaly_token' => '<praefect_external_token>'
  }
})

여러 Gitaly 스토리지를 실행하는 데 대한 추가 정보는 Mixed Configuration을 참조하세요.

Grafana

Grafana는 GitLab과 함께 제공되며, Praefect 클러스터를 모니터링하는 데 사용할 수 있습니다. 자세한 문서는 Grafana Dashboard Service를 참조하세요.

신속하게 시작하려면:

  1. GitLab 노드(또는 Grafana가 활성화된 노드)에 SSH 접속하여 root로 로그인합니다:

    sudo -i
    
  2. /etc/gitlab/gitlab.rb를 편집하여 Grafana 로그인 양식을 활성화합니다.

    grafana['disable_login_form'] = false
    
  3. 변경 사항을 /etc/gitlab/gitlab.rb에 저장하고 GitLab 재구성을 수행합니다:

    gitlab-ctl reconfigure
    
  4. Grafana 관리자 비밀번호를 설정합니다. 이 명령은 새 비밀번호 입력을 요청합니다:

    gitlab-ctl set-grafana-password
    
  5. 웹 브라우저에서 GitLab 서버의 /-/grafana를 엽니다(예: https://gitlab.example.com/-/grafana).

    설정한 비밀번호와 사용자 이름 admin으로 로그인합니다.

  6. Explore로 이동하여 gitlab_build_info를 쿼리하여 모든 머신에서 메트릭을 수집하고 있는지 확인합니다.

축하합니다! Observable Fault-Tolerant Praefect 클러스터를 구성했습니다.

복제 계수 구성

Praefect는 특정 저장 노드를 할당하여 리포지토리별로 복제 계수를 구성하는 것을 지원합니다.

경고: 구성 가능한 복제 계수는 리포지토리별 기본 노드를 요구합니다.

Praefect는 실제 복제 계수를 저장하지 않고, 원하는 복제 계수가 충족되도록 리포지토리를 호스트할 수 있는 충분한 스토리지를 할당합니다. 만약 저장 노드가 나중에 가상 스토리지에서 제거되면, 그 저장소에 할당된 리포지토리의 복제 계수가 그에 따라 감소합니다.

다음 중 하나를 구성할 수 있습니다:

  • 새로 생성된 리포지토리에 적용되는 각 가상 스토리지의 기본 복제 계수.
  • set-replication-factor 하위 명령을 사용하여 기존 리포지토리에 대한 복제 계수.

기본 복제 계수 구성

default_replication_factor가 설정되지 않은 경우, 리포지토리는 항상 virtual_storages에 정의된 모든 저장 노드에서 복제됩니다. 새로운 저장 노드가 가상 스토리지에 도입되면, 새로운 리포지토리와 기존 리포지토리 모두 자동으로 해당 노드에 복제됩니다.

저장 노드가 많은 대규모 Gitaly Cluster 배포의 경우, 모든 저장 노드에 리포지토리를 복제하는 것은 보통 비효율적이며 문제를 야기할 수 있습니다. 일반적으로 3의 복제 계수가 충분하며, 이는 더 많은 스토리지가 있을 때도 세 개의 스토리지에 리포지토리를 복제합니다. 더 높은 복제 계수는 기본 스토리지에 더 많은 부담을 줍니다.

기본 복제 계수를 구성하려면 /etc/gitlab/gitlab.rb 파일에 구성을 추가합니다:

praefect['configuration'] = {
   # ...
   virtual_storage: [
      {
         # ...
         name: 'default',
         default_replication_factor: 3,
      },
   ],
}

기존 리포지토리의 복제 계수 구성

set-replication-factor 서브커맨드는 원하는 복제 계수를 달성하기 위해 필요한 랜덤 스토리지 노드를 자동으로 할당하거나 할당 해제합니다. 리포지토리의 기본 노드는 항상 먼저 할당되며 절대 할당 해제되지 않습니다.

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
  • -virtual-storage는 리포지토리가 위치한 가상 스토리지입니다.
  • -repository는 스토리지 내에서 리포지토리의 상대 경로입니다.
  • -replication-factor는 리포지토리의 원하는 복제 계수입니다. 최소 값은 1이며, 기본 리포지토리에 대한 복사본이 필요합니다. 최대 복제 계수는 가상 스토리지 내의 스토리지 수입니다.

성공 시, 할당된 호스트 스토리지가 출력됩니다. 예를 들어:

$ sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2

current assignments: gitaly-1, gitaly-2

리포지토리 스토리지 권장 사항

필요한 스토리지의 크기는 인스턴스마다 다를 수 있으며 설정된 복제 계수에 따라 달라집니다. 리포지토리 스토리지 중복성을 구현할 수도 있습니다.

복제 계수가 1일 경우:

  • Gitaly 및 Gitaly 클러스터는 대략 동일한 스토리지 요구 사항을 가집니다.

복제 계수가 1 초과일 경우: 필요한 스토리지 양은 사용된 공간 * 복제 계수입니다. 사용된 공간에는 향후 예상 성장도 포함해야 합니다.

리포지토리 검증

Praefect는 데이터베이스에 리포지토리에 대한 메타데이터를 저장합니다. 리포지토리가 Praefect를 거치지 않고 디스크에서 수정되면 메타데이터가 부정확해질 수 있습니다. 예를 들어 Gitaly 노드가 새 노드로 대체되는 것이 아니라 재구성될 경우, 리포지토리 검증을 통해 이를 감지할 수 있습니다.

메타데이터는 복제 및 라우팅 결정을 위해 사용되므로, 모든 부정확성은 문제를 일으킬 수 있습니다.

Praefect는 정기적으로 메타데이터를 실제 디스크 상태와 검증하는 백그라운드 워커를 포함하고 있습니다. 워커는:

  1. 건강한 스토리지에서 확인할 복제본 배치를 선택합니다. 복제본은 검증되지 않았거나 구성된 검증 간격을 초과한 것입니다. 처음 검증되지 않은 복제본이 우선시되며, 그 다음으로는 마지막으로 성공적으로 검증된 시간을 기준으로 정렬된 다른 복제본이 우선시됩니다.

  2. 복제본이 각자의 스토리지에 존재하는지 확인합니다. 만약:

    • 복제본이 존재하면, 마지막 성공적인 검증 시간을 업데이트합니다.
    • 복제본이 존재하지 않으면, 메타데이터 기록을 제거합니다.
    • 확인에 실패하면, 복제본은 다음 워커가 더 많은 작업을 대기열에서 제거할 때 다시 검증을 위해 선택됩니다.

워커는 검증할 복제본마다 독점적인 검증 임대를 확보합니다. 이렇게 하면 여러 워커가 동시에 같은 복제본을 검증하는 것을 방지합니다. 워커는 확인을 완료하면 임대를 해제합니다. 만약 어떤 이유로 워커가 임대를 해제하지 않고 종료된다면, Praefect는 10초마다 오래된 임대를 해제하는 백그라운드 고루틴을 포함하고 있습니다.

워커는 메타데이터 제거를 수행하기 전에 각 메타데이터 삭제를 로그로 기록합니다. perform_deletions 키는 무효한 메타데이터 기록이 실제로 삭제되었는지 여부를 나타냅니다. 예를 들어:

{
  "level": "info",
  "msg": "removing metadata records of non-existent replicas",
  "perform_deletions": false,
  "replicas": {
    "default": {
      "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git": [
        "praefect-internal-0"
      ]
    }
  }
}

검증 워커 구성

워커는 기본적으로 활성화되어 있으며 메타데이터 레코드를 7일마다 검증합니다. 검증 간격은 유효한 Go 지속 시간 문자열로 구성할 수 있습니다.

메타데이터를 3일마다 검증하려면:

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      verification_interval: '72h',
   },
}

0 및 이하의 값은 백그라운드 검증기를 비활성화합니다.

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      verification_interval: '0',
   },
}

삭제 활성화

경고:

삭제는 GitLab 15.9 이전에 기본적으로 비활성화되어 있었으며, 이는 잘못된 삭제를 유발할 수 있는 저장소 이름 변경과의 경쟁 조건 때문입니다. 이는 Geo 인스턴스에서 특히 두드러지며, Geo는 Geo가 없는 인스턴스보다 더 많은 이름 변경을 수행합니다. GitLab 15.0에서 15.5까지는 gitaly_praefect_generated_replica_paths 기능 플래그가 활성화된 경우에만 삭제를 활성화해야 합니다. 해당 기능 플래그는 GitLab 15.6에서 제거되어 삭제를 항상 안전하게 활성화할 수 있게 되었습니다.

기본적으로 워커는 잘못된 메타데이터 레코드를 삭제합니다. 또한 삭제된 레코드를 기록하고 Prometheus 메트릭을 출력합니다.

잘못된 메타데이터 레코드를 삭제하지 않으려면:

praefect['configuration'] = {
   # ...
   background_verification: {
      # ...
      delete_invalid_records: false,
   },
}

검증 수동 우선화

일부 복제본의 검증을 다음 예정된 검증 시간보다 우선시할 수 있습니다.

예를 들어 관리자이 디스크 내용이 변경되었을 수 있음을 알고 있는 경우, 디스크 실패 후에 필요할 수 있습니다. Praefect는 결국 복제본을 다시 검증하겠지만, 그 사이에 사용자가 오류를 반환할 수 있습니다.

일부 복제본의 재검증을 수동으로 우선시하려면 praefect verify 서브 명령을 사용하세요. 서브 명령은 복제본을 미검증으로 표시합니다. 미검증 복제본은 백그라운드 검증 워커에 의해 우선시됩니다. 검증 워커는 복제본이 검증되도록 활성화되어야 합니다.

특정 저장소의 복제본 검증 우선화:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml verify -repository-id=<repository-id>

가상 스토리지에 저장된 모든 복제본 검증 우선화:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml verify -virtual-storage=<virtual-storage>

저장소에 저장된 모든 복제본 검증 우선화:

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml verify -virtual-storage=<virtual-storage> -storage=<storage>

출력에는 미검증으로 표시된 복제본 수가 포함됩니다.

자동 장애 조치 및 기본 선출 전략

Praefect는 각 Gitaly 노드의 상태를 정기적으로 확인하며, 현재 기본 노드가 비정상으로 판단되면 새로 선출된 기본 Gitaly 노드로 자동으로 장애 조치합니다.

저장소별 기본 노드가 유일하게 사용 가능한 선출 전략입니다.

저장소별 기본 노드

Gitaly 클러스터는 각 저장소에 대해 별도로 기본 Gitaly 노드를 선출합니다. 구성 가능한 복제 계수와 결합하여, 저장 용량을 수평 적으로 확장하고 Gitaly 노드 간에 쓰기 부하를 분산할 수 있습니다.

기본 선거는 게으르게 실행됩니다. Praefect는 현재 노드가 건강하지 않더라도 즉시 새 기본 노드를 선출하지 않습니다. 현재 기본이 사용할 수 없을 경우 요청을 처리해야 할 때 새 기본이 선출됩니다.

유효한 기본 노드 후보는 다음과 같은 Gitaly 노드입니다:

  • 건강합니다. Gitaly 노드는 >=50%의 Praefect 노드가 지난 10초 동안 Gitaly 노드를 건강하게 체크한 경우 건강하다고 간주됩니다.

  • 저장소의 완전히 최신 복사본을 가지고 있습니다.

여러 개의 기본 노드 후보가 있는 경우, Praefect는:

  • 그 중 하나를 무작위로 선택합니다.

  • 저장소를 호스팅하도록 할당된 Gitaly 노드를 승격하는 데 우선합니다. 기본으로 선출할 할당된 Gitaly 노드가 없는 경우, Praefect는 할당되지 않은 노드를 일시적으로 선출할 수 있습니다. 할당된 노드가 사용 가능해지면 할당되지 않은 기본이 승격됩니다.

저장소에 대한 유효한 기본 후보가 없는 경우:

  • 건강하지 않은 기본 노드가 강등되고 저장소는 기본 노드 없이 남게 됩니다.

  • 기본 노드가 성공적으로 선출될 때까지 기본 노드가 필요한 작업은 실패합니다.