NFS
You can view information and options set for each of the mounted NFS file
systems by running nfsstat -m
and cat /etc/fstab
.
NOTE: Note: Filesystem performance has a big impact on overall GitLab performance, especially for actions that read or write to Git repositories. See Filesystem Performance Benchmarking for steps to test filesystem performance.
NFS Server features
Required features
File locking: GitLab requires advisory file locking, which is only supported natively in NFS version 4. NFSv3 also supports locking as long as Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not specifically test NFSv3.
Recommended options
When you define your NFS exports, we recommend you also add the following options:
-
no_root_squash
- NFS normally changes theroot
user tonobody
. This is a good security measure when NFS shares will be accessed by many different users. However, in this case only GitLab will use the NFS share so it is safe. GitLab recommends theno_root_squash
setting because we need to manage file permissions automatically. Without the setting you may receive errors when the Omnibus package tries to alter permissions. Note that GitLab and other bundled components do not run asroot
but as non-privileged users. The recommendation forno_root_squash
is to allow the Omnibus package to set ownership and permissions on files, as needed. In some cases where theno_root_squash
option is not available, theroot
flag can achieve the same result. -
sync
- Force synchronous behavior. Default is asynchronous and under certain circumstances it could lead to data loss if a failure occurs before data has synced.
Improving NFS performance with GitLab
NOTE: Note: This is only available with GitLab 11.9 and up.
If you are using NFS to share Git data, we recommend that you enable a number of feature flags that will allow GitLab application processes to access Git data directly instead of going through the Gitaly service. Depending on your workload and disk performance, these flags may help improve performance. See the issue for more details.
To do this, run the Rake task:
gitlab-rake gitlab:features:enable_rugged
If you need to undo this setting for some reason, run:
gitlab-rake gitlab:features:disable_rugged
Known issues
On some customer systems, we have seen NFS clients slow precipitously due to
excessive network traffic from numerous TEST_STATEID
NFS
messages. This is
likely due to a Linux kernel
bug that may be fixed in
more recent kernels with this
commit.
Users encountering a similar issue may be advised to disable the NFS server delegation feature, which is an optimization to reduce the number of network round-trips needed to read or write files. To disable NFS server delegations on an Linux NFS server, do the following:
-
On the NFS server, run:
echo 0 > /proc/sys/fs/leases-enable sysctl -w fs.leases-enable=0
-
Restart the NFS server process. For example, on CentOS run
service nfs restart
.
Avoid using AWS's Elastic File System (EFS)
GitLab strongly recommends against using AWS Elastic File System (EFS). Our support team will not be able to assist on performance issues related to file system access.
Customers and users have reported that AWS EFS does not perform well for GitLab's
use-case. Workloads where many small files are written in a serialized manner, like git
,
are not well-suited for EFS. EBS with an NFS server on top will perform much better.
If you do choose to use EFS, avoid storing GitLab log files (e.g. those in /var/log/gitlab
)
there because this will also affect performance. We recommend that the log files be
stored on a local volume.
For more details on another person's experience with EFS, see Amazon's Elastic File System: Burst Credits
Avoid using PostgreSQL with NFS
GitLab strongly recommends against running your PostgreSQL database across NFS. The GitLab support team will not be able to assist on performance issues related to this configuration.
Additionally, this configuration is specifically warned against in the Postgres Documentation:
PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like locally-connected drives. If the client or server NFS implementation does not provide standard file system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes to the NFS server can cause data corruption problems.
For supported database architecture, please see our documentation on Configuring a Database for GitLab HA.
NFS Client mount options
Below is an example of an NFS mount point defined in /etc/fstab
we use on
GitLab.com:
10.1.1.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,soft,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
Note there are several options that you should consider using:
Setting | Description |
---|---|
vers=4.1 |
NFS v4.1 should be used instead of v4.0 because there is a Linux NFS client bug in v4.0 that can cause significant problems due to stale data. |
nofail |
Don't halt boot process waiting for this mount to become available |
lookupcache=positive |
Tells the NFS client to honor positive cache results but invalidates any negative cache results. Negative cache results cause problems with Git. Specifically, a git push can fail to register uniformly across all NFS clients. The negative cache causes the clients to 'remember' that the files did not exist previously. |
A single NFS mount
It's recommended to nest all gitlab data dirs within a mount, that allows automatic restore of backups without manually moving existing data.
mountpoint
└── gitlab-data
├── builds
├── git-data
├── home-git
├── shared
└── uploads
To do so, we'll need to configure Omnibus with the paths to each directory nested in the mount point as follows:
Mount /gitlab-nfs
then use the following Omnibus
configuration to move each data location to a subdirectory:
git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} })
user['home'] = '/gitlab-nfs/gitlab-data/home'
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'
To move the git
home directory, all GitLab services must be stopped. Run
gitlab-ctl stop && initctl stop gitlab-runsvdir
. Then continue with the
reconfigure.
Run sudo gitlab-ctl reconfigure
to start using the central location. Please
be aware that if you had existing data you will need to manually copy/rsync it
to these new locations and then restart GitLab.
Bind mounts
Alternatively to changing the configuration in Omnibus, bind mounts can be used to store the data on an NFS mount.
Bind mounts provide a way to specify just one NFS mount and then
bind the default GitLab data locations to the NFS mount. Start by defining your
single NFS mount point as you normally would in /etc/fstab
. Let's assume your
NFS mount point is /gitlab-nfs
. Then, add the following bind mounts in
/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
Using bind mounts will require manually making sure the data directories are empty before attempting a restore. Read more about the restore prerequisites.
Multiple NFS mounts
When using default Omnibus configuration you will need to share 5 data locations between all GitLab cluster nodes. No other locations should be shared. The following are the 5 locations need to be shared:
Location | Description | Default configuration |
---|---|---|
/var/opt/gitlab/git-data |
Git repository data. This will account for a large portion of your data | git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} }) |
/var/opt/gitlab/.ssh |
SSH authorized_keys file and keys used to import repositories from some other Git services |
user['home'] = '/var/opt/gitlab/' |
/var/opt/gitlab/gitlab-rails/uploads |
User uploaded attachments | gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads' |
/var/opt/gitlab/gitlab-rails/shared |
Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data | gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared' |
/var/opt/gitlab/gitlab-ci/builds |
GitLab CI build traces | gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds' |
Other GitLab directories should not be shared between nodes. They contain node-specific files and GitLab code that does not need to be shared. To ship logs to a central location consider using remote syslog. GitLab Omnibus packages provide configuration for UDP log shipping.
Having multiple NFS mounts will require manually making sure the data directories are empty before attempting a restore. Read more about the restore prerequisites.
Read more on high-availability configuration: