InfoGrab Docs

Gitaly 구성

요약

다음 두 가지 방법 중 하나로 Gitaly를 구성합니다: 다음 구성 옵션도 사용할 수 있습니다: Gitaly 문서 전반에 걸쳐 참조되는 토큰은 관리자가 선택한 임의의 비밀번호입니다. 기본적으로 Gitaly는 Gitaly 클라이언트와 동일한 서버에서 실행되며 앞서 설명한 것처럼 구성됩니다.

다음 두 가지 방법 중 하나로 Gitaly를 구성합니다:

  1. /etc/gitlab/gitlab.rb를 편집하고 Gitaly 설정을 추가하거나 변경합니다. Gitaly 구성 파일 예제를 참조하세요. 예제 파일의 설정은 Ruby로 변환해야 합니다.
  2. 파일을 저장하고 GitLab을 재구성합니다.
  1. Gitaly 차트를 구성합니다.
  2. Helm 릴리스를 업그레이드합니다.
  1. /home/git/gitaly/config.toml을 편집하고 Gitaly 설정을 추가하거나 변경합니다. Gitaly 구성 파일 예제를 참조하세요.
  2. 파일을 저장하고 GitLab을 재시작합니다.

다음 구성 옵션도 사용할 수 있습니다:

Gitaly 토큰 정보#

Gitaly 문서 전반에 걸쳐 참조되는 토큰은 관리자가 선택한 임의의 비밀번호입니다. GitLab API 또는 유사한 웹 API 토큰을 위해 생성된 토큰과 관련이 없습니다.

Gitaly를 자체 서버에서 실행#

기본적으로 Gitaly는 Gitaly 클라이언트와 동일한 서버에서 실행되며 앞서 설명한 것처럼 구성됩니다. 단일 서버 설치에는 다음에서 사용하는 기본 구성이 가장 적합합니다:

그러나 Gitaly를 자체 서버에 배포할 수 있으며, 이는 여러 머신에 걸친 GitLab 설치에 유리할 수 있습니다.

Note

자체 서버에서 실행하도록 구성된 경우 Gitaly 서버는 클러스터의 Gitaly 클라이언트보다 먼저 업그레이드해야 합니다.

자체 서버에서 Gitaly를 설정하는 프로세스는 다음과 같습니다:

  1. Gitaly 설치.
  2. 인증 구성.
  3. Gitaly 서버 구성.
  4. Gitaly 클라이언트 구성.
  5. 필요하지 않은 곳에서 Gitaly 비활성화 (선택 사항).
Note

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

네트워크 아키텍처#

다음 목록은 Gitaly의 네트워크 아키텍처를 설명합니다:

  • GitLab Rails는 저장소를 저장소 스토리지로 분리합니다.
  • /config/gitlab.yml에는 스토리지 이름에서 (Gitaly 주소, Gitaly 토큰) 쌍으로의 맵이 포함됩니다.
  • /config/gitlab.ymlstorage name -> (Gitaly 주소, Gitaly 토큰) 맵이 Gitaly 네트워크 토폴로지의 단일 소스입니다.
  • (Gitaly 주소, Gitaly 토큰)은 Gitaly 서버에 해당합니다.
  • Gitaly 서버는 하나 이상의 스토리지를 호스팅합니다.
  • Gitaly 클라이언트는 하나 이상의 Gitaly 서버를 사용할 수 있습니다.
  • Gitaly 주소는 모든 Gitaly 클라이언트에 대해 올바르게 확인할 수 있도록 지정해야 합니다.
  • Gitaly 클라이언트는:
    • Puma.
    • Sidekiq.
    • GitLab Workhorse.
    • GitLab Shell.
    • Elasticsearch 인덱서.
    • Gitaly 자체.
  • Gitaly 서버는 /config/gitlab.yml에 지정된 자체 (Gitaly 주소, Gitaly 토큰) 쌍을 사용하여 자신에게 RPC 호출을 할 수 있어야 합니다.
  • 인증은 Gitaly와 GitLab Rails 노드 간에 공유되는 정적 토큰을 통해 수행됩니다.

다음 다이어그램은 HTTP 및 HTTPS 통신에 대한 기본 포트를 보여주는 Gitaly 서버와 GitLab Rails 간의 통신을 보여줍니다.

두 Gitaly 서버와 GitLab Rails가 정보를 교환합니다.

Warning

Gitaly 네트워크 트래픽은 기본적으로 암호화되지 않으므로 Gitaly 서버를 공용 인터넷에 노출해서는 안 됩니다. Gitaly 서버에 대한 액세스를 제한하기 위해 방화벽을 사용하는 것이 강력히 권장됩니다. 또 다른 옵션은 TLS를 사용하는 것입니다.

다음 섹션에서는 비밀 토큰 abc123secret을 사용하는 두 Gitaly 서버를 구성하는 방법을 설명합니다:

  • gitaly1.internal.
  • gitaly2.internal.

GitLab 설치에 세 개의 저장소 스토리지가 있다고 가정합니다:

  • default.
  • storage1.
  • storage2.

원하는 경우 하나의 저장소 스토리지가 있는 서버 하나를 사용할 수 있습니다.

Gitaly 설치#

다음 중 하나를 사용하여 각 Gitaly 서버에 Gitaly를 설치합니다:

Gitaly 서버 구성#

Gitaly 서버를 구성하려면 다음을 수행해야 합니다:

  • 인증 구성.
  • 스토리지 경로 구성.
  • 네트워크 리스너 활성화.

git 사용자는 구성된 스토리지 경로에서 읽고 쓰고 권한을 설정할 수 있어야 합니다.

Gitaly 토큰을 교체하는 동안 다운타임을 방지하려면 gitaly['auth_transitioning'] 설정을 사용하여 인증을 일시적으로 비활성화할 수 있습니다. 자세한 내용은 인증 전환 모드 활성화를 참조하세요.

인증 구성#

Gitaly와 GitLab은 인증을 위해 두 개의 공유 비밀을 사용합니다:

  • Gitaly 토큰: Gitaly에 대한 gRPC 요청을 인증하는 데 사용됩니다. Gitaly 토큰은 GitLab 구성에 직접 지정하거나 토큰 파일에 지정할 수 있습니다. 토큰 파일을 사용하면 시작 시 구성에 시크릿이 렌더링되지 않으므로 컨테이너화된 환경에 더 안전하고 적합합니다. 토큰 파일은 다음 조건을 만족해야 합니다:
    • 토큰 문자열만 포함합니다. 공백은 자동으로 제거됩니다.
    • 파일 권한이 0600 또는 0400이어야 합니다.
  • GitLab Shell 토큰: GitLab Shell에서 GitLab 내부 API로의 인증 콜백에 사용됩니다.
  1. _Gitaly 토큰_을 구성하려면 /etc/gitlab/gitlab.rb를 편집합니다:

    GitLab 18.11에서 token_file 지원이 도입되었습니다.

    토큰 파일을 사용하는 경우:

    gitaly['configuration'] = {
       # ...
       auth: {
         # ...
         token_file: '/etc/gitlab/gitaly_token',
       },
    }
    

    토큰을 직접 지정하는 경우:

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

    tokentoken_file은 상호 배타적입니다.

  2. 다음 두 가지 방법 중 하나로 _GitLab Shell 토큰_을 구성합니다:

    • 방법 1(권장): Gitaly 클라이언트에서 Gitaly 서버 및 다른 Gitaly 클라이언트의 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

    • 방법 2:

      1. GitLab Rails를 실행하는 모든 노드에서 /etc/gitlab/gitlab.rb를 편집합니다.

      2. 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'
          
      3. Gitaly를 실행하는 모든 노드에서 /etc/gitlab/gitlab.rb를 편집합니다.

      4. 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'
          
      5. 변경 사항 적용 후 GitLab을 재구성합니다:

      sudo gitlab-ctl reconfigure
      
  1. Gitaly 클라이언트에서 Gitaly 서버(및 다른 Gitaly 클라이언트)의 동일한 경로로 /home/git/gitlab/.gitlab_shell_secret을 복사합니다.

  2. Gitaly 클라이언트에서 /home/git/gitlab/config/gitlab.yml을 편집합니다:

    gitlab:
      gitaly:
        token: 'abc123secret'
    
  3. 파일을 저장하고 GitLab을 재시작합니다.

  4. Gitaly 서버에서 /home/git/gitaly/config.toml을 편집합니다:

    토큰 파일을 사용하는 경우:

    [auth]
    token_file = '/etc/gitaly/token'
    

    토큰을 직접 지정하는 경우:

    [auth]
    token = 'abc123secret'
    

    tokentoken_file은 상호 배타적입니다.

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

Gitaly 서버 구성#

Gitaly 서버를 구성합니다.

Gitaly에는 클라이언트(Rails 또는 Sidekiq 등)가 제공한 주소를 사용하여 자신에게 네트워크 호출을 하는 RPC가 있습니다.

네트워크 구성으로 인해 Gitaly가 이 방법으로 자신에게 도달할 수 없는 경우(예: Gitaly가 헤어핀 연결을 지원하지 않는 로드 밸런서 뒤에 있는 경우):

  1. Gitaly 서버의 /etc/hosts 파일을 편집합니다.
  2. 클라이언트가 사용하는 Gitaly 주소를 Gitaly 서버 자체의 IP 주소로 리디렉션하는 항목을 추가합니다. 예: 127.0.0.1 gitaly.example.com 또는 <local-ip> gitaly.example.com.
  1. /etc/gitlab/gitlab.rb를 편집합니다:

    # Avoid running unnecessary services on the Gitaly server
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    gitlab_exporter['enable'] = false
    gitlab_kas['enable'] = false
    
    # If you run a separate monitoring node you can disable these services
    prometheus['enable'] = false
    alertmanager['enable'] = false
    
    # If you don't run a separate monitoring node you can
    # enable Prometheus access & disable these extra services.
    # This makes Prometheus listen on all interfaces. You must use firewalls to restrict access to this address/port.
    # prometheus['listen_address'] = '0.0.0.0:9090'
    # prometheus['monitor_kubernetes'] = false
    
    # If you don't want to run monitoring services uncomment the following (not recommended)
    # node_exporter['enable'] = false
    
    # Prevent database connections during 'gitlab-ctl reconfigure'
    gitlab_rails['auto_migrate'] = false
    
    # 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.
    # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from Gitaly client to Gitaly server.
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
    gitaly['configuration'] = {
       # ...
       #
       # Make Gitaly accept connections on all network interfaces. You must use
       # firewalls to restrict access to this address/port.
       # Comment out following line if you only want to support TLS connections
       listen_addr: '0.0.0.0:8075',
       auth: {
         # ...
         #
         # Authentication token to ensure only authorized servers can communicate with
         # Gitaly server
         token: 'AUTH_TOKEN',
       },
    }
    
  2. 각 Gitaly 서버에 대해 /etc/gitlab/gitlab.rb에 다음을 추가합니다:

    gitaly1.internal에서:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'default',
             path: '/var/opt/gitlab/git-data/repositories',
          },
          {
             name: 'storage1',
             path: '/mnt/gitlab/git-data/repositories',
          },
       ],
    }
    

    gitaly2.internal에서:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'storage2',
             path: '/srv/gitlab/git-data/repositories',
          },
       ],
    }
    
  3. 파일을 저장하고 GitLab을 재구성합니다.

  4. Gitaly가 GitLab 내부 API에 콜백을 수행할 수 있는지 확인합니다:

    sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml
    
  1. /home/git/gitaly/config.toml을 편집합니다:

    listen_addr = '0.0.0.0:8075'
    
    runtime_dir = '/var/opt/gitlab/gitaly'
    
    [logging]
    format = 'json'
    level = 'info'
    dir = '/var/log/gitaly'
    
  2. 각 Gitaly 서버에 대해 /home/git/gitaly/config.toml에 다음을 추가합니다:

    gitaly1.internal에서:

    [[storage]]
    name = 'default'
    path = '/var/opt/gitlab/git-data/repositories'
    
    [[storage]]
    name = 'storage1'
    path = '/mnt/gitlab/git-data/repositories'
    

    gitaly2.internal에서:

    [[storage]]
    name = 'storage2'
    path = '/srv/gitlab/git-data/repositories'
    
  3. /home/git/gitlab-shell/config.yml을 편집합니다:

    gitlab_url: https://gitlab.example.com
    
  4. 파일을 저장하고 GitLab을 재시작합니다.

  5. Gitaly가 GitLab 내부 API에 콜백을 수행할 수 있는지 확인합니다:

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

GitLab 서버에서 Gitaly로 저장소 데이터를 직접 복사하는 경우 기본 경로 /var/opt/gitlab/git-data/repositories/.gitaly-metadata의 메타데이터 파일이 전송에 포함되지 않도록 하세요. 이 파일을 복사하면 GitLab이 Gitaly 서버에서 호스팅되는 저장소에 대한 직접 디스크 액세스를 사용하게 되어 Error creating pipelineCommit not found 오류 또는 오래된 데이터가 발생합니다.

Gitaly 클라이언트 구성#

마지막 단계로 로컬 Gitaly 서비스 대신 방금 구성한 Gitaly 서버를 사용하도록 Gitaly 클라이언트를 업데이트해야 합니다.

Note

GitLab에는 default 저장소 스토리지가 구성되어 있어야 합니다. 이 제한 사항에 대해 더 읽어보기.

Gitaly 클라이언트가 Gitaly 서버에 도달하지 못하도록 하는 모든 것이 모든 Gitaly 요청을 실패시키므로 위험할 수 있습니다. 예를 들어, 네트워크, 방화벽 또는 이름 확인 문제가 있을 수 있습니다.

Gitaly는 다음을 가정합니다:

  • gitaly1.internal Gitaly 서버는 Gitaly 클라이언트에서 gitaly1.internal:8075로 도달할 수 있으며, 해당 Gitaly 서버는 /var/opt/gitlab/git-data/mnt/gitlab/git-data에서 읽고 쓰고 권한을 설정할 수 있습니다.
  • gitaly2.internal Gitaly 서버는 Gitaly 클라이언트에서 gitaly2.internal:8075로 도달할 수 있으며, 해당 Gitaly 서버는 /srv/gitlab/git-data에서 읽고 쓰고 권한을 설정할 수 있습니다.
  • gitaly1.internalgitaly2.internal Gitaly 서버는 서로 도달할 수 있습니다.

혼합 구성을 사용하지 않는 한 일부는 로컬 Gitaly 서버(gitaly_address 없음)로, 일부는 원격 서버(gitaly_address 있음)로 Gitaly 서버를 정의할 수 없습니다.

다음 두 가지 방법 중 하나로 Gitaly 클라이언트를 구성합니다. 이 지침은 암호화되지 않은 연결에 대한 것이지만 TLS 지원도 활성화할 수 있습니다:

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

    # Use the same token value configured on all Gitaly servers
    gitlab_rails['gitaly_token'] = ''
    
    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
    }
    

    또는 각 Gitaly 서버가 서로 다른 인증 토큰을 사용하도록 구성된 경우:

    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075', 'gitaly_token' => '' },
    }
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

  3. Gitaly 클라이언트(예: Rails 애플리케이션)에서 sudo gitlab-rake gitlab:gitaly:check를 실행하여 Gitaly 서버에 연결할 수 있는지 확인합니다.

  4. 요청을 보려면 로그를 확인합니다:

    sudo gitlab-ctl tail gitaly
    
  1. /home/git/gitlab/config/gitlab.yml을 편집합니다:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage1:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage2:
            gitaly_address: tcp://gitaly2.internal:8075
            gitaly_token: AUTH_TOKEN_2
    
  2. 파일을 저장하고 GitLab을 재시작합니다.

  3. sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production을 실행하여 Gitaly 클라이언트가 Gitaly 서버에 연결할 수 있는지 확인합니다.

  4. 요청을 보려면 로그를 확인합니다:

    tail -f /home/git/gitlab/log/gitaly.log
    

Gitaly 서버에서 Gitaly 로그를 추적하면 요청이 들어오는 것을 볼 수 있습니다. Gitaly 요청을 트리거하는 확실한 방법은 HTTP 또는 HTTPS를 통해 GitLab에서 저장소를 클론하는 것입니다.

Warning

저장소별 또는 전역으로 서버 훅을 구성한 경우 이를 Gitaly 서버로 이동해야 합니다. Gitaly 서버가 여러 개인 경우 모든 Gitaly 서버에 서버 훅을 복사합니다.

혼합 구성#

GitLab은 여러 Gitaly 서버 중 하나와 동일한 서버에 상주할 수 있지만 로컬 및 원격 구성을 혼합하는 구성은 지원하지 않습니다. 다음 설정은 올바르지 않습니다. 왜냐하면:

  • 모든 주소는 다른 Gitaly 서버에서 도달할 수 있어야 합니다.
  • storage1은 일부 Gitaly 서버에 유효하지 않은 gitaly_address에 Unix 소켓이 할당됩니다.
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  'storage1' => { 'gitaly_address' => 'unix:/var/opt/gitlab/gitaly/gitaly.socket' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

로컬 및 원격 Gitaly 서버를 결합하려면 로컬 Gitaly 서버에 외부 주소를 사용합니다. 예:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  # Address of the GitLab server that also has Gitaly running on it
  'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

gitaly['configuration'] = {
  # ...
  #
  # Make Gitaly accept connections on all network interfaces
  listen_addr: '0.0.0.0:8075',
  # Or for TLS
  tls_listen_addr: '0.0.0.0:9999',
  tls: {
    certificate_path:  '/etc/gitlab/ssl/cert.pem',
    key_path: '/etc/gitlab/ssl/key.pem',
  },
  storage: [
    {
      name: 'storage1',
      path: '/mnt/gitlab/git-data/repositories',
    },
  ],
}

path는 로컬 Gitaly 서버의 스토리지 샤드에만 포함할 수 있습니다. 제외된 경우 해당 스토리지 샤드에 기본 Git 스토리지 디렉터리가 사용됩니다.

GitLab에는 기본 저장소 스토리지 필요#

환경에 Gitaly 서버를 추가할 때 원래 default Gitaly 서비스를 교체하려 할 수 있습니다. 그러나 GitLab에는 default라는 스토리지가 필요하므로 default 스토리지를 제거하기 위해 GitLab 애플리케이션 서버를 재구성할 수 없습니다. 이 제한 사항에 대해서는 여기에서 더 읽어보기를 참조하세요.

이 제한 사항을 해결하려면:

  1. 새 Gitaly 서비스에 추가 스토리지 위치를 정의하고 추가 스토리지를 default로 구성합니다. 스토리지 위치에는 데이터베이스 마이그레이션이 작동하는 스토리지를 예상하므로 Gitaly 서비스가 실행 중이고 사용 가능해야 합니다.
  2. Admin 영역에서 저장소가 저장되지 않도록 default의 가중치를 0으로 설정합니다.

필요하지 않은 곳에서 Gitaly 비활성화(선택 사항)#

원격 서비스로 Gitaly를 실행하는 경우 GitLab 서버에서 기본적으로 실행되는 로컬 Gitaly 서비스를 비활성화하고 필요한 곳에서만 실행하는 것을 고려하세요.

GitLab 인스턴스에서 Gitaly를 비활성화하는 것은 Gitaly가 GitLab 인스턴스와 별도의 머신에서 실행되는 사용자 정의 클러스터 구성에서 GitLab을 실행하는 경우에만 의미가 있습니다. 클러스터의 모든 머신에서 Gitaly를 비활성화하는 것은 유효한 구성이 아닙니다(일부 머신은 Gitaly 서버 역할을 해야 함).

다음 두 가지 방법 중 하나로 GitLab 서버에서 Gitaly를 비활성화합니다:

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

    gitaly['enable'] = false
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

  1. /etc/default/gitlab를 편집합니다:

    gitaly_enabled=false
    
  2. 파일을 저장하고 GitLab을 재시작합니다.

Gitaly 수신 인터페이스 변경#

Gitaly가 수신하는 인터페이스를 변경할 수 있습니다. Gitaly와 통신해야 하는 외부 서비스가 있을 때 수신 인터페이스를 변경할 수 있습니다. 예를 들어, 정확한 코드 검색이 활성화됐지만 실제 서비스가 다른 서버에서 실행 중인 경우 Zoekt를 사용하는 정확한 코드 검색이 있습니다.

gitaly_token은 Gitaly 서비스 인증에 사용되므로 비밀 문자열이어야 합니다. 이 비밀은 openssl rand -base64 24로 생성하여 32자의 무작위 문자열을 만들 수 있습니다.

예를 들어, Gitaly 수신 인터페이스를 0.0.0.0:8075로 변경하려면:

# /etc/gitlab/gitlab.rb
# Add a shared token for Gitaly authentication
gitlab_shell['secret_token'] = 'your_secure_token_here'
gitlab_rails['gitaly_token'] = 'your_secure_token_here'

# Gitaly configuration
gitaly['gitlab_secret'] = 'your_secure_token_here'
gitaly['configuration'] = {
  listen_addr: '0.0.0.0:8075',
  auth: {
    token: 'your_secure_token_here',
  },
  storage: [
    {
      name: 'default',
      path: '/var/opt/gitlab/git-data/repositories',
    },
  ]
}

# Tell Rails where to find Gitaly
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://ip_address_here:8075' },
}

# Internal API URL (important for multi-server setups)
gitlab_rails['internal_api_url'] = 'http://ip_address_here'

제어 그룹#

제어 그룹에 대한 자세한 내용은 Cgroups를 참조하세요.

백그라운드 저장소 최적화#

Git 저장소의 오브젝트 데이터베이스에 데이터를 저장하는 방식이 시간이 지남에 따라 비효율적이 될 수 있어 Git 작업이 느려질 수 있습니다. Gitaly를 최대 지속 시간과 함께 일별 백그라운드 작업을 실행하도록 예약하여 이러한 항목을 정리하고 성능을 향상시킬 수 있습니다.

Warning

백그라운드 저장소 최적화는 실행 중에 호스트에 상당한 부하를 줄 수 있습니다. 피크가 없는 시간에 예약하고 지속 시간을 짧게 유지하세요(예: 30-60분).

다음 두 가지 방법 중 하나로 백그라운드 저장소 최적화를 구성합니다:

/etc/gitlab/gitlab.rb를 편집하고 다음을 추가합니다:

gitaly['configuration'] = {
  # ...
  daily_maintenance: {
    # ...
    start_hour: 4,
    start_minute: 30,
    duration: '30m',
    storages: ['default'],
  },
}

/home/git/gitaly/config.toml을 편집하고 다음을 추가합니다:

[daily_maintenance]
start_hour = 4
start_minute = 30
duration = '30m'
storages = ["default"]

Gitaly 인증 토큰 교체#

프로덕션 환경에서 자격 증명을 교체하면 종종 다운타임이나 중단이 발생하거나 둘 다 발생합니다.

그러나 서비스 중단 없이 Gitaly 자격 증명을 교체할 수 있습니다. Gitaly 인증 토큰 교체 방법:

이 절차는 단일 서버에서 GitLab을 실행하는 경우에도 작동합니다. 이 경우 Gitaly 서버와 Gitaly 클라이언트는 동일한 머신을 가리킵니다.

인증 모니터링 확인#

Gitaly 인증 토큰을 교체하기 전에 Prometheus를 사용하여 GitLab 설치의 인증 동작을 모니터링할 수 있는지 확인합니다.

그런 다음 나머지 절차를 계속할 수 있습니다.

인증 전환 모드 활성화#

다음과 같이 인증 전환 모드에 넣어 Gitaly 서버에서 Gitaly 인증을 일시적으로 비활성화합니다:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: true,
  },
}

이 변경을 수행한 후 Prometheus 쿼리는 다음과 같은 내용을 반환해야 합니다:

{enforced="false",status="would be ok"}  4424.985419441742

enforced="false"이므로 새 토큰을 롤아웃하기 시작해도 안전합니다.

Gitaly 인증 토큰 업데이트#

새 Gitaly 인증 토큰으로 업데이트하려면 각 Gitaly 클라이언트 및 Gitaly 서버에서:

  1. 구성을 업데이트합니다:

    # in /etc/gitlab/gitlab.rb
    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: '<new secret token>',
       },
    }
    

    token_file을 사용하는 경우 참조된 파일의 내용을 새 토큰으로 업데이트합니다. 구성 변경은 필요하지 않습니다. 토큰 파일은 시작 시 읽힙니다.

  2. Gitaly를 재시작합니다:

    gitlab-ctl restart gitaly
    

이 변경이 롤아웃되는 동안 Prometheus 쿼리를 실행하면 enforced="false",status="denied" 카운터에 0이 아닌 값이 표시됩니다.

인증 실패 없음 확인#

새 토큰이 설정되고 관련된 모든 서비스가 재시작된 후 다음의 혼합을 일시적으로 볼 수 있습니다:

  • status="would be ok".
  • status="denied".

모든 Gitaly 클라이언트와 Gitaly 서버가 새 토큰을 가져오면 유일한 0이 아닌 비율은 enforced="false",status="would be ok"이어야 합니다.

인증 전환 모드 비활성화#

Gitaly 인증을 다시 활성화하려면 인증 전환 모드를 비활성화합니다. Gitaly 서버의 구성을 다음과 같이 업데이트합니다:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: false,
  },
}
Warning

이 단계를 완료하지 않으면 Gitaly 인증이 없어집니다.

인증이 적용되는지 확인#

Prometheus 쿼리를 새로 고칩니다. 이제 처음에 보았던 것과 유사한 결과가 표시되어야 합니다. 예:

{enforced="true",status="ok"}  4424.985419441742

enforced="true"는 인증이 적용되고 있음을 의미합니다.

Pack-objects 캐시#

Git 저장소를 위한 스토리지를 제공하는 서비스인 Gitaly는 짧은 롤링 윈도우의 Git 페치 응답을 캐시하도록 구성할 수 있습니다. 이를 통해 서버가 많은 CI 페치 트래픽을 수신할 때 서버 부하를 줄일 수 있습니다.

pack-objects 캐시는 PostUploadPack 및 SSHUploadPack Gitaly RPC를 통해 간접적으로 호출되는 Git의 내부 부분인 git pack-objects를 래핑합니다. Gitaly는 사용자가 HTTP를 사용하여 Git 페치를 수행하면 PostUploadPack을, 사용자가 SSH를 사용하여 Git 페치를 수행하면 SSHUploadPack을 실행합니다. 캐시가 활성화되면 PostUploadPack 또는 SSHUploadPack을 사용하는 모든 것이 혜택을 받을 수 있습니다. 이는 다음에 독립적이고 영향을 받지 않습니다:

  • 전송 방식(HTTP 또는 SSH).
  • Git 프로토콜 버전(v0 또는 v2).
  • 전체 클론, 증분 페치, 얕은 클론 또는 부분 클론과 같은 페치 유형.

이 캐시의 강점은 동시에 동일한 페치를 중복 제거하는 능력입니다. 이는:

  • CI/CD 파이프라인에서 동시 작업이 많은 GitLab 인스턴스에서 혜택을 볼 수 있습니다. 서버 CPU 사용량이 눈에 띄게 감소해야 합니다.
  • 고유한 페치에는 전혀 도움이 되지 않습니다. 예를 들어 로컬 컴퓨터에 저장소를 클론하여 샘플 확인을 수행하는 경우 페치가 고유할 가능성이 높으므로 이 캐시의 혜택을 볼 가능성이 낮습니다.

pack-objects 캐시는 로컬 캐시입니다. 이는:

  • 메타데이터를 활성화된 Gitaly 프로세스의 메모리에 저장합니다.
  • 캐시 중인 실제 Git 데이터를 로컬 스토리지의 파일에 저장합니다.

로컬 파일을 사용하면 운영 체제가 팩 오브젝트 캐시 파일의 일부를 RAM에 자동으로 보관하여 속도를 높일 수 있다는 장점이 있습니다.

pack-objects 캐시는 디스크 쓰기 IO가 크게 증가할 수 있으므로 기본적으로 비활성화됩니다.

캐시 구성#

pack-objects 캐시에 사용할 수 있는 구성 설정이 있습니다. 각 설정에 대해 아래에서 자세히 설명합니다.

설정 기본값 설명
enabled false 캐시를 켭니다. 꺼져 있으면 Gitaly가 각 요청에 대해 전용 git pack-objects 프로세스를 실행합니다.
dir /+gitaly/PackObjectsCache 캐시 파일이 저장되는 로컬 디렉터리.
max_age 5m (5분) 이보다 오래된 캐시 항목은 제거되어 디스크에서 제거됩니다.
min_occurrences 1 캐시 항목이 생성되기 전에 키가 발생해야 하는 최소 횟수.

/etc/gitlab/gitlab.rb에서 다음을 설정합니다:

gitaly['configuration'] = {
  # ...
  pack_objects_cache: {
    enabled: true,
    # The default settings for "dir", "max_age" and "min_occurences" should be fine.
    # If you want to customize these, see details below.
  },
}

enabled 기본값은 false#

캐시는 경우에 따라 디스크에 기록되는 바이트 수가 극단적으로 증가할 수 있으므로 기본적으로 비활성화됩니다. GitLab.com에서 저장소 스토리지 디스크가 이 추가 작업량을 처리할 수 있음을 확인했지만 이것이 어디서나 사실이라고 가정할 수 없다고 판단했습니다.

캐시 스토리지 디렉터리 dir#

캐시는 파일을 저장할 디렉터리가 필요합니다. 이 디렉터리는 다음과 같아야 합니다:

  • 충분한 공간이 있는 파일 시스템에 있어야 합니다. 캐시 파일 시스템의 공간이 부족하면 모든 페치가 실패하기 시작합니다.
  • 충분한 IO 대역폭이 있는 디스크에 있어야 합니다. 캐시 디스크의 IO 대역폭이 부족하면 모든 페치, 그리고 서버 전체가 느려질 수 있습니다.
Warning

지정된 디렉터리의 모든 기존 데이터는 제거됩니다. 기존 데이터가 있는 디렉터리를 사용하지 않도록 주의하세요.

기본적으로 캐시 스토리지 디렉터리는 구성 파일에 정의된 첫 번째 Gitaly 스토리지의 하위 디렉터리로 설정됩니다.

여러 Gitaly 프로세스는 캐시 스토리지에 동일한 디렉터리를 사용할 수 있습니다. 각 Gitaly 프로세스는 생성하는 캐시 파일 이름의 일부로 고유한 무작위 문자열을 사용합니다. 이는 다음을 의미합니다:

  • 충돌하지 않습니다.
  • 다른 프로세스의 파일을 재사용하지 않습니다.

기본 디렉터리가 저장소 데이터와 동일한 파일 시스템에 캐시 파일을 배치하지만 이것이 요구 사항은 아닙니다. 인프라에 더 적합한 경우 다른 파일 시스템에 캐시 파일을 배치할 수 있습니다.

디스크에서 필요한 IO 대역폭은 다음에 따라 달라집니다:

  • Gitaly 서버의 저장소 크기와 형태.
  • 사용자가 생성하는 트래픽 종류.

캐시 적중률이 0%라고 가정하는 비관적인 추정으로 gitaly_pack_objects_generated_bytes_total 메트릭을 사용할 수 있습니다.

필요한 공간은 다음에 따라 달라집니다:

  • 사용자가 캐시에서 끌어내는 초당 바이트 수.
  • max_age 캐시 제거 윈도우 크기.

사용자가 100MB/s를 끌어내고 5분 윈도우를 사용하면 캐시 디렉터리에 평균 5*60*100 MB = 30 GB 데이터가 있습니다. 이 평균은 예상 평균이지 보장이 아닙니다. 최대 크기는 이 평균을 초과할 수 있습니다.

캐시 제거 윈도우 max_age#

max_age 구성 설정을 통해 캐시 적중 가능성과 캐시 파일에 사용되는 평균 스토리지 양을 제어할 수 있습니다. max_age보다 오래된 항목은 디스크에서 삭제됩니다.

제거는 진행 중인 요청을 방해하지 않습니다. max_age가 느린 연결을 통해 페치하는 데 걸리는 시간보다 짧아도 괜찮습니다. 왜냐하면 Unix 파일 시스템은 삭제된 파일을 읽고 있는 모든 프로세스가 해당 파일을 닫을 때까지 실제로 파일을 삭제하지 않기 때문입니다.

최소 키 발생 횟수 min_occurrences#

min_occurrences 설정은 새 캐시 항목을 생성하기 전에 동일한 요청이 발생해야 하는 횟수를 제어합니다. 기본값은 1이며, 이는 고유한 요청이 캐시에 기록되지 않음을 의미합니다.

다음의 경우:

  • 이 숫자를 늘리면 캐시 적중률이 낮아지고 캐시가 더 적은 디스크 공간을 사용합니다.
  • 이 숫자를 줄이면 캐시 적중률이 높아지고 캐시가 더 많은 디스크 공간을 사용합니다.

min_occurrences1로 설정해야 합니다. GitLab.com에서 0에서 1로 증가하면 캐시 적중률에는 거의 영향을 주지 않으면서 캐시 디스크 공간의 50%를 절약했습니다.

캐시 모니터링#

히스토리
  • pack-objects 캐싱에 대한 로그가 GitLab 16.0에서 변경됨.

Prometheus 메트릭과 로그 필드를 사용하여 캐시를 모니터링할 수 있습니다.

Prometheus 메트릭#

Gitaly는 pack-objects 캐시 모니터링을 위해 다음 Prometheus 메트릭을 내보냅니다:

메트릭 유형 설명
gitaly_pack_objects_served_bytes_total Counter 클라이언트에게 제공된 git-pack-objects 데이터의 총 바이트 수
gitaly_pack_objects_cache_lookups_total Counter hit 또는 miss를 나타내는 result 레이블이 있는 캐시 조회 수
gitaly_pack_objects_generated_bytes_total Counter git-pack-objects 실행으로 생성된 총 바이트 수

예제 Prometheus 쿼리:

캐시 적중률:

sum(rate(gitaly_pack_objects_cache_lookups_total{result="hit"}[5m])) /
sum(rate(gitaly_pack_objects_cache_lookups_total[5m]))

초당 캐시에서 제공된 바이트:

rate(gitaly_pack_objects_served_bytes_total[5m])

초당 생성된 바이트(캐시 미스):

rate(gitaly_pack_objects_generated_bytes_total[5m])

캐시 효율성(제공된 바이트 대 생성된 바이트):

rate(gitaly_pack_objects_served_bytes_total[5m]) /
rate(gitaly_pack_objects_generated_bytes_total[5m])

로그 필드#

이러한 로그는 gRPC 로그의 일부이며 호출이 실행될 때 발견할 수 있습니다.

필드 설명
pack_objects_cache.hit 현재 pack-objects 캐시가 적중됐는지 여부(true 또는 false)
pack_objects_cache.key pack-objects 캐시에 사용된 캐시 키
pack_objects_cache.generated_bytes 작성 중인 새 캐시의 크기(바이트)
pack_objects_cache.served_bytes 제공 중인 캐시의 크기(바이트)
pack_objects.compression_statistics pack-objects 생성에 관한 통계
pack_objects.enumerate_objects_ms 클라이언트가 보낸 오브젝트를 열거하는 데 소요된 총 시간(ms)
pack_objects.prepare_pack_ms 클라이언트에 다시 보내기 전에 팩파일을 준비하는 데 소요된 총 시간(ms)
pack_objects.write_pack_file_ms 클라이언트에 팩파일을 다시 보내는 데 소요된 총 시간(ms). 클라이언트의 인터넷 연결에 크게 의존함
pack_objects.written_object_count Gitaly가 클라이언트에 다시 보내는 총 오브젝트 수

다음의 경우:

  • 캐시 미스: Gitaly는 pack_objects_cache.generated_bytespack_objects_cache.served_bytes 메시지를 모두 기록합니다. Gitaly는 pack-object 생성에 대한 더 자세한 통계도 기록합니다.
  • 캐시 적중: Gitaly는 pack_objects_cache.served_bytes 메시지만 기록합니다.

예제:

{
  "bytes":26186490,
  "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
  "grpc.meta.deadline_type":"none",
  "grpc.method":"PackObjectsHook",
  "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
  "grpc.request.glProjectPath":"root/gitlab-workhorse",
  "grpc.request.glRepository":"project-2",
  "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
  "grpc.request.repoStorage":"default",
  "grpc.request.topLevelGroup":"@hashed",
  "grpc.service":"gitaly.HookService",
  "grpc.start_time":"2021-03-25T14:57:52.747Z",
  "level":"info",
  "msg":"finished unary call with code OK",
  "peer.address":"@",
  "pid":20961,
  "span.kind":"server",
  "system":"grpc",
  "time":"2021-03-25T14:57:53.543Z",
  "pack_objects.compression_statistics": "Total 145991 (delta 68), reused 6 (delta 2), pack-reused 145911",
  "pack_objects.enumerate_objects_ms": 170,
  "pack_objects.prepare_pack_ms": 7,
  "pack_objects.write_pack_file_ms": 786,
  "pack_objects.written_object_count": 145991,
  "pack_objects_cache.generated_bytes": 49533030,
  "pack_objects_cache.hit": "false",
  "pack_objects_cache.key": "123456789",
  "pack_objects_cache.served_bytes": 49533030,
  "peer.address": "127.0.0.1",
  "pid": 8813,
}

cat-file 캐시#

많은 Gitaly RPC는 저장소에서 Git 오브젝트를 조회해야 합니다. 대부분의 경우 git cat-file --batch 프로세스를 사용합니다. 더 나은 성능을 위해 Gitaly는 RPC 호출 전반에 걸쳐 이러한 git cat-file 프로세스를 재사용할 수 있습니다. 이전에 사용된 프로세스는 git cat-file 캐시에 보관됩니다. 이것이 사용하는 시스템 리소스를 제어하기 위해 캐시에 들어갈 수 있는 최대 cat-file 프로세스 수가 있습니다.

기본 제한은 git cat-file --batchgit cat-file --batch-check 프로세스 쌍을 구성하는 100개의 cat-file입니다. "too many open files" 또는 새 프로세스 생성 불가 오류가 발생하면 이 제한을 낮추고 싶을 수 있습니다.

이상적으로 숫자는 표준 트래픽을 처리하기에 충분히 커야 합니다. 제한을 높이면 이전과 이후의 캐시 적중률을 측정해야 합니다. 적중률이 개선되지 않으면 더 높은 제한이 의미 있는 차이를 만들지 않는 것입니다. 다음은 적중률을 보는 예제 Prometheus 쿼리입니다:

sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m]))

Gitaly 구성 파일에서 cat-file 캐시를 구성합니다.

GitLab UI 커밋에 대한 커밋 서명 구성#

히스토리
  • GitLab 16.3에서 서명된 GitLab UI 커밋에 대한 Verified 배지 표시가 gitaly_gpg_signing이라는 플래그와 함께 도입됨. 기본적으로 비활성화.
  • rotated_signing_keys 옵션에 지정된 여러 키를 사용하여 서명 검증이 GitLab 16.3에서 도입됨.
  • GitLab 17.0에서 GitLab Self-Managed 및 GitLab Dedicated에서 기본적으로 활성화됨.
Feature flag

GitLab Self-Managed에서 기본적으로 이 기능을 사용할 수 있습니다. 기능을 숨기려면 관리자가 gitaly_gpg_signing이라는 기능 플래그를 비활성화할 수 있습니다. GitLab.com에서는 이 기능을 사용할 수 없습니다. GitLab Dedicated에서는 이 기능을 사용할 수 있습니다.

기본적으로 Gitaly는 GitLab UI를 사용하여 수행된 커밋에 서명하지 않습니다. 예를 들어 다음을 사용하여 수행된 커밋:

  • Web 편집기.
  • Web IDE.
  • 머지 요청.

Gitaly에서 커밋 서명을 활성화하면:

  • GitLab이 UI를 통해 수행된 모든 커밋에 서명합니다.
  • 서명은 저자의 신원이 아닌 커미터의 신원을 검증합니다.
  • committer_emailcommitter_name을 설정하여 커밋이 인스턴스에 의해 커밋됐음을 반영하도록 Gitaly를 구성할 수 있습니다. 예를 들어 GitLab.com에서 이러한 구성 옵션은 noreply@gitlab.comGitLab으로 설정됩니다.

rotated_signing_keys는 검증에만 사용할 키 목록입니다. Gitaly는 구성된 signing_key를 사용하여 웹 커밋을 검증하고 성공할 때까지 교체된 키를 하나씩 사용합니다. 다음과 같은 경우 rotated_signing_keys 옵션을 설정합니다:

  • 서명 키가 교체됩니다.
  • 다른 인스턴스에서 프로젝트를 마이그레이션하고 웹 커밋을 Verified로 표시하기 위해 여러 키를 지정하려 합니다.

다음 두 가지 방법 중 하나로 GitLab UI로 수행된 커밋에 서명하도록 Gitaly를 구성합니다:

  1. GPG 키를 생성하고 내보내거나, SSH 키를 생성합니다. 최적의 성능을 위해 EdDSA 키를 사용하세요.

    GPG 키 내보내기:

    gpg --export-secret-keys  > signing_key.gpg
    

    또는 SSH 키 생성(패스프레이즈 없음):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. Gitaly 노드에서 /etc/gitlab/gitaly/에 키를 복사하고 git 사용자가 파일을 읽을 수 있는 권한이 있는지 확인합니다.

  3. /etc/gitlab/gitlab.rb를 편집하고 gitaly['git']['signing_key']를 구성합니다:

    gitaly['configuration'] = {
       # ...
       git: {
         # ...
         committer_name: 'Your Instance',
         committer_email: 'noreply@yourinstance.com',
         signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
         rotated_signing_keys: ['/etc/gitlab/gitaly/previous_signing_key.gpg'],
         # ...
       },
    }
    
  4. 파일을 저장하고 GitLab을 재구성합니다.

  1. GPG 키를 생성하고 내보내거나, SSH 키를 생성합니다. 최적의 성능을 위해 EdDSA 키를 사용하세요.

    GPG 키 내보내기:

    gpg --export-secret-keys  > signing_key.gpg
    

    또는 SSH 키 생성(패스프레이즈 없음):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. Gitaly 노드에서 /etc/gitlab에 키를 복사합니다.

  3. /home/git/gitaly/config.toml을 편집하고 signing_key를 구성합니다:

    [git]
    committer_name = "Your Instance"
    committer_email = "noreply@yourinstance.com"
    signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
    rotated_signing_keys = ["/etc/gitlab/gitaly/previous_signing_key.gpg"]
    
  4. 파일을 저장하고 GitLab을 재시작합니다.

사용자 정의 Git 구성 구성#

Gitaly는 시스템 또는 사용자 수준 Git 구성 파일을 읽지 않습니다. Gitaly 서버에서 사용자 정의 Git 구성을 제공하려면 git.config 설정을 사용합니다.

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

gitaly['configuration'] = {
  # ...
  git: {
    # ...
    config: [
      { key: "fsck.badDate", value: "ignore" },
      ...
    ],
  },
}

/home/git/gitaly/config.toml을 편집합니다:

[[git.config]]
key = "fsck.badDate"
value = "ignore"

Gitaly에서 설정하는 Git 구성#

Gitaly는 git.config 설정을 사용하여 재정의할 수 없는 다음 Git 구성 값을 설정합니다:

  • advice.fetchShowForcedUpdates
  • attr.tree
  • bundle.heuristic
  • bundle.mode
  • bundle.version
  • core.alternateRefsCommand
  • core.autocrlf
  • core.bigFileThreshold
  • core.filesRefLockTimeout
  • core.fsync
  • core.fsyncMethod
  • core.hooksPath
  • core.packedRefsTimeout
  • core.useReplaceRefs
  • diff.noprefix
  • fetch.fsck.badTimezone
  • fetch.fsck.missingSpaceBeforeDate
  • fetch.fsck.zeroPaddedFilemode
  • fetch.fsckObjects
  • fetch.negotiationAlgorithm
  • fetch.recurseSubmodules
  • fetch.writeCommitGraph
  • fsck.badTimezone
  • fsck.missingSpaceBeforeDate
  • fsck.zeroPaddedFilemode
  • gc.auto
  • grep.threads
  • http.<url>.extraHeader
  • http.curloptResolve
  • http.extraHeader
  • http.followRedirects
  • init.defaultBranch
  • init.templateDir
  • maintenance.auto
  • pack.allowPackReuse
  • pack.island
  • pack.islandCore
  • pack.threads
  • pack.windowMemory
  • pack.writeBitmapLookupTable
  • pack.writeReverseIndex
  • receive.advertisePushOptions
  • receive.autogc
  • receive.fsck.badTimezone
  • receive.fsck.missingSpaceBeforeDate
  • receive.fsck.zeroPaddedFilemode
  • receive.hideRefs
  • receive.procReceiveRefs
  • remote.inmemory.fetch
  • remote.inmemory.url
  • remote.origin.fetch
  • remote.origin.url
  • repack.updateServerInfo
  • repack.writeBitmaps
  • transfer.bundleURI
  • transfer.fsckObjects
  • uploadpack.advertiseBundleURIs
  • uploadpack.allowAnySHA1InWant
  • uploadpack.allowFilter
  • uploadpack.hideRefs

외부 명령을 사용하여 구성 생성#

외부 명령을 사용하여 Gitaly 구성의 일부를 생성할 수 있습니다. 이를 수행하는 이유:

  • 전체 구성을 각 노드에 배포하지 않고 노드를 구성하기 위해.
  • 예를 들어 DNS 항목을 사용하여 노드 설정의 자동 검색을 통해 구성하기 위해.
  • 노드 시작 시 비밀을 구성하여 일반 텍스트로 표시될 필요가 없도록 하기 위해.

외부 명령을 사용하여 구성을 생성하려면 Gitaly 노드의 원하는 구성을 JSON 형식으로 표준 출력에 덤프하는 스크립트를 제공해야 합니다.

예를 들어 다음 명령은 AWS 비밀을 사용하여 GitLab 내부 API에 연결하는 데 사용되는 HTTP 비밀번호를 구성합니다:

#!/usr/bin/env ruby
require 'json'
JSON.generate({"gitlab": {"http_settings": {"password": `aws get-secret-value --secret-id ...`}}})

그런 다음 다음 두 가지 방법 중 하나로 Gitaly에 스크립트 경로를 알려야 합니다:

/etc/gitlab/gitlab.rb를 편집하고 config_command를 구성합니다:

gitaly['configuration'] = {
    config_command: '/path/to/config_command',
}

/home/git/gitaly/config.toml을 편집하고 config_command를 구성합니다:

config_command = "/path/to/config_command"

구성 후 Gitaly는 시작 시 명령을 실행하고 표준 출력을 JSON으로 파싱합니다. 결과 구성은 다른 Gitaly 구성으로 다시 병합됩니다.

다음과 같은 경우 Gitaly가 시작에 실패합니다:

  • 구성 명령이 실패합니다.
  • 명령에서 생성된 출력을 유효한 JSON으로 파싱할 수 없습니다.

서버측 백업 구성#

히스토리
  • GitLab 16.3에서 도입됨.
  • GitLab 16.6에서 최신 백업 대신 지정된 백업 복원에 대한 서버측 지원이 도입됨.
  • GitLab 16.6에서 증분 백업 생성에 대한 서버측 지원이 도입됨.
  • GitLab 17.0에서 Helm 차트 설치에 대한 서버측 지원이 추가됨.

저장소 백업을 구성하면 각 저장소를 호스팅하는 Gitaly 노드가 백업을 생성하고 오브젝트 스토리지로 스트리밍하는 역할을 담당할 수 있습니다. 이렇게 하면 백업을 생성하고 복원하는 데 필요한 네트워크 리소스를 줄일 수 있습니다.

각 Gitaly 노드는 백업을 위해 오브젝트 스토리지에 연결하도록 구성해야 합니다.

서버측 백업을 구성한 후 서버측 저장소 백업을 생성할 수 있습니다.

Azure Blob 스토리지 구성#

백업을 위한 Azure Blob 스토리지 구성 방법은 설치 유형에 따라 달라집니다. 소스 컴파일 설치의 경우 GitLab 외부에서 AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEY 환경 변수를 설정해야 합니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AZURE_STORAGE_ACCOUNT' => 'azure_storage_account',
    'AZURE_STORAGE_KEY' => 'azure_storage_key' # or 'AZURE_STORAGE_SAS_TOKEN'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'azblob://<bucket>'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "azblob://<bucket>"

Google Cloud 스토리지 구성#

Google Cloud 스토리지(GCP)는 애플리케이션 기본 자격 증명을 사용하여 인증합니다. 다음 중 하나를 사용하여 각 Gitaly 서버에서 애플리케이션 기본 자격 증명을 설정합니다:

자세한 내용은 애플리케이션 기본 자격 증명을 참조하세요.

대상 버킷은 go_cloud_url 옵션을 사용하여 구성됩니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'GOOGLE_APPLICATION_CREDENTIALS' => '/path/to/service.json'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'gs://<bucket>'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "gs://<bucket>"

S3 스토리지 구성#

S3 스토리지 인증을 구성하려면:

  • AWS CLI로 인증하는 경우 기본 AWS 세션을 사용할 수 있습니다.
  • 그렇지 않으면 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 환경 변수를 사용할 수 있습니다. 소스 컴파일 설치의 경우 GitLab 외부에서 환경 변수를 설정합니다.

자세한 내용은 AWS 세션 문서를 참조하세요.

대상 버킷과 리전은 go_cloud_url 옵션을 사용하여 구성됩니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'aws_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'aws_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-west-1'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "s3://<bucket>?region=us-west-1"

S3 호환 서버 구성#

S3 호환 서버는 endpoint 파라미터를 추가하여 S3와 유사하게 구성됩니다.

다음 파라미터를 지원합니다:

  • region: AWS 리전.
  • endpoint: 엔드포인트 URL.
  • disabledSSL: true 값은 SSL을 비활성화합니다.
  • s3ForcePathStyle: true 값은 경로 스타일 주소를 강제합니다.

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => '<your_access_key_id>',
    'AWS_SECRET_ACCESS_KEY' => '<your_secret_access_key>'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-east-1&endpoint=s3.example.com:9000&disableSSL=true&s3ForcePathStyle=true'
    }
}

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "s3://<bucket>?region=us-east-1&endpoint=s3.example.com:9000&disableSSL=true&s3ForcePathStyle=true"

Gitaly 구성

Tier: Free, Premium, Ultimate
Offering: GitLab Self-Managed
원문 보기
요약

다음 두 가지 방법 중 하나로 Gitaly를 구성합니다: 다음 구성 옵션도 사용할 수 있습니다: Gitaly 문서 전반에 걸쳐 참조되는 토큰은 관리자가 선택한 임의의 비밀번호입니다. 기본적으로 Gitaly는 Gitaly 클라이언트와 동일한 서버에서 실행되며 앞서 설명한 것처럼 구성됩니다.

다음 두 가지 방법 중 하나로 Gitaly를 구성합니다:

  1. /etc/gitlab/gitlab.rb를 편집하고 Gitaly 설정을 추가하거나 변경합니다. Gitaly 구성 파일 예제를 참조하세요. 예제 파일의 설정은 Ruby로 변환해야 합니다.
  2. 파일을 저장하고 GitLab을 재구성합니다.
  1. Gitaly 차트를 구성합니다.
  2. Helm 릴리스를 업그레이드합니다.
  1. /home/git/gitaly/config.toml을 편집하고 Gitaly 설정을 추가하거나 변경합니다. Gitaly 구성 파일 예제를 참조하세요.
  2. 파일을 저장하고 GitLab을 재시작합니다.

다음 구성 옵션도 사용할 수 있습니다:

Gitaly 토큰 정보#

Gitaly 문서 전반에 걸쳐 참조되는 토큰은 관리자가 선택한 임의의 비밀번호입니다. GitLab API 또는 유사한 웹 API 토큰을 위해 생성된 토큰과 관련이 없습니다.

Gitaly를 자체 서버에서 실행#

기본적으로 Gitaly는 Gitaly 클라이언트와 동일한 서버에서 실행되며 앞서 설명한 것처럼 구성됩니다. 단일 서버 설치에는 다음에서 사용하는 기본 구성이 가장 적합합니다:

그러나 Gitaly를 자체 서버에 배포할 수 있으며, 이는 여러 머신에 걸친 GitLab 설치에 유리할 수 있습니다.

Note

자체 서버에서 실행하도록 구성된 경우 Gitaly 서버는 클러스터의 Gitaly 클라이언트보다 먼저 업그레이드해야 합니다.

자체 서버에서 Gitaly를 설정하는 프로세스는 다음과 같습니다:

  1. Gitaly 설치.
  2. 인증 구성.
  3. Gitaly 서버 구성.
  4. Gitaly 클라이언트 구성.
  5. 필요하지 않은 곳에서 Gitaly 비활성화 (선택 사항).
Note

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

네트워크 아키텍처#

다음 목록은 Gitaly의 네트워크 아키텍처를 설명합니다:

  • GitLab Rails는 저장소를 저장소 스토리지로 분리합니다.
  • /config/gitlab.yml에는 스토리지 이름에서 (Gitaly 주소, Gitaly 토큰) 쌍으로의 맵이 포함됩니다.
  • /config/gitlab.ymlstorage name -> (Gitaly 주소, Gitaly 토큰) 맵이 Gitaly 네트워크 토폴로지의 단일 소스입니다.
  • (Gitaly 주소, Gitaly 토큰)은 Gitaly 서버에 해당합니다.
  • Gitaly 서버는 하나 이상의 스토리지를 호스팅합니다.
  • Gitaly 클라이언트는 하나 이상의 Gitaly 서버를 사용할 수 있습니다.
  • Gitaly 주소는 모든 Gitaly 클라이언트에 대해 올바르게 확인할 수 있도록 지정해야 합니다.
  • Gitaly 클라이언트는:
    • Puma.
    • Sidekiq.
    • GitLab Workhorse.
    • GitLab Shell.
    • Elasticsearch 인덱서.
    • Gitaly 자체.
  • Gitaly 서버는 /config/gitlab.yml에 지정된 자체 (Gitaly 주소, Gitaly 토큰) 쌍을 사용하여 자신에게 RPC 호출을 할 수 있어야 합니다.
  • 인증은 Gitaly와 GitLab Rails 노드 간에 공유되는 정적 토큰을 통해 수행됩니다.

다음 다이어그램은 HTTP 및 HTTPS 통신에 대한 기본 포트를 보여주는 Gitaly 서버와 GitLab Rails 간의 통신을 보여줍니다.

두 Gitaly 서버와 GitLab Rails가 정보를 교환합니다.

Warning

Gitaly 네트워크 트래픽은 기본적으로 암호화되지 않으므로 Gitaly 서버를 공용 인터넷에 노출해서는 안 됩니다. Gitaly 서버에 대한 액세스를 제한하기 위해 방화벽을 사용하는 것이 강력히 권장됩니다. 또 다른 옵션은 TLS를 사용하는 것입니다.

다음 섹션에서는 비밀 토큰 abc123secret을 사용하는 두 Gitaly 서버를 구성하는 방법을 설명합니다:

  • gitaly1.internal.
  • gitaly2.internal.

GitLab 설치에 세 개의 저장소 스토리지가 있다고 가정합니다:

  • default.
  • storage1.
  • storage2.

원하는 경우 하나의 저장소 스토리지가 있는 서버 하나를 사용할 수 있습니다.

Gitaly 설치#

다음 중 하나를 사용하여 각 Gitaly 서버에 Gitaly를 설치합니다:

Gitaly 서버 구성#

Gitaly 서버를 구성하려면 다음을 수행해야 합니다:

  • 인증 구성.
  • 스토리지 경로 구성.
  • 네트워크 리스너 활성화.

git 사용자는 구성된 스토리지 경로에서 읽고 쓰고 권한을 설정할 수 있어야 합니다.

Gitaly 토큰을 교체하는 동안 다운타임을 방지하려면 gitaly['auth_transitioning'] 설정을 사용하여 인증을 일시적으로 비활성화할 수 있습니다. 자세한 내용은 인증 전환 모드 활성화를 참조하세요.

인증 구성#

Gitaly와 GitLab은 인증을 위해 두 개의 공유 비밀을 사용합니다:

  • Gitaly 토큰: Gitaly에 대한 gRPC 요청을 인증하는 데 사용됩니다. Gitaly 토큰은 GitLab 구성에 직접 지정하거나 토큰 파일에 지정할 수 있습니다. 토큰 파일을 사용하면 시작 시 구성에 시크릿이 렌더링되지 않으므로 컨테이너화된 환경에 더 안전하고 적합합니다. 토큰 파일은 다음 조건을 만족해야 합니다:
    • 토큰 문자열만 포함합니다. 공백은 자동으로 제거됩니다.
    • 파일 권한이 0600 또는 0400이어야 합니다.
  • GitLab Shell 토큰: GitLab Shell에서 GitLab 내부 API로의 인증 콜백에 사용됩니다.
  1. _Gitaly 토큰_을 구성하려면 /etc/gitlab/gitlab.rb를 편집합니다:

    GitLab 18.11에서 token_file 지원이 도입되었습니다.

    토큰 파일을 사용하는 경우:

    gitaly['configuration'] = {
       # ...
       auth: {
         # ...
         token_file: '/etc/gitlab/gitaly_token',
       },
    }
    

    토큰을 직접 지정하는 경우:

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

    tokentoken_file은 상호 배타적입니다.

  2. 다음 두 가지 방법 중 하나로 _GitLab Shell 토큰_을 구성합니다:

    • 방법 1(권장): Gitaly 클라이언트에서 Gitaly 서버 및 다른 Gitaly 클라이언트의 동일한 경로로 /etc/gitlab/gitlab-secrets.json을 복사합니다.

    • 방법 2:

      1. GitLab Rails를 실행하는 모든 노드에서 /etc/gitlab/gitlab.rb를 편집합니다.

      2. 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'
          
      3. Gitaly를 실행하는 모든 노드에서 /etc/gitlab/gitlab.rb를 편집합니다.

      4. 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'
          
      5. 변경 사항 적용 후 GitLab을 재구성합니다:

      sudo gitlab-ctl reconfigure
      
  1. Gitaly 클라이언트에서 Gitaly 서버(및 다른 Gitaly 클라이언트)의 동일한 경로로 /home/git/gitlab/.gitlab_shell_secret을 복사합니다.

  2. Gitaly 클라이언트에서 /home/git/gitlab/config/gitlab.yml을 편집합니다:

    gitlab:
      gitaly:
        token: 'abc123secret'
    
  3. 파일을 저장하고 GitLab을 재시작합니다.

  4. Gitaly 서버에서 /home/git/gitaly/config.toml을 편집합니다:

    토큰 파일을 사용하는 경우:

    [auth]
    token_file = '/etc/gitaly/token'
    

    토큰을 직접 지정하는 경우:

    [auth]
    token = 'abc123secret'
    

    tokentoken_file은 상호 배타적입니다.

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

Gitaly 서버 구성#

Gitaly 서버를 구성합니다.

Gitaly에는 클라이언트(Rails 또는 Sidekiq 등)가 제공한 주소를 사용하여 자신에게 네트워크 호출을 하는 RPC가 있습니다.

네트워크 구성으로 인해 Gitaly가 이 방법으로 자신에게 도달할 수 없는 경우(예: Gitaly가 헤어핀 연결을 지원하지 않는 로드 밸런서 뒤에 있는 경우):

  1. Gitaly 서버의 /etc/hosts 파일을 편집합니다.
  2. 클라이언트가 사용하는 Gitaly 주소를 Gitaly 서버 자체의 IP 주소로 리디렉션하는 항목을 추가합니다. 예: 127.0.0.1 gitaly.example.com 또는 <local-ip> gitaly.example.com.
  1. /etc/gitlab/gitlab.rb를 편집합니다:

    # Avoid running unnecessary services on the Gitaly server
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    gitlab_exporter['enable'] = false
    gitlab_kas['enable'] = false
    
    # If you run a separate monitoring node you can disable these services
    prometheus['enable'] = false
    alertmanager['enable'] = false
    
    # If you don't run a separate monitoring node you can
    # enable Prometheus access & disable these extra services.
    # This makes Prometheus listen on all interfaces. You must use firewalls to restrict access to this address/port.
    # prometheus['listen_address'] = '0.0.0.0:9090'
    # prometheus['monitor_kubernetes'] = false
    
    # If you don't want to run monitoring services uncomment the following (not recommended)
    # node_exporter['enable'] = false
    
    # Prevent database connections during 'gitlab-ctl reconfigure'
    gitlab_rails['auto_migrate'] = false
    
    # 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.
    # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from Gitaly client to Gitaly server.
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
    gitaly['configuration'] = {
       # ...
       #
       # Make Gitaly accept connections on all network interfaces. You must use
       # firewalls to restrict access to this address/port.
       # Comment out following line if you only want to support TLS connections
       listen_addr: '0.0.0.0:8075',
       auth: {
         # ...
         #
         # Authentication token to ensure only authorized servers can communicate with
         # Gitaly server
         token: 'AUTH_TOKEN',
       },
    }
    
  2. 각 Gitaly 서버에 대해 /etc/gitlab/gitlab.rb에 다음을 추가합니다:

    gitaly1.internal에서:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'default',
             path: '/var/opt/gitlab/git-data/repositories',
          },
          {
             name: 'storage1',
             path: '/mnt/gitlab/git-data/repositories',
          },
       ],
    }
    

    gitaly2.internal에서:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'storage2',
             path: '/srv/gitlab/git-data/repositories',
          },
       ],
    }
    
  3. 파일을 저장하고 GitLab을 재구성합니다.

  4. Gitaly가 GitLab 내부 API에 콜백을 수행할 수 있는지 확인합니다:

    sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml
    
  1. /home/git/gitaly/config.toml을 편집합니다:

    listen_addr = '0.0.0.0:8075'
    
    runtime_dir = '/var/opt/gitlab/gitaly'
    
    [logging]
    format = 'json'
    level = 'info'
    dir = '/var/log/gitaly'
    
  2. 각 Gitaly 서버에 대해 /home/git/gitaly/config.toml에 다음을 추가합니다:

    gitaly1.internal에서:

    [[storage]]
    name = 'default'
    path = '/var/opt/gitlab/git-data/repositories'
    
    [[storage]]
    name = 'storage1'
    path = '/mnt/gitlab/git-data/repositories'
    

    gitaly2.internal에서:

    [[storage]]
    name = 'storage2'
    path = '/srv/gitlab/git-data/repositories'
    
  3. /home/git/gitlab-shell/config.yml을 편집합니다:

    gitlab_url: https://gitlab.example.com
    
  4. 파일을 저장하고 GitLab을 재시작합니다.

  5. Gitaly가 GitLab 내부 API에 콜백을 수행할 수 있는지 확인합니다:

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

GitLab 서버에서 Gitaly로 저장소 데이터를 직접 복사하는 경우 기본 경로 /var/opt/gitlab/git-data/repositories/.gitaly-metadata의 메타데이터 파일이 전송에 포함되지 않도록 하세요. 이 파일을 복사하면 GitLab이 Gitaly 서버에서 호스팅되는 저장소에 대한 직접 디스크 액세스를 사용하게 되어 Error creating pipelineCommit not found 오류 또는 오래된 데이터가 발생합니다.

Gitaly 클라이언트 구성#

마지막 단계로 로컬 Gitaly 서비스 대신 방금 구성한 Gitaly 서버를 사용하도록 Gitaly 클라이언트를 업데이트해야 합니다.

Note

GitLab에는 default 저장소 스토리지가 구성되어 있어야 합니다. 이 제한 사항에 대해 더 읽어보기.

Gitaly 클라이언트가 Gitaly 서버에 도달하지 못하도록 하는 모든 것이 모든 Gitaly 요청을 실패시키므로 위험할 수 있습니다. 예를 들어, 네트워크, 방화벽 또는 이름 확인 문제가 있을 수 있습니다.

Gitaly는 다음을 가정합니다:

  • gitaly1.internal Gitaly 서버는 Gitaly 클라이언트에서 gitaly1.internal:8075로 도달할 수 있으며, 해당 Gitaly 서버는 /var/opt/gitlab/git-data/mnt/gitlab/git-data에서 읽고 쓰고 권한을 설정할 수 있습니다.
  • gitaly2.internal Gitaly 서버는 Gitaly 클라이언트에서 gitaly2.internal:8075로 도달할 수 있으며, 해당 Gitaly 서버는 /srv/gitlab/git-data에서 읽고 쓰고 권한을 설정할 수 있습니다.
  • gitaly1.internalgitaly2.internal Gitaly 서버는 서로 도달할 수 있습니다.

혼합 구성을 사용하지 않는 한 일부는 로컬 Gitaly 서버(gitaly_address 없음)로, 일부는 원격 서버(gitaly_address 있음)로 Gitaly 서버를 정의할 수 없습니다.

다음 두 가지 방법 중 하나로 Gitaly 클라이언트를 구성합니다. 이 지침은 암호화되지 않은 연결에 대한 것이지만 TLS 지원도 활성화할 수 있습니다:

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

    # Use the same token value configured on all Gitaly servers
    gitlab_rails['gitaly_token'] = ''
    
    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
    }
    

    또는 각 Gitaly 서버가 서로 다른 인증 토큰을 사용하도록 구성된 경우:

    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075', 'gitaly_token' => '' },
    }
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

  3. Gitaly 클라이언트(예: Rails 애플리케이션)에서 sudo gitlab-rake gitlab:gitaly:check를 실행하여 Gitaly 서버에 연결할 수 있는지 확인합니다.

  4. 요청을 보려면 로그를 확인합니다:

    sudo gitlab-ctl tail gitaly
    
  1. /home/git/gitlab/config/gitlab.yml을 편집합니다:

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage1:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage2:
            gitaly_address: tcp://gitaly2.internal:8075
            gitaly_token: AUTH_TOKEN_2
    
  2. 파일을 저장하고 GitLab을 재시작합니다.

  3. sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production을 실행하여 Gitaly 클라이언트가 Gitaly 서버에 연결할 수 있는지 확인합니다.

  4. 요청을 보려면 로그를 확인합니다:

    tail -f /home/git/gitlab/log/gitaly.log
    

Gitaly 서버에서 Gitaly 로그를 추적하면 요청이 들어오는 것을 볼 수 있습니다. Gitaly 요청을 트리거하는 확실한 방법은 HTTP 또는 HTTPS를 통해 GitLab에서 저장소를 클론하는 것입니다.

Warning

저장소별 또는 전역으로 서버 훅을 구성한 경우 이를 Gitaly 서버로 이동해야 합니다. Gitaly 서버가 여러 개인 경우 모든 Gitaly 서버에 서버 훅을 복사합니다.

혼합 구성#

GitLab은 여러 Gitaly 서버 중 하나와 동일한 서버에 상주할 수 있지만 로컬 및 원격 구성을 혼합하는 구성은 지원하지 않습니다. 다음 설정은 올바르지 않습니다. 왜냐하면:

  • 모든 주소는 다른 Gitaly 서버에서 도달할 수 있어야 합니다.
  • storage1은 일부 Gitaly 서버에 유효하지 않은 gitaly_address에 Unix 소켓이 할당됩니다.
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  'storage1' => { 'gitaly_address' => 'unix:/var/opt/gitlab/gitaly/gitaly.socket' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

로컬 및 원격 Gitaly 서버를 결합하려면 로컬 Gitaly 서버에 외부 주소를 사용합니다. 예:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  # Address of the GitLab server that also has Gitaly running on it
  'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

gitaly['configuration'] = {
  # ...
  #
  # Make Gitaly accept connections on all network interfaces
  listen_addr: '0.0.0.0:8075',
  # Or for TLS
  tls_listen_addr: '0.0.0.0:9999',
  tls: {
    certificate_path:  '/etc/gitlab/ssl/cert.pem',
    key_path: '/etc/gitlab/ssl/key.pem',
  },
  storage: [
    {
      name: 'storage1',
      path: '/mnt/gitlab/git-data/repositories',
    },
  ],
}

path는 로컬 Gitaly 서버의 스토리지 샤드에만 포함할 수 있습니다. 제외된 경우 해당 스토리지 샤드에 기본 Git 스토리지 디렉터리가 사용됩니다.

GitLab에는 기본 저장소 스토리지 필요#

환경에 Gitaly 서버를 추가할 때 원래 default Gitaly 서비스를 교체하려 할 수 있습니다. 그러나 GitLab에는 default라는 스토리지가 필요하므로 default 스토리지를 제거하기 위해 GitLab 애플리케이션 서버를 재구성할 수 없습니다. 이 제한 사항에 대해서는 여기에서 더 읽어보기를 참조하세요.

이 제한 사항을 해결하려면:

  1. 새 Gitaly 서비스에 추가 스토리지 위치를 정의하고 추가 스토리지를 default로 구성합니다. 스토리지 위치에는 데이터베이스 마이그레이션이 작동하는 스토리지를 예상하므로 Gitaly 서비스가 실행 중이고 사용 가능해야 합니다.
  2. Admin 영역에서 저장소가 저장되지 않도록 default의 가중치를 0으로 설정합니다.

필요하지 않은 곳에서 Gitaly 비활성화(선택 사항)#

원격 서비스로 Gitaly를 실행하는 경우 GitLab 서버에서 기본적으로 실행되는 로컬 Gitaly 서비스를 비활성화하고 필요한 곳에서만 실행하는 것을 고려하세요.

GitLab 인스턴스에서 Gitaly를 비활성화하는 것은 Gitaly가 GitLab 인스턴스와 별도의 머신에서 실행되는 사용자 정의 클러스터 구성에서 GitLab을 실행하는 경우에만 의미가 있습니다. 클러스터의 모든 머신에서 Gitaly를 비활성화하는 것은 유효한 구성이 아닙니다(일부 머신은 Gitaly 서버 역할을 해야 함).

다음 두 가지 방법 중 하나로 GitLab 서버에서 Gitaly를 비활성화합니다:

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

    gitaly['enable'] = false
    
  2. 파일을 저장하고 GitLab을 재구성합니다.

  1. /etc/default/gitlab를 편집합니다:

    gitaly_enabled=false
    
  2. 파일을 저장하고 GitLab을 재시작합니다.

Gitaly 수신 인터페이스 변경#

Gitaly가 수신하는 인터페이스를 변경할 수 있습니다. Gitaly와 통신해야 하는 외부 서비스가 있을 때 수신 인터페이스를 변경할 수 있습니다. 예를 들어, 정확한 코드 검색이 활성화됐지만 실제 서비스가 다른 서버에서 실행 중인 경우 Zoekt를 사용하는 정확한 코드 검색이 있습니다.

gitaly_token은 Gitaly 서비스 인증에 사용되므로 비밀 문자열이어야 합니다. 이 비밀은 openssl rand -base64 24로 생성하여 32자의 무작위 문자열을 만들 수 있습니다.

예를 들어, Gitaly 수신 인터페이스를 0.0.0.0:8075로 변경하려면:

# /etc/gitlab/gitlab.rb
# Add a shared token for Gitaly authentication
gitlab_shell['secret_token'] = 'your_secure_token_here'
gitlab_rails['gitaly_token'] = 'your_secure_token_here'

# Gitaly configuration
gitaly['gitlab_secret'] = 'your_secure_token_here'
gitaly['configuration'] = {
  listen_addr: '0.0.0.0:8075',
  auth: {
    token: 'your_secure_token_here',
  },
  storage: [
    {
      name: 'default',
      path: '/var/opt/gitlab/git-data/repositories',
    },
  ]
}

# Tell Rails where to find Gitaly
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://ip_address_here:8075' },
}

# Internal API URL (important for multi-server setups)
gitlab_rails['internal_api_url'] = 'http://ip_address_here'

제어 그룹#

제어 그룹에 대한 자세한 내용은 Cgroups를 참조하세요.

백그라운드 저장소 최적화#

Git 저장소의 오브젝트 데이터베이스에 데이터를 저장하는 방식이 시간이 지남에 따라 비효율적이 될 수 있어 Git 작업이 느려질 수 있습니다. Gitaly를 최대 지속 시간과 함께 일별 백그라운드 작업을 실행하도록 예약하여 이러한 항목을 정리하고 성능을 향상시킬 수 있습니다.

Warning

백그라운드 저장소 최적화는 실행 중에 호스트에 상당한 부하를 줄 수 있습니다. 피크가 없는 시간에 예약하고 지속 시간을 짧게 유지하세요(예: 30-60분).

다음 두 가지 방법 중 하나로 백그라운드 저장소 최적화를 구성합니다:

/etc/gitlab/gitlab.rb를 편집하고 다음을 추가합니다:

gitaly['configuration'] = {
  # ...
  daily_maintenance: {
    # ...
    start_hour: 4,
    start_minute: 30,
    duration: '30m',
    storages: ['default'],
  },
}

/home/git/gitaly/config.toml을 편집하고 다음을 추가합니다:

[daily_maintenance]
start_hour = 4
start_minute = 30
duration = '30m'
storages = ["default"]

Gitaly 인증 토큰 교체#

프로덕션 환경에서 자격 증명을 교체하면 종종 다운타임이나 중단이 발생하거나 둘 다 발생합니다.

그러나 서비스 중단 없이 Gitaly 자격 증명을 교체할 수 있습니다. Gitaly 인증 토큰 교체 방법:

이 절차는 단일 서버에서 GitLab을 실행하는 경우에도 작동합니다. 이 경우 Gitaly 서버와 Gitaly 클라이언트는 동일한 머신을 가리킵니다.

인증 모니터링 확인#

Gitaly 인증 토큰을 교체하기 전에 Prometheus를 사용하여 GitLab 설치의 인증 동작을 모니터링할 수 있는지 확인합니다.

그런 다음 나머지 절차를 계속할 수 있습니다.

인증 전환 모드 활성화#

다음과 같이 인증 전환 모드에 넣어 Gitaly 서버에서 Gitaly 인증을 일시적으로 비활성화합니다:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: true,
  },
}

이 변경을 수행한 후 Prometheus 쿼리는 다음과 같은 내용을 반환해야 합니다:

{enforced="false",status="would be ok"}  4424.985419441742

enforced="false"이므로 새 토큰을 롤아웃하기 시작해도 안전합니다.

Gitaly 인증 토큰 업데이트#

새 Gitaly 인증 토큰으로 업데이트하려면 각 Gitaly 클라이언트 및 Gitaly 서버에서:

  1. 구성을 업데이트합니다:

    # in /etc/gitlab/gitlab.rb
    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: '<new secret token>',
       },
    }
    

    token_file을 사용하는 경우 참조된 파일의 내용을 새 토큰으로 업데이트합니다. 구성 변경은 필요하지 않습니다. 토큰 파일은 시작 시 읽힙니다.

  2. Gitaly를 재시작합니다:

    gitlab-ctl restart gitaly
    

이 변경이 롤아웃되는 동안 Prometheus 쿼리를 실행하면 enforced="false",status="denied" 카운터에 0이 아닌 값이 표시됩니다.

인증 실패 없음 확인#

새 토큰이 설정되고 관련된 모든 서비스가 재시작된 후 다음의 혼합을 일시적으로 볼 수 있습니다:

  • status="would be ok".
  • status="denied".

모든 Gitaly 클라이언트와 Gitaly 서버가 새 토큰을 가져오면 유일한 0이 아닌 비율은 enforced="false",status="would be ok"이어야 합니다.

인증 전환 모드 비활성화#

Gitaly 인증을 다시 활성화하려면 인증 전환 모드를 비활성화합니다. Gitaly 서버의 구성을 다음과 같이 업데이트합니다:

# in /etc/gitlab/gitlab.rb
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: false,
  },
}
Warning

이 단계를 완료하지 않으면 Gitaly 인증이 없어집니다.

인증이 적용되는지 확인#

Prometheus 쿼리를 새로 고칩니다. 이제 처음에 보았던 것과 유사한 결과가 표시되어야 합니다. 예:

{enforced="true",status="ok"}  4424.985419441742

enforced="true"는 인증이 적용되고 있음을 의미합니다.

Pack-objects 캐시#

Git 저장소를 위한 스토리지를 제공하는 서비스인 Gitaly는 짧은 롤링 윈도우의 Git 페치 응답을 캐시하도록 구성할 수 있습니다. 이를 통해 서버가 많은 CI 페치 트래픽을 수신할 때 서버 부하를 줄일 수 있습니다.

pack-objects 캐시는 PostUploadPack 및 SSHUploadPack Gitaly RPC를 통해 간접적으로 호출되는 Git의 내부 부분인 git pack-objects를 래핑합니다. Gitaly는 사용자가 HTTP를 사용하여 Git 페치를 수행하면 PostUploadPack을, 사용자가 SSH를 사용하여 Git 페치를 수행하면 SSHUploadPack을 실행합니다. 캐시가 활성화되면 PostUploadPack 또는 SSHUploadPack을 사용하는 모든 것이 혜택을 받을 수 있습니다. 이는 다음에 독립적이고 영향을 받지 않습니다:

  • 전송 방식(HTTP 또는 SSH).
  • Git 프로토콜 버전(v0 또는 v2).
  • 전체 클론, 증분 페치, 얕은 클론 또는 부분 클론과 같은 페치 유형.

이 캐시의 강점은 동시에 동일한 페치를 중복 제거하는 능력입니다. 이는:

  • CI/CD 파이프라인에서 동시 작업이 많은 GitLab 인스턴스에서 혜택을 볼 수 있습니다. 서버 CPU 사용량이 눈에 띄게 감소해야 합니다.
  • 고유한 페치에는 전혀 도움이 되지 않습니다. 예를 들어 로컬 컴퓨터에 저장소를 클론하여 샘플 확인을 수행하는 경우 페치가 고유할 가능성이 높으므로 이 캐시의 혜택을 볼 가능성이 낮습니다.

pack-objects 캐시는 로컬 캐시입니다. 이는:

  • 메타데이터를 활성화된 Gitaly 프로세스의 메모리에 저장합니다.
  • 캐시 중인 실제 Git 데이터를 로컬 스토리지의 파일에 저장합니다.

로컬 파일을 사용하면 운영 체제가 팩 오브젝트 캐시 파일의 일부를 RAM에 자동으로 보관하여 속도를 높일 수 있다는 장점이 있습니다.

pack-objects 캐시는 디스크 쓰기 IO가 크게 증가할 수 있으므로 기본적으로 비활성화됩니다.

캐시 구성#

pack-objects 캐시에 사용할 수 있는 구성 설정이 있습니다. 각 설정에 대해 아래에서 자세히 설명합니다.

설정 기본값 설명
enabled false 캐시를 켭니다. 꺼져 있으면 Gitaly가 각 요청에 대해 전용 git pack-objects 프로세스를 실행합니다.
dir /+gitaly/PackObjectsCache 캐시 파일이 저장되는 로컬 디렉터리.
max_age 5m (5분) 이보다 오래된 캐시 항목은 제거되어 디스크에서 제거됩니다.
min_occurrences 1 캐시 항목이 생성되기 전에 키가 발생해야 하는 최소 횟수.

/etc/gitlab/gitlab.rb에서 다음을 설정합니다:

gitaly['configuration'] = {
  # ...
  pack_objects_cache: {
    enabled: true,
    # The default settings for "dir", "max_age" and "min_occurences" should be fine.
    # If you want to customize these, see details below.
  },
}

enabled 기본값은 false#

캐시는 경우에 따라 디스크에 기록되는 바이트 수가 극단적으로 증가할 수 있으므로 기본적으로 비활성화됩니다. GitLab.com에서 저장소 스토리지 디스크가 이 추가 작업량을 처리할 수 있음을 확인했지만 이것이 어디서나 사실이라고 가정할 수 없다고 판단했습니다.

캐시 스토리지 디렉터리 dir#

캐시는 파일을 저장할 디렉터리가 필요합니다. 이 디렉터리는 다음과 같아야 합니다:

  • 충분한 공간이 있는 파일 시스템에 있어야 합니다. 캐시 파일 시스템의 공간이 부족하면 모든 페치가 실패하기 시작합니다.
  • 충분한 IO 대역폭이 있는 디스크에 있어야 합니다. 캐시 디스크의 IO 대역폭이 부족하면 모든 페치, 그리고 서버 전체가 느려질 수 있습니다.
Warning

지정된 디렉터리의 모든 기존 데이터는 제거됩니다. 기존 데이터가 있는 디렉터리를 사용하지 않도록 주의하세요.

기본적으로 캐시 스토리지 디렉터리는 구성 파일에 정의된 첫 번째 Gitaly 스토리지의 하위 디렉터리로 설정됩니다.

여러 Gitaly 프로세스는 캐시 스토리지에 동일한 디렉터리를 사용할 수 있습니다. 각 Gitaly 프로세스는 생성하는 캐시 파일 이름의 일부로 고유한 무작위 문자열을 사용합니다. 이는 다음을 의미합니다:

  • 충돌하지 않습니다.
  • 다른 프로세스의 파일을 재사용하지 않습니다.

기본 디렉터리가 저장소 데이터와 동일한 파일 시스템에 캐시 파일을 배치하지만 이것이 요구 사항은 아닙니다. 인프라에 더 적합한 경우 다른 파일 시스템에 캐시 파일을 배치할 수 있습니다.

디스크에서 필요한 IO 대역폭은 다음에 따라 달라집니다:

  • Gitaly 서버의 저장소 크기와 형태.
  • 사용자가 생성하는 트래픽 종류.

캐시 적중률이 0%라고 가정하는 비관적인 추정으로 gitaly_pack_objects_generated_bytes_total 메트릭을 사용할 수 있습니다.

필요한 공간은 다음에 따라 달라집니다:

  • 사용자가 캐시에서 끌어내는 초당 바이트 수.
  • max_age 캐시 제거 윈도우 크기.

사용자가 100MB/s를 끌어내고 5분 윈도우를 사용하면 캐시 디렉터리에 평균 5*60*100 MB = 30 GB 데이터가 있습니다. 이 평균은 예상 평균이지 보장이 아닙니다. 최대 크기는 이 평균을 초과할 수 있습니다.

캐시 제거 윈도우 max_age#

max_age 구성 설정을 통해 캐시 적중 가능성과 캐시 파일에 사용되는 평균 스토리지 양을 제어할 수 있습니다. max_age보다 오래된 항목은 디스크에서 삭제됩니다.

제거는 진행 중인 요청을 방해하지 않습니다. max_age가 느린 연결을 통해 페치하는 데 걸리는 시간보다 짧아도 괜찮습니다. 왜냐하면 Unix 파일 시스템은 삭제된 파일을 읽고 있는 모든 프로세스가 해당 파일을 닫을 때까지 실제로 파일을 삭제하지 않기 때문입니다.

최소 키 발생 횟수 min_occurrences#

min_occurrences 설정은 새 캐시 항목을 생성하기 전에 동일한 요청이 발생해야 하는 횟수를 제어합니다. 기본값은 1이며, 이는 고유한 요청이 캐시에 기록되지 않음을 의미합니다.

다음의 경우:

  • 이 숫자를 늘리면 캐시 적중률이 낮아지고 캐시가 더 적은 디스크 공간을 사용합니다.
  • 이 숫자를 줄이면 캐시 적중률이 높아지고 캐시가 더 많은 디스크 공간을 사용합니다.

min_occurrences1로 설정해야 합니다. GitLab.com에서 0에서 1로 증가하면 캐시 적중률에는 거의 영향을 주지 않으면서 캐시 디스크 공간의 50%를 절약했습니다.

캐시 모니터링#

히스토리
  • pack-objects 캐싱에 대한 로그가 GitLab 16.0에서 변경됨.

Prometheus 메트릭과 로그 필드를 사용하여 캐시를 모니터링할 수 있습니다.

Prometheus 메트릭#

Gitaly는 pack-objects 캐시 모니터링을 위해 다음 Prometheus 메트릭을 내보냅니다:

메트릭 유형 설명
gitaly_pack_objects_served_bytes_total Counter 클라이언트에게 제공된 git-pack-objects 데이터의 총 바이트 수
gitaly_pack_objects_cache_lookups_total Counter hit 또는 miss를 나타내는 result 레이블이 있는 캐시 조회 수
gitaly_pack_objects_generated_bytes_total Counter git-pack-objects 실행으로 생성된 총 바이트 수

예제 Prometheus 쿼리:

캐시 적중률:

sum(rate(gitaly_pack_objects_cache_lookups_total{result="hit"}[5m])) /
sum(rate(gitaly_pack_objects_cache_lookups_total[5m]))

초당 캐시에서 제공된 바이트:

rate(gitaly_pack_objects_served_bytes_total[5m])

초당 생성된 바이트(캐시 미스):

rate(gitaly_pack_objects_generated_bytes_total[5m])

캐시 효율성(제공된 바이트 대 생성된 바이트):

rate(gitaly_pack_objects_served_bytes_total[5m]) /
rate(gitaly_pack_objects_generated_bytes_total[5m])

로그 필드#

이러한 로그는 gRPC 로그의 일부이며 호출이 실행될 때 발견할 수 있습니다.

필드 설명
pack_objects_cache.hit 현재 pack-objects 캐시가 적중됐는지 여부(true 또는 false)
pack_objects_cache.key pack-objects 캐시에 사용된 캐시 키
pack_objects_cache.generated_bytes 작성 중인 새 캐시의 크기(바이트)
pack_objects_cache.served_bytes 제공 중인 캐시의 크기(바이트)
pack_objects.compression_statistics pack-objects 생성에 관한 통계
pack_objects.enumerate_objects_ms 클라이언트가 보낸 오브젝트를 열거하는 데 소요된 총 시간(ms)
pack_objects.prepare_pack_ms 클라이언트에 다시 보내기 전에 팩파일을 준비하는 데 소요된 총 시간(ms)
pack_objects.write_pack_file_ms 클라이언트에 팩파일을 다시 보내는 데 소요된 총 시간(ms). 클라이언트의 인터넷 연결에 크게 의존함
pack_objects.written_object_count Gitaly가 클라이언트에 다시 보내는 총 오브젝트 수

다음의 경우:

  • 캐시 미스: Gitaly는 pack_objects_cache.generated_bytespack_objects_cache.served_bytes 메시지를 모두 기록합니다. Gitaly는 pack-object 생성에 대한 더 자세한 통계도 기록합니다.
  • 캐시 적중: Gitaly는 pack_objects_cache.served_bytes 메시지만 기록합니다.

예제:

{
  "bytes":26186490,
  "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
  "grpc.meta.deadline_type":"none",
  "grpc.method":"PackObjectsHook",
  "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
  "grpc.request.glProjectPath":"root/gitlab-workhorse",
  "grpc.request.glRepository":"project-2",
  "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
  "grpc.request.repoStorage":"default",
  "grpc.request.topLevelGroup":"@hashed",
  "grpc.service":"gitaly.HookService",
  "grpc.start_time":"2021-03-25T14:57:52.747Z",
  "level":"info",
  "msg":"finished unary call with code OK",
  "peer.address":"@",
  "pid":20961,
  "span.kind":"server",
  "system":"grpc",
  "time":"2021-03-25T14:57:53.543Z",
  "pack_objects.compression_statistics": "Total 145991 (delta 68), reused 6 (delta 2), pack-reused 145911",
  "pack_objects.enumerate_objects_ms": 170,
  "pack_objects.prepare_pack_ms": 7,
  "pack_objects.write_pack_file_ms": 786,
  "pack_objects.written_object_count": 145991,
  "pack_objects_cache.generated_bytes": 49533030,
  "pack_objects_cache.hit": "false",
  "pack_objects_cache.key": "123456789",
  "pack_objects_cache.served_bytes": 49533030,
  "peer.address": "127.0.0.1",
  "pid": 8813,
}

cat-file 캐시#

많은 Gitaly RPC는 저장소에서 Git 오브젝트를 조회해야 합니다. 대부분의 경우 git cat-file --batch 프로세스를 사용합니다. 더 나은 성능을 위해 Gitaly는 RPC 호출 전반에 걸쳐 이러한 git cat-file 프로세스를 재사용할 수 있습니다. 이전에 사용된 프로세스는 git cat-file 캐시에 보관됩니다. 이것이 사용하는 시스템 리소스를 제어하기 위해 캐시에 들어갈 수 있는 최대 cat-file 프로세스 수가 있습니다.

기본 제한은 git cat-file --batchgit cat-file --batch-check 프로세스 쌍을 구성하는 100개의 cat-file입니다. "too many open files" 또는 새 프로세스 생성 불가 오류가 발생하면 이 제한을 낮추고 싶을 수 있습니다.

이상적으로 숫자는 표준 트래픽을 처리하기에 충분히 커야 합니다. 제한을 높이면 이전과 이후의 캐시 적중률을 측정해야 합니다. 적중률이 개선되지 않으면 더 높은 제한이 의미 있는 차이를 만들지 않는 것입니다. 다음은 적중률을 보는 예제 Prometheus 쿼리입니다:

sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m]))

Gitaly 구성 파일에서 cat-file 캐시를 구성합니다.

GitLab UI 커밋에 대한 커밋 서명 구성#

히스토리
  • GitLab 16.3에서 서명된 GitLab UI 커밋에 대한 Verified 배지 표시가 gitaly_gpg_signing이라는 플래그와 함께 도입됨. 기본적으로 비활성화.
  • rotated_signing_keys 옵션에 지정된 여러 키를 사용하여 서명 검증이 GitLab 16.3에서 도입됨.
  • GitLab 17.0에서 GitLab Self-Managed 및 GitLab Dedicated에서 기본적으로 활성화됨.
Feature flag

GitLab Self-Managed에서 기본적으로 이 기능을 사용할 수 있습니다. 기능을 숨기려면 관리자가 gitaly_gpg_signing이라는 기능 플래그를 비활성화할 수 있습니다. GitLab.com에서는 이 기능을 사용할 수 없습니다. GitLab Dedicated에서는 이 기능을 사용할 수 있습니다.

기본적으로 Gitaly는 GitLab UI를 사용하여 수행된 커밋에 서명하지 않습니다. 예를 들어 다음을 사용하여 수행된 커밋:

  • Web 편집기.
  • Web IDE.
  • 머지 요청.

Gitaly에서 커밋 서명을 활성화하면:

  • GitLab이 UI를 통해 수행된 모든 커밋에 서명합니다.
  • 서명은 저자의 신원이 아닌 커미터의 신원을 검증합니다.
  • committer_emailcommitter_name을 설정하여 커밋이 인스턴스에 의해 커밋됐음을 반영하도록 Gitaly를 구성할 수 있습니다. 예를 들어 GitLab.com에서 이러한 구성 옵션은 noreply@gitlab.comGitLab으로 설정됩니다.

rotated_signing_keys는 검증에만 사용할 키 목록입니다. Gitaly는 구성된 signing_key를 사용하여 웹 커밋을 검증하고 성공할 때까지 교체된 키를 하나씩 사용합니다. 다음과 같은 경우 rotated_signing_keys 옵션을 설정합니다:

  • 서명 키가 교체됩니다.
  • 다른 인스턴스에서 프로젝트를 마이그레이션하고 웹 커밋을 Verified로 표시하기 위해 여러 키를 지정하려 합니다.

다음 두 가지 방법 중 하나로 GitLab UI로 수행된 커밋에 서명하도록 Gitaly를 구성합니다:

  1. GPG 키를 생성하고 내보내거나, SSH 키를 생성합니다. 최적의 성능을 위해 EdDSA 키를 사용하세요.

    GPG 키 내보내기:

    gpg --export-secret-keys  > signing_key.gpg
    

    또는 SSH 키 생성(패스프레이즈 없음):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. Gitaly 노드에서 /etc/gitlab/gitaly/에 키를 복사하고 git 사용자가 파일을 읽을 수 있는 권한이 있는지 확인합니다.

  3. /etc/gitlab/gitlab.rb를 편집하고 gitaly['git']['signing_key']를 구성합니다:

    gitaly['configuration'] = {
       # ...
       git: {
         # ...
         committer_name: 'Your Instance',
         committer_email: 'noreply@yourinstance.com',
         signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
         rotated_signing_keys: ['/etc/gitlab/gitaly/previous_signing_key.gpg'],
         # ...
       },
    }
    
  4. 파일을 저장하고 GitLab을 재구성합니다.

  1. GPG 키를 생성하고 내보내거나, SSH 키를 생성합니다. 최적의 성능을 위해 EdDSA 키를 사용하세요.

    GPG 키 내보내기:

    gpg --export-secret-keys  > signing_key.gpg
    

    또는 SSH 키 생성(패스프레이즈 없음):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. Gitaly 노드에서 /etc/gitlab에 키를 복사합니다.

  3. /home/git/gitaly/config.toml을 편집하고 signing_key를 구성합니다:

    [git]
    committer_name = "Your Instance"
    committer_email = "noreply@yourinstance.com"
    signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
    rotated_signing_keys = ["/etc/gitlab/gitaly/previous_signing_key.gpg"]
    
  4. 파일을 저장하고 GitLab을 재시작합니다.

사용자 정의 Git 구성 구성#

Gitaly는 시스템 또는 사용자 수준 Git 구성 파일을 읽지 않습니다. Gitaly 서버에서 사용자 정의 Git 구성을 제공하려면 git.config 설정을 사용합니다.

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

gitaly['configuration'] = {
  # ...
  git: {
    # ...
    config: [
      { key: "fsck.badDate", value: "ignore" },
      ...
    ],
  },
}

/home/git/gitaly/config.toml을 편집합니다:

[[git.config]]
key = "fsck.badDate"
value = "ignore"

Gitaly에서 설정하는 Git 구성#

Gitaly는 git.config 설정을 사용하여 재정의할 수 없는 다음 Git 구성 값을 설정합니다:

  • advice.fetchShowForcedUpdates
  • attr.tree
  • bundle.heuristic
  • bundle.mode
  • bundle.version
  • core.alternateRefsCommand
  • core.autocrlf
  • core.bigFileThreshold
  • core.filesRefLockTimeout
  • core.fsync
  • core.fsyncMethod
  • core.hooksPath
  • core.packedRefsTimeout
  • core.useReplaceRefs
  • diff.noprefix
  • fetch.fsck.badTimezone
  • fetch.fsck.missingSpaceBeforeDate
  • fetch.fsck.zeroPaddedFilemode
  • fetch.fsckObjects
  • fetch.negotiationAlgorithm
  • fetch.recurseSubmodules
  • fetch.writeCommitGraph
  • fsck.badTimezone
  • fsck.missingSpaceBeforeDate
  • fsck.zeroPaddedFilemode
  • gc.auto
  • grep.threads
  • http.<url>.extraHeader
  • http.curloptResolve
  • http.extraHeader
  • http.followRedirects
  • init.defaultBranch
  • init.templateDir
  • maintenance.auto
  • pack.allowPackReuse
  • pack.island
  • pack.islandCore
  • pack.threads
  • pack.windowMemory
  • pack.writeBitmapLookupTable
  • pack.writeReverseIndex
  • receive.advertisePushOptions
  • receive.autogc
  • receive.fsck.badTimezone
  • receive.fsck.missingSpaceBeforeDate
  • receive.fsck.zeroPaddedFilemode
  • receive.hideRefs
  • receive.procReceiveRefs
  • remote.inmemory.fetch
  • remote.inmemory.url
  • remote.origin.fetch
  • remote.origin.url
  • repack.updateServerInfo
  • repack.writeBitmaps
  • transfer.bundleURI
  • transfer.fsckObjects
  • uploadpack.advertiseBundleURIs
  • uploadpack.allowAnySHA1InWant
  • uploadpack.allowFilter
  • uploadpack.hideRefs

외부 명령을 사용하여 구성 생성#

외부 명령을 사용하여 Gitaly 구성의 일부를 생성할 수 있습니다. 이를 수행하는 이유:

  • 전체 구성을 각 노드에 배포하지 않고 노드를 구성하기 위해.
  • 예를 들어 DNS 항목을 사용하여 노드 설정의 자동 검색을 통해 구성하기 위해.
  • 노드 시작 시 비밀을 구성하여 일반 텍스트로 표시될 필요가 없도록 하기 위해.

외부 명령을 사용하여 구성을 생성하려면 Gitaly 노드의 원하는 구성을 JSON 형식으로 표준 출력에 덤프하는 스크립트를 제공해야 합니다.

예를 들어 다음 명령은 AWS 비밀을 사용하여 GitLab 내부 API에 연결하는 데 사용되는 HTTP 비밀번호를 구성합니다:

#!/usr/bin/env ruby
require 'json'
JSON.generate({"gitlab": {"http_settings": {"password": `aws get-secret-value --secret-id ...`}}})

그런 다음 다음 두 가지 방법 중 하나로 Gitaly에 스크립트 경로를 알려야 합니다:

/etc/gitlab/gitlab.rb를 편집하고 config_command를 구성합니다:

gitaly['configuration'] = {
    config_command: '/path/to/config_command',
}

/home/git/gitaly/config.toml을 편집하고 config_command를 구성합니다:

config_command = "/path/to/config_command"

구성 후 Gitaly는 시작 시 명령을 실행하고 표준 출력을 JSON으로 파싱합니다. 결과 구성은 다른 Gitaly 구성으로 다시 병합됩니다.

다음과 같은 경우 Gitaly가 시작에 실패합니다:

  • 구성 명령이 실패합니다.
  • 명령에서 생성된 출력을 유효한 JSON으로 파싱할 수 없습니다.

서버측 백업 구성#

히스토리
  • GitLab 16.3에서 도입됨.
  • GitLab 16.6에서 최신 백업 대신 지정된 백업 복원에 대한 서버측 지원이 도입됨.
  • GitLab 16.6에서 증분 백업 생성에 대한 서버측 지원이 도입됨.
  • GitLab 17.0에서 Helm 차트 설치에 대한 서버측 지원이 추가됨.

저장소 백업을 구성하면 각 저장소를 호스팅하는 Gitaly 노드가 백업을 생성하고 오브젝트 스토리지로 스트리밍하는 역할을 담당할 수 있습니다. 이렇게 하면 백업을 생성하고 복원하는 데 필요한 네트워크 리소스를 줄일 수 있습니다.

각 Gitaly 노드는 백업을 위해 오브젝트 스토리지에 연결하도록 구성해야 합니다.

서버측 백업을 구성한 후 서버측 저장소 백업을 생성할 수 있습니다.

Azure Blob 스토리지 구성#

백업을 위한 Azure Blob 스토리지 구성 방법은 설치 유형에 따라 달라집니다. 소스 컴파일 설치의 경우 GitLab 외부에서 AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEY 환경 변수를 설정해야 합니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AZURE_STORAGE_ACCOUNT' => 'azure_storage_account',
    'AZURE_STORAGE_KEY' => 'azure_storage_key' # or 'AZURE_STORAGE_SAS_TOKEN'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'azblob://<bucket>'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "azblob://<bucket>"

Google Cloud 스토리지 구성#

Google Cloud 스토리지(GCP)는 애플리케이션 기본 자격 증명을 사용하여 인증합니다. 다음 중 하나를 사용하여 각 Gitaly 서버에서 애플리케이션 기본 자격 증명을 설정합니다:

자세한 내용은 애플리케이션 기본 자격 증명을 참조하세요.

대상 버킷은 go_cloud_url 옵션을 사용하여 구성됩니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'GOOGLE_APPLICATION_CREDENTIALS' => '/path/to/service.json'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'gs://<bucket>'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "gs://<bucket>"

S3 스토리지 구성#

S3 스토리지 인증을 구성하려면:

  • AWS CLI로 인증하는 경우 기본 AWS 세션을 사용할 수 있습니다.
  • 그렇지 않으면 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 환경 변수를 사용할 수 있습니다. 소스 컴파일 설치의 경우 GitLab 외부에서 환경 변수를 설정합니다.

자세한 내용은 AWS 세션 문서를 참조하세요.

대상 버킷과 리전은 go_cloud_url 옵션을 사용하여 구성됩니다.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'aws_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'aws_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-west-1'
    }
}

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "s3://<bucket>?region=us-west-1"

S3 호환 서버 구성#

S3 호환 서버는 endpoint 파라미터를 추가하여 S3와 유사하게 구성됩니다.

다음 파라미터를 지원합니다:

  • region: AWS 리전.
  • endpoint: 엔드포인트 URL.
  • disabledSSL: true 값은 SSL을 비활성화합니다.
  • s3ForcePathStyle: true 값은 경로 스타일 주소를 강제합니다.

Helm 기반 배포의 경우 Gitaly 차트에 대한 서버측 백업 문서를 참조하세요.

/etc/gitlab/gitlab.rb를 편집하고 go_cloud_url을 구성합니다:

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => '<your_access_key_id>',
    'AWS_SECRET_ACCESS_KEY' => '<your_secret_access_key>'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-east-1&endpoint=s3.example.com:9000&disableSSL=true&s3ForcePathStyle=true'
    }
}

/home/git/gitaly/config.toml을 편집하고 go_cloud_url을 구성합니다:

[backup]
go_cloud_url = "s3://<bucket>?region=us-east-1&endpoint=s3.example.com:9000&disableSSL=true&s3ForcePathStyle=true"