GitLab에서 NFS 사용하기

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

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

객체 저장소가 가능한 경우 NFS보다는 객체 저장소 서비스를 권장합니다. 성능이 향상되기 때문입니다. NFS 사용을 제거하는 경우에는 Object Storage로 이전하는 데 추가 단계가 필요합니다.

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

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

승인된 SSH 키의 빠른 조회

GitLab 애플리케이션을 사용하는 인스턴스의 성능을 향상시킬 수 있는 빠른 SSH 키 조회 기능이 제공됩니다.

빠른 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 exports를 정의할 때 다음 옵션도 추가하는 것을 권장합니다:

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

LDAP를 사용하여 Linux 패키지를 실행하고 LDAP 없이 ID 매핑을 유지하는 복잡성과 어려움으로, 대부분의 경우 간단화된 권한 관리를 위해 숫자 UIDs 및 GIDs를 활성화해야 합니다(일부 경우에는 기본으로 비활성화됨):

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를 실행하세요.

soft 마운트 옵션

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

GitLab.com이 NFS를 사용할 때는 NFS 서버가 재부팅되었을 때 soft를 사용했으며, 이로 인해 NFS 서버의 가용성이 향상되었지만, 각각의 인프라가 다르기 때문에 일반적으로 soft를 사용하지 않는 것이 좋습니다. 예를 들어 온프레미스 저장소 어레이의 여분 컨트롤러에서 NFS를 제공하는 경우 NFS 서버의 가용성에 대해 걱정할 필요가 없습니다.

NFS 맨 페이지에는 다음과 같이 명시되어 있습니다:

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

차이를 이해하려면 Linux 맨 페이지를 참조하세요. soft를 사용하는 경우, 리스폰시브함이 데이터 무결성보다 중요한 경우에만 사용하고 있음을 확인하세요.

기타 업체들도 읽기-쓰기 디렉토리에 대한 권장 마운트 옵션 및 NetApp의 지식 베이스에서 동일한 권장을 하고 있으며, 만약 NFS 클라이언트 드라이버가 데이터를 캐시하는 경우, soft는 GitLab에 의해 쓰여진 데이터가 실제로 디스크에 있는지에 대한 확신이 없음을 의미합니다.

옵션 hard로 설정된 마운트 지점이 성능이 나쁠 수 있으며, NFS 서버가 다운된 경우, hard는 프로세스가 마운트 지점과 상호 작용할 때 멈출 수 있습니다. 멈춘 프로세스를 처리하려면 SIGKILL(kill -9)을 사용하세요. 옵션 intr2.6 커널에서 작동이 중지되었습니다.

nocto 마운트 옵션

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

nocto를 사용하면 덴트리 캐시가 항상 사용되며, acdirmax(속성 캐시 시간)초까지는 계속 사용됩니다.

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

Linux 맨 페이지에서 중요한 부분:

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

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

우리는 푸시 후 refs를 찾을 수 없는 문제에서 이러한 현상을 확인했으며, 새롭게 추가된 루즈된 refs는 지역 덴트리 캐시가 있는 다른 클라이언트에서 누락된 것으로 보입니다. 이에 대해 이 이슈에서 설명하고 있습니다.

단일 NFS 마운트

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

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

이를 위해 Linux 패키지를 다음과 같이 각 디렉토리 경로로 구성하세요:

/gitlab-nfs를 마운트하고 각 데이터 위치를 하위 디렉토리로 이동하기 위해 다음과 같이 Linux 패키지를 구성하세요:

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을 다시 시작해야 합니다.

Bind 마운트

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

바인드 마운트는 하나의 NFS 마운트만 지정한 후 기본 GitLab 데이터 위치를 해당 NFS 마운트에 바인드하는 방법을 제공합니다. 보통 /etc/fstab에 있는 것과 같이 단일 NFS 마운트 지점을 정의합니다. NFS 마운트 지점이 /gitlab-nfs라고 가정합시다. 그런 다음 /etc/fstab에 다음 바인드 마운트를 추가하세요:

/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 클러스터 노드 간에 3개의 데이터 위치를 공유해야 합니다. 다른 위치를 공유해서는 안 됩니다. 공유해야 하는 3개의 위치는 다음과 같습니다:

위치 설명 기본 구성
/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 (TDLP)의 이 가이드에서는 방화벽으로 보호된 환경에서 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과 같은 많은 작은 파일이 연속적으로 작성되는 작업은 클라우드 기반 파일 시스템에 적합하지 않습니다.

이를 사용하려는 경우 /var/log/gitlab과 같은 GitLab 로그 파일을 거기에 저장하지 않는 것이 좋습니다. 로그 파일은 로컬 볼륨에 저장하는 것이 좋습니다.

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

CephFS 및 GlusterFS 사용 피하기

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

NFS로 PostgreSQL 사용 피하기

GitLab은 NFS를 통해 PostgreSQL 데이터베이스를 실행하는 것을 강력히 권장하지 않습니다. PostgreSQL 문서에서도 이러한 구성에 대해 명시적으로 경고하고 있습니다. PostgreSQL Documentation:

PostgreSQL은 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)