GitLab에서 NFS 사용하기

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

NFS는 객체 스토리지의 대안으로 사용할 수 있지만, 일반적으로 성능상의 이유로 권장되지는 않습니다.

LFS, 업로드 및 아티팩트와 같은 데이터 객체의 경우 객체 스토리지 서비스가 가능한 경우 NFS 대신 권장됩니다. 이는 더 나은 성능을 위해 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에서만 네이티브로 지원되며, Linux Kernel 2.6.5+가 사용된 경우 NFSv3도 잠금을 지원합니다. 우리는 버전 4를 사용하는 것을 권장하며 명시적으로 NFSv3을 테스트하지는 않습니다.

권장 옵션

NFS export를 정의할 때 다음 옵션도 추천합니다:

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

Linux 패키지를 LDAP으로 실행하고 ID 매핑을 유지하는 복잡성과 관련하여 대부분의 경우, 다른 시스템간에 간단한 권한 관리를 위해 숫자 UID와 GID를 사용할 수 있도록 권장합니다(경우에 따라 기본적으로 비활성화되어 있음):

NFS 서버 위임 비활성화

모든 NFS 사용자가 NFS 서버 위임 기능을 비활성화하는 것을 권장합니다. 이는 NFS 클라이언트가 많은 TEST_STATEID NFS 메시지로 인한 과도한 네트워크 트래픽으로 인해 급격하게 느려지는 Linux 커널 버그를 피하기 위한 것입니다.

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

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

    echo 0 > /proc/sys/fs/leases-enable
    sysctl -w fs.leases-enable=0
    
  2. NFS 서버 프로세스를 다시 시작합니다. CentOS의 경우 service nfs restart를 실행합니다.

note
커널 버그는 이 커밋을 사용한 더 최신 커널에서 수정될 수 있습니다. Red Hat Enterprise 7은 2019년 8월 6일에 커널 업데이트를 제공하여이 문제를 해결할 수 있습니다. 이러한 문제가 해결된 Linux 커널 버전을 사용하는 것을 알고 있다면 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

각 NFS 파일 시스템에 대해 설정 및 옵션을 보려면 nfsstat -mcat /etc/fstab를 실행할 수 있습니다.

고려해야 할 옵션 디렉터리이 있습니다:

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

soft 마운트 옵션

일반적으로 목적이 명확하지 않다면 마운트 옵션으로 hard를 사용하는 것이 좋습니다.

GitLab.com이 NFS를 사용했던 시기에는 NFS 서버가 재부팅되는 경우가 있었기 때문에 soft를 사용했습니다. 그러나 모든 인프라 환경이 다르기 때문에 soft가 가용성을 향상시켰습니다. 예를 들어, 온프레미스 스토리지 어레이에 중복 컨트롤러가 있는 경우 NFS 서버 가용성에 대해 걱정할 필요가 없습니다.

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

“soft” 타임아웃은 특정 경우에 데이터 손상을 유발할 수 있습니다.

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

만약 NFS 서버에서 디스크에 쓰기 작업이 실제로 발생하지 않았을 수 있는 커밋이 누락된 것으로 보이는 동작을 경험했다면, (매뉴얼에서와 같이):

클라이언트 응답성이 데이터 무결성보다 더 중요한 경우에만 soft 옵션을 사용하세요.

와 같이 hard 옵션을 사용하세요.

기타 벤더들도 유사한 권장 사항을 하고 있으며, 읽기-쓰기 디렉터리용 권장 마운트 옵션와 NetApp의 지식 베이스를 포함합니다. 이들은 NFS 클라이언트 드라이버가 데이터를 캐시하는 경우, soft는 GitLab에 의한 쓰기 작업이 실제로 디스크에 있는지의 확신이 없다는 것을 강조합니다.

옵션으로 hard가 설정된 마운트 포인트는 성능이 좋지 않을 수 있으며, NFS 서버가 다운되면 hard는 마운트 포인트와 상호 작용할 때 프로세스가 멈추도록 합니다. 멈춘 프로세스를 처리하려면 SIGKILL( kill -9)을 사용하세요. intr 옵션이 커널 2.6에서 작동이 중지되었습니다.

nocto 마운트 옵션

nocto 대신 기본값인 cto를 사용하세요.

nocto를 사용하는 경우 dentry 캐시가 항상 사용되며, 생성된 후 acdirmax(속성 캐시 시간) 초까지 유지되게 됩니다.

이로 인해 여러 클라이언트에서 오래된 dentry 캐시 문제가 발생할 수 있는데, 각 클라이언트가 디렉터리의 다른(캐시된) 버전을 볼 수 있습니다.

리눅스 매뉴얼 페이지에서 중요 부분은 다음과 같습니다:

nocto 옵션을 지정하면 클라이언트는 서버의 파일이 언제 변경되었는지를 결정하는 비표준적인 휴리스틱을 사용합니다.

nocto 옵션을 사용하면 읽기 전용 마운트의 성능을 향상시킬 수 있지만, 서버의 데이터가 가끔씩만 변경되는 경우에만 사용해야 합니다.

이와 같은 동작이 푸시 후 찾을 수 없는 참조 문제에서 확인되었습니다. 여기서 새로 추가된 루즈 참조가 로컬 dentry 캐시를 가진 다른 클라이언트에서 실제로 누락된 것으로 보일 수 있습니다.

단일 NFS 마운트

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

마운트 지점
└── gitlab-data
    ├── builds
    ├── git-data
    ├── shared
    └── uploads

이를 위해 Linux 패키지를 다음과 같이 각 디렉터리 경로가 마운트 지점의 하위 디렉터리에 위치하도록 구성하세요:

/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 마운트 지점을 정의하고 다음과 같이 바인드 마운트를 추가하세요:

/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개의 데이터 위치를 공유해야 합니다. 다른 위치는 공유하면 안 됩니다. 다음은 모든 GitLab 클러스터 노드 간에 공유해야 하는 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 코드를 포함하고 있으며, 이는 공유할 필요가 없습니다. 로그를 중앙 위치로 전송하려면 원격 시스로그를 사용하는 것을 고려하세요. Linux 패키지는 UDP 로그 전송에 대한 구성을 제공합니다.

여러 개의 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와 같은 클라우드 기반 파일 시스템의 사용을 강력히 권장하지 않습니다.

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

이러한 파일 시스템은 GitLab이 요구하는 파일 시스템 액세스에 적합하지 않다고 사용자 및 고객이 보고하고 있습니다. 많은 작은 파일이 직렬적으로 작성되는 작업에서는 클라우드 기반 파일 시스템이 적합하지 않습니다.

이러한 파일 시스템을 사용하는 경우 /var/log/gitlab과 같은 GitLab 로그 파일을 저장하지 않도록 하고 성능에 영향을 줄 수 있습니다. 로그 파일은 로컬 볼륨에 저장하는 것이 좋습니다.

GitLab을 사용하면서 클라우드 기반 파일 시스템을 사용한 경험에 대한 자세한 내용은 이 커밋 브루클린 2019 비디오를 참조하세요.

CephFS 및 GlusterFS의 사용을 피하세요

GitLab은 CephFS 및 GlusterFS 사용을 강력히 권장하지 않습니다. 이러한 분산 파일 시스템은 GitLab의 입출력 액세스 패턴에 적합하지 않습니다. Git은 많은 작은 파일을 사용하고 액세스 및 파일 잠금 시간을 전파하는 것이 Git 활동을 매우 느리게 만듭니다.

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)