The dynamic mount feature for File Storage NAS allows each user session of a function instance to be mounted to a dedicated subdirectory. This provides secure isolation for persistent data in a multitenancy environment.
Background
AI agent applications are developing rapidly. Many scenarios now require running custom user code in a sandboxed container. These scenarios also require saving key assets generated during a session, such as files, project code, and datasets, to persistent storage. These applications are often deployed as multitenant Software as a Service (SaaS). Thousands of user sessions can run at the same time. Each session needs its own isolated storage space.
Previously, developers mounted all sessions to a single shared NAS root directory. This created a serious risk of unauthorized access. A malicious or abnormal session could use directory traversal or privilege escalation to access or modify other tenants' data. This method does not meet enterprise security and compliance requirements.
To address this challenge, Function Compute now extends isolation to the persistent storage layer. This builds on existing support for session affinity and session isolation. Function Compute introduces the dynamic mount feature for File Storage NAS. This feature allows each AI Sandbox session to be automatically and securely mounted to a dedicated NAS subdirectory when it starts. This provides end-to-end multi-tenant data isolation, from compute to storage.
Features
Core capabilities
The dynamic NAS mount feature in Function Compute lets you mount a dedicated NAS directory for a session when you create the session. You can also specify an independent user identity (POSIX UID/GID) as needed. The core features include the following:
Dynamic and on-demand: Storage mounting is tied to the session lifecycle. Storage is allocated only when needed and is automatically detached when the session is destroyed.
Strong isolation: By assigning a unique User ID and Group ID to each session, you can completely isolate data access permissions for different tenants at the file system level.
High flexibility: You can mount different subdirectories of the NAS file system for different tenants. This makes data partitioning easy.
Performance optimization: Combined with session prefetching, you can pre-mount data directories when an instance starts. This speeds up the loading of models or data.
How it works
This feature deeply integrates the NAS mount operation with the CreateSession API call. The following process uses HeaderField affinity as an example:
Preparation phase: Create and configure a session with storage
The goal of this phase is to create an isolated session environment that is bound to specific storage for later use.
Initiate a creation request: The backend management service calls the
CreateSessionAPI. The request specifies the NAS mount configuration and the user identity (UID/GID) for isolation.Prepare the instance and mount: After Function Compute receives the request, it prepares a function instance. This instance performs the NAS mount operation based on the configuration and mounts the dedicated directory to a specified path in the instance, such as
/mnt/data.Bind and return the ID: After the mount is successful, the platform binds the instance to a newly generated unique
SessionIDand returns this ID to the backend service.
Invocation phase: Use the configured session
This phase uses the prepared session environment to execute the actual business logic.
Initiate an invocation request: When the backend management service calls the
InvokeFunctionAPI, it passes the previously obtainedSessionIDin a specific HTTP request header, such asx-affinity-header-v1.Route the request: The gateway and scheduler of the Function Compute platform use this
SessionIDto accurately route the request to the specific, bound function instance.Execute the code: The function code runs in the instance. Because the environment and permissions are already configured, the code can directly read from and write to the mounted NAS directory.
Return the result: After the function finishes running, the result is returned through the various layers to the original caller.
Scope
Feature availability: The session lifecycle management feature is in public preview. To use this feature, submit a ticket to request access.
Region restrictions: This feature is not supported in the China (Hohhot) region. The dynamic NAS mount feature is available only in the US (Silicon Valley) region. If you need support for other regions, specify this when you submit a ticket.
File Storage NAS: You must have already created a NAS file system and planned the directory structure for multi-tenant data isolation.
Session affinity types: This feature applies to HeaderField and Cookie affinity types.
Procedure
The following sections use the Python SDK as an example to demonstrate how to configure and use dynamic NAS mounting for a function.
Step 1: Configure the function (prerequisites)
To enable dynamic NAS mounting for a session, you must complete three key settings when you create a function or update its configuration:
Enable session affinity:
Log on to the Function Compute console and click Function Management > Functions.
On the Functions page, click the name of the target function to go to its details page.
Choose the Configurations tab. Click
to the right of Advanced Settings.Turn on the Session Affinity switch, select HeaderField affinity, and configure the Header Name (example:
x-affinity-header-v1).NoteThe name cannot start with the
x-fc-prefix. It must start with a letter. The subsequent characters can be digits, hyphens (-), underscores (_), or letters. The length must be between 5 and 40 characters.Click Deploy to apply the configuration.
Enable instance isolation: Navigate to Configurations > Advanced Settings > Instance isolation and select Session Isolation.
Allow access to VPC:
Navigate to Configurations > Advanced Settings > Network and enable Access To VPC.
For Configuration Mode, select Custom Configuration.
For VPC, select the VPC that contains the mount target.
Step 2: Create a session with a NAS configuration
Install dependencies
macOS / Linux
# Install using pip3 pip3 install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util # If you encounter permission issues, use the --user parameter pip3 install --user alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util # For macOS Homebrew Python environments, use --break-system-packages pip3 install --break-system-packages alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_utilWindows
# Install using pip pip install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util # Or, specify Python 3 py -3 -m pip install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_utilWrite the code to create a session
Create a Python code file, for example,
createSession.py. Copy the following code into the file and replace the core parameters. The example shows how to create a session for 'Tenant A'. It mounts the tenant's dedicated NAS directory (<YOUR-NAS-SERVER-ADDR>:/tenant-a-data) to the/mnt/datapath in the instance and specifies the user identity asUID=1001andGID=1001.Core methods and parameters:
ImportantYou can simultaneously configure dynamic NAS mounting for a session and NAS mounting for a function in Configuration > Advanced Configuration > Storage. However, note the following:
The
User ID/Group IDdefined inNASConfigbelow must be consistent with the user (User ID)/user group (Group ID) used in the function mount configuration.The same mount path (
mount_dir) cannot be used for both session dynamic mounting and function mounting.
config.endpoint:<Account ID>: Replace with your Alibaba Cloud account ID.
<Endpoint>: For more information, see the list of Function Compute 3.0 service endpoints. The format is
fcv3.[region_id].aliyuns.com.
CreateSessionInput:session_ttlin_seconds: The total session lifecycle in seconds.
session_idle_timeout_in_seconds: The session idle timeout in seconds.
client.create_session_with_options: Replace <Function Name> with the name of the function for which you are creating the session.NASMountConfig: NAS mount configuration.mount_dir: The mount path in the instance, such as/home/test.server_addr: The NAS file system address and the tenant's dedicated subdirectory.
user_id: Specifies an independent POSIX User ID for this session.group_id: Specifies an independent POSIX Group ID for this session.
# -*- coding: utf-8 -*- from alibabacloud_fc20230330.client import Client as FC20230330Client from alibabacloud_credentials.client import Client as CredentialClient from alibabacloud_tea_openapi import models as open_api_models from alibabacloud_fc20230330 import models as fc20230330_models from alibabacloud_tea_util import models as util_models # 1. Create an account client. credential = CredentialClient() config = open_api_models.Config(credential=credential) config.endpoint = f'<Account ID>.<Endpoint>' client = FC20230330Client(config) # 2. Prepare the NAS mount configuration. nas_mount_config = fc20230330_models.NASMountConfig( mount_dir='/mnt/data', # Mount path in the instance server_addr='<YOUR-NAS-SERVER-ADDR>:/<tenant-a-path>' # NAS file system address and the tenant's dedicated subdirectory ) # 3. Configure NAS and user identity (assign a unique UID/GID to Tenant A). nas_config = fc20230330_models.NASConfig( mount_points=[nas_mount_config], user_id=1001, # Specify an independent POSIX User ID for this session. group_id=1001 # Specify an independent POSIX Group ID for this session. ) # 4. Construct the CreateSession request. create_session_input = fc20230330_models.CreateSessionInput( nas_config=nas_config, session_ttlin_seconds=3600, session_idle_timeout_in_seconds=600 ) create_session_request = fc20230330_models.CreateSessionRequest( body=create_session_input ) # 5. Send the request. runtime = util_models.RuntimeOptions() response = client.create_session_with_options('<Function Name>', create_session_request, {}, runtime) # 6. Get the session ID from the response. print(response.body.to_map()) session_id = response.body.session_id print(f"Session created successfully. Session ID: {session_id}")Run the code
export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI**************** export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<yourAccessKeySecret> python3 creatSession.pyParameters:
ALIBABA_CLOUD_ACCESS_KEY_ID: The AccessKey ID of your Alibaba Cloud account or RAM user.
ALIBABA_CLOUD_ACCESS_KEY_SECRET: The AccessKey secret of your Alibaba Cloud account or RAM user.
Sample response
{ 'containerId': 'c-********-********-************', 'createdTime': '2025-10-30T06:38:10Z', 'functionName': '****', 'lastModifiedTime': '2025-10-30T06:38:10Z', 'nasConfig': { 'groupId': 1001, 'mountPoints': [ { 'enableTLS': False, 'mountDir': '/home/test', 'serverAddr': '*-*.*.nas.aliyuncs.com:/test' } ], 'userId': 1001 }, 'qualifier': 'LATEST', 'sessionAffinityType': 'HEADER_FIELD', 'sessionId': '******************', 'sessionIdleTimeoutInSeconds': 600, 'sessionStatus': 'Active', 'sessionTTLInSeconds': 3600 } Session created successfully. Session ID: ************
Step 3: Use the mounted NAS in the function
Now, when you call the function, you can include the SessionID obtained in the previous step. The function instance can then access the mounted /mnt/data directory. The following example uses a web function:
Modify the function code and redeploy it.
import os from flask import Flask, request, jsonify # ... (app setup) ... # Assume the NAS mount target is at /mnt/data NAS_MOUNT_PATH = '/mnt/data' app = Flask(__name__) @app.route('/<path:path>', methods=['GET', 'POST']) def handle_nas_request(path): rid = request.headers.get('x-fc-request-id') print(f"FC Invoke Start RequestId: {rid}") # Construct the full path of the file on NAS # Note: Prevent path traversal attacks safe_path = os.path.normpath(os.path.join(NAS_MOUNT_PATH, path)) if not safe_path.startswith(NAS_MOUNT_PATH): return "Path traversal attempt detected!", 400 response_data = {} if request.method == 'POST': # Write to the file body = request.data.decode('utf-8') try: with open(safe_path, 'w') as f: f.write(body) response_data['message'] = f"Successfully wrote to {safe_path}" print(f"Wrote to {safe_path}") except Exception as e: return str(e), 500 elif request.method == 'GET': # Read from the file try: if os.path.exists(safe_path) and os.path.isfile(safe_path): with open(safe_path, 'r') as f: content = f.read() response_data['content'] = content print(f"Read from {safe_path}") else: return f"File not found: {safe_path}", 404 except Exception as e: return str(e), 500 print(f"FC Invoke End RequestId: {rid}") return jsonify(response_data) # Use jsonify to return a response in JSON format # ... (if __name__ == '__main__': block) ...Call the function and verify the result.
Call the InvokeFunction API to call the function with the session.
Sample code and description:
InvokeFunctionHeaders: Construct the request header. Include thesessionIdreturned in the previous step in the request header. The value of theHeader Keymust be the same as the value that you set when you enabled session affinity, for example,x-affinity-header-v1. This binds the session for routing.# -*- coding: utf-8 -*- from alibabacloud_fc20230330.client import Client as FC20230330Client from alibabacloud_credentials.client import Client as CredentialClient from alibabacloud_tea_openapi import models as open_api_models from alibabacloud_fc20230330 import models as fc20230330_models from alibabacloud_tea_util import models as util_models session_id = '************' function_name = 'my-session-nas' # 1. Create an account client. credential = CredentialClient() config = open_api_models.Config(credential=credential) config.endpoint = f'<Account ID>.<Endpoint>' client = FC20230330Client(config) # 2. Construct the request header. The Header Key (x-affinity-header-v1) must match the session affinity key configured for the function. headers = fc20230330_models.InvokeFunctionHeaders( common_headers={ "x-affinity-header-v1": session_id } ) # 3. Construct the invocation request (you can pass a body as needed). invoke_request = fc20230330_models.InvokeFunctionRequest( body='your_request_payload'.encode('utf-8') # Sample payload ) runtime = util_models.RuntimeOptions() try: # 4. Send the invocation. invoke_response = client.invoke_function_with_options( function_name, invoke_request, headers, runtime ) # 5. Process the response. print(f"Status Code: {invoke_response.status_code}") print(f"Response Body: {invoke_response.body.decode('utf-8')}") except Exception as error: print(error.message)
What to do next: Delete the session
After the task is complete, you can call the DeleteSession API to release the session resources.
Production environment recommendations
UID/GID planning: To ensure isolation, you must assign a unique POSIX UID to each tenant.
Directory quotas: To prevent a single tenant from using up all the shared storage space, configure directory quotas for each tenant's root directory on the NAS side.
Data Garbage Collection (GC): The
<a baseurl="t3177146_v1_0_0.xdita" data-node="6117158" data-root="85764" data-tag="xref" href="t3144017.xdita#" id="3eaee6079d3g7">DeleteSession - Delete session resources</a>operation does not automatically delete file data on NAS. You need to set up an asynchronous garbage collection mechanism to periodically scan and delete unreferenced file directories to reclaim storage space.
Billing
Billing starts after a session is successfully created by calling the CreateSession API. You are charged based on the instance runtime.
You are charged for a session even if it is idle, as long as it has not expired or been deleted.
After you call the DeleteSession API, the billing behavior varies based on the following two scenarios:
In non-isolated mode, DeleteSession does not stop ongoing invocations. The instance resources associated with the session continue to be billed until the execution is complete.
In isolated mode, DeleteSession stops running requests, destroys the bound instance resources, and stops billing.
During the active period of a session, if there are requests, you are billed at the rate for active elastic instances. If there are no requests, you are billed at the rate for idle elastic instances.
References and API descriptions
Feature | Behavior |
| |
| |
Lists the sessions for a specified function. Supports filtering by
| |
Updates the session idle timeout ( | |
|