Using an External File System (Volume Services)
Page last updated:
This topic describes how Pivotal Application Service (PAS) app developers can read and write to a mounted file system from their apps. In PAS, a volume service provides a volume so your app can read or write to a reliable, non-ephemeral file system.
Note: If you are using Pivotal Application Service for Windows, see Using SMB Volumes in .NET Apps.
NFS is not available on Windows systems.
Prerequisite
Before you can use a volume service with your app, your Pivotal Platform admin must add a volume service to your deployment. For more information, see Enabling Volume Services.
You can run the Cloud Foundry Command Line Interface (cf CLI) cf marketplace
command to determine if any volume services are available. See the following example output of the NFS volume service:
$ cf marketplace service plans description nfs Existing Service for connecting to NFS volumes
If no volume service that fits your requirements exists, contact your Pivotal Platform admin.
Mount an External Filesystem
The sections below describe how to mount an external filesystem to your app.
Create and Bind a Service Instance
To use a volume service deployed by your Pivotal Platform admin, you must first create an instance of the specific volume service that you need. Follow the instructions below to create this service instance.
Note: For NFS-specific instructions and information, see NFS Volume Service.
In a terminal window, run
cf create-service SERVICE-NAME PLAN SERVICE-INSTANCE -c SHARE-JSON
to create a service instance. Replace the following with the specified values:SERVICE
: The name of the volume service that you want to use.PLAN
: The name of the service plan. Service plans are a way for providers to offer varying levels of resources or features for the same service.SERVICE-INSTANCE
: A name you provide for your service instance. Use any series of alpha-numeric characters, hyphens, and underscores. You can rename the instance at any time.- (NFS only)
SHARE-JSON
: If you create an instance of the NFS volume service, you must supply an extra parameter,share
, by using the-c
flag with a JSON string, in-line or in a file. This parameter forwards information to the broker about the NFS server and share required for the service.
The following example shows creating an instance of the
Existing
NFS service plan, passing an in-line JSON string:$ cf create-service nfs Existing nfs_service_instance -c '{"share": "10.10.10.10/export/myshare"}'
Run
cf bind-service YOUR-APP SERVICE-NAME -c GID-AND-UID-JSON MOUNT-PATH READ-ONLY-TRUE
to bind your service instance to an app. Replace the following with the specified values:YOUR-APP
: The name of the app for which you want to use the volume service.SERVICE-NAME
: The name of the volume service instance you created in the previous step.- (NFS only)
GID-AND-UID-JSON
: If you bind an instance of the NFS volume service, you must supply two extra parameters:gid
anduid
. You can specify these parameters with the-c
flag and a JSON string. The JSON can be inline or from a file. This parameter specifies thegid
anduid
to use when mounting the share to the app.UID
andGID
must be positive integer values.Note: For security reasons, nfs-volume v2.0.0 and later does not support
uid
andgid
values of0
. - (Optional)
MOUNT-PATH
: To mount the volume to a particular path within your app rather than the default path, you supply themount
parameter. Choose a path with a root-level folder that already exists in the container, such as/home
,/usr
, or/var
.Note: Do not specify a
MOUNT-PATH
within the/app
directory. For more information, see Mount Path Limitation. - (Optional)
READ-ONLY-TRUE
: When you issue thecf bind-service
command, Volume Services mounts a read-write file system by default. You can specify a read-only mount by adding"readonly":true
to the bind configuration JSON string.
The following example shows binding
my-app
to thenfs_service_instance
and specifying a read-only volume to be mounted to/var/volume1
, passing an in-line JSON string:$ cf bind-service my-app nfs_service_instance -c '{"uid":"1000","gid":"1000","mount":"/var/volume1","readonly":true}'
If you use an LDAP server, you must specifyusername
andpassword
instead of a UID and GID in this command. For example:$ cf bind-service my-app nfs_service_instance -c '{"username":"user1000","password":"secret","mount":"/var/volume1","readonly":true}'
Run
cf restage YOUR-APP
to complete the service binding by restaging your app. ReplaceYOUR-APP
with the name of your app.$ cf restage YOUR-APP
Access the Volume Service from Your App
To access the volume service from your app, you must know which file path to use in your code. You can view the file path in the details of the service binding, which are available from the VCAP_SERVICES environment variable.
Run
cf env YOUR-APP
to view environment variables for your app. ReplaceYOUR-APP
with the name of your app.$ cf env YOUR-APP "VCAP_SERVICES": { "nfs": [ { "credentials": {}, "label": "nfs", "name": "nfs_service_instance", "plan": "Existing", "provider": null, "syslog_drain_url": null, "tags": [ "nfs" ], "volume_mounts": [ { "container_dir": "/var/vcap/data/153e3c4b-1151-4cf7-b311-948dd77fce64", "device_type": "shared", "mode": "rw" } ] } ] }
Use the properties under
volume_mounts
for any information your app needs. Refer to the following table:Property Description container_dir
String containing the path to the mounted volume that you bound to your app. device_type
The NFS volume release. This currently only supports shared
devices. Ashared
device represents a distributed file system that can mount on all app instances simultaneously.mode
String that informs what type of access your app has to NFS, either read-only, ro
, or read and write,rw
.
Bind with an App Manifest
You can also bind volume services using an app manifest as described in the Services section of the Deploying with App Manifests topic. However, app manifests do not support bind configuration. If you want to bind a volume service using an app manifest, you must specify bind configuration when you create the service instance. The releases that support this are nfs-volume
v1.3.1 and later and smb-volume
v1.0.0 and later.
Mount Path Limitation
Do not specify a MOUNT-PATH
within the /app
directory, which is where PAS unpacks the droplet. If you specify a mount inside the /app
directory, the app may fail to start and parts of the app droplet may be written to the remote file share. This is because PAS mounts the volume before moving your compiled app into the droplet.
If your app requires the shared volume to be placed within the /app
directory:
Specify a mount volume in a location outside of the
/app
directory.Create a symbolic link at app startup time, prior to launching the app. For example:
cf push YOUR-APP -c "ln -s /var/volume1 /app/volume1 && \$HOME/boot.sh"
NFS Volume Service
This section describes how to use the NFS volume service.
Note: NFS is not available on Windows systems.
Create an NFS Volume Service
PAS offers two NFS volume services:
nfs
: This volume service provides support for NFS volumes using both v3 and v4.x protocols.- If you do not specify a
version
parameter in the create configuration, the protocol version used is negotiated between client and server at mount time. This usually results in the latest available version being used. - If you want to request a specific protocol version, include a
version
parameter in the create configuration. - For read-only mounts, the driver enables attribute caching. This results in fewer attribute RPCs and better performance.
- When you omit
uid
andgid
orusername
andpassword
in bind configuration, the driver skipsmapfs
mounting and performs just the normal kernel mount of the NFS file system without the overhead associated with FUSE mounts.
- If you do not specify a
nfs-legacy
(deprecated): Although it is deprecated, this volume service is still available due to the difficulty of retiring services. If you use this service, it performs exactly the same mount as thenfs
service.
Both services offer a single plan called Existing
.
To create an NFS volume service, follow the procedure below that corresponds to your use case.
Create an nfs Service (Auto-Negotiated Version)
You can create an NFS volume service using the Existing
plan of the nfs
service. Run the following command:
$ cf create-service nfs Existing SERVICE-INSTANCE-NAME -c '{"share":"SERVER/SHARE"}'
Where:
SERVICE-INSTANCE-NAME
is a name you provide for this NFS volume service instance.SERVER/SHARE
is the NFS address of your server and share.
Note: Ensure you omit the :
that usually follows the server name in the address.
You can run the cf services
command to confirm that your newly-created NFS volume service displays in the output.
Create an nfs Service (Explicit Version)
You can create an NFS volume service with a specific NFS protocol version using the Existing
plan of the nfs
service. Run the following command:
$ cf create-service nfs Existing SERVICE-INSTANCE-NAME -c '{"share":"SERVER/SHARE", "version":"NFS-PROTOCOL"}'
Where:
SERVICE-INSTANCE-NAME
is a name you provide for this NFS volume service instance.SERVER/SHARE
is the NFS address of your server and share.VERSION
is the NFS protocol you want to use. For example, if you want to use NFSv4, set the version to4.1
. Valid values are3.0
,4.0
,4.1
or4.2
.
Note: Ensure you omit the :
that usually follows the server name in the address.
You can run the cf services
command to confirm that your newly-created NFS volume service displays in the output.
Existing nfs-legacy Services:
With the release of NFS Volume Service v1.5.4, the original fuse-based NFS service has been deprecated in favor of the newer kernel mount-based NFS service. Existing NFS volume service bindings will now be listed as nfs-legacy
. To switch over from nfs-legacy
to the newer nfs
service, Pivotal recommends you re-create and re-bind your nfs
service instances.
With the release of NFS Volume Service v2.0.0, the nfs-legacy
service has been rewritten to use the nfs
service. To avoid being affected when the nfs-legacy
service is retired, re-create and re-bind your service instances using the nfs
service.
Deploy and Bind a Sample App
This section describes how to deploy a sample app and bind it to the NFS volume service.
Clone the GitHub repository and push the
pora
test app:cd ~/workspace
git clone https://github.com/cloudfoundry/persi-acceptance-tests.git
cd ~/workspace/persi-acceptance-tests/assets/pora
cf push pora --no-start
Bind your service instance to an app. Run:
cf bind-service YOUR-APP SERVICE-NAME -c '{"uid":"UID","gid":"GID","mount":"OPTIONAL-MOUNT-PATH","readonly":true}'
Where:
YOUR-APP
is the name of the app for which you want to use the volume service.SERVICE-NAME
is the name of the volume service instance you created above.- (Optional)
UID
andGID
are the UID and GID to use when mounting the share to the app. TheGID
andUID
must be positive integer values. Provide the UID and GID as a JSON string in-line or in a file. If you omituid
andgid
, the driver skipsmapfs
mounting and performs just the normal kernel mount of the NFS file system without the overhead associated with FUSE mounts.Note: For security reasons, nfs-volume v2.0.0 and later does not support
uid
andgid
values of0
.Note: The user specified by
uid
must have access to the files on the share. Whenuid
andgid
are omitted, the app file operations use the UID of the running app process. For buildpack apps, this UID is always2000
. For Docker apps, the effective UID is the same as the UID of the process inside the Docker container, except forroot
, which is mapped to4294967294
outside the Docker container.- (Optional)
OPTIONAL-MOUNT-PATH
is a JSON string that indicates the volume should be mounted to a particular path within your app rather than the default path. Choose a path with a root-level folder that already exists in the container, such as/home
,/usr
, or/var
.Note: Do not specify a
MOUNT-PATH
within the/app
directory, which is where PAS unpacks the droplet. For more information, see Mount a Shared Volume in the /app Directory. - (Optional)
"readonly":true
is a JSON string that creates a read-only mount. By default, Volume Services mounts a read-write file system. For read-only mounts, the driver enables attribute caching. This results in fewer attribute RPCs and better performance. - (Optional)
cache
is a parameter that enables attribute caching for read-write mounts using your operating system’s default values. When you run thecf bind-service
command, Volume Services mounts the remote file system with attribute caching disabled by default. You can enable attribute caching for read-write mounts by adding"cache":true
to the bind configuration JSON string.
- (Optional)
Start the app:
$ cf start pora
Use the following
curl
command to confirm the app is running. The command returns an instance index for your app.$ curl http://pora.YOUR-CF-DOMAIN.com
Use the following
curl
command to confirm the app can access the shared volume. The command writes a file to the share and then reads it back out again.$ curl http://pora.YOUR-CF-DOMAIN.com/write
Additional Information
This section provides additional information about using the NFS Volume Service.
Configure LDAP Credentials with Service Instance Creation
If your Pivotal Platform deployment has LDAP enabled, you can configure LDAP credentials for your NFS Volume Service instance.
To configure LDAP credentials while creating your NFS Volume Service instance:
- Specify values for
username
andpassword
in the JSON string for yourcf create-service
command:$ cf create-service nfs PLAN SERVICE-INSTANCE-NAME -c '{"share":"SERVER/SHARE", "username":"USERNAME", "password":"PASSWORD"}'
Where:PLAN
is the name of the service plan.SERVICE-INSTANCE-NAME
is a name you provide for this NFS Volume Service instance.SERVER/SHARE
is the NFS address of your server and share.USERNAME
is a username you provide for this NFS Volume Service instance.PASSWORD
is a password you provide for this NFS Volume Service instance.
Specify Bind Parameters During Service Instance Creation
As of nfs-volume-release
v1.3.1, you can specify bind parameters in advance, when you create a service instance. Use this option if you bind the service to your app in an app manifest, where bind configuration is not supported.
File Locking with flock() and lockf()/fcntl()
Apps that use file locking through unix system calls such as flock()
and fcntl()
or script commands such as flock
may use the nfs
service. The nfs-legacy
service uses a fuse mounting process that does not enforce locks across Diego Cells.
Hard Links in the NFS Service
The mapfs UID mapping layer used by the NFS service does not support hard link operations.
You get a Function not implemented
error if you try to create a hard link in an NFS share
when uid
or username
has been specified for the service.
Workarounds for this issue:
- Use symbolic links,
ln -s
, instead of hard links. - Omit the
uid
andgid
or theusername
andpassword
parameters to mount the share without UID mapping. For this workaround, the app user must have access to the files on the share.
SMB Volume Service
This section describes how to use a Server Message Block (SMB) volume service. For more information about SMB volume services, see Microsoft SMB Protocol and CIFS Protocol Overview in the Microsoft documentation.
Note: If you are using Pivotal Application Service for Windows, see Using SMB Volumes in .NET Apps.
Create an SMB Volume Service
PAS offers one SMB volume service:
smb
: This volume service provides support for existing SMB shares.
The service offers a single plan called Existing
.
To create an SMB volume service:
Create the service. Run:
$ cf create-service smb Existing SERVICE-INSTANCE-NAME -c '{"share":"//SERVER/SHARE", "version":"SMB-VERSION"}'
Where:
SERVICE-INSTANCE-NAME
is a name you provide for this SMB volume service instance.//SERVER/SHARE
is the SMB address of your server and share.- (Optional)
SMB-VERSION
is the SMB protocol version you want to use. For example, to use SMB 2.1, set the version to2.1
. Valid values are1.0
,2.0
,2.1
, or3.0
. If you do not specify aversion
, the client and server negotiate a protocol version at mount time. The client and server usually select the latest available version.
Confirm that the SMB volume service appears in your list of services. Run:
cf services
Deploy and Bind a Sample App
This section describes how to deploy a sample app and bind it to the SMB volume service.
Clone the GitHub repository and push the
pora
test app:cd ~/workspace
git clone https://github.com/cloudfoundry/persi-acceptance-tests.git
cd ~/workspace/persi-acceptance-tests/assets/pora
cf push pora --no-start
Bind the service to your app:
$ cf bind-service pora SERVICE-INSTANCE-NAME -c '{"username":"USERNAME","password":"PASSWORD"}'
Where:
SERVICE-INSTANCE-NAME
: The name of the volume service instance you created previously.USERNAME
andPASSWORD
: The username and password to use when mounting the share to the app. This allows you to interact with your SMB server as a specific user while allowing PAS to run your app as an arbitrary user.Optional parameters:
mount
: Use this option to specify the path at which volumes mount to the app container. The default is an arbitrarily-named folder in/var/vcap/data
. You may need to modify this value if your app has specific requirements. For example:cf bind-service pora myVolume -c '{"username":"some-user","password":"some-password","mount":"/var/path"}'
readonly
: When you issue thecf bind-service
command, Volume Services mounts a read-write file system by default. You can specify a read-only mount by adding"readonly":true
to the bind configuration JSON string.domain
: In case if your user is in windows domain you can specifydomain
parameter.
Start the app:
$ cf start pora
Use the following
curl
command to confirm the app is running. The command returns an instance index for your app.$ curl http://pora.YOUR-CF-DOMAIN.com
Use the following
curl
command to confirm the app can access the shared volume. The command writes a file to the share and then reads it back out again.$ curl http://pora.YOUR-CF-DOMAIN.com/write