GitLab で NFS を使う

NFSをオブジェクトストレージの代わりに使うこともできますが、パフォーマンス上の理由から通常は推奨されません。

LFS、アップロード、アーティファクトなどのデータオブジェクトについては、パフォーマンスが向上するため、可能な限りNFSよりもオブジェクトストレージサービスを推奨します。NFSの使用を排除する場合、オブジェクトストレージへの移行に加えて、さらに必要な手順があります。

NFS はリポジトリストレージには使用できません。

ファイルシステムのパフォーマンスをテストする手順については、ファイルシステムのパフォーマンスベンチマークを参照してください。

作成者SSHキーの高速ルックアップ

SSHキーの高速ルックアップ機能は、ブロックストレージを使用している場合でもGitLabインスタンスのパフォーマンスを向上させることができます。

高速SSHキールックアップは、GitLabデータベースを使用したauthorized_keys (/var/opt/gitlab/.ssh)の置き換えです。

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エクスポートを定義する際には、以下のオプションも追加することをお勧めします:

  • no_root_squash - NFSは通常、root ユーザーをnobody に変更します。これは、NFS共有が多くの異なるユーザーによってアクセスされる場合に有効なセキュリティ対策です。しかし、この場合はGitLabだけがNFS共有を使うので安全です。GitLabでは、ファイルの権限を自動的に管理する必要があるため、no_root_squash の設定を推奨しています。この設定がないと、Linuxパッケージが権限を変更しようとしたときにエラーが発生する可能性があります。GitLabや他のバンドルされたコンポーネントは、root 非特権ユーザーとしてではなく、非特権 rootユーザーとして実行されます。root no_root_squash Linuxパッケージが必要に応じてファイルの所有権と権限を設定 no_root_squashできるようにすることをお勧めします。no_root_squash この no_root_squashオプションが利用 rootできないroot no_root_squash 場合 no_root_squashrootフラグによって同じ結果を得ることができます。
  • sync - 同期動作を強制します。デフォルトは非同期であり、特定の状況下では、データが同期される前に障害が発生した場合、データ損失につながる可能性があります。

LinuxパッケージをLDAPで実行するのは複雑であり、LDAPなしでIDマッピングをメンテナーするのも複雑であるため、システム間の権限管理を簡単にするために、ほとんどの場合、数値UIDとGIDを有効にするべきです(デフォルトではオフになっている場合もあります):

NFSサーバの委任を無効にします。

すべてのNFSユーザーは、NFSサーバー委任機能を無効にすることをお勧めします。これは、多数のTEST_STATEID NFSメッセージによる過剰なネットワーク・トラフィックによって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

nfsstat -mcat /etc/fstab を実行すると、マウントされている各NFSファイルシステムの情報と設定されているオプションを見ることができます。

使用を検討すべきオプションがいくつかあることに注意してください:

設定説明
vers=4.1NFS v4.0 には LinuxNFS クライアントのバグがあり、古いデータが原因で重大な問題が発生する可能性があるため、v4.0 ではなく v4.1 を使用すべきです。
nofailこのマウントが利用可能になるのを待ってブート・プロセスを停止しないでください
lookupcache=positiveNFS クライアントに、positive のキャッシュ結果は尊重するが、negative のキャッシュ結果は無効にするように指示します。否定的なキャッシュ結果はGitの問題を引き起こします。具体的には、git push 、すべてのNFSクライアントで一様に登録できないことがあります。否定的なキャッシュは、クライアントが以前にファイルが存在しなかったことを「記憶」する原因となります。
hard soft.詳細の代わりに。
cto cto がデフォルトのオプションです。nocto は使用しないでください。詳細はこちら。
_netdevネットワークがオンラインになるまでファイルシステムのマウントを待ちます。high_availability['mountpoint'] オプションも参照してください。

soft マウントオプション

soft を使う特別な理由がない限り、マウントオプションにはhard を使うことをお勧めします。

GitLab.comがNFSを使っていたときは、NFSサーバーがリブートすることがあったのでsoftsoft 、可用性を向上させることができたからです。しかし、インフラは人それぞれです。例えば、NFSが冗長コントローラを備えたオンプレミスのストレージアレイによって提供されている場合は、NFSサーバーの可用性を心配する必要はありません。

NFSのマニュアルページにはこうあります:

“ソフト “タイムアウトは、特定の場合にサイレントデータ破損を引き起こす可能性があります。

Linux の man ページを読んで違いを理解し、soft を使用する場合は、リスクを軽減するための措置を講じていることを確認してください。

コミットが行方不明になるなど、NFSサーバーのディスクへの書き込みが発生しないことが原因と思われる動作が発生した場合は、hard オプションを使用してください(マニュアルページより):

ソフトオプションは、データの整合性よりもクライアントの応答性が重要な場合にのみ使用してください。

他のベンダーも同様の推奨をしており、System Applications and Products in Data Processing(SAP)や NetApp のナレッジベースでは、NFS クライアントドライバがデータをキャッシュしている場合、](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount) 、GitLab による書き込みが実際にディスク上にあるかどうかは確実ではないことを強調しています。

hard また、NFSサーバーがダウン hardした場合、そのマウントポイントとやりとりするプロセスがハングする可能性があります。ハングしたプロセスに対処するにはSIGKILL (kill -9) を使ってください。intr オプションは2.6 カーネルで動作しなくなりました。

nocto マウントオプション

nocto は使用しないでください。代わりに、デフォルトのcto を使用してください。

nocto を使用する場合、acdirmax 秒(アトリビュート・キャッシュ時間)までは常にデントリー・キャッシュが使用されます。

この結果、複数のクライアントで古い dentry キャッシュのイシューが発生し、各クライアントが異なる (キャッシュされた) バージョンのディレクトリを見ることになります。

Linuxのmanページから、重要な部分を引用します:

nocto オプションが指定された場合、クライアントはサーバ上のファイルがいつ変更されたかを判断するために、非標準のヒューリスティックを使用します。

nocto オプションを使用すると、読み取り専用マウントのパフォーマンスが向上する可能性がありますが、サーバ上のデータが時々しか変更されない場合にのみ使用してください。

このイシューで説明されているように、プッシュ後に見つからない refs に関する問題で、新しく追加されたルース refs がローカルの dentry キャッシュを持つ別のクライアントで見つからないように見えることがあります。

単一のNFSマウント

既存のデータを手動で移動することなく、バックアップを自動的にリストアできるように、GitLabのデータディレクトリをすべてマウント内にネストすることをお勧めします。

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マウントポイントを定義することから始めましょう。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/git-dataGit リポジトリのデータ。これはデータの大部分を占めますgit_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })
/var/opt/gitlab/gitlab-rails/uploadsユーザーがアップロードした添付ファイルgitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'
/var/opt/gitlab/gitlab-rails/sharedビルドアーティファクト、GitLab ページ、LFS オブジェクト、一時ファイルなどのオブジェクト。LFS を使っている場合は、これがデータの大部分を占めることもあります。gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'
/var/opt/gitlab/gitlab-ci/buildsGitLab 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 のように、多くの小さなファイルがシリアライズされた方法で書かれるワークロードは、クラウドベースのファイルシステムには適していません。

もしこれらを使うのであれば、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 関連の問題が発生した場合、perf を使用して、実行されているファイルシステム要求をトレースすると便利です:

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

Ubuntu 16.04では、以下を使用します:

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