GitLab에서 NFS 사용하기

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에서만 기본으로 지원됩니다. Linux 커널 2.6.5+를 사용하는 경우 NFSv3도 잠금을 지원합니다. 4 버전을 사용할 것을 권장하며 명시적으로 NFSv3는 테스트하지 않습니다.

권장 옵션

NFS export를 정의할 때 다음 옵션도 추가하는 것이 좋습니다:

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

Linux 패키지를 LDAP와 함께 실행하는 복잡성 및 LDAP 없이 ID 매핑을 유지하는 복잡성을 고려하여 대부분의 경우 간단한 권한 관리를 위해 숫자 UID와 GID를 사용해야 합니다(이것은 일부 경우에 기본적으로 off되어 있음):

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
리눅스 커널 버그는 이 커밋로 해결된 최신 커널에서 해결되었을 수 있습니다. 2019년 8월 6일 Red Hat Enterprise 7은 이 문제를 해결한 커널 업데이트를 배포했을 수 있습니다. 해당 리눅스 커널 버전을 사용 중인 경우 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 사용해야 하는 기본 옵션입니다. nocto를 사용하지 마십시오. 자세한 내용.
_netdev 네트워크가 온라인일 때 파일 시스템을 마운트할 때까지 대기합니다. 또한 high_availability['mountpoint'] 옵션도 확인하십시오.
#### `soft` 마운트 옵션

특정 이유가 없다면 마운트 옵션으로 `hard`를 사용하는 것이 권장됩니다.

GitLab.com이 NFS를 사용했던 시기에는 NFS 서버가 다시 부팅되는 경우에 `soft`를 사용하였으며, 이로써 가용성이 향상되었습니다. 그러나 모든 인프라는 다릅니다. 예를 들어, 온프레미스 스토리지 어레이에서 제공되는 NFS가 중복 컨트롤러로 제공된다면 NFS 서버 가용성에 대해 걱정할 필요가 없습니다.

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

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

차이를 이해하려면 [Linux 매뉴얼 페이지](https://linux.die.net/man/5/nfs)를 참조하고, `soft`를 사용하는 경우, 리스크를 완화하기 위한 조치를 취했는지 확인하세요.

예를 들어, NFS 서버에서 디스크로의 쓰기가 발생하지 않아 commit이 누락되는 것과 같은 문제를 경험하면, [매뉴얼 페이지에서와 같이 공개적으로 알려진 것과 같은 이유로](https://linux.die.net/man/5/nfs)`hard` 옵션을 사용하세요.

다른 공급업체들도 비슷한 권장을 하고 있으며, 그 중에는 [읽기-쓰기 디렉터리에 대한 권장 마운트 옵션](https://help.sap.com/docs/SUPPORT_CONTENT/basis/3354611703.html) 및 NetApp의 [지식 베이스](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount)도 포함됩니다. 이들은 NFS 클라이언트 드라이버가 데이터를 캐시하는 경우, `soft`를 사용하면 GitLab에 의한 쓰기가 실제로 디스크에 있는지 여부를 확신할 수 없다는 것을 강조합니다.

옵션 `hard`로 설정된 마운트 포인트는 성능이 나쁠 수 있으며, NFS 서버가 다운되면 `hard`는 마운트 포인트와 상호 작용하는 프로세스를 멈추게 합니다. 멈춘 프로세스를 처리하기 위해 `SIGKILL` (`kill -9`)을 사용하세요.
`intr` 옵션은 [2.6 커널에서 작동을 멈췄습니다](https://access.redhat.com/solutions/157873).

#### `nocto` 마운트 옵션

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

`nocto`를 사용하는 경우에는 Dentry 캐시가 항상 사용되며, `acdirmax`초(속성 캐시 시간)가 경과할 때까지 유지됩니다.

이로 인해 여러 클라이언트간에 스테일한 Dentry 캐시 문제가 발생하여 각 클라이언트가 디렉터리의 다른 (캐시된) 버전을 볼 수 있습니다.

[Linux 매뉴얼 페이지](https://linux.die.net/man/5/nfs)의 중요한 부분은 다음과 같습니다:

> `nocto` 옵션이 지정된 경우, 클라이언트는 서버의 파일이 변경된 것을 결정하기 위해 비표준 휴리스틱을 사용합니다.

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

우리는 [푸시 후 refs를 찾을 수 없는 문제](https://gitlab.com/gitlab-org/gitlab/-/issues/326066)에서 이와 같은 동작을 확인하였으며, 새로 추가된 루즈 refs가 로컬 Dentry 캐시를 가진 다른 클라이언트에서 누락된 것으로 볼 수 있습니다. [해당 문제에서 설명된 것과 같습니다](https://gitlab.com/gitlab-org/gitlab/-/issues/326066#note_539436931).

### 단일 NFS 마운트

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

```plaintext
mountpoint
└── 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개의 데이터 위치를 공유해야 합니다. 다른 위치를 공유해서는 안 됩니다. 다음은 공유해야 하는 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 코드를 포함하고 있습니다. 중앙 위치로 로그를 이동하기 위해서는 원격 syslog를 사용하는 것을 고려해보세요. 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 (TLDP)의 이 가이드는 방화벽 환경에서 NFS 사용의 기본을 다룹니다. 또한, 귀하의 운영 체제나 배포 및 방화벽 소프트웨어에 대한 구체적인 문서를 찾아 검토할 것을 권장합니다.

Ubuntu의 경우:

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

sudo ufw allow from <client_ip_address> to any port nfs

알려진 문제

클라우드 기반 파일 시스템 사용을 피하십시오

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

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

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

고객 및 사용자들은 이러한 파일 시스템이 GitLab이 필요로 하는 파일 시스템 액세스에 대해 성능이 좋지 않다고 보고했습니다. git과 같이 많은 작은 파일이 직렬 방식으로 작성되는 작업들은 클라우드 기반 파일 시스템에 적합하지 않습니다.

만약 이를 사용하기로 결정한다면, GitLab 로그 파일(예: /var/log/gitlab에 있는 파일)을 거기에 저장하지 마십시오. 이것 또한 성능에 영향을 미치기 때문입니다. 로그 파일은 로컬 볼륨에 저장하는 것을 권장합니다.

GitLab과 클라우드 기반 파일 시스템을 사용한 경험에 대한 더 많은 정보는 Commit Brooklyn 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)