NFS를 GitLab에서 사용하기

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

NFS는 대개 성능 상의 이유로 권장되지 않지만 객체 저장소의 대안으로 사용될 수 있습니다.

LFS, 업로드 및 아티팩트와 같은 데이터 객체의 경우 가능한 경우 NFS보다는 객체 저장소 서비스를 권장합니다. 이는 성능이 더 우수하기 때문입니다. NFS 사용을 제거할 때는 객체 저장소로 이동하는 데 추가 단계가 필요합니다. 파일 시스템 저장소 대체 방법에 대해서도 이를 참조하세요.

NFS는 저장소 저장에 사용할 수 없습니다.

파일 시스템 성능을 테스트하는 데 사용할 수 있는 단계에 대해서는 파일 시스템 성능 벤치마킹을 참조하세요.

권한 부여된 SSH 키의 빠른 조회

빠른 SSH 키 조회 기능은 블록 스토리지를 사용하더라도 GitLab 인스턴스의 성능을 향상시킬 수 있습니다.

빠른 SSH 키 조회는 GitLab 데이터베이스를 사용하여 /var/opt/gitlab/.sshauthorized_keys를 대체하는 기능입니다.

NFS는 지연 시간을 증가시키므로, /var/opt/gitlab이 NFS로 이동되면 빠른 조회가 권장됩니다.

우리는 기본값으로 빠른 조회 사용을 조사하고 있습니다.

NFS 서버

nfs-kernel-server 패키지를 설치하면 GitLab 애플리케이션을 실행하는 클라이언트와 디렉터리를 공유할 수 있습니다.

sudo apt-get update
sudo apt-get install nfs-kernel-server

필요한 기능

파일 잠금: GitLab은 오로지 NFS 버전 4에서만 기본으로 지원되는 자문 파일 잠금을 필요로 합니다. NFSv3도 리눅스 커널 2.6.5+가 사용될 경우 잠금을 지원합니다. 4 버전을 사용하고 특별히 NFSv3를 테스트하지 않는 것을 권장합니다.

권장 옵션

NFS 익스포트를 정의할 때 다음 옵션도 추가하는 것을 권장합니다:

  • no_root_squash - NFS는 일반적으로 root 사용자를 nobody로 변경합니다. 이는 NFS 공유가 많은 다른 사용자에 의해 액세스될 때 좋은 보안 조치입니다. 그러나 이 경우 GitLab만 NFS 공유를 사용하므로 안전합니다. GitLab은 파일 권한을 자동으로 관리해야 하므로 no_root_squash 설정이 권장됩니다. 설정하지 않으면 리눅스 패키지가 권한을 변경하려고 시도할 때 오류가 발생할 수 있습니다. GitLab 및 다른 번들된 구성 요소는 root가 아닌 권한이 없는 사용자로 실행됩니다. no_root_squash를 권장하는 이유는 리눅스 패키지가 필요한 대로 파일의 소유권 및 권한을 설정할 수 있도록 하는 것입니다. no_root_squash 옵션이 사용할 수 없는 특정 경우에는 root 플래그가 동일한 결과를 얻을 수 있습니다.
  • sync - 동기식 동작을 강제합니다. 기본값은 비동기식이며 특정 상황에서는 데이터가 동기화되기 전에 장애가 발생할 수 있습니다.

LDAP로 리눅스 패키지를 실행하는 복잡성과 LDAP 없이 ID 매핑을 유지하는 복잡성으로 인해 대부분의 경우 시스템 간의 단순화된 권한 관리를 위해 숫자 UID와 GID를 활성화해야 합니다 (이는 경우에 따라 기본적으로 꺼져 있음):

NFS 서버 위임 비활성화

모든 NFS 사용자는 NFS 서버 위임 기능을 비활성화하는 것이 좋습니다. 이는 NFS 클라이언트가 너무 많은 TEST_STATEID NFS 메시지로 인한 과도한 네트워크 트래픽으로 인해 급속히 느려지는 리눅스 커널 버그를 피하기 위함입니다.

NFS 서버 위임을 비활성화하려면 다음을 수행하세요:

  1. NFS 서버에서 다음을 실행합니다:

    echo 0 > /proc/sys/fs/leases-enable
    sysctl -w fs.leases-enable=0
    
  2. NFS 서버 프로세스를 다시 시작합니다. 예를 들어, CentOS에서는 service nfs restart를 실행합니다.

참고: 더 최근의 커널에서는 이 버그가 수정되었을 수 있습니다. Red Hat Enterprise 7은 2019년 8월 6일에 커널 업데이트를 배포하여 이 문제가 해결되었을 수 있습니다. 커널 버전이 수정된 것을 알고 있다면 NFS 서버 위임을 비활성화할 필요가 없을 수 있습니다. 그렇지만, GitLab은 여전히 NFS 서버 위임을 비활성화할 것을 권장합니다.

NFS 클라이언트

nfs-common은 응용 프로그램 노드에서 실행할 필요가 없는 서버 구성 요소를 설치하지 않고 NFS 기능을 제공합니다.

apt-get update
apt-get install nfs-common

마운트 옵션

다음은 /etc/fstab에 추가할 예시 코드 조각입니다.

10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2

nfsstat -mcat /etc/fstab를 실행하여 마운트된 각 NFS 파일 시스템의 정보 및 설정을 볼 수 있습니다.

사용해야 할 여러 옵션이 있습니다.

설정 설명
vers=4.1 Linux NFS 클라이언트 버그로 인해 의미 없는 데이터로 인한 중대한 문제가 발생할 수 있으므로 NFS v4.1을 사용해야 합니다.
nofail 이 마운트가 사용 가능해질 때까지 부팅 프로세스를 중지하지 않습니다.
lookupcache=positive NFS 클라이언트에게 positive 캐시 결과를 존중하도록 하지만 negative 캐시 결과를 무효화합니다. negative 캐시 결과는 Git과 관련된 문제를 발생시킵니다. 특히 git push가 모든 NFS 클라이언트 전체에 일관되게 등록되지 못할 수 있습니다. negative 캐시는 클라이언트가 이전에 파일이 존재하지 않았다고 ‘기억’하도록 합니다.
hard soft 대신 사용합니다. 추가 정보.
cto cto가 기본 옵션으로 사용해야 합니다. nocto를 사용하지 마십시오. 추가 정보.
_netdev 네트워크가 온라인 상태가 될 때까지 파일 시스템을 마운트 대기합니다. 또한 high_availability['mountpoint'] 옵션을 확인하세요.

soft 마운트 옵션

특별한 이유가 없는 한 마운트 옵션으로 hard를 사용하는 것이 좋습니다.

GitLab.com에서 NFS를 사용할 때 NFS 서버가 다시 부팅되는 경우가 있었기 때문에 soft를 사용했으며, 이는 soft가 가용성을 향상시켰지만, 각자의 인프라는 다릅니다. 예를 들어 온프레미스 저장 장치 어레이가 중복 컨트롤러로 제공하는 경우 NFS 서버 가용성에 대해 걱정할 필요가 없습니다.

NFS 매뉴얼에는 다음과 같이 기술되어 있습니다.

“soft” 타임아웃은 특정 경우에 데이터의 은폐된 손상을 야기할 수 있습니다.

차이를 이해하려면 Linux 매뉴얼 페이지를 참조하고, soft를 사용하는 경우 위험을 완화하기 위한 조치를 취했는지 확인하세요.

예를 들어 커밋이 사라지는 등 NFS 서버의 디스크에 쓰기가 발생하지 않는 것처럼 보이는 동작을 경험하는 경우 (매뉴얼에 따르면) hard 옵션을 사용하세요.

다른 공급 업체들도 유사한 권장 사항을 제공하며, 읽기-쓰기 디렉터리를 위한 권장 마운트 옵션 및 NetApp의 지식 베이스은 NFS 클라이언트 드라이버가 데이터를 캐시하는 경우, soft는 GitLab에 의한 쓰기가 실제로 디스크에 있는지에 대한 확신이 없음을 의미한다는 점을 강조하고 있습니다.

옵션 hard로 설정된 마운트 포인트는 성능이 나오지 않을 수 있으며, NFS 서버가 다운되면 hard는 마운트 지점과 상호작용할 때 프로세스가 멈추도록 합니다. 멈춘 프로세스에 대해 SIGKILL(kill -9)를 사용하여 대응하십시오. intr 옵션은 2.6 커널에서 작동이 중단되었습니다.

nocto 마운트 옵션

nocto를 사용하지 마십시오. 대신 기본값인 cto를 사용하십시오.

nocto를 사용할 때 덴트리 캐시는 항상 사용되며, 생성된 후 acdirmax초(속성 캐시 시간)까지 유지됩니다.

이로 인해 여러 클라이언트에서 덴트리 캐시 오류가 발생하여 각 클라이언트가 디렉터리의 서로 다른(캐시된) 버전을 볼 수 있습니다.

Linux 맨 페이지에 따르면 중요한 부분은 다음과 같습니다:

nocto 옵션이 지정된 경우, 클라이언트는 서버의 파일이 언제 변경되었는지를 판단하기 위해 표준이 아닌 휴리스틱을 사용합니다.

nocto 옵션을 사용하면 읽기 전용 마운트의 성능이 향상될 수 있지만, 서버의 데이터가 geleglarara 약간 변경될 때만 사용해야 합니다.

우리는 푸시 이후 참조를 찾을 수 없는 문제에서 이러한 동작을 발견했습니다. 여기서 새로 추가된 루즈 참조가 로컬 덴트리 캐시를 가진 다른 클라이언트에서 누락된 것으로 보일 수 있습니다.

단일 NFS 마운트

기존 데이터를 수동으로 이동하지 않고도 백업을 자동으로 복원할 수 있는 마운트 내의 모든 GitLab 데이터 디렉터리를 중첩하는 것이 좋습니다.

다음과 같이 Linux 패키지를 설정하여 마운트 포인트에 중첩된 각 디렉터리의 경로를 구성하십시오.

mountpoint
└── gitlab-data
    ├── builds
    ├── git-data
    ├── shared
    └── uploads

그런 다음 /gitlab-nfs를 마운트하고 다음과 같이 Linux 패키지 구성을 사용하여 각 데이터 위치를 하위 디렉터리로 이동하십시오.

git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} })
gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads'
gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared'
gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds'

중앙 위치를 사용하도록 sudo gitlab-ctl reconfigure를 실행하여 시작하십시오. 기존 데이터가 있는 경우 새 위치로 수동으로 복사하거나 rsync해야 하며, 그런 다음 GitLab을 다시 시작해야 합니다.

바인드 마운트

Linux 패키지 구성을 변경하는 대신, 데이터를 NFS 마운트에 저장하는 데 바인드 마운트를 사용할 수 있습니다.

바인드 마운트는 하나의 NFS 마운트만 지정한 후 기본 GitLab 데이터 위치를 NFS 마운트에 바인딩하는 방법을 제공합니다. 주로 /etc/fstab에서 일반적으로 하나의 NFS 마운트 지점을 정의하는 것으로 시작하십시오. NFS 마운트 지점이 /gitlab-nfs라고 가정합니다. 그런 다음 /etc/fstab에 다음과 같이 바인드 마운트를 추가하십시오.

/gitlab-nfs/gitlab-data/git-data /var/opt/gitlab/git-data none bind 0 0
/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0
/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0
/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0
/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0

바인드 마운트를 사용하려면 복원을 시도하기 전에 데이터 디렉터리가 비어 있는지 수동으로 확인해야 합니다. 복원 전 요구 사항에 대해 자세히 알아보세요.

여러 NFS 마운트

기본 Linux 패키지 구성을 사용할 때, GitLab 클러스터 노드 간에 4개의 데이터 위치를 공유해야 합니다. 다른 위치를 공유해서는 안 됩니다. 다음은 공유해야 하는 4개의 위치입니다:

위치 설명 기본 구성
/var/opt/gitlab/gitlab-rails/uploads 사용자가 업로드한 첨부 파일 gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'
/var/opt/gitlab/gitlab-rails/shared 빌드 아티팩트, GitLab Pages, LFS 객체 및 임시 파일과 같은 객체. LFS를 사용하는 경우 데이터의 큰 부분을 차지할 수 있습니다. gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'
/var/opt/gitlab/gitlab-ci/builds GitLab CI/CD 빌드 추적 gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'

다른 GitLab 디렉터리를 노드 간에 공유하지 않아야 합니다. 이들은 노드별 파일과 공유할 필요가 없는 GitLab 코드를 포함합니다. 중앙 위치로 로그를 전송하려면 원격 시스로그를 사용하여 로그를 배송하는 것을 고려해 보세요. UDP 로그 배송에 대한 Linux 패키지 구성을 제공합니다.

여러 NFS 마운트를 사용하려면 복원을 시도하기 전에 데이터 디렉터리가 비어 있는지 수동으로 확인해야 합니다. 복원 전 요구 사항에 대해 자세히 알아보세요.

NFS 테스트

NFS 서버와 클라이언트를 설정한 후, 다음 명령어를 테스트하여 NFS가 올바르게 구성되었는지 확인할 수 있습니다.

sudo mkdir /gitlab-nfs/test-dir
sudo chown git /gitlab-nfs/test-dir
sudo chgrp root /gitlab-nfs/test-dir
sudo chmod 0700 /gitlab-nfs/test-dir
sudo chgrp gitlab-www /gitlab-nfs/test-dir
sudo chmod 0751 /gitlab-nfs/test-dir
sudo chgrp git /gitlab-nfs/test-dir
sudo chmod 2770 /gitlab-nfs/test-dir
sudo chmod 2755 /gitlab-nfs/test-dir
sudo -u git mkdir /gitlab-nfs/test-dir/test2
sudo -u git chmod 2755 /gitlab-nfs/test-dir/test2
sudo ls -lah /gitlab-nfs/test-dir/test2
sudo -u git rm -r /gitlab-nfs/test-dir

“Operation not permitted” 오류가 발생하면 NFS 서버 내보내기 옵션을 조사해야 합니다.

방화벽 환경에서의 NFS

NFS 서버와 NFS 클라이언트 간의 트래픽이 방화벽에 의해 포트 필터링되는 경우 해당 방화벽을 재구성하여 NFS 통신을 허용해야 합니다.

The Linux Documentation Project (TDLP)의 이 가이드에서는 방화벽 환경에서 NFS를 사용하는 기본 사항을 다루고 있습니다. 또한, 귀하의 운영 체제나 배포 및 방화벽 소프트웨어의 구체적인 문서를 검색하고 검토하는 것을 권장합니다.

Ubuntu의 예시:

호스트에서 sudo ufw status 명령을 실행하여 방화벽에서 클라이언트로부터의 NFS 트래픽이 허용되는지 확인하세요. 차단되고 있다면 아래 명령을 사용하여 특정 클라이언트로부터의 트래픽을 허용할 수 있습니다.

sudo ufw allow from <client_ip_address> to any port nfs

알려진 문제

클라우드 기반 파일 시스템 사용 지양

GitLab은 다음과 같은 클라우드 기반 파일 시스템 사용을 강력하게 권장하지 않습니다:

  • AWS Elastic File System (EFS).
  • Google Cloud Filestore.
  • Azure Files.

저희 지원팀은 클라우드 기반 파일 시스템 액세스와 관련된 성능 문제에 대한 지원을 제공할 수 없습니다.

많은 소량 파일이 직렬적으로 작성되는 작업은 클라우드 기반 파일 시스템에 적합하지 않다는 사용자와 고객의 보고가 있습니다. 이러한 경우, 예를 들어 /var/log/gitlab에 있는 로그 파일과 같은 GitLab 로그 파일을 저장하는 것도 성능에 영향을 미칩니다. 로그 파일은 로컬 볼륨에 저장하는 것이 좋습니다.

GitLab에서 클라우드 기반 파일 시스템을 사용한 경험의 자세한 내용은 Commit Brooklyn 2019 비디오를 참조하세요.

CephFS 및 GlusterFS 사용 지양

GitLab은 CephFS 및 GlusterFS 사용을 강력히 권장하지 않습니다. 이러한 분산 파일 시스템은 Git의 많은 소량 파일 및 액세스 시간 및 파일 잠금 시간을 전파하는 접근 패턴과 맞지 않기 때문에 GitLab에서 이용하려는 목적에 적합하지 않습니다.

NFS와 함께 PostgreSQL 사용 지양

GitLab은 PostgreSQL 데이터베이스를 NFS에서 실행하는 것을 강력히 권장하지 않습니다. GitLab 지원팀은 이 구성과 관련된 성능 문제에 대한 지원을 제공할 수 없습니다.

또한, 이 구성은 PostgreSQL 문서에서 구체적으로 경고하고 있습니다:

PostgreSQL은 NFS 파일 시스템에 대해 특별한 처리를 하지 않으며, NFS가 로컬로 연결된 드라이브와 정확히 같이 동작한다고 가정합니다. 클라이언트 또는 서버 NFS 구현이 표준 파일 시스템 의미론을 제공하지 않으면 신뢰성 문제를 유발할 수 있습니다. 특히 NFS 서버로의 지연(비동기) 쓰기는 데이터 손상 문제를 유발할 수 있습니다.

지원되는 데이터베이스 아키텍처에 대한 자세한 내용은 복제 및 장애 조치를 위한 데이터베이스 구성에 대한 저희 문서를 참조하세요.

문제 해결

NFS에 대한 요청 추적

NFS와 관련된 문제의 경우, perf를 사용하여 만들어지는 파일 시스템 요청을 추적하는 것이 도움이 될 수 있습니다:

sudo perf trace -e 'nfs4:*' -p $(pgrep -fd ',' puma)

Ubuntu 16.04의 경우:

sudo perf trace --no-syscalls --event 'nfs4:*' -p $(pgrep -fd ',' puma)