InfoGrab DocsInfoGrab Docs

Troubleshooting Gitaly

요약

다음 절에서는 Gitaly 오류에 대한 해결 방법을 제시합니다. Gitaly 타임아웃 설정과 gitaly/current 파일 파싱에 관한 안내도 함께 참고합니다. 관리자 액세스 권한이 있어야 합니다. 독립형 Gitaly 서버를 사용할 때는 완전한 호환성을 확보하기 위해 해당 서버가 GitLab과 같은 버전인지 확인해야 합니다.

다음 절에서는 Gitaly 오류에 대한 해결 방법을 제시합니다.

Gitaly 타임아웃 설정과 gitaly/current 파일 파싱에 관한 안내도 함께 참고합니다.

사전 요구 사항#

관리자 액세스 권한이 있어야 합니다.

독립형 Gitaly 서버를 사용할 때 버전 확인#

독립형 Gitaly 서버를 사용할 때는 완전한 호환성을 확보하기 위해 해당 서버가 GitLab과 같은 버전인지 확인해야 합니다.

  1. 오른쪽 위에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 Overview > Gitaly servers를 선택합니다.
  3. 모든 Gitaly 서버가 최신 상태로 표시되는지 확인합니다.

스토리지 리소스 세부 정보 확인#

Rails 콘솔에서 다음 명령을 실행하면 Gitaly 스토리지의 사용 가능 공간과 사용 중인 공간을 확인할 수 있습니다.

Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
# For Gitaly Cluster (Praefect)
Gitlab::GitalyClient::ServerService.new("<storage name>").disk_statistics

gitaly-debug 사용#

gitaly-debug 명령은 Gitaly와 Git 성능을 위한 "프로덕션 디버깅" 도구를 제공합니다. 프로덕션 엔지니어와 지원 엔지니어가 Gitaly 성능 문제를 조사하는 데 도움을 주기 위한 것입니다.

지원되는 하위 명령 목록을 확인하려면 다음을 실행해 gitaly-debug의 도움말 페이지를 봅니다.

gitaly-debug -h

문제 해결에 Git이 필요할 때 gitaly git 사용#

디버깅이나 테스트 목적으로 Gitaly와 동일한 Git 실행 환경에서 Git 명령을 실행하려면 gitaly git을 사용합니다. 버전 호환성을 보장하려면 gitaly git이 권장되는 방법입니다.

gitaly git은 모든 인수를 하위 Git 호출로 전달하며 Git이 지원하는 모든 형태의 입력을 지원합니다. gitaly git을 사용하려면 다음을 실행합니다.

sudo -u git -- /opt/gitlab/embedded/bin/gitaly git <git-command>

예를 들어 리포지터리의 작업 디렉터리에서 Linux 패키지 인스턴스의 Gitaly를 통해 git ls-tree를 실행하려면 다음과 같이 합니다.

sudo -u git -- /opt/gitlab/embedded/bin/gitaly git ls-tree --name-status HEAD

커밋, 푸시, 클론이 401을 반환하는 경우#

remote: GitLab: 401 Unauthorized

gitlab-secrets.json 파일을 GitLab 애플리케이션 노드와 동기화해야 합니다.

리포지터리 페이지의 500 및 fetching folder content 오류#

Fetching folder content 오류와, 경우에 따라 발생하는 500 오류는 GitLab과 Gitaly 사이의 연결 문제를 나타냅니다. 자세한 내용은 클라이언트 측 gRPC 로그를 확인합니다.

클라이언트 측 gRPC 로그#

Gitaly는 gRPC RPC 프레임워크를 사용합니다. Ruby gRPC 클라이언트에는 자체 로그 파일이 있으며, Gitaly 오류가 나타날 때 도움이 되는 정보가 들어 있을 수 있습니다. gRPC 클라이언트의 로그 수준은 GRPC_LOG_LEVEL 환경 변수로 제어할 수 있습니다. 기본 수준은 WARN입니다.

다음 방법으로 gRPC 트레이스를 실행할 수 있습니다.

sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check

이 명령이 failed to connect to all addresses 오류로 실패하면 SSL 또는 TLS 문제가 있는지 확인합니다.

/opt/gitlab/embedded/bin/openssl s_client -connect <gitaly-ipaddress>:<port> -verify_return_error

Verify return code 필드가 알려진 Linux 패키지 설치 구성 문제를 나타내는지 확인합니다.

openssl은 성공하지만 gitlab-rake gitlab:gitaly:check가 실패하면 Gitaly의 인증서 요구 사항을 확인합니다.

서버 측 gRPC 로그#

GODEBUG=http2debug 환경 변수로 Gitaly 자체에서도 gRPC 트레이싱을 활성화할 수 있습니다. Linux 패키지 설치에서 설정하려면 다음과 같이 합니다.

  1. gitlab.rb 파일에 다음을 추가합니다.

    gitaly['env'] = {
      "GODEBUG=http2debug" => "2"
    }
    
  2. GitLab을 재구성합니다.

Git 프로세스와 RPC 상관관계 파악#

특정 Git 프로세스를 어떤 Gitaly RPC가 생성했는지 확인해야 할 때가 있습니다.

한 가지 방법은 DEBUG 로깅을 사용하는 것입니다. 다만 이 방법은 미리 활성화해야 하고 생성되는 로그가 방대합니다.

더 가벼운 방법은 Git 프로세스의 환경을 PID로 확인해 CORRELATION_ID 변수를 살펴보는 것입니다.

PID=
sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=

이 방법은 git cat-file 프로세스에는 신뢰할 수 없습니다. Gitaly가 내부적으로 해당 프로세스를 풀에 두고 여러 RPC에서 재사용하기 때문입니다.

401 Unauthorized 오류로 리포지터리 변경이 실패하는 경우#

Gitaly를 자체 서버에서 실행하는데 다음 상황이 나타나는 경우입니다.

  • 사용자가 SSH와 HTTPS 모두로 리포지터리를 클론하고 가져올 수 있습니다.
  • 사용자가 리포지터리에 푸시할 수 없거나, 웹 UI에서 리포지터리를 변경하려고 할 때 401 Unauthorized 메시지를 받습니다.

Gitaly가 잘못된 시크릿 파일을 갖고 있어서 Gitaly 클라이언트와의 인증에 실패하는 것일 수 있습니다.

다음이 모두 사실인지 확인합니다.

  • 어떤 사용자가 이 Gitaly 서버의 어떤 리포지터리로 git push를 수행해도 401 Unauthorized 오류로 실패합니다.

    remote: GitLab: 401 Unauthorized
    To 
    ! [remote rejected] branch-name -> branch-name (pre-receive hook declined)
    error: failed to push some refs to ''
    
  • 어떤 사용자가 GitLab UI에서 리포지터리의 파일을 추가하거나 수정하면 즉시 빨간색 401 Unauthorized 배너와 함께 실패합니다.

  • 새 프로젝트를 만들고 README로 초기화하면 프로젝트는 생성되지만 README는 생성되지 않습니다.

  • Gitaly 클라이언트에서 로그를 tail하면서 오류를 재현하면 /api/v4/internal/allowed 엔드포인트에 도달할 때 401 오류가 발생합니다.

    # api_json.log
    {
      "time": "2019-07-18T00:30:14.967Z",
      "severity": "INFO",
      "duration": 0.57,
      "db": 0,
      "view": 0.57,
      "status": 401,
      "method": "POST",
      "path": "\/api\/v4\/internal\/allowed",
      "params": [
        {
          "key": "action",
          "value": "git-receive-pack"
        },
        {
          "key": "changes",
          "value": "REDACTED"
        },
        {
          "key": "gl_repository",
          "value": "REDACTED"
        },
        {
          "key": "project",
          "value": "\/path\/to\/project.git"
        },
        {
          "key": "protocol",
          "value": "web"
        },
        {
          "key": "env",
          "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}"
        },
        {
          "key": "user_id",
          "value": "2"
        },
        {
          "key": "secret_token",
          "value": "[FILTERED]"
        }
      ],
      "host": "gitlab.example.com",
      "ip": "REDACTED",
      "ua": "Ruby",
      "route": "\/api\/:version\/internal\/allowed",
      "queue_duration": 4.24,
      "gitaly_calls": 0,
      "gitaly_duration": 0,
      "correlation_id": "XPUZqTukaP3"
    }
    
    # nginx_access.log
    [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby"
    

이 문제를 해결하려면 Gitaly 서버의 gitlab-secrets.json 파일이 Gitaly 클라이언트의 파일과 일치하는지 확인합니다. 일치하지 않으면 Gitaly 서버의 시크릿 파일을 Gitaly 클라이언트와 같게 업데이트한 다음 재구성합니다.

모든 Gitaly 서버와 클라이언트의 gitlab-secrets.json 파일이 같다고 확인했다면, 애플리케이션이 다른 파일에서 이 시크릿을 가져오고 있을 수 있습니다. Gitaly 서버의 config.toml file이 사용 중인 시크릿 파일을 알려줍니다.

401 Unauthorized 및 JWT::VerificationError로 리포지터리 푸시가 실패하는 경우#

git push를 시도할 때 다음이 나타날 수 있습니다.

  • 401 Unauthorized 오류.

  • 서버 로그에 다음 내용.

    {
      ...
      "exception.class":"JWT::VerificationError",
      "exception.message":"Signature verification raised",
      ...
    }
    

이 오류 조합은 GitLab 서버는 업그레이드되었지만 Gitaly는 아직 업그레이드되지 않았을 때 발생합니다.

GitLab은 공유 시크릿 대신 JWT 토큰으로 GitLab Shell과 인증합니다. GitLab 서버를 업그레이드하기 전에 외부 Gitaly 서버를 업그레이드하는 것이 좋습니다.

deny updating a hidden ref 오류로 리포지터리 푸시가 실패하는 경우#

Gitaly에는 사용자가 업데이트할 수 없는 읽기 전용 내부 GitLab 참조가 있습니다. git push --mirror로 내부 참조를 업데이트하려고 하면 Git은 거부 오류 deny updating a hidden ref를 반환합니다.

다음 참조는 읽기 전용입니다.

  • refs/environments/
  • refs/keep-around/
  • refs/merge-requests/
  • refs/pipelines/

브랜치와 태그만 미러 푸시하고 보호된 참조를 미러 푸시하지 않으려면 다음을 실행합니다.

git push --force-with-lease origin 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*'

관리자가 푸시하려는 다른 네임스페이스도 추가 refspec으로 함께 포함할 수 있습니다.

명령줄 도구가 Gitaly에 연결할 수 없는 경우#

다음과 같은 경우 gRPC가 Gitaly 서버에 도달할 수 없습니다.

  • 명령줄 도구로 Gitaly 서버에 연결할 수 없습니다.
  • 특정 작업에서 14: Connect Failed 오류 메시지가 발생합니다.

TCP로 Gitaly에 도달할 수 있는지 확인합니다.

sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]

TCP 연결 결과는 다음과 같이 해석합니다.

  • 실패하면 네트워크 설정과 방화벽 규칙을 확인합니다.
  • 성공하면 네트워크와 방화벽 규칙이 올바릅니다.

Bash 같은 명령줄 환경에서 프록시 서버를 사용하면 gRPC 트래픽에 간섭이 발생할 수 있습니다.

Bash 또는 호환되는 명령줄 환경을 사용하는 경우 다음 명령을 실행해 프록시 서버가 구성되어 있는지 확인합니다.

echo $http_proxy
echo $https_proxy

두 변수 중 하나에 값이 있으면 Gitaly CLI 연결이 Gitaly에 연결할 수 없는 프록시를 거쳐 라우팅되고 있을 수 있습니다.

프록시 설정을 제거하려면 값이 있던 변수에 따라 다음 명령을 실행합니다.

unset http_proxy
unset https_proxy

리포지터리에 액세스할 때 Gitaly 또는 Praefect 로그에 권한 거부 오류가 나타나는 경우#

Gitaly와 Praefect 로그에 다음 내용이 나타날 수 있습니다.

{
  ...
  "error":"rpc error: code = PermissionDenied desc = permission denied: token has expired",
  "grpc.code":"PermissionDenied",
  "grpc.meta.client_name":"gitlab-web",
  "grpc.request.fullMethod":"/gitaly.ServerService/ServerInfo",
  "level":"warning",
  "msg":"finished unary call with code PermissionDenied",
  ...
}

로그에 나타나는 이 정보는 gRPC 호출의 오류 응답 코드입니다.

이 오류는 Gitaly 인증 토큰이 올바르게 설정되어 있는데도 발생할 수 있으며, 이 경우 Gitaly 서버에 클록 드리프트가 발생한 것일 가능성이 높습니다. Gitaly로 전송되는 인증 토큰에는 타임스탬프가 포함됩니다. Gitaly는 그 타임스탬프가 Gitaly 서버 시간과 60초 이내일 때만 유효하다고 판단합니다.

Gitaly 클라이언트와 서버의 시간이 동기화되어 있는지 확인하고, Network Time Protocol(NTP) 시간 서버를 사용해 동기화를 유지합니다.

재구성 후 Gitaly가 새 주소에서 수신 대기하지 않는 경우#

gitaly['configuration'][:listen_addr] 또는 gitaly['configuration'][:prometheus_listen_addr] 값을 업데이트할 때 sudo gitlab-ctl reconfigure를 실행한 뒤에도 Gitaly가 이전 주소에서 계속 수신 대기할 수 있습니다.

이 경우 sudo gitlab-ctl restart를 실행하면 문제가 해결됩니다. 이 이슈가 해결되었으므로 더 이상 이 작업이 필요하지 않습니다.

헬스 체크 경고#

/var/log/gitlab/praefect/current에 나타나는 다음 경고는 무시할 수 있습니다.

"error":"full method name not found: /grpc.health.v1.Health/Check",
"msg":"error when looking up method info"

파일을 찾을 수 없음 오류#

/var/log/gitlab/gitaly/current에 나타나는 다음 오류는 무시할 수 있습니다. 이 오류는 GitLab Rails 애플리케이션이 리포지터리에 없는 특정 파일을 확인하기 때문에 발생합니다.

"error":"not found: .gitlab/route-map.yml"
"error":"not found: Dockerfile"
"error":"not found: .gitlab-ci.yml"

Dynatrace가 활성화된 경우 Git 푸시가 느린 문제#

Dynatrace 때문에 sudo -u git -- /opt/gitlab/embedded/bin/gitaly-hooks 참조 트랜잭션 훅이 시작하고 종료하는 데 몇 초가 걸릴 수 있습니다. 사용자가 푸시할 때 gitaly-hooks가 두 번 실행되므로 상당한 지연이 발생합니다.

Dynatrace는 .so 파일을 동적으로 로드해 바이너리를 계측하는 것으로 보이며, 이 때문에 비교적 수명이 짧은 gitaly-hooks 프로세스의 성능이 나빠집니다.

Dynatrace가 활성화된 상태에서 Git 푸시가 너무 느리면 Dynatrace를 비활성화합니다. .so 파일이 로드되지 않도록 Gitaly가 실행되는 시스템에서 Dynatrace를 완전히 제거해야 할 수도 있습니다.

gitaly check가 401 상태 코드로 실패하는 경우#

Gitaly가 내부 GitLab API에 액세스할 수 없으면 gitaly check가 401 상태 코드로 실패할 수 있습니다.

이를 해결하는 한 가지 방법은 gitlab.rb에서 gitlab_rails['internal_api_url']로 구성한 GitLab 내부 API URL 항목이 올바른지 확인하는 것입니다.

Gitaly TLS를 사용할 때 새 머지 리퀘스트의 변경 사항(diff)이 로드되지 않는 경우#

TLS를 사용하는 Gitaly를 활성화한 뒤 새 머지 리퀘스트의 변경 사항(diff)이 생성되지 않고 GitLab에 다음 메시지가 표시됩니다.

Building your merge request... This page will update when the build is complete

Gitaly는 일부 작업을 완료하기 위해 자기 자신에 연결할 수 있어야 합니다. Gitaly 서버가 Gitaly 인증서를 신뢰하지 않으면 머지 리퀘스트 diff를 생성할 수 없습니다.

Gitaly가 자기 자신에 연결할 수 없으면 Gitaly 로그에 다음과 같은 메시지가 표시됩니다.

{
   "level":"warning",
   "msg":"[core] [Channel #16 SubChannel #17] grpc: addrConn.createTransport failed to connect to {Addr: \"ext-gitaly.example.com:9999\", ServerName: \"ext-gitaly.example.com:9999\", }. Err: connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate signed by unknown authority\"",
   "pid":820,
   "system":"system",
   "time":"2023-11-06T05:40:04.169Z"
}
{
   "level":"info",
   "msg":"[core] [Server #3] grpc: Server.Serve failed to create ServerTransport: connection error: desc = \"ServerHandshake(\\\"x.x.x.x:x\\\") failed: wrapped server handshake: remote error: tls: bad certificate\"",
   "pid":820,
   "system":"system",
   "time":"2023-11-06T05:40:04.169Z"
}

이 문제를 해결하려면 Gitaly 서버의 /etc/gitlab/trusted-certs 폴더에 Gitaly 인증서를 추가했는지 확인하고 다음을 수행합니다.

  1. 인증서가 심링크되도록 GitLab을 재구성합니다
  2. Gitaly 프로세스가 인증서를 로드하도록 sudo gitlab-ctl restart gitaly로 Gitaly를 수동으로 재시작합니다.

noexec 파일 시스템에 저장된 프로세스를 Gitaly가 포크하지 못하는 경우#

마운트 지점(예: /var)에 noexec 옵션을 적용하면 Gitaly가 프로세스 포크와 관련된 permission denied 오류를 발생시킵니다. 예를 들면 다음과 같습니다.

fork/exec /var/opt/gitlab/gitaly/run/gitaly-2057/gitaly-git2go: permission denied

이를 해결하려면 파일 시스템 마운트에서 noexec 옵션을 제거합니다. 대안으로 Gitaly 런타임 디렉터리를 변경할 수 있습니다.

  1. /etc/gitlab/gitlab.rb에 gitaly['runtime_dir'] = ''를 추가하고 noexec가 설정되지 않은 위치를 지정합니다.
  2. sudo gitlab-ctl reconfigure를 실행합니다.

invalid argument 또는 invalid data로 커밋 서명이 실패하는 경우#

커밋 서명이 다음 오류 중 하나로 실패하는 경우입니다.

  • invalid argument: signing key is encrypted
  • invalid data: tag byte does not have MSB set

이 오류는 Gitaly 커밋 서명이 헤드리스이고 특정 사용자와 연결되지 않기 때문에 발생합니다. GPG 서명 키는 패스프레이즈 없이 생성해야 하거나, 내보내기 전에 패스프레이즈를 제거해야 합니다.

Gitaly 프로파일링#

Gitaly는 Go에 내장된 여러 성능 프로파일링 도구를 Prometheus 수신 포트에 노출합니다. 예를 들어 Prometheus가 GitLab 서버의 9236 포트에서 수신 대기하는 경우는 다음과 같습니다.

  • 실행 중인 goroutines 목록과 백트레이스를 가져옵니다.

    curl --output goroutines.txt "http://<gitaly_server>:9236/debug/pprof/goroutine?debug=2"
    
  • 30초 동안 CPU 프로파일을 실행합니다.

    curl --output cpu.bin "http://<gitaly_server>:9236/debug/pprof/profile"
    
  • 힙 메모리 사용량을 프로파일링합니다.

    curl --output heap.bin "http://<gitaly_server>:9236/debug/pprof/heap"
    
  • 5초 동안 실행 트레이스를 기록합니다. 실행하는 동안 Gitaly 성능에 영향을 줍니다.

    curl --output trace.bin "http://<gitaly_server>:9236/debug/pprof/trace?seconds=5"
    

go가 설치된 호스트에서는 CPU 프로파일과 힙 프로파일을 브라우저에서 볼 수 있습니다.

go tool pprof -http=:8001 cpu.bin
go tool pprof -http=:8001 heap.bin

실행 트레이스는 다음을 실행해 볼 수 있습니다.

go tool trace heap.bin

Git 작업 프로파일링#

히스토리
Feature flag

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

Git 작업에 관한 추가 정보를 Gitaly 로그로 보내면 Gitaly가 수행하는 Git 작업을 프로파일링할 수 있습니다. 이 정보를 통해 사용자는 성능 최적화, 디버깅, 일반적인 텔레메트리 수집에 관해 더 깊이 파악할 수 있습니다. 자세한 내용은 Git Trace2 API 참조를 참고합니다.

시스템 과부하를 방지하기 위해 추가 정보 로깅에는 속도 제한이 적용됩니다. 속도 제한을 초과하면 트레이스를 건너뜁니다. 다만 속도가 정상 상태로 돌아오면 트레이스가 다시 자동으로 처리됩니다. 속도 제한은 시스템을 안정적으로 유지하고 과도한 트레이스 처리로 인한 악영향을 방지합니다.

GitLab 복원 후 리포지터리가 비어 있는 것으로 표시되는 경우#

보안 강화를 위해 fapolicyd를 사용할 때 GitLab은 GitLab 백업 파일에서 복원이 성공했다고 보고하지만 다음 현상이 나타날 수 있습니다.

  • 리포지터리가 비어 있는 것으로 표시됩니다.

  • 새 파일을 만들면 다음과 유사한 오류가 발생합니다.

    13:commit: commit: starting process [/var/opt/gitlab/gitaly/run/gitaly-5428/gitaly-git2go -log-format json -log-level -correlation-id
    01GP1383JV6JD6MQJBH2E1RT03 -enabled-feature-flags -disabled-feature-flags commit]: fork/exec /var/opt/gitlab/gitaly/run/gitaly-5428/gitaly-git2go: operation not permitted.
    
  • Gitaly 로그에 다음과 유사한 오류가 포함될 수 있습니다.

     "error": "exit status 128, stderr: \"fatal: cannot exec '/var/opt/gitlab/gitaly/run/gitaly-5428/hooks-1277154941.d/reference-transaction':
    
      Operation not permitted\\nfatal: cannot exec '/var/opt/gitlab/gitaly/run/gitaly-5428/hooks-1277154941.d/reference-transaction': Operation
      not permitted\\nfatal: ref updates aborted by hook\\n\"",
     "grpc.code": "Internal",
     "grpc.meta.deadline_type": "none",
     "grpc.meta.method_type": "client_stream",
     "grpc.method": "FetchBundle",
     "grpc.request.fullMethod": "/gitaly.RepositoryService/FetchBundle",
    ...
    

현재 규칙에 따라 fapolicyd가 실행을 거부하고 있는지 판단하는 데 디버그 모드를 사용할 수 있습니다.

fapolicyd가 실행을 거부하고 있다면 다음을 고려합니다.

  1. fapolicyd 구성에서 /var/opt/gitlab/gitaly의 모든 실행 파일을 허용합니다.

    allow perm=any all : ftype=application/x-executable dir=/var/opt/gitlab/gitaly/
    
  2. 서비스를 재시작합니다.

    sudo systemctl restart fapolicyd
    
    sudo gitlab-ctl restart gitaly
    

fapolicyd가 활성화된 RHEL 인스턴스에 푸시할 때 발생하는 Pre-receive hook declined 오류#

fapolicyd가 활성화된 RHEL 기반 인스턴스에 푸시할 때 Pre-receive hook declined 오류가 발생할 수 있습니다. fapolicyd가 Gitaly 바이너리의 실행을 차단할 수 있기 때문입니다. 이 문제를 해결하려면 다음 중 하나를 수행합니다.

  • fapolicyd를 비활성화합니다.
  • fapolicyd를 활성화한 상태로 Gitaly 바이너리의 실행을 허용하는 fapolicyd 규칙을 만듭니다.

Gitaly 바이너리 실행을 허용하는 규칙을 만들려면 다음과 같이 합니다.

  1. /etc/fapolicyd/rules.d/89-gitlab.rules 파일을 만듭니다.

  2. 파일에 다음을 입력합니다.

    allow perm=any all : ftype=application/x-executable dir=/var/opt/gitlab/gitaly/
    
  3. 서비스를 재시작합니다.

    systemctl restart fapolicyd
    

새 규칙은 데몬이 재시작된 후에 적용됩니다.

중복 경로가 있는 스토리지를 제거한 후 리포지터리 업데이트#

히스토리
  • GitLab 17.1에서 Rake 태스크 gitlab:gitaly:update_removed_storage_projects가 도입되었습니다.

GitLab 17.0에서 중복 경로로 스토리지를 구성하는 기능이 제거되었습니다. 따라서 gitaly 구성에서 중복 스토리지 구성을 제거해야 할 수 있습니다.

Warning

이 Rake 태스크는 이전 스토리지와 새 스토리지가 같은 Gitaly 서버에서 같은 디스크 경로를 공유할 때만 사용합니다. 다른 상황에서 이 Rake 태스크를 사용하면 리포지터리를 사용할 수 없게 됩니다. 그 외 모든 상황에서 스토리지 간에 프로젝트를 이전할 때는 프로젝트 리포지터리 스토리지 이동 API를 사용합니다.

다른 스토리지와 같은 경로를 사용한 스토리지를 Gitaly 구성에서 제거할 때는 이전 스토리지에 연결된 프로젝트를 새 스토리지로 다시 할당해야 합니다.

예를 들어 다음과 유사한 구성이 있을 수 있습니다.

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

구성에서 duplicate-path를 제거하는 경우, 여기에 할당된 프로젝트를 대신 default에 연결하기 위해 다음 Rake 태스크를 실행합니다.

sudo gitlab-rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]"
sudo -u git -H bundle exec rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]" RAILS_ENV=production

오류: ZIP 파일로 리포지터리를 다운로드할 때 발생하는 fatal: deflate error (0)\n#

Git 버전 2.51에서 수정된 Git 버그(이슈 575) 때문에 리포지터리를 ZIP 아카이브로 다운로드할 때 경우에 따라 불완전한 ZIP 파일이 생성됩니다. 이 경우 Gitaly 로그에 다음 오류가 표시됩니다.

  "msg": "fatal: deflate error (0)\n",

이 문제를 해결하려면 수정된 Git 버전을 사용하는 GitLab 및 Gitaly 버전으로 업그레이드합니다. 업그레이드할 수 없다면 다음 단계로 문제를 우회합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. core.bigFileThreshold를 가장 큰 블롭 크기보다 크게 구성합니다(기본값은 50m).

      gitaly['configuration'] = {
       # ... your existing configuration ...
       git: {
         config: [
           # ... any existing git config entries ...
           {
             key: 'core.bigFileThreshold',
             value: '500m'
           }
         ]
       }
     }
    
  3. gitlab-ctl reconfigure를 실행합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. values.yml 파일에서 core.bigFileThreshold를 구성합니다.

    git:
      config:
        - key: "core.bigFileThreshold"
          value: "500m"
    
  3. 구성을 업데이트하려면 helm upgrade <gitlab_release> gitlab/gitlab -f values.yaml을 실행합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. /home/git/gitaly/config.toml에서 core.bigFileThreshold를 구성합니다.

    # [[git.config]]
    # key = core.bigFileThreshold
    # value = 500m
    

Troubleshooting Gitaly

GitLab v19.4
Tier: Free, Premium, Ultimate
Offering: GitLab Self-Managed
원문 보기

요약

다음 절에서는 Gitaly 오류에 대한 해결 방법을 제시합니다. Gitaly 타임아웃 설정과 gitaly/current 파일 파싱에 관한 안내도 함께 참고합니다. 관리자 액세스 권한이 있어야 합니다. 독립형 Gitaly 서버를 사용할 때는 완전한 호환성을 확보하기 위해 해당 서버가 GitLab과 같은 버전인지 확인해야 합니다.

다음 절에서는 Gitaly 오류에 대한 해결 방법을 제시합니다.

Gitaly 타임아웃 설정과 gitaly/current 파일 파싱에 관한 안내도 함께 참고합니다.

사전 요구 사항#

관리자 액세스 권한이 있어야 합니다.

독립형 Gitaly 서버를 사용할 때 버전 확인#

독립형 Gitaly 서버를 사용할 때는 완전한 호환성을 확보하기 위해 해당 서버가 GitLab과 같은 버전인지 확인해야 합니다.

  1. 오른쪽 위에서 Admin을 선택합니다.
  2. 왼쪽 사이드바에서 Overview > Gitaly servers를 선택합니다.
  3. 모든 Gitaly 서버가 최신 상태로 표시되는지 확인합니다.

스토리지 리소스 세부 정보 확인#

Rails 콘솔에서 다음 명령을 실행하면 Gitaly 스토리지의 사용 가능 공간과 사용 중인 공간을 확인할 수 있습니다.

Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
# For Gitaly Cluster (Praefect)
Gitlab::GitalyClient::ServerService.new("<storage name>").disk_statistics

gitaly-debug 사용#

gitaly-debug 명령은 Gitaly와 Git 성능을 위한 "프로덕션 디버깅" 도구를 제공합니다. 프로덕션 엔지니어와 지원 엔지니어가 Gitaly 성능 문제를 조사하는 데 도움을 주기 위한 것입니다.

지원되는 하위 명령 목록을 확인하려면 다음을 실행해 gitaly-debug의 도움말 페이지를 봅니다.

gitaly-debug -h

문제 해결에 Git이 필요할 때 gitaly git 사용#

디버깅이나 테스트 목적으로 Gitaly와 동일한 Git 실행 환경에서 Git 명령을 실행하려면 gitaly git을 사용합니다. 버전 호환성을 보장하려면 gitaly git이 권장되는 방법입니다.

gitaly git은 모든 인수를 하위 Git 호출로 전달하며 Git이 지원하는 모든 형태의 입력을 지원합니다. gitaly git을 사용하려면 다음을 실행합니다.

sudo -u git -- /opt/gitlab/embedded/bin/gitaly git <git-command>

예를 들어 리포지터리의 작업 디렉터리에서 Linux 패키지 인스턴스의 Gitaly를 통해 git ls-tree를 실행하려면 다음과 같이 합니다.

sudo -u git -- /opt/gitlab/embedded/bin/gitaly git ls-tree --name-status HEAD

커밋, 푸시, 클론이 401을 반환하는 경우#

remote: GitLab: 401 Unauthorized

gitlab-secrets.json 파일을 GitLab 애플리케이션 노드와 동기화해야 합니다.

리포지터리 페이지의 500 및 fetching folder content 오류#

Fetching folder content 오류와, 경우에 따라 발생하는 500 오류는 GitLab과 Gitaly 사이의 연결 문제를 나타냅니다. 자세한 내용은 클라이언트 측 gRPC 로그를 확인합니다.

클라이언트 측 gRPC 로그#

Gitaly는 gRPC RPC 프레임워크를 사용합니다. Ruby gRPC 클라이언트에는 자체 로그 파일이 있으며, Gitaly 오류가 나타날 때 도움이 되는 정보가 들어 있을 수 있습니다. gRPC 클라이언트의 로그 수준은 GRPC_LOG_LEVEL 환경 변수로 제어할 수 있습니다. 기본 수준은 WARN입니다.

다음 방법으로 gRPC 트레이스를 실행할 수 있습니다.

sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check

이 명령이 failed to connect to all addresses 오류로 실패하면 SSL 또는 TLS 문제가 있는지 확인합니다.

/opt/gitlab/embedded/bin/openssl s_client -connect <gitaly-ipaddress>:<port> -verify_return_error

Verify return code 필드가 알려진 Linux 패키지 설치 구성 문제를 나타내는지 확인합니다.

openssl은 성공하지만 gitlab-rake gitlab:gitaly:check가 실패하면 Gitaly의 인증서 요구 사항을 확인합니다.

서버 측 gRPC 로그#

GODEBUG=http2debug 환경 변수로 Gitaly 자체에서도 gRPC 트레이싱을 활성화할 수 있습니다. Linux 패키지 설치에서 설정하려면 다음과 같이 합니다.

  1. gitlab.rb 파일에 다음을 추가합니다.

    gitaly['env'] = {
      "GODEBUG=http2debug" => "2"
    }
    
  2. GitLab을 재구성합니다.

Git 프로세스와 RPC 상관관계 파악#

특정 Git 프로세스를 어떤 Gitaly RPC가 생성했는지 확인해야 할 때가 있습니다.

한 가지 방법은 DEBUG 로깅을 사용하는 것입니다. 다만 이 방법은 미리 활성화해야 하고 생성되는 로그가 방대합니다.

더 가벼운 방법은 Git 프로세스의 환경을 PID로 확인해 CORRELATION_ID 변수를 살펴보는 것입니다.

PID=
sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=

이 방법은 git cat-file 프로세스에는 신뢰할 수 없습니다. Gitaly가 내부적으로 해당 프로세스를 풀에 두고 여러 RPC에서 재사용하기 때문입니다.

401 Unauthorized 오류로 리포지터리 변경이 실패하는 경우#

Gitaly를 자체 서버에서 실행하는데 다음 상황이 나타나는 경우입니다.

  • 사용자가 SSH와 HTTPS 모두로 리포지터리를 클론하고 가져올 수 있습니다.
  • 사용자가 리포지터리에 푸시할 수 없거나, 웹 UI에서 리포지터리를 변경하려고 할 때 401 Unauthorized 메시지를 받습니다.

Gitaly가 잘못된 시크릿 파일을 갖고 있어서 Gitaly 클라이언트와의 인증에 실패하는 것일 수 있습니다.

다음이 모두 사실인지 확인합니다.

  • 어떤 사용자가 이 Gitaly 서버의 어떤 리포지터리로 git push를 수행해도 401 Unauthorized 오류로 실패합니다.

    remote: GitLab: 401 Unauthorized
    To 
    ! [remote rejected] branch-name -> branch-name (pre-receive hook declined)
    error: failed to push some refs to ''
    
  • 어떤 사용자가 GitLab UI에서 리포지터리의 파일을 추가하거나 수정하면 즉시 빨간색 401 Unauthorized 배너와 함께 실패합니다.

  • 새 프로젝트를 만들고 README로 초기화하면 프로젝트는 생성되지만 README는 생성되지 않습니다.

  • Gitaly 클라이언트에서 로그를 tail하면서 오류를 재현하면 /api/v4/internal/allowed 엔드포인트에 도달할 때 401 오류가 발생합니다.

    # api_json.log
    {
      "time": "2019-07-18T00:30:14.967Z",
      "severity": "INFO",
      "duration": 0.57,
      "db": 0,
      "view": 0.57,
      "status": 401,
      "method": "POST",
      "path": "\/api\/v4\/internal\/allowed",
      "params": [
        {
          "key": "action",
          "value": "git-receive-pack"
        },
        {
          "key": "changes",
          "value": "REDACTED"
        },
        {
          "key": "gl_repository",
          "value": "REDACTED"
        },
        {
          "key": "project",
          "value": "\/path\/to\/project.git"
        },
        {
          "key": "protocol",
          "value": "web"
        },
        {
          "key": "env",
          "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}"
        },
        {
          "key": "user_id",
          "value": "2"
        },
        {
          "key": "secret_token",
          "value": "[FILTERED]"
        }
      ],
      "host": "gitlab.example.com",
      "ip": "REDACTED",
      "ua": "Ruby",
      "route": "\/api\/:version\/internal\/allowed",
      "queue_duration": 4.24,
      "gitaly_calls": 0,
      "gitaly_duration": 0,
      "correlation_id": "XPUZqTukaP3"
    }
    
    # nginx_access.log
    [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby"
    

이 문제를 해결하려면 Gitaly 서버의 gitlab-secrets.json 파일이 Gitaly 클라이언트의 파일과 일치하는지 확인합니다. 일치하지 않으면 Gitaly 서버의 시크릿 파일을 Gitaly 클라이언트와 같게 업데이트한 다음 재구성합니다.

모든 Gitaly 서버와 클라이언트의 gitlab-secrets.json 파일이 같다고 확인했다면, 애플리케이션이 다른 파일에서 이 시크릿을 가져오고 있을 수 있습니다. Gitaly 서버의 config.toml file이 사용 중인 시크릿 파일을 알려줍니다.

401 Unauthorized 및 JWT::VerificationError로 리포지터리 푸시가 실패하는 경우#

git push를 시도할 때 다음이 나타날 수 있습니다.

  • 401 Unauthorized 오류.

  • 서버 로그에 다음 내용.

    {
      ...
      "exception.class":"JWT::VerificationError",
      "exception.message":"Signature verification raised",
      ...
    }
    

이 오류 조합은 GitLab 서버는 업그레이드되었지만 Gitaly는 아직 업그레이드되지 않았을 때 발생합니다.

GitLab은 공유 시크릿 대신 JWT 토큰으로 GitLab Shell과 인증합니다. GitLab 서버를 업그레이드하기 전에 외부 Gitaly 서버를 업그레이드하는 것이 좋습니다.

deny updating a hidden ref 오류로 리포지터리 푸시가 실패하는 경우#

Gitaly에는 사용자가 업데이트할 수 없는 읽기 전용 내부 GitLab 참조가 있습니다. git push --mirror로 내부 참조를 업데이트하려고 하면 Git은 거부 오류 deny updating a hidden ref를 반환합니다.

다음 참조는 읽기 전용입니다.

  • refs/environments/
  • refs/keep-around/
  • refs/merge-requests/
  • refs/pipelines/

브랜치와 태그만 미러 푸시하고 보호된 참조를 미러 푸시하지 않으려면 다음을 실행합니다.

git push --force-with-lease origin 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*'

관리자가 푸시하려는 다른 네임스페이스도 추가 refspec으로 함께 포함할 수 있습니다.

명령줄 도구가 Gitaly에 연결할 수 없는 경우#

다음과 같은 경우 gRPC가 Gitaly 서버에 도달할 수 없습니다.

  • 명령줄 도구로 Gitaly 서버에 연결할 수 없습니다.
  • 특정 작업에서 14: Connect Failed 오류 메시지가 발생합니다.

TCP로 Gitaly에 도달할 수 있는지 확인합니다.

sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]

TCP 연결 결과는 다음과 같이 해석합니다.

  • 실패하면 네트워크 설정과 방화벽 규칙을 확인합니다.
  • 성공하면 네트워크와 방화벽 규칙이 올바릅니다.

Bash 같은 명령줄 환경에서 프록시 서버를 사용하면 gRPC 트래픽에 간섭이 발생할 수 있습니다.

Bash 또는 호환되는 명령줄 환경을 사용하는 경우 다음 명령을 실행해 프록시 서버가 구성되어 있는지 확인합니다.

echo $http_proxy
echo $https_proxy

두 변수 중 하나에 값이 있으면 Gitaly CLI 연결이 Gitaly에 연결할 수 없는 프록시를 거쳐 라우팅되고 있을 수 있습니다.

프록시 설정을 제거하려면 값이 있던 변수에 따라 다음 명령을 실행합니다.

unset http_proxy
unset https_proxy

리포지터리에 액세스할 때 Gitaly 또는 Praefect 로그에 권한 거부 오류가 나타나는 경우#

Gitaly와 Praefect 로그에 다음 내용이 나타날 수 있습니다.

{
  ...
  "error":"rpc error: code = PermissionDenied desc = permission denied: token has expired",
  "grpc.code":"PermissionDenied",
  "grpc.meta.client_name":"gitlab-web",
  "grpc.request.fullMethod":"/gitaly.ServerService/ServerInfo",
  "level":"warning",
  "msg":"finished unary call with code PermissionDenied",
  ...
}

로그에 나타나는 이 정보는 gRPC 호출의 오류 응답 코드입니다.

이 오류는 Gitaly 인증 토큰이 올바르게 설정되어 있는데도 발생할 수 있으며, 이 경우 Gitaly 서버에 클록 드리프트가 발생한 것일 가능성이 높습니다. Gitaly로 전송되는 인증 토큰에는 타임스탬프가 포함됩니다. Gitaly는 그 타임스탬프가 Gitaly 서버 시간과 60초 이내일 때만 유효하다고 판단합니다.

Gitaly 클라이언트와 서버의 시간이 동기화되어 있는지 확인하고, Network Time Protocol(NTP) 시간 서버를 사용해 동기화를 유지합니다.

재구성 후 Gitaly가 새 주소에서 수신 대기하지 않는 경우#

gitaly['configuration'][:listen_addr] 또는 gitaly['configuration'][:prometheus_listen_addr] 값을 업데이트할 때 sudo gitlab-ctl reconfigure를 실행한 뒤에도 Gitaly가 이전 주소에서 계속 수신 대기할 수 있습니다.

이 경우 sudo gitlab-ctl restart를 실행하면 문제가 해결됩니다. 이 이슈가 해결되었으므로 더 이상 이 작업이 필요하지 않습니다.

헬스 체크 경고#

/var/log/gitlab/praefect/current에 나타나는 다음 경고는 무시할 수 있습니다.

"error":"full method name not found: /grpc.health.v1.Health/Check",
"msg":"error when looking up method info"

파일을 찾을 수 없음 오류#

/var/log/gitlab/gitaly/current에 나타나는 다음 오류는 무시할 수 있습니다. 이 오류는 GitLab Rails 애플리케이션이 리포지터리에 없는 특정 파일을 확인하기 때문에 발생합니다.

"error":"not found: .gitlab/route-map.yml"
"error":"not found: Dockerfile"
"error":"not found: .gitlab-ci.yml"

Dynatrace가 활성화된 경우 Git 푸시가 느린 문제#

Dynatrace 때문에 sudo -u git -- /opt/gitlab/embedded/bin/gitaly-hooks 참조 트랜잭션 훅이 시작하고 종료하는 데 몇 초가 걸릴 수 있습니다. 사용자가 푸시할 때 gitaly-hooks가 두 번 실행되므로 상당한 지연이 발생합니다.

Dynatrace는 .so 파일을 동적으로 로드해 바이너리를 계측하는 것으로 보이며, 이 때문에 비교적 수명이 짧은 gitaly-hooks 프로세스의 성능이 나빠집니다.

Dynatrace가 활성화된 상태에서 Git 푸시가 너무 느리면 Dynatrace를 비활성화합니다. .so 파일이 로드되지 않도록 Gitaly가 실행되는 시스템에서 Dynatrace를 완전히 제거해야 할 수도 있습니다.

gitaly check가 401 상태 코드로 실패하는 경우#

Gitaly가 내부 GitLab API에 액세스할 수 없으면 gitaly check가 401 상태 코드로 실패할 수 있습니다.

이를 해결하는 한 가지 방법은 gitlab.rb에서 gitlab_rails['internal_api_url']로 구성한 GitLab 내부 API URL 항목이 올바른지 확인하는 것입니다.

Gitaly TLS를 사용할 때 새 머지 리퀘스트의 변경 사항(diff)이 로드되지 않는 경우#

TLS를 사용하는 Gitaly를 활성화한 뒤 새 머지 리퀘스트의 변경 사항(diff)이 생성되지 않고 GitLab에 다음 메시지가 표시됩니다.

Building your merge request... This page will update when the build is complete

Gitaly는 일부 작업을 완료하기 위해 자기 자신에 연결할 수 있어야 합니다. Gitaly 서버가 Gitaly 인증서를 신뢰하지 않으면 머지 리퀘스트 diff를 생성할 수 없습니다.

Gitaly가 자기 자신에 연결할 수 없으면 Gitaly 로그에 다음과 같은 메시지가 표시됩니다.

{
   "level":"warning",
   "msg":"[core] [Channel #16 SubChannel #17] grpc: addrConn.createTransport failed to connect to {Addr: \"ext-gitaly.example.com:9999\", ServerName: \"ext-gitaly.example.com:9999\", }. Err: connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate signed by unknown authority\"",
   "pid":820,
   "system":"system",
   "time":"2023-11-06T05:40:04.169Z"
}
{
   "level":"info",
   "msg":"[core] [Server #3] grpc: Server.Serve failed to create ServerTransport: connection error: desc = \"ServerHandshake(\\\"x.x.x.x:x\\\") failed: wrapped server handshake: remote error: tls: bad certificate\"",
   "pid":820,
   "system":"system",
   "time":"2023-11-06T05:40:04.169Z"
}

이 문제를 해결하려면 Gitaly 서버의 /etc/gitlab/trusted-certs 폴더에 Gitaly 인증서를 추가했는지 확인하고 다음을 수행합니다.

  1. 인증서가 심링크되도록 GitLab을 재구성합니다
  2. Gitaly 프로세스가 인증서를 로드하도록 sudo gitlab-ctl restart gitaly로 Gitaly를 수동으로 재시작합니다.

noexec 파일 시스템에 저장된 프로세스를 Gitaly가 포크하지 못하는 경우#

마운트 지점(예: /var)에 noexec 옵션을 적용하면 Gitaly가 프로세스 포크와 관련된 permission denied 오류를 발생시킵니다. 예를 들면 다음과 같습니다.

fork/exec /var/opt/gitlab/gitaly/run/gitaly-2057/gitaly-git2go: permission denied

이를 해결하려면 파일 시스템 마운트에서 noexec 옵션을 제거합니다. 대안으로 Gitaly 런타임 디렉터리를 변경할 수 있습니다.

  1. /etc/gitlab/gitlab.rb에 gitaly['runtime_dir'] = ''를 추가하고 noexec가 설정되지 않은 위치를 지정합니다.
  2. sudo gitlab-ctl reconfigure를 실행합니다.

invalid argument 또는 invalid data로 커밋 서명이 실패하는 경우#

커밋 서명이 다음 오류 중 하나로 실패하는 경우입니다.

  • invalid argument: signing key is encrypted
  • invalid data: tag byte does not have MSB set

이 오류는 Gitaly 커밋 서명이 헤드리스이고 특정 사용자와 연결되지 않기 때문에 발생합니다. GPG 서명 키는 패스프레이즈 없이 생성해야 하거나, 내보내기 전에 패스프레이즈를 제거해야 합니다.

Gitaly 프로파일링#

Gitaly는 Go에 내장된 여러 성능 프로파일링 도구를 Prometheus 수신 포트에 노출합니다. 예를 들어 Prometheus가 GitLab 서버의 9236 포트에서 수신 대기하는 경우는 다음과 같습니다.

  • 실행 중인 goroutines 목록과 백트레이스를 가져옵니다.

    curl --output goroutines.txt "http://<gitaly_server>:9236/debug/pprof/goroutine?debug=2"
    
  • 30초 동안 CPU 프로파일을 실행합니다.

    curl --output cpu.bin "http://<gitaly_server>:9236/debug/pprof/profile"
    
  • 힙 메모리 사용량을 프로파일링합니다.

    curl --output heap.bin "http://<gitaly_server>:9236/debug/pprof/heap"
    
  • 5초 동안 실행 트레이스를 기록합니다. 실행하는 동안 Gitaly 성능에 영향을 줍니다.

    curl --output trace.bin "http://<gitaly_server>:9236/debug/pprof/trace?seconds=5"
    

go가 설치된 호스트에서는 CPU 프로파일과 힙 프로파일을 브라우저에서 볼 수 있습니다.

go tool pprof -http=:8001 cpu.bin
go tool pprof -http=:8001 heap.bin

실행 트레이스는 다음을 실행해 볼 수 있습니다.

go tool trace heap.bin

Git 작업 프로파일링#

히스토리
Feature flag

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

Git 작업에 관한 추가 정보를 Gitaly 로그로 보내면 Gitaly가 수행하는 Git 작업을 프로파일링할 수 있습니다. 이 정보를 통해 사용자는 성능 최적화, 디버깅, 일반적인 텔레메트리 수집에 관해 더 깊이 파악할 수 있습니다. 자세한 내용은 Git Trace2 API 참조를 참고합니다.

시스템 과부하를 방지하기 위해 추가 정보 로깅에는 속도 제한이 적용됩니다. 속도 제한을 초과하면 트레이스를 건너뜁니다. 다만 속도가 정상 상태로 돌아오면 트레이스가 다시 자동으로 처리됩니다. 속도 제한은 시스템을 안정적으로 유지하고 과도한 트레이스 처리로 인한 악영향을 방지합니다.

GitLab 복원 후 리포지터리가 비어 있는 것으로 표시되는 경우#

보안 강화를 위해 fapolicyd를 사용할 때 GitLab은 GitLab 백업 파일에서 복원이 성공했다고 보고하지만 다음 현상이 나타날 수 있습니다.

  • 리포지터리가 비어 있는 것으로 표시됩니다.

  • 새 파일을 만들면 다음과 유사한 오류가 발생합니다.

    13:commit: commit: starting process [/var/opt/gitlab/gitaly/run/gitaly-5428/gitaly-git2go -log-format json -log-level -correlation-id
    01GP1383JV6JD6MQJBH2E1RT03 -enabled-feature-flags -disabled-feature-flags commit]: fork/exec /var/opt/gitlab/gitaly/run/gitaly-5428/gitaly-git2go: operation not permitted.
    
  • Gitaly 로그에 다음과 유사한 오류가 포함될 수 있습니다.

     "error": "exit status 128, stderr: \"fatal: cannot exec '/var/opt/gitlab/gitaly/run/gitaly-5428/hooks-1277154941.d/reference-transaction':
    
      Operation not permitted\\nfatal: cannot exec '/var/opt/gitlab/gitaly/run/gitaly-5428/hooks-1277154941.d/reference-transaction': Operation
      not permitted\\nfatal: ref updates aborted by hook\\n\"",
     "grpc.code": "Internal",
     "grpc.meta.deadline_type": "none",
     "grpc.meta.method_type": "client_stream",
     "grpc.method": "FetchBundle",
     "grpc.request.fullMethod": "/gitaly.RepositoryService/FetchBundle",
    ...
    

현재 규칙에 따라 fapolicyd가 실행을 거부하고 있는지 판단하는 데 디버그 모드를 사용할 수 있습니다.

fapolicyd가 실행을 거부하고 있다면 다음을 고려합니다.

  1. fapolicyd 구성에서 /var/opt/gitlab/gitaly의 모든 실행 파일을 허용합니다.

    allow perm=any all : ftype=application/x-executable dir=/var/opt/gitlab/gitaly/
    
  2. 서비스를 재시작합니다.

    sudo systemctl restart fapolicyd
    
    sudo gitlab-ctl restart gitaly
    

fapolicyd가 활성화된 RHEL 인스턴스에 푸시할 때 발생하는 Pre-receive hook declined 오류#

fapolicyd가 활성화된 RHEL 기반 인스턴스에 푸시할 때 Pre-receive hook declined 오류가 발생할 수 있습니다. fapolicyd가 Gitaly 바이너리의 실행을 차단할 수 있기 때문입니다. 이 문제를 해결하려면 다음 중 하나를 수행합니다.

  • fapolicyd를 비활성화합니다.
  • fapolicyd를 활성화한 상태로 Gitaly 바이너리의 실행을 허용하는 fapolicyd 규칙을 만듭니다.

Gitaly 바이너리 실행을 허용하는 규칙을 만들려면 다음과 같이 합니다.

  1. /etc/fapolicyd/rules.d/89-gitlab.rules 파일을 만듭니다.

  2. 파일에 다음을 입력합니다.

    allow perm=any all : ftype=application/x-executable dir=/var/opt/gitlab/gitaly/
    
  3. 서비스를 재시작합니다.

    systemctl restart fapolicyd
    

새 규칙은 데몬이 재시작된 후에 적용됩니다.

중복 경로가 있는 스토리지를 제거한 후 리포지터리 업데이트#

히스토리
  • GitLab 17.1에서 Rake 태스크 gitlab:gitaly:update_removed_storage_projects가 도입되었습니다.

GitLab 17.0에서 중복 경로로 스토리지를 구성하는 기능이 제거되었습니다. 따라서 gitaly 구성에서 중복 스토리지 구성을 제거해야 할 수 있습니다.

Warning

이 Rake 태스크는 이전 스토리지와 새 스토리지가 같은 Gitaly 서버에서 같은 디스크 경로를 공유할 때만 사용합니다. 다른 상황에서 이 Rake 태스크를 사용하면 리포지터리를 사용할 수 없게 됩니다. 그 외 모든 상황에서 스토리지 간에 프로젝트를 이전할 때는 프로젝트 리포지터리 스토리지 이동 API를 사용합니다.

다른 스토리지와 같은 경로를 사용한 스토리지를 Gitaly 구성에서 제거할 때는 이전 스토리지에 연결된 프로젝트를 새 스토리지로 다시 할당해야 합니다.

예를 들어 다음과 유사한 구성이 있을 수 있습니다.

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

구성에서 duplicate-path를 제거하는 경우, 여기에 할당된 프로젝트를 대신 default에 연결하기 위해 다음 Rake 태스크를 실행합니다.

sudo gitlab-rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]"
sudo -u git -H bundle exec rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]" RAILS_ENV=production

오류: ZIP 파일로 리포지터리를 다운로드할 때 발생하는 fatal: deflate error (0)\n#

Git 버전 2.51에서 수정된 Git 버그(이슈 575) 때문에 리포지터리를 ZIP 아카이브로 다운로드할 때 경우에 따라 불완전한 ZIP 파일이 생성됩니다. 이 경우 Gitaly 로그에 다음 오류가 표시됩니다.

  "msg": "fatal: deflate error (0)\n",

이 문제를 해결하려면 수정된 Git 버전을 사용하는 GitLab 및 Gitaly 버전으로 업그레이드합니다. 업그레이드할 수 없다면 다음 단계로 문제를 우회합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. core.bigFileThreshold를 가장 큰 블롭 크기보다 크게 구성합니다(기본값은 50m).

      gitaly['configuration'] = {
       # ... your existing configuration ...
       git: {
         config: [
           # ... any existing git config entries ...
           {
             key: 'core.bigFileThreshold',
             value: '500m'
           }
         ]
       }
     }
    
  3. gitlab-ctl reconfigure를 실행합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. values.yml 파일에서 core.bigFileThreshold를 구성합니다.

    git:
      config:
        - key: "core.bigFileThreshold"
          value: "500m"
    
  3. 구성을 업데이트하려면 helm upgrade <gitlab_release> gitlab/gitlab -f values.yaml을 실행합니다.

  1. git-sizer로 블롭 크기를 확인합니다.

  2. /home/git/gitaly/config.toml에서 core.bigFileThreshold를 구성합니다.

    # [[git.config]]
    # key = core.bigFileThreshold
    # value = 500m