InfoGrab DocsInfoGrab Docs

Gitaly Cluster(Praefect) 구성

요약

Gitaly Cluster(Praefect)는 다음 중 하나를 사용하여 구성합니다: 60 RPS 또는 사용자 3,000명. 100 RPS 또는 사용자 5,000명. 200 RPS 또는 사용자 10,000명. 500 RPS 또는 사용자 25,000명.

Gitaly Cluster(Praefect)는 다음 중 하나를 사용하여 구성합니다:

  • 다음 규모 이하 설치를 위한 참조 아키텍처에 포함된 Gitaly Cluster(Praefect) 구성 지침:

60 RPS 또는 사용자 3,000명.

소규모 GitLab 설치에는 Gitaly 자체만 필요할 수 있습니다.

Gitaly Cluster(Praefect)는 아직 쿠버네티스, Amazon ECS 또는 유사한 컨테이너 환경에서 지원되지 않습니다. 자세한 내용은 에픽 6127을 참조하세요.

요구 사항#

Gitaly Cluster(Praefect)의 최소 권장 구성에 필요한 항목:

  • 로드 밸런서 1대

  • PostgreSQL 서버 1대(지원되는 버전)

  • Praefect 노드 3대

  • Gitaly 노드 3대(primary 1대, secondary 2대)

디스크 요구 사항이 Gitaly 노드에 적용됩니다.

트랜잭션에서 Gitaly 노드 중 하나가 뮤테이팅 RPC 호출 도중 실패할 경우 타이브레이커가 있도록 홀수 개의 Gitaly 노드를 구성해야 합니다.

구현 세부 사항은 설계 문서를 참조하세요.

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

네트워크 지연 및 연결성#

Gitaly Cluster(Praefect)의 네트워크 지연은 이상적으로 한 자릿수 밀리초 단위여야 합니다. 지연은 특히 다음 항목에서 중요합니다:

  • Gitaly 노드 상태 확인. 노드는 1초 이내에 응답할 수 있어야 합니다.

  • 강력한 일관성을 적용하는 참조 트랜잭션. 지연이 낮을수록 Gitaly 노드가 변경 사항에 더 빠르게 동의할 수 있습니다.

Gitaly 노드 간 허용 가능한 지연을 달성하는 방법:

  • 물리적 네트워크에서는 일반적으로 고대역폭, 단일 위치 연결을 의미합니다.

  • 클라우드에서는 일반적으로 교차 가용 영역 복제를 허용하는 동일 리전 내를 의미합니다. 이러한 링크는 이런 유형의 동기화를 위해 설계되었습니다. Gitaly Cluster(Praefect)의 경우 2ms 미만의 지연이면 충분합니다.

원격지 간과 같이 복제를 위한 낮은 네트워크 지연을 제공할 수 없는 경우 Geo를 고려하세요. 자세한 내용은 Geo와의 비교를 참조하세요.

Gitaly Cluster(Praefect) 구성 요소는 다양한 경로를 통해 서로 통신합니다. Gitaly Cluster(Praefect)가 올바르게 작동하려면 방화벽 규칙에서 다음을 허용해야 합니다:

출발지 목적지 기본 포트 TLS 포트
GitLab Praefect 로드 밸런서 2305 3305
Praefect 로드 밸런서 Praefect 2305 3305
Praefect Gitaly 8075 9999
Praefect GitLab (내부 API) 80 443
Gitaly GitLab (내부 API) 80 443
Gitaly Praefect 로드 밸런서 2305 3305
Gitaly Praefect 2305 3305
Gitaly Gitaly 8075 9999

Gitaly는 Praefect에 직접 연결하지 않습니다. 그러나 Praefect 노드의 방화벽이 Gitaly 노드의 트래픽을 허용하지 않으면 Gitaly에서 Praefect 로드 밸런서로의 요청이 차단될 수 있습니다.

Praefect 데이터베이스 스토리지#

데이터베이스에는 다음 메타데이터만 포함되므로 요구 사항이 비교적 낮습니다:

  • 리포지터리의 위치.

  • 일부 대기 중인 작업.

리포지터리 수에 따라 다르지만 최소 5~10 GB가 적합하며, 이는 메인 GitLab 애플리케이션 데이터베이스와 유사한 크기입니다.

설치 지침#

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

준비#

시작하기 전에 이미 작동 중인 GitLab 인스턴스가 있어야 합니다. GitLab 설치 방법을 알아보세요.

PostgreSQL 서버를 프로비저닝합니다. Linux 패키지와 함께 제공되는 PostgreSQL을 사용하여 PostgreSQL 데이터베이스를 구성하는 것이 좋습니다. 외부 PostgreSQL 서버를 사용할 수 있지만 수동으로 설정해야 합니다.

GitLab을 설치하여 모든 새 노드를 준비합니다. 다음이 필요합니다:

  • PostgreSQL 노드 1대

  • PgBouncer 노드 1대(선택 사항)

  • Praefect 노드 최소 1대(최소 스토리지 필요)

  • Gitaly 노드 3대(높은 CPU, 높은 메모리, 빠른 스토리지)

  • GitLab 서버 1대

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

  • PRAEFECT_LOADBALANCER_HOST: Praefect 로드 밸런서의 IP/호스트 주소

  • POSTGRESQL_HOST: PostgreSQL 서버의 IP/호스트 주소

  • PGBOUNCER_HOST: PostgreSQL 서버의 IP/호스트 주소

  • PRAEFECT_HOST: Praefect 서버의 IP/호스트 주소

  • GITALY_HOST_*: 각 Gitaly 서버의 IP 또는 호스트 주소

  • GITLAB_HOST: GitLab 서버의 IP/호스트 주소

Google Cloud Platform, SoftLayer 또는 가상 프라이빗 클라우드(VPC)를 제공하는 다른 공급업체를 사용하는 경우 PRAEFECT_HOST, GITALY_HOST_*, GITLAB_HOST에 각 클라우드 인스턴스의 사설 주소(Google Cloud Platform의 경우 "내부 주소"에 해당)를 사용할 수 있습니다.

시크릿#

구성 요소 간 통신은 아래에 설명된 다양한 시크릿으로 보호됩니다. 시작하기 전에 각각에 대한 고유 시크릿을 생성하고 메모해 두세요. 이를 통해 설정 프로세스를 완료하면서 이 자리 표시자 토큰을 안전한 토큰으로 교체할 수 있습니다.

  • GITLAB_SHELL_SECRET_TOKEN: Git 푸시를 수락할 때 Git 훅이 GitLab에 콜백 HTTP API 요청을 하는 데 사용됩니다. 이 시크릿은 레거시 이유로 GitLab Shell과 공유됩니다.

  • PRAEFECT_EXTERNAL_TOKEN: Praefect 클러스터에서 호스팅되는 리포지터리는 이 토큰을 전달하는 Gitaly 클라이언트만 접근할 수 있습니다.

  • PRAEFECT_INTERNAL_TOKEN: 이 토큰은 Praefect 클러스터 내의 복제 트래픽에 사용됩니다. Gitaly 클라이언트가 Praefect 클러스터의 내부 노드에 직접 접근할 수 없어야 하기 때문에 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 구별됩니다. 그렇지 않으면 데이터 손실이 발생할 수 있습니다.

  • PRAEFECT_SQL_PASSWORD: Praefect가 PostgreSQL에 연결하는 데 사용하는 암호입니다.

  • PRAEFECT_SQL_PASSWORD_HASH: Praefect 사용자의 암호 해시입니다. gitlab-ctl pg-password-md5 praefect를 사용하여 해시를 생성합니다. 명령은 praefect 사용자의 암호를 입력하도록 요청합니다. PRAEFECT_SQL_PASSWORD 일반 텍스트 암호를 입력하세요. 기본적으로 Praefect는 praefect 사용자를 사용하지만 변경할 수 있습니다.

  • PGBOUNCER_SQL_PASSWORD_HASH: PgBouncer 사용자의 암호 해시입니다. PgBouncer는 이 암호를 사용하여 PostgreSQL에 연결합니다. 자세한 내용은 번들 PgBouncer 설명서를 참조하세요.

이러한 시크릿이 필요한 위치는 아래 지침에 표시되어 있습니다.

Linux 패키지 설치는 GITLAB_SHELL_SECRET_TOKENgitlab-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#

Praefect는 GitLab 애플리케이션 데이터베이스와 분리된 데이터베이스를 사용하여 Gitaly 리포지터리 복제 상태를 관리합니다. Geo와 Gitaly Cluster(Praefect)를 함께 사용할 경우 Praefect 복제 상태는 각 사이트마다 고유합니다. 각 Geo 사이트에는 Praefect 데이터베이스를 위한 별도의 읽기-쓰기 PostgreSQL 데이터베이스 인스턴스가 있어야 합니다.

  • GitLab 애플리케이션 데이터베이스와 Praefect 데이터베이스를 동일한 PostgreSQL 서버에 저장하지 마세요.

  • Geo primary 사이트의 Praefect Postgres 데이터베이스가 Geo secondary 사이트로 복제되도록 구성하지 마세요.

이 지침은 단일 장애 지점을 만드는 단일 PostgreSQL 데이터베이스를 설정하는 데 도움이 됩니다. 이를 방지하려면 자체 클러스터링된 PostgreSQL을 구성할 수 있습니다. 다른 데이터베이스(예: Praefect 및 Geo 데이터베이스)에 대한 클러스터링 데이터베이스 지원은 이슈 7292에서 제안되었습니다.

다음 옵션을 사용할 수 있습니다:

  • Geo가 아닌 설치의 경우 다음 중 하나를 선택합니다:

문서화된 PostgreSQL 설정 중 하나를 사용합니다.

  • 자체 타사 데이터베이스 설정을 사용합니다. 이 경우 수동 설정이 필요합니다.

  • Geo 인스턴스의 경우 다음 중 하나를 선택합니다:

별도의 PostgreSQL 인스턴스를 설정합니다.

PostgreSQL을 설정하면 빈 Praefect 테이블이 생성됩니다. 자세한 내용은 관련 트러블슈팅 섹션을 참조하세요.

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

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

  • 사용 불가.

  • 읽기 전용 모드.

수동 데이터베이스 설정#

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

  • Praefect 노드 1대

  • PostgreSQL 노드 1대

데이터베이스 서버를 관리할 권한이 있는 PostgreSQL 사용자

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

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

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

CREATE ROLE praefect WITH LOGIN PASSWORD 'PRAEFECT_SQL_PASSWORD';

PRAEFECT_SQL_PASSWORD를 준비 단계에서 생성한 강력한 암호로 교체합니다.

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

CREATE DATABASE praefect_production WITH OWNER praefect ENCODING UTF8;

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

Linux 패키지 제공 PgBouncer의 경우 실제 암호 대신 praefect 암호의 해시를 사용해야 합니다:

ALTER ROLE praefect WITH PASSWORD 'md5';

를 준비 단계에서 생성한 암호의 해시로 교체합니다. md5 리터럴이 앞에 붙습니다.

PgBouncer에서 사용할 새 사용자 pgbouncer를 생성합니다:

CREATE ROLE pgbouncer WITH LOGIN;
ALTER USER pgbouncer WITH password 'md5';

PGBOUNCER_SQL_PASSWORD_HASH를 준비 단계에서 생성한 강력한 암호 해시로 교체합니다.

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 데이터베이스 오류가 발생하면 트러블슈팅 단계를 참조하세요.

읽기 분산 캐싱#

session_pooled 설정을 추가로 구성하여 Praefect 성능을 향상시킬 수 있습니다:

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

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         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 인스턴스를 사용할 수 있습니다.

PostgreSQL 인스턴스 앞에 PgBouncer를 구성하려면 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 데이터베이스 엔드포인트를 사용하지만 다른 풀 모드(pool_mode = session)를 가진 새 PgBouncer 데이터베이스를 구성합니다.

  • Praefect가 PostgreSQL에 직접 연결하고 PgBouncer를 우회하도록 합니다.

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

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

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

그런 다음 PgBouncer 호스트에서 별도의 연결 풀을 구성합니다:

pgbouncer['databases'] = {
  # Other database configuration including gitlabhq_production
  ...

  praefect_production: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    pool_mode: 'transaction'
  },
  praefect_production_direct: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    dbname: 'praefect_production',
    pool_mode: 'session'
  },

  ...
}

# Allow the praefect user to connect to 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` is the plain-text password of
      # Praefect user. Not to be confused with `PRAEFECT_SQL_PASSWORD_HASH`.
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      session_pooled: {
         # ...
         dbname: 'praefect_production_direct',
         # There is no need to repeat the following. Parameters of direct
         # database connection will fall back to the values specified in the
         # database block.
         #
         # host: PGBOUNCER_HOST,
         # port: 6432,
         # user: 'praefect',
         # password: PRAEFECT_SQL_PASSWORD,
      },
   },
}

이 구성으로 Praefect는 두 연결 유형 모두에 PgBouncer를 사용합니다.

Linux 패키지 설치는 인증 요구 사항을 처리하지만(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,

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         #
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      },
   },
}

Praefect#

Praefect를 구성하기 전에 Praefect 구성 파일 예시를 참조하여 숙지하세요. Linux 패키지를 사용하여 GitLab을 설치한 경우 예시 파일의 설정을 Ruby로 변환해야 합니다.

Praefect 노드가 여러 개인 경우:

  • 하나의 노드를 배포 노드로 지정하고 다음 단계를 사용하여 구성합니다.

  • 각 추가 노드에 대해 다음 단계를 완료합니다.

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

Praefect는 전용 노드에서 실행해야 합니다. 애플리케이션 서버 또는 Gitaly 노드에서 Praefect를 실행하지 마세요.

Praefect 노드에서:

  • /etc/gitlab/gitlab.rb를 편집하여 다른 모든 서비스를 비활성화합니다:
# Avoid running unnecessary services on the Praefect server
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

# Enable only the Praefect service
praefect['enable'] = true

# Prevent database migrations from running on upgrade automatically
praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false

/etc/gitlab/gitlab.rb를 편집하여 Praefect가 네트워크 인터페이스에서 수신 대기하도록 구성합니다:

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

/etc/gitlab/gitlab.rb를 편집하여 Prometheus 메트릭을 구성합니다:

praefect['configuration'] = {
   # ...
   #
   # Enable Prometheus metrics access to Praefect. You must use firewalls
   # to restrict access to this address/port.
   # The default metrics endpoint is /metrics
   prometheus_listen_addr: '0.0.0.0:9652',
   # Some metrics run queries against the database. Enabling separate database metrics allows
   # these metrics to be collected when the metrics are
   # scraped on a separate /db_metrics endpoint.
   prometheus_exclude_database_from_default_metrics: true,
}

/etc/gitlab/gitlab.rb를 편집하여 Praefect에 대한 강력한 인증 토큰을 구성합니다. 클러스터 외부의 클라이언트(예: GitLab Shell)가 Praefect 클러스터와 통신하는 데 필요합니다:

praefect['configuration'] = {
   # ...
   auth: {
      # ...
      token: 'PRAEFECT_EXTERNAL_TOKEN',
   },
}

PostgreSQL 데이터베이스에 연결하도록 Praefect를 구성합니다. PgBouncer도 함께 사용하는 것을 강력히 권장합니다.

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

praefect['configuration'] = {
   # ...
   database: {
      # ...
      #
      # Connect to PostgreSQL using a TLS client certificate
      # sslcert: '/path/to/client-cert',
      # sslkey: '/path/to/client-key',
      #
      # Trust a custom certificate authority
      # sslrootcert: '/path/to/rootcert',
   },
}

기본적으로 Praefect는 PostgreSQL에 연결할 때 기회적 TLS를 사용합니다. 즉, Praefect는 sslmodeprefer로 설정하여 PostgreSQL에 연결을 시도합니다. 다음 줄의 주석을 제거하여 이를 재정의할 수 있습니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      # sslmode: 'disable',
   },
}

/etc/gitlab/gitlab.rb를 편집하여 Praefect 클러스터가 클러스터의 각 Gitaly 노드에 연결하도록 구성합니다.

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

이미 default라는 스토리지에 데이터가 있는 경우 다른 이름으로 가상 스토리지를 구성하고 나중에 데이터를 Gitaly Cluster(Praefect) 스토리지로 마이그레이션해야 합니다.

PRAEFECT_INTERNAL_TOKEN을 강력한 시크릿으로 교체합니다. 클러스터의 Gitaly 노드와 통신할 때 Praefect에서 사용합니다. 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 구별됩니다.

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

복제본 수를 늘리기 위해 클러스터에 더 많은 Gitaly 노드를 추가할 수 있습니다. 매우 큰 GitLab 인스턴스의 경우 더 많은 클러스터를 추가할 수도 있습니다.

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

# Name of storage hash must match storage name in gitlab_rails['repositories_storages'] on GitLab
# server ('default') and in gitaly['configuration'][:storage][INDEX][:name] on Gitaly nodes ('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'
            },
         ],
      },
   ],
}

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

다음의 경우:

"배포 노드":

/etc/gitlab/gitlab.rb에서 praefect['auto_migrate'] = true를 설정하여 Praefect 데이터베이스 자동 마이그레이션을 다시 활성화합니다.

업그레이드 시 자동으로 마이그레이션이 실행되지 않고 재구성 중에만 실행되도록 하려면 다음을 실행합니다:

sudo touch /etc/gitlab/skip-auto-reconfigure

다른 노드의 경우 설정을 그대로 둘 수 있습니다. /etc/gitlab/skip-auto-reconfigure가 필수는 아니지만 apt-get update와 같은 명령을 실행할 때 GitLab이 자동으로 재구성되는 것을 방지하기 위해 설정할 수 있습니다. 이렇게 하면 추가 구성 변경을 수행한 다음 수동으로 재구성을 실행할 수 있습니다.

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

Praefect가 Prometheus 수신 주소를 업데이트했는지 확인하려면 Praefect를 재시작합니다:

gitlab-ctl restart praefect

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 인스턴스와 통신하려면 다음을 해야 합니다:

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

  • 자체 인증서를 가져오세요. 이는 자동으로 제공되지 않습니다. 각 Praefect 서버에 해당하는 인증서를 해당 Praefect 서버에 설치해야 합니다.

또한 인증서 또는 인증 기관은 아래 설명된 절차에 따라 모든 Gitaly 서버 및 Praefect와 통신하는 모든 Praefect 클라이언트에 설치되어야 합니다. GitLab 사용자 정의 인증서 구성(아래에 반복됨).

다음 사항에 유의하세요:

인증서는 Praefect 서버에 접근하는 데 사용하는 주소를 지정해야 합니다. 인증서에 호스트 이름 또는 IP 주소를 Subject Alternative Name으로 추가해야 합니다.

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 패키지 설치의 경우:

Praefect 서버의 인증서를 생성합니다.

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

/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',
   },
}

파일을 저장하고 재구성합니다.

Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서 또는 인증 기관을 /etc/gitlab/trusted-certs에 복사합니다:

sudo cp cert.pem /etc/gitlab/trusted-certs/

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다:

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:3305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

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

소스 컴파일 설치의 경우:

Praefect 서버의 인증서를 생성합니다.

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

Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서 또는 인증 기관을 시스템 신뢰 인증서에 복사합니다:

sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
sudo update-ca-certificates

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

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: tls://PRAEFECT_LOADBALANCER_HOST:3305

파일을 저장하고 GitLab을 재시작합니다.

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

sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
sudo update-ca-certificates

/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'

파일을 저장하고 GitLab을 재시작합니다.

서비스 검색#

사전 요구 사항:

  • DNS 서버.

GitLab은 서비스 검색을 사용하여 Praefect 호스트 목록을 검색합니다. 서비스 검색은 DNS A 또는 AAAA 레코드를 주기적으로 확인하며, 레코드에서 검색된 IP가 타깃 노드의 주소 역할을 합니다. Praefect는 SRV 레코드를 통한 서비스 검색을 지원하지 않습니다.

기본적으로 레코드의 TTL에 관계없이 확인 사이의 최소 시간은 5분입니다. 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]
히스토리

TLS 암호화와 함께 서비스 검색을 사용하려면 dns+tls 스킴을 사용합니다:

  • dns+tls:[host]:[port](단축 형식)

  • dns+tls:///[host]:[port](슬래시 세 개 주의)

  • dns+tls://[authority_host]:[authority_port]/[host]:[port]

dns+tls:// 스킴은 DNS 기반 서비스 검색과 TLS 암호화를 결합합니다. 이 스킴을 사용하기 전에 Praefect 서버에 TLS를 구성해야 합니다. 자세한 내용은 TLS 활성화를 참조하세요.

각 Praefect 엔드포인트의 TLS 인증서에는 아래 PRAEFECT_SERVICE_DISCOVERY_ADDRESS에서 사용되는 호스트 이름과 일치하는 Subject Alternative Name(SAN)이 포함되어야 합니다. 예를 들어 주소가 dns+tls:///praefect.service.consul:3305인 경우 각 Praefect 노드의 인증서에 praefect.service.consul이 SAN 항목으로 있어야 합니다. SAN이 일치하지 않으면 연결이 실패합니다.

Linux 패키지(Omnibus)

각 Praefect 노드의 IP 주소를 DNS 서비스 검색 주소에 추가합니다.

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다. PRAEFECT_SERVICE_DISCOVERY_ADDRESSpraefect.service.consul과 같은 Praefect 서비스 검색 주소로 교체합니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

TLS를 사용하려면 스킴을 dns+tls://로 변경합니다:

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns+tls://DNS_SERVER_ADDRESS:53/PRAEFECT_SERVICE_DISCOVERY_ADDRESS:3305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

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

소스 컴파일(source)

DNS 서비스 검색 서비스를 설치합니다. 모든 Praefect 노드를 서비스에 등록합니다.

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

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305

TLS를 사용하려면 스킴을 dns+tls://로 변경합니다:

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: dns+tls://DNS_SERVER_ADDRESS:53/PRAEFECT_SERVICE_DISCOVERY_ADDRESS:3305

파일을 저장하고 GitLab을 재시작합니다.

Consul로 서비스 검색 구성#

아키텍처에 이미 Consul 서버가 있는 경우 각 Praefect 노드에 Consul 에이전트를 추가하고 praefect 서비스를 등록할 수 있습니다. 이렇게 하면 각 노드의 IP 주소가 praefect.service.consul에 등록되어 서비스 검색으로 찾을 수 있습니다.

사전 요구 사항:

  • Consul 에이전트를 추적하기 위한 Consul 서버 하나 이상.

각 Praefect 서버에서 /etc/gitlab/gitlab.rb에 다음을 추가합니다:

consul['enable'] = true
praefect['consul_service_name'] = 'praefect'

# The following must also be added until this issue is addressed:
# https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/8321
consul['monitoring_service_discovery'] = true
praefect['configuration'] = {
  # ...
  #
  prometheus_listen_addr: '0.0.0.0:9652',
}

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

서비스 검색과 함께 사용할 각 Praefect 서버에서 이전 단계를 반복합니다.

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다. CONSUL_SERVER를 Consul 서버의 IP 또는 주소로 교체합니다. 기본 Consul DNS 포트는 8600입니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns://CONSUL_SERVER:8600/praefect.service.consul:2305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

Praefect 클라이언트에서 dig를 사용하여 각 IP 주소가 praefect.service.consuldig A praefect.service.consul @CONSUL_SERVER -p 8600으로 등록되었는지 확인합니다. CONSUL_SERVER를 이전에 구성한 값으로 교체하면 모든 Praefect 노드 IP 주소가 출력에 있어야 합니다.

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

Gitaly#

각 Gitaly 노드마다 이 단계를 완료합니다.

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

  • 구성된 Praefect 노드

  • GitLab이 설치된 서버 3대(이상). Gitaly 노드로 구성됩니다. 전용 노드여야 하며, 이 노드에서 다른 서비스를 실행하지 마세요.

Praefect 클러스터에 할당된 모든 Gitaly 서버는 구성되어야 합니다. 구성은 표준 독립형 Gitaly 서버와 동일하지만 다음 점에서 다릅니다:

  • 스토리지 이름은 GitLab이 아닌 Praefect에 노출됩니다.

  • 시크릿 토큰은 GitLab이 아닌 Praefect와 공유됩니다.

Praefect가 올바르게 작업을 라우팅하기 때문에 Praefect 클러스터의 모든 Gitaly 노드 구성은 동일할 수 있습니다.

특별히 주의해야 할 사항:

  • 이 섹션에서 구성된 gitaly['configuration'][:auth][:token]은 Praefect 노드의 praefect['configuration'][:virtual_storage][<index>][:node][<index>][:token] 값과 일치해야 합니다. 이 값은 이전 섹션에서 설정되었습니다. 이 문서는 전체적으로 자리 표시자 PRAEFECT_INTERNAL_TOKEN을 사용합니다.

  • 이 섹션에서 구성된 gitaly['configuration'][:storage]의 물리적 스토리지 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage]의 물리적 스토리지 이름과 일치해야 합니다. 이는 이전 섹션에서 설정되었습니다. 이 문서는 물리적 스토리지 이름으로 gitaly-1, gitaly-2, gitaly-3을 사용합니다.

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

Gitaly 노드에 SSH로 접속하고 root로 로그인합니다:

sudo -i

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

# Disable all other services on the Gitaly node
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

# Enable only the Gitaly service
gitaly['enable'] = true

# Enable Prometheus if needed
prometheus['enable'] = true

# Disable database migrations to prevent database connections during 'gitlab-ctl reconfigure'
gitlab_rails['auto_migrate'] = false

/etc/gitlab/gitlab.rb를 편집하여 Gitaly가 네트워크 인터페이스에서 수신 대기하도록 구성합니다:

gitaly['configuration'] = {
   # ...
   #
   # Make Gitaly accept connections on all network interfaces.
   # Use firewalls to restrict access to this address/port.
   listen_addr: '0.0.0.0:8075',
   # Enable Prometheus metrics access to Gitaly. You must use firewalls
   # to restrict access to this address/port.
   prometheus_listen_addr: '0.0.0.0:9236',
}

/etc/gitlab/gitlab.rb를 편집하여 Gitaly에 대한 강력한 auth_token을 구성합니다. 클라이언트가 이 Gitaly 노드와 통신하는 데 필요합니다. 일반적으로 이 토큰은 모든 Gitaly 노드에서 동일합니다.

gitaly['configuration'] = {
   # ...
   auth: {
      # ...
      token: 'PRAEFECT_INTERNAL_TOKEN',
   },
}

git push 작업에 필요한 GitLab Shell 시크릿 토큰을 구성합니다. 다음 중 하나를 선택합니다:

방법 1:

Gitaly 클라이언트에서 Gitaly 서버와 다른 Gitaly 클라이언트에 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

방법 2:

/etc/gitlab/gitlab.rb를 편집합니다.

GITLAB_SHELL_SECRET_TOKEN을 실제 시크릿으로 교체합니다.

GitLab 17.5 이상:

gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'

GitLab 17.4 이하:

gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'

git push 작업에도 필요한 internal_api_url을 구성합니다:

# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your front door GitLab URL or an internal load balancer.
# Examples: 'https://gitlab.example.com', 'http://10.0.2.2'
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'

/etc/gitlab/gitlab.rb에서 gitaly['configuration'][:storage]를 설정하여 Git 데이터의 스토리지 위치를 구성합니다. 각 Gitaly 노드에는 고유한 스토리지 이름(예: gitaly-1)이 있어야 하며 다른 Gitaly 노드에서 중복되어서는 안 됩니다.

gitaly['configuration'] = {
   # ...
   storage: [
     # Replace with appropriate name for each Gitaly nodes.
     {
       name: 'gitaly-1',
       path: '/var/opt/gitlab/git-data/repositories',
     },
   ],
}

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Gitaly를 재구성합니다:

gitlab-ctl reconfigure

Gitaly가 Prometheus 수신 주소를 업데이트했는지 확인하려면 Gitaly를 재시작합니다:

gitlab-ctl restart gitaly

이전 단계는 각 Gitaly 노드마다 완료해야 합니다!

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

각 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

TCP 로드 밸런서를 사용해야 합니다. Gitaly 사이드채널 때문에 Praefect에 HTTP/2 또는 gRPC 로드 밸런서를 사용하면 작동하지 않습니다. 이 최적화는 gRPC 핸드셰이킹 프로세스를 차단합니다. 모든 무거운 Git 작업을 gRPC보다 더 효율적인 "채널"로 리디렉션하지만 HTTP/2 또는 gRPC 로드 밸런서는 이러한 요청을 올바르게 처리하지 못합니다.

TLS가 활성화된 경우 일부 Praefect 버전에서는 RFC 7540에 따라 Application-Layer Protocol Negotiation(ALPN) 확장을 사용해야 합니다. TCP 로드 밸런서는 추가 구성 없이 ALPN을 직접 전달합니다:

sequenceDiagram
    autonumber
    participant Client as Client
    participant LB as TCP Load Balancer
    participant Praefect as Praefect

    Client->>LB: Establish TLS Session (w/ ALPN Extension)
    LB->>Praefect: Establish TLS Session (w/ ALPN Extension)
    Client->>LB: Encrypted TCP packets
    LB->>Praefect: Encrypted TCP packets
    Praefect->>LB: Encrypted Response
    LB->>Client: Encrypted Response

일부 TCP 로드 밸런서는 TLS 클라이언트 연결을 수락하고 새 TLS 연결로 Praefect에 프록시하도록 구성할 수 있습니다. 그러나 이는 두 연결 모두에서 ALPN이 지원되는 경우에만 작동합니다.

이러한 이유로 NGINX의 ngx_stream_proxy_moduleproxy_ssl 구성 옵션이 활성화된 경우 작동하지 않습니다:

sequenceDiagram
    autonumber
    participant Client as Client
    participant NGINX as NGINX Stream Proxy
    participant Praefect as Praefect

    Client->>NGINX: Establish TLS Session (w/ ALPN Extension)
    NGINX->>Praefect: Establish New TLS Session
    Praefect->>NGINX: Connection failed: missing selected ALPN property

2단계에서 NGINX가 이를 지원하지 않기 때문에 ALPN이 사용되지 않습니다. 자세한 내용은 NGINX 이슈 406을 따르세요.

ALPN 적용#

ALPN 적용은 일부 GitLab 버전에서 활성화되었습니다. 그러나 ALPN 적용이 배포를 중단시켰기 때문에 마이그레이션 경로를 제공하기 위해 비활성화되었습니다. 다음 GitLab 버전에서는 ALPN 적용이 활성화되어 있습니다:

  • GitLab 17.7.0

  • GitLab 17.6.0 - 17.6.2

  • GitLab 17.5.0 - 17.5.4

  • GitLab 17.4.x

GitLab 17.5.5, 17.6.3, 17.7.1부터 ALPN 적용이 다시 비활성화됩니다. GitLab 17.4 이하에서는 ALPN 적용이 활성화된 적이 없습니다.

GitLab#

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

Praefect 클러스터는 gitlab_rails['repositories_storages']를 업데이트하여 GitLab 애플리케이션에 스토리지 위치로 노출되어야 합니다.

특별히 주의해야 할 사항:

  • 이 섹션에서 gitlab_rails['repositories_storages']에 추가된 스토리지 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage] 아래의 스토리지 이름과 일치해야 합니다. 이는 이 가이드의 Praefect 섹션에서 설정되었습니다. 이 문서는 Praefect 스토리지 이름으로 default를 사용합니다.

GitLab 노드에 SSH로 접속하고 root로 로그인합니다:

sudo -i

/etc/gitlab/gitlab.rb를 편집하여 파일이 적절한 엔드포인트 접근으로 GitLab에 의해 제공될 수 있도록 external_url을 구성합니다:

현재 GitLab 인스턴스가 서비스하는 실제 외부 URL로 GITLAB_SERVER_URL을 교체해야 합니다:

external_url 'GITLAB_SERVER_URL'

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

기본 Gitaly 스토리지에 저장된 기존 데이터가 있는 경우 먼저 데이터를 Gitaly Cluster(Praefect) 스토리지로 마이그레이션해야 합니다.

gitaly['enable'] = false

/etc/gitlab/gitlab.rb를 편집하여 Praefect 클러스터를 스토리지 위치로 추가합니다.

다음을 교체해야 합니다:

PRAEFECT_LOADBALANCER_HOST: 로드 밸런서의 IP 주소 또는 호스트 이름

  • PRAEFECT_EXTERNAL_TOKEN: 실제 시크릿

TLS를 사용하는 경우:

  • gitaly_address는 대신 tls://로 시작해야 합니다.

  • 포트는 3305로 변경해야 합니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => "tcp://PRAEFECT_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

git push 중 Gitaly 노드의 콜백이 올바르게 인증되도록 GitLab Shell 시크릿 토큰을 구성합니다. 다음 중 하나를 선택합니다:

방법 1:

Gitaly 클라이언트에서 Gitaly 서버와 다른 Gitaly 클라이언트에 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

방법 2:

/etc/gitlab/gitlab.rb를 편집합니다.

GITLAB_SHELL_SECRET_TOKEN을 실제 시크릿으로 교체합니다:

GitLab 17.5 이상:

gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'

GitLab 17.4 이하:

gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'

/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
      ]
    ]
  }
]

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

각 Gitaly 노드에서 Git Hooks가 GitLab에 도달할 수 있는지 확인합니다. 각 Gitaly 노드에서 다음을 실행합니다:

sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml

GitLab이 Praefect에 도달할 수 있는지 확인합니다:

gitlab-rake gitlab:gitaly:check

Praefect 스토리지가 새 리포지터리를 저장하도록 구성되어 있는지 확인합니다:

오른쪽 상단 모서리에서 Admin을 선택합니다.

  • 왼쪽 사이드바에서 Settings > Repository를 선택합니다.

  • Repository storage 섹션을 확장합니다.

이 가이드에 따라 default 스토리지의 가중치는 모든 새 리포지터리를 저장하기 위해 100이어야 합니다.

새 프로젝트를 생성하여 모든 것이 작동하는지 확인합니다. 볼 수 있는 콘텐츠가 리포지터리에 있도록 "Initialize repository with a README" 박스를 선택합니다. 프로젝트가 생성되고 README 파일을 볼 수 있다면 작동하는 것입니다!

기존 GitLab 인스턴스에 TCP 사용#

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

예를 들면:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://old-gitaly.internal:8075' },
  'cluster' => {
    'gitaly_address' => 'tls://:3305',
    'gitaly_token' => '<praefect_external_token>'
  }
}

여러 Gitaly 스토리지를 실행하는 방법에 대한 자세한 내용은 혼합 구성을 참조하세요.

여러 가상 스토리지 구성#

여러 가상 스토리지를 구성하여 리포지터리를 별도의 Gitaly Cluster(Praefect) 클러스터로 구성할 수 있습니다. 각 가상 스토리지는 자체 Gitaly 노드 세트와 복제 설정으로 독립적으로 작동합니다.

여러 가상 스토리지를 구성하려면:

각 Praefect 노드에서 /etc/gitlab/gitlab.rb를 편집하여 virtual_storage 배열에 여러 항목을 추가합니다:

praefect['configuration'] = {
   # ...
   virtual_storage: [
      {
         name: 'storage-1',
         default_replication_factor: 3,
         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'
            }
         ]
      },
      {
         name: 'storage-2',
         default_replication_factor: 2,
         node: [
            {
               storage: 'gitaly-4',
               address: 'tcp://GITALY_HOST_4:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            },
            {
               storage: 'gitaly-5',
               address: 'tcp://GITALY_HOST_5:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            },
            {
               storage: 'gitaly-6',
               address: 'tcp://GITALY_HOST_6:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            }
         ]
      }
   ]
}

변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

GitLab 서버에서 /etc/gitlab/gitlab.rb를 편집하여 두 가상 스토리지를 모두 구성합니다:

gitlab_rails['repositories_storages'] = {
  "storage-1" => {
    "gitaly_address" => "tcp://PRAEFECT_1_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  },
  "storage-2" => {
    "gitaly_address" => "tcp://PRAEFECT_2_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

구성을 확인합니다:

gitlab-rake gitlab:gitaly:check

구성 후에 다음을 수행할 수 있습니다:

독립형 및 클러스터 스토리지 혼합 구성#

GitLab을 독립형 Gitaly 인스턴스와 Gitaly Cluster(Praefect) 가상 스토리지를 동시에 사용하도록 구성할 수 있습니다. 마이그레이션 중이거나 일부 리포지터리만 고가용성이 필요한 경우 이렇게 할 수 있습니다.

혼합 설정을 구성하려면:

독립형 Gitaly 인스턴스가 TCP에서 수신 대기하도록 구성되어 있는지 확인합니다. 독립형 Gitaly 노드에서 /etc/gitlab/gitlab.rb를 편집합니다:

gitaly['configuration'] = {
   # ...
   listen_addr: '0.0.0.0:8075'
}

독립형 Gitaly 인스턴스의 인증을 구성합니다:

gitaly['configuration'] = {
   # ...
   auth: {
      token: 'GITALY_AUTH_TOKEN',
   },
}

저장하고 재구성합니다:

gitlab-ctl reconfigure

GitLab 서버에서 /etc/gitlab/gitlab.rb를 편집하여 독립형 스토리지와 클러스터 스토리지를 모두 구성합니다:

gitlab_rails['repositories_storages'] = {
  'default' => {
    'gitaly_address' => 'tcp://STANDALONE_GITALY_HOST:8075',
    'gitaly_token' => 'GITALY_AUTH_TOKEN'
  },
  'cluster' => {
    'gitaly_address' => 'tcp://PRAEFECT_LOADBALANCER_HOST:2305',
    'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

두 스토리지 모두 접근 가능한지 확인합니다:

gitlab-rake gitlab:gitaly:check

이 구성에서:

  • default 스토리지는 독립형 Gitaly 노드에 직접 연결합니다.

  • cluster 스토리지는 로드 밸런서를 통해 Gitaly Cluster(Praefect)에 연결합니다.

  • GitLab은 두 스토리지를 동등하게 취급하며 어느 스토리지에나 리포지터리를 저장할 수 있습니다.

  • 새 리포지터리에 대해 하나의 스토리지를 선호하도록 스토리지 가중치를 구성할 수 있습니다.

자세한 내용은 혼합 구성을 참조하세요.

Grafana#

Grafana는 GitLab에 포함되어 있으며 Praefect 클러스터를 모니터링하는 데 사용할 수 있습니다. 자세한 설명서는 Grafana 대시보드 서비스를 참조하세요.

빠르게 시작하려면:

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

sudo -i

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

grafana['disable_login_form'] = false

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

Grafana 관리자 암호를 설정합니다. 이 명령은 새 암호를 입력하도록 요청합니다:

gitlab-ctl set-grafana-password

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

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

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

축하합니다! 관찰 가능한 내결함성 Praefect 클러스터를 구성했습니다.

복제 인수 구성#

Praefect는 특정 스토리지 노드를 리포지터리를 호스팅하도록 할당하여 리포지터리별로 복제 인수를 구성하는 것을 지원합니다.

오브젝트 풀, 포크된 리포지터리 또는 포크 자체의 복제 인수를 줄이지 마세요. 이로 인해 전체 포크 네트워크가 손상될 수 있습니다. 오브젝트 풀은 @pools/로 시작하는 상대 경로를 가집니다. GitLab UI를 통해 리포지터리가 포크되었는지 확인할 수 있습니다.

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

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

  • 새로 생성된 리포지터리에 적용되는 각 가상 스토리지의 기본 복제 인수.

  • set-replication-factor 하위 명령으로 기존 리포지터리의 복제 인수.

기본 복제 인수 구성#

오브젝트 풀이 있을 때 기본 복제를 줄이면 일부 연결된 리포지터리가 손상될 수 있습니다. 오브젝트 풀은 @pools/로 시작하는 상대 경로를 가집니다.

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

많은 스토리지 노드가 있는 대규모 Gitaly Cluster(Praefect) 배포의 경우 모든 스토리지 노드에 리포지터리를 복제하는 것은 종종 합리적이지 않으며 문제를 일으킬 수 있습니다. 복제 인수 3이 일반적으로 충분하며, 더 많이 사용 가능하더라도 리포지터리를 세 개의 스토리지에 복제하는 것을 의미합니다. 높은 복제 인수는 primary 스토리지에 대한 압력을 증가시킵니다.

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

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

기존 리포지터리의 복제 인수 구성#

set-replication-factor 하위 명령은 원하는 복제 인수에 도달하기 위해 필요에 따라 임의의 스토리지 노드를 자동으로 할당하거나 할당 해제합니다. 리포지터리의 primary 노드는 항상 먼저 할당되며 할당 해제되지 않습니다.

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -relative-path <relative-path> -replication-factor <replication-factor>
  • -virtual-storage는 리포지터리가 위치한 가상 스토리지입니다.

  • -relative-path는 스토리지에서 리포지터리의 상대 경로입니다.

  • -replication-factor는 리포지터리의 원하는 복제 인수입니다. primary는 리포지터리 사본이 필요하기 때문에 최솟값은 1입니다. 최대 복제 인수는 가상 스토리지의 스토리지 수입니다.

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

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

current assignments: gitaly-1, gitaly-2

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

필요한 스토리지의 크기는 인스턴스에 따라 다르며 설정된 복제 인수에 따라 달라집니다. 리포지터리 스토리지 이중화 구현을 고려할 수 있습니다.

복제 인수의 경우:

  • 1인 경우: Gitaly와 Gitaly Cluster(Praefect)의 스토리지 요구 사항은 거의 동일합니다.

  • 1보다 큰 경우: 필요한 스토리지 양은 사용된 공간 * 복제 인수입니다. 사용된 공간에는 계획된 미래 성장도 포함해야 합니다.

리포지터리 검증#

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

메타데이터는 복제 및 라우팅 결정에 사용되므로 부정확한 경우 문제가 발생할 수 있습니다. Praefect에는 디스크의 실제 상태와 메타데이터를 주기적으로 확인하는 백그라운드 워커가 포함되어 있습니다. 워커는:

  • 정상 스토리지에서 확인할 복제본 배치를 선택합니다. 복제본은 확인되지 않았거나 구성된 확인 간격을 초과한 것입니다. 한 번도 확인되지 않은 복제본이 우선순위가 지정되며, 그 다음으로 마지막 성공적인 확인 이후 가장 오랜 시간이 지난 복제본 순으로 정렬됩니다.

  • 복제본이 해당 스토리지에 존재하는지 확인합니다. 다음의 경우:

복제본이 존재하면 마지막 성공적인 확인 시간을 업데이트합니다.

  • 복제본이 존재하지 않으면 메타데이터 레코드를 제거합니다.

  • 확인에 실패하면 다음 워커가 더 많은 작업을 대기열에서 가져올 때 복제본이 다시 확인을 위해 선택됩니다.

워커는 확인하려는 각 복제본에 대해 독점적 확인 리스를 획득합니다. 이렇게 하면 여러 워커가 동일한 복제본을 동시에 확인하는 것을 방지합니다. 워커는 확인을 완료하면 리스를 해제합니다. 어떤 이유로 워커가 리스를 해제하지 않고 종료된 경우 Praefect에는 10초마다 오래된 리스를 해제하는 백그라운드 goroutine이 포함되어 있습니다.

워커는 실행하기 전에 각 메타데이터 제거를 로그에 기록합니다. 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.0에서 도입되어 기본적으로 비활성화됨

삭제는 리포지터리 이름 변경의 경쟁 조건으로 인해 GitLab 15.9 이전에는 기본적으로 비활성화되었으며, 이로 인해 잘못된 삭제가 발생할 수 있습니다. 이는 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>

출력에는 확인되지 않은 것으로 표시된 복제본의 수가 포함됩니다.

자동 페일오버 및 primary 선출#

Praefect는 각 Gitaly 노드의 상태를 정기적으로 확인하며, 현재 primary 노드가 비정상으로 확인되면 새로 선출된 primary Gitaly 노드로 자동 페일오버하는 데 사용됩니다.

리포지터리별 primary 노드가 유일하게 사용 가능한 선출 전략입니다.

리포지터리별 primary 노드#

Gitaly Cluster(Praefect)는 각 리포지터리에 대해 별도로 primary Gitaly 노드를 선출합니다. 구성 가능한 복제 인수와 결합하여 스토리지 용량을 수평으로 확장하고 Gitaly 노드 전체에 쓰기 로드를 분산할 수 있습니다.

primary 선출은 지연 방식으로 실행됩니다. 현재 primary가 비정상적인 경우 Praefect는 즉시 새 primary 노드를 선출하지 않습니다. 현재 primary를 사용할 수 없는 상태에서 요청을 처리해야 하는 경우 새 primary가 선출됩니다.

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

  • 정상 상태. Praefect 노드의 >=50%가 이전 10초 동안 Gitaly 노드의 상태를 성공적으로 확인한 경우 Gitaly 노드는 정상으로 간주됩니다.

  • 리포지터리의 최신 사본이 있습니다.

primary 노드 후보가 여러 개인 경우 Praefect는:

  • 임의로 하나를 선택합니다.

  • 리포지터리를 호스팅하도록 할당된 Gitaly 노드의 승진을 우선시합니다. primary로 선출할 할당된 Gitaly 노드가 없는 경우 Praefect는 일시적으로 할당되지 않은 노드를 선출할 수 있습니다. 할당되지 않은 primary는 할당된 노드가 사용 가능해지면 해당 노드에게 자리를 내줍니다.

리포지터리에 유효한 primary 후보가 없는 경우:

  • 비정상적인 primary 노드가 강등되고 리포지터리는 primary 노드 없이 남습니다.

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

Gitaly Cluster(Praefect) 구성

GitLab v19.2
원문 보기
요약

Gitaly Cluster(Praefect)는 다음 중 하나를 사용하여 구성합니다: 60 RPS 또는 사용자 3,000명. 100 RPS 또는 사용자 5,000명. 200 RPS 또는 사용자 10,000명. 500 RPS 또는 사용자 25,000명.

Gitaly Cluster(Praefect)는 다음 중 하나를 사용하여 구성합니다:

  • 다음 규모 이하 설치를 위한 참조 아키텍처에 포함된 Gitaly Cluster(Praefect) 구성 지침:

60 RPS 또는 사용자 3,000명.

소규모 GitLab 설치에는 Gitaly 자체만 필요할 수 있습니다.

Gitaly Cluster(Praefect)는 아직 쿠버네티스, Amazon ECS 또는 유사한 컨테이너 환경에서 지원되지 않습니다. 자세한 내용은 에픽 6127을 참조하세요.

요구 사항#

Gitaly Cluster(Praefect)의 최소 권장 구성에 필요한 항목:

  • 로드 밸런서 1대

  • PostgreSQL 서버 1대(지원되는 버전)

  • Praefect 노드 3대

  • Gitaly 노드 3대(primary 1대, secondary 2대)

디스크 요구 사항이 Gitaly 노드에 적용됩니다.

트랜잭션에서 Gitaly 노드 중 하나가 뮤테이팅 RPC 호출 도중 실패할 경우 타이브레이커가 있도록 홀수 개의 Gitaly 노드를 구성해야 합니다.

구현 세부 사항은 설계 문서를 참조하세요.

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

네트워크 지연 및 연결성#

Gitaly Cluster(Praefect)의 네트워크 지연은 이상적으로 한 자릿수 밀리초 단위여야 합니다. 지연은 특히 다음 항목에서 중요합니다:

  • Gitaly 노드 상태 확인. 노드는 1초 이내에 응답할 수 있어야 합니다.

  • 강력한 일관성을 적용하는 참조 트랜잭션. 지연이 낮을수록 Gitaly 노드가 변경 사항에 더 빠르게 동의할 수 있습니다.

Gitaly 노드 간 허용 가능한 지연을 달성하는 방법:

  • 물리적 네트워크에서는 일반적으로 고대역폭, 단일 위치 연결을 의미합니다.

  • 클라우드에서는 일반적으로 교차 가용 영역 복제를 허용하는 동일 리전 내를 의미합니다. 이러한 링크는 이런 유형의 동기화를 위해 설계되었습니다. Gitaly Cluster(Praefect)의 경우 2ms 미만의 지연이면 충분합니다.

원격지 간과 같이 복제를 위한 낮은 네트워크 지연을 제공할 수 없는 경우 Geo를 고려하세요. 자세한 내용은 Geo와의 비교를 참조하세요.

Gitaly Cluster(Praefect) 구성 요소는 다양한 경로를 통해 서로 통신합니다. Gitaly Cluster(Praefect)가 올바르게 작동하려면 방화벽 규칙에서 다음을 허용해야 합니다:

출발지 목적지 기본 포트 TLS 포트
GitLab Praefect 로드 밸런서 2305 3305
Praefect 로드 밸런서 Praefect 2305 3305
Praefect Gitaly 8075 9999
Praefect GitLab (내부 API) 80 443
Gitaly GitLab (내부 API) 80 443
Gitaly Praefect 로드 밸런서 2305 3305
Gitaly Praefect 2305 3305
Gitaly Gitaly 8075 9999

Gitaly는 Praefect에 직접 연결하지 않습니다. 그러나 Praefect 노드의 방화벽이 Gitaly 노드의 트래픽을 허용하지 않으면 Gitaly에서 Praefect 로드 밸런서로의 요청이 차단될 수 있습니다.

Praefect 데이터베이스 스토리지#

데이터베이스에는 다음 메타데이터만 포함되므로 요구 사항이 비교적 낮습니다:

  • 리포지터리의 위치.

  • 일부 대기 중인 작업.

리포지터리 수에 따라 다르지만 최소 5~10 GB가 적합하며, 이는 메인 GitLab 애플리케이션 데이터베이스와 유사한 크기입니다.

설치 지침#

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

준비#

시작하기 전에 이미 작동 중인 GitLab 인스턴스가 있어야 합니다. GitLab 설치 방법을 알아보세요.

PostgreSQL 서버를 프로비저닝합니다. Linux 패키지와 함께 제공되는 PostgreSQL을 사용하여 PostgreSQL 데이터베이스를 구성하는 것이 좋습니다. 외부 PostgreSQL 서버를 사용할 수 있지만 수동으로 설정해야 합니다.

GitLab을 설치하여 모든 새 노드를 준비합니다. 다음이 필요합니다:

  • PostgreSQL 노드 1대

  • PgBouncer 노드 1대(선택 사항)

  • Praefect 노드 최소 1대(최소 스토리지 필요)

  • Gitaly 노드 3대(높은 CPU, 높은 메모리, 빠른 스토리지)

  • GitLab 서버 1대

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

  • PRAEFECT_LOADBALANCER_HOST: Praefect 로드 밸런서의 IP/호스트 주소

  • POSTGRESQL_HOST: PostgreSQL 서버의 IP/호스트 주소

  • PGBOUNCER_HOST: PostgreSQL 서버의 IP/호스트 주소

  • PRAEFECT_HOST: Praefect 서버의 IP/호스트 주소

  • GITALY_HOST_*: 각 Gitaly 서버의 IP 또는 호스트 주소

  • GITLAB_HOST: GitLab 서버의 IP/호스트 주소

Google Cloud Platform, SoftLayer 또는 가상 프라이빗 클라우드(VPC)를 제공하는 다른 공급업체를 사용하는 경우 PRAEFECT_HOST, GITALY_HOST_*, GITLAB_HOST에 각 클라우드 인스턴스의 사설 주소(Google Cloud Platform의 경우 "내부 주소"에 해당)를 사용할 수 있습니다.

시크릿#

구성 요소 간 통신은 아래에 설명된 다양한 시크릿으로 보호됩니다. 시작하기 전에 각각에 대한 고유 시크릿을 생성하고 메모해 두세요. 이를 통해 설정 프로세스를 완료하면서 이 자리 표시자 토큰을 안전한 토큰으로 교체할 수 있습니다.

  • GITLAB_SHELL_SECRET_TOKEN: Git 푸시를 수락할 때 Git 훅이 GitLab에 콜백 HTTP API 요청을 하는 데 사용됩니다. 이 시크릿은 레거시 이유로 GitLab Shell과 공유됩니다.

  • PRAEFECT_EXTERNAL_TOKEN: Praefect 클러스터에서 호스팅되는 리포지터리는 이 토큰을 전달하는 Gitaly 클라이언트만 접근할 수 있습니다.

  • PRAEFECT_INTERNAL_TOKEN: 이 토큰은 Praefect 클러스터 내의 복제 트래픽에 사용됩니다. Gitaly 클라이언트가 Praefect 클러스터의 내부 노드에 직접 접근할 수 없어야 하기 때문에 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 구별됩니다. 그렇지 않으면 데이터 손실이 발생할 수 있습니다.

  • PRAEFECT_SQL_PASSWORD: Praefect가 PostgreSQL에 연결하는 데 사용하는 암호입니다.

  • PRAEFECT_SQL_PASSWORD_HASH: Praefect 사용자의 암호 해시입니다. gitlab-ctl pg-password-md5 praefect를 사용하여 해시를 생성합니다. 명령은 praefect 사용자의 암호를 입력하도록 요청합니다. PRAEFECT_SQL_PASSWORD 일반 텍스트 암호를 입력하세요. 기본적으로 Praefect는 praefect 사용자를 사용하지만 변경할 수 있습니다.

  • PGBOUNCER_SQL_PASSWORD_HASH: PgBouncer 사용자의 암호 해시입니다. PgBouncer는 이 암호를 사용하여 PostgreSQL에 연결합니다. 자세한 내용은 번들 PgBouncer 설명서를 참조하세요.

이러한 시크릿이 필요한 위치는 아래 지침에 표시되어 있습니다.

Linux 패키지 설치는 GITLAB_SHELL_SECRET_TOKENgitlab-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#

Praefect는 GitLab 애플리케이션 데이터베이스와 분리된 데이터베이스를 사용하여 Gitaly 리포지터리 복제 상태를 관리합니다. Geo와 Gitaly Cluster(Praefect)를 함께 사용할 경우 Praefect 복제 상태는 각 사이트마다 고유합니다. 각 Geo 사이트에는 Praefect 데이터베이스를 위한 별도의 읽기-쓰기 PostgreSQL 데이터베이스 인스턴스가 있어야 합니다.

  • GitLab 애플리케이션 데이터베이스와 Praefect 데이터베이스를 동일한 PostgreSQL 서버에 저장하지 마세요.

  • Geo primary 사이트의 Praefect Postgres 데이터베이스가 Geo secondary 사이트로 복제되도록 구성하지 마세요.

이 지침은 단일 장애 지점을 만드는 단일 PostgreSQL 데이터베이스를 설정하는 데 도움이 됩니다. 이를 방지하려면 자체 클러스터링된 PostgreSQL을 구성할 수 있습니다. 다른 데이터베이스(예: Praefect 및 Geo 데이터베이스)에 대한 클러스터링 데이터베이스 지원은 이슈 7292에서 제안되었습니다.

다음 옵션을 사용할 수 있습니다:

  • Geo가 아닌 설치의 경우 다음 중 하나를 선택합니다:

문서화된 PostgreSQL 설정 중 하나를 사용합니다.

  • 자체 타사 데이터베이스 설정을 사용합니다. 이 경우 수동 설정이 필요합니다.

  • Geo 인스턴스의 경우 다음 중 하나를 선택합니다:

별도의 PostgreSQL 인스턴스를 설정합니다.

PostgreSQL을 설정하면 빈 Praefect 테이블이 생성됩니다. 자세한 내용은 관련 트러블슈팅 섹션을 참조하세요.

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

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

  • 사용 불가.

  • 읽기 전용 모드.

수동 데이터베이스 설정#

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

  • Praefect 노드 1대

  • PostgreSQL 노드 1대

데이터베이스 서버를 관리할 권한이 있는 PostgreSQL 사용자

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

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

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

CREATE ROLE praefect WITH LOGIN PASSWORD 'PRAEFECT_SQL_PASSWORD';

PRAEFECT_SQL_PASSWORD를 준비 단계에서 생성한 강력한 암호로 교체합니다.

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

CREATE DATABASE praefect_production WITH OWNER praefect ENCODING UTF8;

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

Linux 패키지 제공 PgBouncer의 경우 실제 암호 대신 praefect 암호의 해시를 사용해야 합니다:

ALTER ROLE praefect WITH PASSWORD 'md5';

를 준비 단계에서 생성한 암호의 해시로 교체합니다. md5 리터럴이 앞에 붙습니다.

PgBouncer에서 사용할 새 사용자 pgbouncer를 생성합니다:

CREATE ROLE pgbouncer WITH LOGIN;
ALTER USER pgbouncer WITH password 'md5';

PGBOUNCER_SQL_PASSWORD_HASH를 준비 단계에서 생성한 강력한 암호 해시로 교체합니다.

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 데이터베이스 오류가 발생하면 트러블슈팅 단계를 참조하세요.

읽기 분산 캐싱#

session_pooled 설정을 추가로 구성하여 Praefect 성능을 향상시킬 수 있습니다:

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

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         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 인스턴스를 사용할 수 있습니다.

PostgreSQL 인스턴스 앞에 PgBouncer를 구성하려면 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 데이터베이스 엔드포인트를 사용하지만 다른 풀 모드(pool_mode = session)를 가진 새 PgBouncer 데이터베이스를 구성합니다.

  • Praefect가 PostgreSQL에 직접 연결하고 PgBouncer를 우회하도록 합니다.

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

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

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

그런 다음 PgBouncer 호스트에서 별도의 연결 풀을 구성합니다:

pgbouncer['databases'] = {
  # Other database configuration including gitlabhq_production
  ...

  praefect_production: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    pool_mode: 'transaction'
  },
  praefect_production_direct: {
    host: POSTGRESQL_HOST,
    # Use `pgbouncer` user to connect to database backend.
    user: 'pgbouncer',
    password: PGBOUNCER_SQL_PASSWORD_HASH,
    dbname: 'praefect_production',
    pool_mode: 'session'
  },

  ...
}

# Allow the praefect user to connect to 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` is the plain-text password of
      # Praefect user. Not to be confused with `PRAEFECT_SQL_PASSWORD_HASH`.
      password: PRAEFECT_SQL_PASSWORD,
      dbname: 'praefect_production',
      session_pooled: {
         # ...
         dbname: 'praefect_production_direct',
         # There is no need to repeat the following. Parameters of direct
         # database connection will fall back to the values specified in the
         # database block.
         #
         # host: PGBOUNCER_HOST,
         # port: 6432,
         # user: 'praefect',
         # password: PRAEFECT_SQL_PASSWORD,
      },
   },
}

이 구성으로 Praefect는 두 연결 유형 모두에 PgBouncer를 사용합니다.

Linux 패키지 설치는 인증 요구 사항을 처리하지만(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,

         # Use the following to override parameters of direct database connection.
         # Comment out where the parameters are the same for both connections.
         #
         user: 'praefect',
         password: PRAEFECT_SQL_PASSWORD,
         dbname: 'praefect_production',
         # sslmode: '...',
         # sslcert: '...',
         # sslkey: '...',
         # sslrootcert: '...',
      },
   },
}

Praefect#

Praefect를 구성하기 전에 Praefect 구성 파일 예시를 참조하여 숙지하세요. Linux 패키지를 사용하여 GitLab을 설치한 경우 예시 파일의 설정을 Ruby로 변환해야 합니다.

Praefect 노드가 여러 개인 경우:

  • 하나의 노드를 배포 노드로 지정하고 다음 단계를 사용하여 구성합니다.

  • 각 추가 노드에 대해 다음 단계를 완료합니다.

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

Praefect는 전용 노드에서 실행해야 합니다. 애플리케이션 서버 또는 Gitaly 노드에서 Praefect를 실행하지 마세요.

Praefect 노드에서:

  • /etc/gitlab/gitlab.rb를 편집하여 다른 모든 서비스를 비활성화합니다:
# Avoid running unnecessary services on the Praefect server
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

# Enable only the Praefect service
praefect['enable'] = true

# Prevent database migrations from running on upgrade automatically
praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false

/etc/gitlab/gitlab.rb를 편집하여 Praefect가 네트워크 인터페이스에서 수신 대기하도록 구성합니다:

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

/etc/gitlab/gitlab.rb를 편집하여 Prometheus 메트릭을 구성합니다:

praefect['configuration'] = {
   # ...
   #
   # Enable Prometheus metrics access to Praefect. You must use firewalls
   # to restrict access to this address/port.
   # The default metrics endpoint is /metrics
   prometheus_listen_addr: '0.0.0.0:9652',
   # Some metrics run queries against the database. Enabling separate database metrics allows
   # these metrics to be collected when the metrics are
   # scraped on a separate /db_metrics endpoint.
   prometheus_exclude_database_from_default_metrics: true,
}

/etc/gitlab/gitlab.rb를 편집하여 Praefect에 대한 강력한 인증 토큰을 구성합니다. 클러스터 외부의 클라이언트(예: GitLab Shell)가 Praefect 클러스터와 통신하는 데 필요합니다:

praefect['configuration'] = {
   # ...
   auth: {
      # ...
      token: 'PRAEFECT_EXTERNAL_TOKEN',
   },
}

PostgreSQL 데이터베이스에 연결하도록 Praefect를 구성합니다. PgBouncer도 함께 사용하는 것을 강력히 권장합니다.

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

praefect['configuration'] = {
   # ...
   database: {
      # ...
      #
      # Connect to PostgreSQL using a TLS client certificate
      # sslcert: '/path/to/client-cert',
      # sslkey: '/path/to/client-key',
      #
      # Trust a custom certificate authority
      # sslrootcert: '/path/to/rootcert',
   },
}

기본적으로 Praefect는 PostgreSQL에 연결할 때 기회적 TLS를 사용합니다. 즉, Praefect는 sslmodeprefer로 설정하여 PostgreSQL에 연결을 시도합니다. 다음 줄의 주석을 제거하여 이를 재정의할 수 있습니다:

praefect['configuration'] = {
   # ...
   database: {
      # ...
      # sslmode: 'disable',
   },
}

/etc/gitlab/gitlab.rb를 편집하여 Praefect 클러스터가 클러스터의 각 Gitaly 노드에 연결하도록 구성합니다.

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

이미 default라는 스토리지에 데이터가 있는 경우 다른 이름으로 가상 스토리지를 구성하고 나중에 데이터를 Gitaly Cluster(Praefect) 스토리지로 마이그레이션해야 합니다.

PRAEFECT_INTERNAL_TOKEN을 강력한 시크릿으로 교체합니다. 클러스터의 Gitaly 노드와 통신할 때 Praefect에서 사용합니다. 이 토큰은 PRAEFECT_EXTERNAL_TOKEN과 구별됩니다.

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

복제본 수를 늘리기 위해 클러스터에 더 많은 Gitaly 노드를 추가할 수 있습니다. 매우 큰 GitLab 인스턴스의 경우 더 많은 클러스터를 추가할 수도 있습니다.

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

# Name of storage hash must match storage name in gitlab_rails['repositories_storages'] on GitLab
# server ('default') and in gitaly['configuration'][:storage][INDEX][:name] on Gitaly nodes ('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'
            },
         ],
      },
   ],
}

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

다음의 경우:

"배포 노드":

/etc/gitlab/gitlab.rb에서 praefect['auto_migrate'] = true를 설정하여 Praefect 데이터베이스 자동 마이그레이션을 다시 활성화합니다.

업그레이드 시 자동으로 마이그레이션이 실행되지 않고 재구성 중에만 실행되도록 하려면 다음을 실행합니다:

sudo touch /etc/gitlab/skip-auto-reconfigure

다른 노드의 경우 설정을 그대로 둘 수 있습니다. /etc/gitlab/skip-auto-reconfigure가 필수는 아니지만 apt-get update와 같은 명령을 실행할 때 GitLab이 자동으로 재구성되는 것을 방지하기 위해 설정할 수 있습니다. 이렇게 하면 추가 구성 변경을 수행한 다음 수동으로 재구성을 실행할 수 있습니다.

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

Praefect가 Prometheus 수신 주소를 업데이트했는지 확인하려면 Praefect를 재시작합니다:

gitlab-ctl restart praefect

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 인스턴스와 통신하려면 다음을 해야 합니다:

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

  • 자체 인증서를 가져오세요. 이는 자동으로 제공되지 않습니다. 각 Praefect 서버에 해당하는 인증서를 해당 Praefect 서버에 설치해야 합니다.

또한 인증서 또는 인증 기관은 아래 설명된 절차에 따라 모든 Gitaly 서버 및 Praefect와 통신하는 모든 Praefect 클라이언트에 설치되어야 합니다. GitLab 사용자 정의 인증서 구성(아래에 반복됨).

다음 사항에 유의하세요:

인증서는 Praefect 서버에 접근하는 데 사용하는 주소를 지정해야 합니다. 인증서에 호스트 이름 또는 IP 주소를 Subject Alternative Name으로 추가해야 합니다.

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 패키지 설치의 경우:

Praefect 서버의 인증서를 생성합니다.

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

/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',
   },
}

파일을 저장하고 재구성합니다.

Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서 또는 인증 기관을 /etc/gitlab/trusted-certs에 복사합니다:

sudo cp cert.pem /etc/gitlab/trusted-certs/

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다:

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'tls://PRAEFECT_LOADBALANCER_HOST:3305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

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

소스 컴파일 설치의 경우:

Praefect 서버의 인증서를 생성합니다.

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

Praefect 클라이언트(각 Gitaly 서버 포함)에서 인증서 또는 인증 기관을 시스템 신뢰 인증서에 복사합니다:

sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
sudo update-ca-certificates

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

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: tls://PRAEFECT_LOADBALANCER_HOST:3305

파일을 저장하고 GitLab을 재시작합니다.

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

sudo cp cert.pem /usr/local/share/ca-certificates/praefect.crt
sudo update-ca-certificates

/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'

파일을 저장하고 GitLab을 재시작합니다.

서비스 검색#

사전 요구 사항:

  • DNS 서버.

GitLab은 서비스 검색을 사용하여 Praefect 호스트 목록을 검색합니다. 서비스 검색은 DNS A 또는 AAAA 레코드를 주기적으로 확인하며, 레코드에서 검색된 IP가 타깃 노드의 주소 역할을 합니다. Praefect는 SRV 레코드를 통한 서비스 검색을 지원하지 않습니다.

기본적으로 레코드의 TTL에 관계없이 확인 사이의 최소 시간은 5분입니다. 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]
히스토리

TLS 암호화와 함께 서비스 검색을 사용하려면 dns+tls 스킴을 사용합니다:

  • dns+tls:[host]:[port](단축 형식)

  • dns+tls:///[host]:[port](슬래시 세 개 주의)

  • dns+tls://[authority_host]:[authority_port]/[host]:[port]

dns+tls:// 스킴은 DNS 기반 서비스 검색과 TLS 암호화를 결합합니다. 이 스킴을 사용하기 전에 Praefect 서버에 TLS를 구성해야 합니다. 자세한 내용은 TLS 활성화를 참조하세요.

각 Praefect 엔드포인트의 TLS 인증서에는 아래 PRAEFECT_SERVICE_DISCOVERY_ADDRESS에서 사용되는 호스트 이름과 일치하는 Subject Alternative Name(SAN)이 포함되어야 합니다. 예를 들어 주소가 dns+tls:///praefect.service.consul:3305인 경우 각 Praefect 노드의 인증서에 praefect.service.consul이 SAN 항목으로 있어야 합니다. SAN이 일치하지 않으면 연결이 실패합니다.

Linux 패키지(Omnibus)

각 Praefect 노드의 IP 주소를 DNS 서비스 검색 주소에 추가합니다.

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다. PRAEFECT_SERVICE_DISCOVERY_ADDRESSpraefect.service.consul과 같은 Praefect 서비스 검색 주소로 교체합니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

TLS를 사용하려면 스킴을 dns+tls://로 변경합니다:

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns+tls://DNS_SERVER_ADDRESS:53/PRAEFECT_SERVICE_DISCOVERY_ADDRESS:3305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

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

소스 컴파일(source)

DNS 서비스 검색 서비스를 설치합니다. 모든 Praefect 노드를 서비스에 등록합니다.

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

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: dns:PRAEFECT_SERVICE_DISCOVERY_ADDRESS:2305

TLS를 사용하려면 스킴을 dns+tls://로 변경합니다:

gitlab:
  repositories:
    storages:
      default:
        gitaly_address: dns+tls://DNS_SERVER_ADDRESS:53/PRAEFECT_SERVICE_DISCOVERY_ADDRESS:3305

파일을 저장하고 GitLab을 재시작합니다.

Consul로 서비스 검색 구성#

아키텍처에 이미 Consul 서버가 있는 경우 각 Praefect 노드에 Consul 에이전트를 추가하고 praefect 서비스를 등록할 수 있습니다. 이렇게 하면 각 노드의 IP 주소가 praefect.service.consul에 등록되어 서비스 검색으로 찾을 수 있습니다.

사전 요구 사항:

  • Consul 에이전트를 추적하기 위한 Consul 서버 하나 이상.

각 Praefect 서버에서 /etc/gitlab/gitlab.rb에 다음을 추가합니다:

consul['enable'] = true
praefect['consul_service_name'] = 'praefect'

# The following must also be added until this issue is addressed:
# https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/8321
consul['monitoring_service_discovery'] = true
praefect['configuration'] = {
  # ...
  #
  prometheus_listen_addr: '0.0.0.0:9652',
}

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

서비스 검색과 함께 사용할 각 Praefect 서버에서 이전 단계를 반복합니다.

Praefect 클라이언트(Gitaly 서버 제외)에서 /etc/gitlab/gitlab.rbgitlab_rails['repositories_storages']를 다음과 같이 편집합니다. CONSUL_SERVER를 Consul 서버의 IP 또는 주소로 교체합니다. 기본 Consul DNS 포트는 8600입니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => 'dns://CONSUL_SERVER:8600/praefect.service.consul:2305',
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

Praefect 클라이언트에서 dig를 사용하여 각 IP 주소가 praefect.service.consuldig A praefect.service.consul @CONSUL_SERVER -p 8600으로 등록되었는지 확인합니다. CONSUL_SERVER를 이전에 구성한 값으로 교체하면 모든 Praefect 노드 IP 주소가 출력에 있어야 합니다.

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

Gitaly#

각 Gitaly 노드마다 이 단계를 완료합니다.

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

  • 구성된 Praefect 노드

  • GitLab이 설치된 서버 3대(이상). Gitaly 노드로 구성됩니다. 전용 노드여야 하며, 이 노드에서 다른 서비스를 실행하지 마세요.

Praefect 클러스터에 할당된 모든 Gitaly 서버는 구성되어야 합니다. 구성은 표준 독립형 Gitaly 서버와 동일하지만 다음 점에서 다릅니다:

  • 스토리지 이름은 GitLab이 아닌 Praefect에 노출됩니다.

  • 시크릿 토큰은 GitLab이 아닌 Praefect와 공유됩니다.

Praefect가 올바르게 작업을 라우팅하기 때문에 Praefect 클러스터의 모든 Gitaly 노드 구성은 동일할 수 있습니다.

특별히 주의해야 할 사항:

  • 이 섹션에서 구성된 gitaly['configuration'][:auth][:token]은 Praefect 노드의 praefect['configuration'][:virtual_storage][<index>][:node][<index>][:token] 값과 일치해야 합니다. 이 값은 이전 섹션에서 설정되었습니다. 이 문서는 전체적으로 자리 표시자 PRAEFECT_INTERNAL_TOKEN을 사용합니다.

  • 이 섹션에서 구성된 gitaly['configuration'][:storage]의 물리적 스토리지 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage]의 물리적 스토리지 이름과 일치해야 합니다. 이는 이전 섹션에서 설정되었습니다. 이 문서는 물리적 스토리지 이름으로 gitaly-1, gitaly-2, gitaly-3을 사용합니다.

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

Gitaly 노드에 SSH로 접속하고 root로 로그인합니다:

sudo -i

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

# Disable all other services on the Gitaly node
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

# Enable only the Gitaly service
gitaly['enable'] = true

# Enable Prometheus if needed
prometheus['enable'] = true

# Disable database migrations to prevent database connections during 'gitlab-ctl reconfigure'
gitlab_rails['auto_migrate'] = false

/etc/gitlab/gitlab.rb를 편집하여 Gitaly가 네트워크 인터페이스에서 수신 대기하도록 구성합니다:

gitaly['configuration'] = {
   # ...
   #
   # Make Gitaly accept connections on all network interfaces.
   # Use firewalls to restrict access to this address/port.
   listen_addr: '0.0.0.0:8075',
   # Enable Prometheus metrics access to Gitaly. You must use firewalls
   # to restrict access to this address/port.
   prometheus_listen_addr: '0.0.0.0:9236',
}

/etc/gitlab/gitlab.rb를 편집하여 Gitaly에 대한 강력한 auth_token을 구성합니다. 클라이언트가 이 Gitaly 노드와 통신하는 데 필요합니다. 일반적으로 이 토큰은 모든 Gitaly 노드에서 동일합니다.

gitaly['configuration'] = {
   # ...
   auth: {
      # ...
      token: 'PRAEFECT_INTERNAL_TOKEN',
   },
}

git push 작업에 필요한 GitLab Shell 시크릿 토큰을 구성합니다. 다음 중 하나를 선택합니다:

방법 1:

Gitaly 클라이언트에서 Gitaly 서버와 다른 Gitaly 클라이언트에 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

방법 2:

/etc/gitlab/gitlab.rb를 편집합니다.

GITLAB_SHELL_SECRET_TOKEN을 실제 시크릿으로 교체합니다.

GitLab 17.5 이상:

gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'

GitLab 17.4 이하:

gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'

git push 작업에도 필요한 internal_api_url을 구성합니다:

# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your front door GitLab URL or an internal load balancer.
# Examples: 'https://gitlab.example.com', 'http://10.0.2.2'
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'

/etc/gitlab/gitlab.rb에서 gitaly['configuration'][:storage]를 설정하여 Git 데이터의 스토리지 위치를 구성합니다. 각 Gitaly 노드에는 고유한 스토리지 이름(예: gitaly-1)이 있어야 하며 다른 Gitaly 노드에서 중복되어서는 안 됩니다.

gitaly['configuration'] = {
   # ...
   storage: [
     # Replace with appropriate name for each Gitaly nodes.
     {
       name: 'gitaly-1',
       path: '/var/opt/gitlab/git-data/repositories',
     },
   ],
}

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 Gitaly를 재구성합니다:

gitlab-ctl reconfigure

Gitaly가 Prometheus 수신 주소를 업데이트했는지 확인하려면 Gitaly를 재시작합니다:

gitlab-ctl restart gitaly

이전 단계는 각 Gitaly 노드마다 완료해야 합니다!

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

각 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

TCP 로드 밸런서를 사용해야 합니다. Gitaly 사이드채널 때문에 Praefect에 HTTP/2 또는 gRPC 로드 밸런서를 사용하면 작동하지 않습니다. 이 최적화는 gRPC 핸드셰이킹 프로세스를 차단합니다. 모든 무거운 Git 작업을 gRPC보다 더 효율적인 "채널"로 리디렉션하지만 HTTP/2 또는 gRPC 로드 밸런서는 이러한 요청을 올바르게 처리하지 못합니다.

TLS가 활성화된 경우 일부 Praefect 버전에서는 RFC 7540에 따라 Application-Layer Protocol Negotiation(ALPN) 확장을 사용해야 합니다. TCP 로드 밸런서는 추가 구성 없이 ALPN을 직접 전달합니다:

sequenceDiagram
    autonumber
    participant Client as Client
    participant LB as TCP Load Balancer
    participant Praefect as Praefect

    Client->>LB: Establish TLS Session (w/ ALPN Extension)
    LB->>Praefect: Establish TLS Session (w/ ALPN Extension)
    Client->>LB: Encrypted TCP packets
    LB->>Praefect: Encrypted TCP packets
    Praefect->>LB: Encrypted Response
    LB->>Client: Encrypted Response

일부 TCP 로드 밸런서는 TLS 클라이언트 연결을 수락하고 새 TLS 연결로 Praefect에 프록시하도록 구성할 수 있습니다. 그러나 이는 두 연결 모두에서 ALPN이 지원되는 경우에만 작동합니다.

이러한 이유로 NGINX의 ngx_stream_proxy_moduleproxy_ssl 구성 옵션이 활성화된 경우 작동하지 않습니다:

sequenceDiagram
    autonumber
    participant Client as Client
    participant NGINX as NGINX Stream Proxy
    participant Praefect as Praefect

    Client->>NGINX: Establish TLS Session (w/ ALPN Extension)
    NGINX->>Praefect: Establish New TLS Session
    Praefect->>NGINX: Connection failed: missing selected ALPN property

2단계에서 NGINX가 이를 지원하지 않기 때문에 ALPN이 사용되지 않습니다. 자세한 내용은 NGINX 이슈 406을 따르세요.

ALPN 적용#

ALPN 적용은 일부 GitLab 버전에서 활성화되었습니다. 그러나 ALPN 적용이 배포를 중단시켰기 때문에 마이그레이션 경로를 제공하기 위해 비활성화되었습니다. 다음 GitLab 버전에서는 ALPN 적용이 활성화되어 있습니다:

  • GitLab 17.7.0

  • GitLab 17.6.0 - 17.6.2

  • GitLab 17.5.0 - 17.5.4

  • GitLab 17.4.x

GitLab 17.5.5, 17.6.3, 17.7.1부터 ALPN 적용이 다시 비활성화됩니다. GitLab 17.4 이하에서는 ALPN 적용이 활성화된 적이 없습니다.

GitLab#

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

Praefect 클러스터는 gitlab_rails['repositories_storages']를 업데이트하여 GitLab 애플리케이션에 스토리지 위치로 노출되어야 합니다.

특별히 주의해야 할 사항:

  • 이 섹션에서 gitlab_rails['repositories_storages']에 추가된 스토리지 이름은 Praefect 노드의 praefect['configuration'][:virtual_storage] 아래의 스토리지 이름과 일치해야 합니다. 이는 이 가이드의 Praefect 섹션에서 설정되었습니다. 이 문서는 Praefect 스토리지 이름으로 default를 사용합니다.

GitLab 노드에 SSH로 접속하고 root로 로그인합니다:

sudo -i

/etc/gitlab/gitlab.rb를 편집하여 파일이 적절한 엔드포인트 접근으로 GitLab에 의해 제공될 수 있도록 external_url을 구성합니다:

현재 GitLab 인스턴스가 서비스하는 실제 외부 URL로 GITLAB_SERVER_URL을 교체해야 합니다:

external_url 'GITLAB_SERVER_URL'

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

기본 Gitaly 스토리지에 저장된 기존 데이터가 있는 경우 먼저 데이터를 Gitaly Cluster(Praefect) 스토리지로 마이그레이션해야 합니다.

gitaly['enable'] = false

/etc/gitlab/gitlab.rb를 편집하여 Praefect 클러스터를 스토리지 위치로 추가합니다.

다음을 교체해야 합니다:

PRAEFECT_LOADBALANCER_HOST: 로드 밸런서의 IP 주소 또는 호스트 이름

  • PRAEFECT_EXTERNAL_TOKEN: 실제 시크릿

TLS를 사용하는 경우:

  • gitaly_address는 대신 tls://로 시작해야 합니다.

  • 포트는 3305로 변경해야 합니다.

gitlab_rails['repositories_storages'] = {
  "default" => {
    "gitaly_address" => "tcp://PRAEFECT_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

git push 중 Gitaly 노드의 콜백이 올바르게 인증되도록 GitLab Shell 시크릿 토큰을 구성합니다. 다음 중 하나를 선택합니다:

방법 1:

Gitaly 클라이언트에서 Gitaly 서버와 다른 Gitaly 클라이언트에 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

방법 2:

/etc/gitlab/gitlab.rb를 편집합니다.

GITLAB_SHELL_SECRET_TOKEN을 실제 시크릿으로 교체합니다:

GitLab 17.5 이상:

gitaly['gitlab_secret'] = 'GITLAB_SHELL_SECRET_TOKEN'

GitLab 17.4 이하:

gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'

/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
      ]
    ]
  }
]

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

각 Gitaly 노드에서 Git Hooks가 GitLab에 도달할 수 있는지 확인합니다. 각 Gitaly 노드에서 다음을 실행합니다:

sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml

GitLab이 Praefect에 도달할 수 있는지 확인합니다:

gitlab-rake gitlab:gitaly:check

Praefect 스토리지가 새 리포지터리를 저장하도록 구성되어 있는지 확인합니다:

오른쪽 상단 모서리에서 Admin을 선택합니다.

  • 왼쪽 사이드바에서 Settings > Repository를 선택합니다.

  • Repository storage 섹션을 확장합니다.

이 가이드에 따라 default 스토리지의 가중치는 모든 새 리포지터리를 저장하기 위해 100이어야 합니다.

새 프로젝트를 생성하여 모든 것이 작동하는지 확인합니다. 볼 수 있는 콘텐츠가 리포지터리에 있도록 "Initialize repository with a README" 박스를 선택합니다. 프로젝트가 생성되고 README 파일을 볼 수 있다면 작동하는 것입니다!

기존 GitLab 인스턴스에 TCP 사용#

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

예를 들면:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://old-gitaly.internal:8075' },
  'cluster' => {
    'gitaly_address' => 'tls://:3305',
    'gitaly_token' => '<praefect_external_token>'
  }
}

여러 Gitaly 스토리지를 실행하는 방법에 대한 자세한 내용은 혼합 구성을 참조하세요.

여러 가상 스토리지 구성#

여러 가상 스토리지를 구성하여 리포지터리를 별도의 Gitaly Cluster(Praefect) 클러스터로 구성할 수 있습니다. 각 가상 스토리지는 자체 Gitaly 노드 세트와 복제 설정으로 독립적으로 작동합니다.

여러 가상 스토리지를 구성하려면:

각 Praefect 노드에서 /etc/gitlab/gitlab.rb를 편집하여 virtual_storage 배열에 여러 항목을 추가합니다:

praefect['configuration'] = {
   # ...
   virtual_storage: [
      {
         name: 'storage-1',
         default_replication_factor: 3,
         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'
            }
         ]
      },
      {
         name: 'storage-2',
         default_replication_factor: 2,
         node: [
            {
               storage: 'gitaly-4',
               address: 'tcp://GITALY_HOST_4:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            },
            {
               storage: 'gitaly-5',
               address: 'tcp://GITALY_HOST_5:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            },
            {
               storage: 'gitaly-6',
               address: 'tcp://GITALY_HOST_6:8075',
               token: 'PRAEFECT_INTERNAL_TOKEN'
            }
         ]
      }
   ]
}

변경 사항을 저장하고 Praefect를 재구성합니다:

gitlab-ctl reconfigure

GitLab 서버에서 /etc/gitlab/gitlab.rb를 편집하여 두 가상 스토리지를 모두 구성합니다:

gitlab_rails['repositories_storages'] = {
  "storage-1" => {
    "gitaly_address" => "tcp://PRAEFECT_1_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  },
  "storage-2" => {
    "gitaly_address" => "tcp://PRAEFECT_2_LOADBALANCER_HOST:2305",
    "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

구성을 확인합니다:

gitlab-rake gitlab:gitaly:check

구성 후에 다음을 수행할 수 있습니다:

독립형 및 클러스터 스토리지 혼합 구성#

GitLab을 독립형 Gitaly 인스턴스와 Gitaly Cluster(Praefect) 가상 스토리지를 동시에 사용하도록 구성할 수 있습니다. 마이그레이션 중이거나 일부 리포지터리만 고가용성이 필요한 경우 이렇게 할 수 있습니다.

혼합 설정을 구성하려면:

독립형 Gitaly 인스턴스가 TCP에서 수신 대기하도록 구성되어 있는지 확인합니다. 독립형 Gitaly 노드에서 /etc/gitlab/gitlab.rb를 편집합니다:

gitaly['configuration'] = {
   # ...
   listen_addr: '0.0.0.0:8075'
}

독립형 Gitaly 인스턴스의 인증을 구성합니다:

gitaly['configuration'] = {
   # ...
   auth: {
      token: 'GITALY_AUTH_TOKEN',
   },
}

저장하고 재구성합니다:

gitlab-ctl reconfigure

GitLab 서버에서 /etc/gitlab/gitlab.rb를 편집하여 독립형 스토리지와 클러스터 스토리지를 모두 구성합니다:

gitlab_rails['repositories_storages'] = {
  'default' => {
    'gitaly_address' => 'tcp://STANDALONE_GITALY_HOST:8075',
    'gitaly_token' => 'GITALY_AUTH_TOKEN'
  },
  'cluster' => {
    'gitaly_address' => 'tcp://PRAEFECT_LOADBALANCER_HOST:2305',
    'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
  }
}

저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

두 스토리지 모두 접근 가능한지 확인합니다:

gitlab-rake gitlab:gitaly:check

이 구성에서:

  • default 스토리지는 독립형 Gitaly 노드에 직접 연결합니다.

  • cluster 스토리지는 로드 밸런서를 통해 Gitaly Cluster(Praefect)에 연결합니다.

  • GitLab은 두 스토리지를 동등하게 취급하며 어느 스토리지에나 리포지터리를 저장할 수 있습니다.

  • 새 리포지터리에 대해 하나의 스토리지를 선호하도록 스토리지 가중치를 구성할 수 있습니다.

자세한 내용은 혼합 구성을 참조하세요.

Grafana#

Grafana는 GitLab에 포함되어 있으며 Praefect 클러스터를 모니터링하는 데 사용할 수 있습니다. 자세한 설명서는 Grafana 대시보드 서비스를 참조하세요.

빠르게 시작하려면:

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

sudo -i

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

grafana['disable_login_form'] = false

/etc/gitlab/gitlab.rb에 변경 사항을 저장하고 GitLab을 재구성합니다:

gitlab-ctl reconfigure

Grafana 관리자 암호를 설정합니다. 이 명령은 새 암호를 입력하도록 요청합니다:

gitlab-ctl set-grafana-password

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

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

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

축하합니다! 관찰 가능한 내결함성 Praefect 클러스터를 구성했습니다.

복제 인수 구성#

Praefect는 특정 스토리지 노드를 리포지터리를 호스팅하도록 할당하여 리포지터리별로 복제 인수를 구성하는 것을 지원합니다.

오브젝트 풀, 포크된 리포지터리 또는 포크 자체의 복제 인수를 줄이지 마세요. 이로 인해 전체 포크 네트워크가 손상될 수 있습니다. 오브젝트 풀은 @pools/로 시작하는 상대 경로를 가집니다. GitLab UI를 통해 리포지터리가 포크되었는지 확인할 수 있습니다.

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

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

  • 새로 생성된 리포지터리에 적용되는 각 가상 스토리지의 기본 복제 인수.

  • set-replication-factor 하위 명령으로 기존 리포지터리의 복제 인수.

기본 복제 인수 구성#

오브젝트 풀이 있을 때 기본 복제를 줄이면 일부 연결된 리포지터리가 손상될 수 있습니다. 오브젝트 풀은 @pools/로 시작하는 상대 경로를 가집니다.

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

많은 스토리지 노드가 있는 대규모 Gitaly Cluster(Praefect) 배포의 경우 모든 스토리지 노드에 리포지터리를 복제하는 것은 종종 합리적이지 않으며 문제를 일으킬 수 있습니다. 복제 인수 3이 일반적으로 충분하며, 더 많이 사용 가능하더라도 리포지터리를 세 개의 스토리지에 복제하는 것을 의미합니다. 높은 복제 인수는 primary 스토리지에 대한 압력을 증가시킵니다.

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

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

기존 리포지터리의 복제 인수 구성#

set-replication-factor 하위 명령은 원하는 복제 인수에 도달하기 위해 필요에 따라 임의의 스토리지 노드를 자동으로 할당하거나 할당 해제합니다. 리포지터리의 primary 노드는 항상 먼저 할당되며 할당 해제되지 않습니다.

sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -relative-path <relative-path> -replication-factor <replication-factor>
  • -virtual-storage는 리포지터리가 위치한 가상 스토리지입니다.

  • -relative-path는 스토리지에서 리포지터리의 상대 경로입니다.

  • -replication-factor는 리포지터리의 원하는 복제 인수입니다. primary는 리포지터리 사본이 필요하기 때문에 최솟값은 1입니다. 최대 복제 인수는 가상 스토리지의 스토리지 수입니다.

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

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

current assignments: gitaly-1, gitaly-2

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

필요한 스토리지의 크기는 인스턴스에 따라 다르며 설정된 복제 인수에 따라 달라집니다. 리포지터리 스토리지 이중화 구현을 고려할 수 있습니다.

복제 인수의 경우:

  • 1인 경우: Gitaly와 Gitaly Cluster(Praefect)의 스토리지 요구 사항은 거의 동일합니다.

  • 1보다 큰 경우: 필요한 스토리지 양은 사용된 공간 * 복제 인수입니다. 사용된 공간에는 계획된 미래 성장도 포함해야 합니다.

리포지터리 검증#

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

메타데이터는 복제 및 라우팅 결정에 사용되므로 부정확한 경우 문제가 발생할 수 있습니다. Praefect에는 디스크의 실제 상태와 메타데이터를 주기적으로 확인하는 백그라운드 워커가 포함되어 있습니다. 워커는:

  • 정상 스토리지에서 확인할 복제본 배치를 선택합니다. 복제본은 확인되지 않았거나 구성된 확인 간격을 초과한 것입니다. 한 번도 확인되지 않은 복제본이 우선순위가 지정되며, 그 다음으로 마지막 성공적인 확인 이후 가장 오랜 시간이 지난 복제본 순으로 정렬됩니다.

  • 복제본이 해당 스토리지에 존재하는지 확인합니다. 다음의 경우:

복제본이 존재하면 마지막 성공적인 확인 시간을 업데이트합니다.

  • 복제본이 존재하지 않으면 메타데이터 레코드를 제거합니다.

  • 확인에 실패하면 다음 워커가 더 많은 작업을 대기열에서 가져올 때 복제본이 다시 확인을 위해 선택됩니다.

워커는 확인하려는 각 복제본에 대해 독점적 확인 리스를 획득합니다. 이렇게 하면 여러 워커가 동일한 복제본을 동시에 확인하는 것을 방지합니다. 워커는 확인을 완료하면 리스를 해제합니다. 어떤 이유로 워커가 리스를 해제하지 않고 종료된 경우 Praefect에는 10초마다 오래된 리스를 해제하는 백그라운드 goroutine이 포함되어 있습니다.

워커는 실행하기 전에 각 메타데이터 제거를 로그에 기록합니다. 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.0에서 도입되어 기본적으로 비활성화됨

삭제는 리포지터리 이름 변경의 경쟁 조건으로 인해 GitLab 15.9 이전에는 기본적으로 비활성화되었으며, 이로 인해 잘못된 삭제가 발생할 수 있습니다. 이는 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>

출력에는 확인되지 않은 것으로 표시된 복제본의 수가 포함됩니다.

자동 페일오버 및 primary 선출#

Praefect는 각 Gitaly 노드의 상태를 정기적으로 확인하며, 현재 primary 노드가 비정상으로 확인되면 새로 선출된 primary Gitaly 노드로 자동 페일오버하는 데 사용됩니다.

리포지터리별 primary 노드가 유일하게 사용 가능한 선출 전략입니다.

리포지터리별 primary 노드#

Gitaly Cluster(Praefect)는 각 리포지터리에 대해 별도로 primary Gitaly 노드를 선출합니다. 구성 가능한 복제 인수와 결합하여 스토리지 용량을 수평으로 확장하고 Gitaly 노드 전체에 쓰기 로드를 분산할 수 있습니다.

primary 선출은 지연 방식으로 실행됩니다. 현재 primary가 비정상적인 경우 Praefect는 즉시 새 primary 노드를 선출하지 않습니다. 현재 primary를 사용할 수 없는 상태에서 요청을 처리해야 하는 경우 새 primary가 선출됩니다.

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

  • 정상 상태. Praefect 노드의 >=50%가 이전 10초 동안 Gitaly 노드의 상태를 성공적으로 확인한 경우 Gitaly 노드는 정상으로 간주됩니다.

  • 리포지터리의 최신 사본이 있습니다.

primary 노드 후보가 여러 개인 경우 Praefect는:

  • 임의로 하나를 선택합니다.

  • 리포지터리를 호스팅하도록 할당된 Gitaly 노드의 승진을 우선시합니다. primary로 선출할 할당된 Gitaly 노드가 없는 경우 Praefect는 일시적으로 할당되지 않은 노드를 선출할 수 있습니다. 할당되지 않은 primary는 할당된 노드가 사용 가능해지면 해당 노드에게 자리를 내줍니다.

리포지터리에 유효한 primary 후보가 없는 경우:

  • 비정상적인 primary 노드가 강등되고 리포지터리는 primary 노드 없이 남습니다.

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