在 Linux 客户端上装载 SMB Azure 文件共享

可以使用 SMB 内核客户端在 Linux 分发版中装载 Azure 文件共享。

本文介绍如何使用 NTLMv2 身份验证(存储帐户密钥)装载 SMB Azure 文件共享。 出于安全原因,首选使用基于标识的身份验证。 请参阅 通过 SMB 为访问 Azure 文件的 Linux 客户端启用 Active Directory 身份验证

适用于

文件共享类型 SMB NFS
标准文件共享 (GPv2)、LRS/ZRS 是 否
标准文件共享 (GPv2)、GRS/GZRS 是 否
高级文件共享 (FileStorage)、LRS/ZRS 是 否

协议

建议使用 SMB 3.1.1。 默认情况下,Azure 文件存储要求进行传输中加密,而只有 SMB 3.0+ 支持传输中加密。 Azure 文件存储也支持 SMB 2.1(后者不支持传输中加密),但出于安全原因,你无法使用 SMB 2.1 从另一 Azure 区域或本地装载 Azure 文件共享。 除非应用程序专门需要用到 SMB 2.1,否则请使用 SMB 3.1.1。 SMB 2.1 支持已添加到 Linux 内核版本 3.7,因此,如果在 3.7 之后的版本使用 Linux 内核版本,则应支持 SMB 2.1。

配送 SMB 3.1.1(推荐) SMB 3.0
Linux 内核版本
  • 基本 3.1.1 支持:4.17
  • 默认装载:5.0
  • AES-128-GCM 加密:5.3
  • AES-256-GCM 加密:5.10
  • 基本3.0支持:3.12
  • AES-128-CCM 加密:4.11
Ubuntu AES-128-GCM 加密:18.04.5 LTS+ AES-128-CCM 加密:16.04.4 LTS+
Red Hat Enterprise Linux (RHEL)
  • 基本:8.0+
  • 默认装载:8.2+
  • AES-128-GCM 加密:8.2+
7.5+
Debian 基本:10+ AES-128-CCM 加密:10+
SUSE Linux Enterprise Server AES-128-GCM 加密:15 SP2+ AES-128-CCM 加密:12 SP2+

如果 Linux 分发版未在表中列出,可以使用以下命令检查 Linux 内核版本 uname

uname -r

先决条件

  • 确保已安装 cifs-utils 包。在所选的 Linux 发行版上使用包管理器安装最新版 cifs-utils 包。

在 Ubuntu 和 Debian 上,使用 apt 包管理器:

sudo apt update
sudo apt install cifs-utils

在其他分发版上,请使用相应的包管理器,或从源编译

  • 最新版本的 Azure 命令行接口 (CLI)。 若要详细了解如何安装 Azure CLI,请参阅安装 Azure CLI 并选择操作系统。 如果你想要在 PowerShell 6+ 中使用 Azure PowerShell 模块,也可使用;不过,本文中的说明适用于 Azure CLI。

  • 确保已打开端口 445:SMB 通过 TCP 端口 445 通信 - 请确保防火墙或 ISP 未阻止 TCP 端口 445 与客户端计算机通信。 替换 <your-resource-group><your-storage-account>,然后运行以下脚本:

    RESOURCE_GROUP_NAME="<your-resource-group>"
    STORAGE_ACCOUNT_NAME="<your-storage-account>"
    
    # This command assumes you have logged in with az login
    HTTP_ENDPOINT=$(az storage account show \
        --resource-group $RESOURCE_GROUP_NAME \
        --name $STORAGE_ACCOUNT_NAME \
        --query "primaryEndpoints.file" --output tsv | tr -d '"')
    SMBPATH=$(echo $HTTP_ENDPOINT | cut -c7-${#HTTP_ENDPOINT})
    FILE_HOST=$(echo $SMBPATH | tr -d "/")
    
    nc -zvw3 $FILE_HOST 445
    

    如果连接成功,应会看到如下所示的输出:

    Connection to <your-storage-account> 445 port [tcp/microsoft-ds] succeeded!
    

    如果无法在企业网络中打开端口 445,或者 ISP 阻止此类操作,可以使用 VPN 连接或 ExpressRoute 来解决端口 445 的相关问题。 有关详细信息,请参阅直接访问 Azure 文件共享时的网络注意事项

权限

本文中的所有装载脚本都将使用默认的 0755 Linux 文件和文件夹权限装载文件共享。 这意味着为文件/目录所有者读取、写入和执行、为所有者组中的用户读取和执行,以及为其他用户读取和执行。 根据组织的安全策略,可能需要在装载选项中设置备用 uid/giddir_modefile_mode 权限。 若要详细了解如何设置权限,请参阅 Unix 符号表示法。 有关装载选项的列表,请参阅装载选项

Unix 样式权限支持

您还可以通过客户端实施访问控制,并在您的装载命令中添加 modefromsid,idsfromsid 装载选项,以获得 Unix 风格权限支持。 要使此工作正常进行:

  • 访问共享的所有客户端都需要使用 modefromsid,idsfromsid 进行装载
  • UID/GID 必须跨所有客户端保持一致
  • 客户端必须运行以下受支持的发行版之一:Ubuntu 20.04+、SLES 15 SP3+

使用 mount 按需装载 Azure 文件共享

在 Linux OS 上装载文件共享时,远程文件共享将在本地文件系统中以文件夹的形式表示。 可将文件共享装载到系统上的任何位置。 以下示例将装载到 /media 路径下。 可以通过修改 $MNT_ROOT 变量将此路径更改为所需的首选路径。

请将 <resource-group-name><storage-account-name><file-share-name> 替换为适合你的环境的信息。

RESOURCE_GROUP_NAME="<resource-group-name>"
STORAGE_ACCOUNT_NAME="<storage-account-name>"
FILE_SHARE_NAME="<file-share-name>"

MNT_ROOT="/media"
MNT_PATH="$MNT_ROOT/$STORAGE_ACCOUNT_NAME/$FILE_SHARE_NAME"

sudo mkdir -p $MNT_PATH

接下来,运行以下脚本来初始化凭据文件。

# Create a folder to store the credentials for this storage account and
# any other that you might set up.
CREDENTIAL_ROOT="/etc/smbcredentials"
sudo mkdir -p "/etc/smbcredentials"

# Get the storage account key for the indicated storage account.
# You must be logged in with az login and your user identity must have
# permissions to list the storage account keys for this command to work.
STORAGE_ACCOUNT_KEY=$(az storage account keys list \
    --resource-group $RESOURCE_GROUP_NAME \
    --account-name $STORAGE_ACCOUNT_NAME \
    --query "[0].value" --output tsv | tr -d '"')

# Create the credential file for this individual storage account
SMB_CREDENTIAL_FILE="$CREDENTIAL_ROOT/$STORAGE_ACCOUNT_NAME.cred"
if [ ! -f $SMB_CREDENTIAL_FILE ]; then
    echo "username=$STORAGE_ACCOUNT_NAME" | sudo tee $SMB_CREDENTIAL_FILE > /dev/null
    echo "password=$STORAGE_ACCOUNT_KEY" | sudo tee -a $SMB_CREDENTIAL_FILE > /dev/null
else
    echo "The credential file $SMB_CREDENTIAL_FILE already exists, and was not modified."
fi

# Change permissions on the credential file so only root can read or modify the password file.
sudo chmod 600 $SMB_CREDENTIAL_FILE

现在,你可以使用凭据文件通过 mount 命令装载文件共享。 在以下示例中,该 $SMB_PATH 命令使用存储帐户的文件终结点的完全限定域名进行填充。 有关 SMB 装载选项的列表,请参阅装载选项

注意

从 Linux 内核版本 5.0 开始,SMB 3.1.1 是默认的协商协议。 如果使用的 Linux 内核版本低于 5.0,请在装载选项列表中指定 vers=3.1.1

# This command assumes you have logged in with az login
HTTP_ENDPOINT=$(az storage account show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $STORAGE_ACCOUNT_NAME \
    --query "primaryEndpoints.file" --output tsv | tr -d '"')
SMB_PATH=$(echo $HTTP_ENDPOINT | cut -c7-${#HTTP_ENDPOINT})$FILE_SHARE_NAME

STORAGE_ACCOUNT_KEY=$(az storage account keys list \
    --resource-group $RESOURCE_GROUP_NAME \
    --account-name $STORAGE_ACCOUNT_NAME \
    --query "[0].value" --output tsv | tr -d '"')

sudo mount -t cifs $SMB_PATH $MNT_PATH -o credentials=$SMB_CREDENTIAL_FILE,serverino,nosharesock,actimeo=30,mfsymlinks

如果需要,还可将同一个 Azure 文件共享装载到多个装入点。

使用完 Azure 文件共享后,请使用 sudo umount $mntPath 卸载共享。

自动装载文件共享

在 Linux OS 上装载文件共享时,远程文件共享将在本地文件系统中以文件夹的形式表示。 可将文件共享装载到系统上的任何位置。 以下示例将装载到 /media 路径下。 可以通过修改 $MNT_ROOT 变量将此路径更改为所需的首选路径。

MNT_ROOT="/media"
sudo mkdir -p $MNT_ROOT

使用存储帐户名称作为文件共享的用户名,将存储帐户密钥用作密码。 因为存储帐户凭据可随时更改,所以应将存储帐户的凭据与装载配置分开存储。

以下示例演示如何创建一个用于存储凭据的文件。 请记得将 <resource-group-name><storage-account-name> 替换为适合你的环境的信息。

RESOURCE_GROUP_NAME="<resource-group-name>"
STORAGE_ACCOUNT_NAME="<storage-account-name>"

# Create a folder to store the credentials for this storage account and
# any other that you might set up.
CREDENTIAL_ROOT="/etc/smbcredentials"
sudo mkdir -p "/etc/smbcredentials"

# Get the storage account key for the indicated storage account.
# You must be logged in with az login and your user identity must have
# permissions to list the storage account keys for this command to work.
STORAGE_ACCOUNT_KEY=$(az storage account keys list \
    --resource-group $RESOURCE_GROUP_NAME \
    --account-name $STORAGE_ACCOUNT_NAME \
    --query "[0].value" --output tsv | tr -d '"')

# Create the credential file for this individual storage account
SMB_CREDENTIAL_FILE="$CREDENTIAL_ROOT/$STORAGE_ACCOUNT_NAME.cred"
if [ ! -f $SMB_CREDENTIAL_FILE ]; then
    echo "username=$STORAGE_ACCOUNT_NAME" | sudo tee $SMB_CREDENTIAL_FILE > /dev/null
    echo "password=$STORAGE_ACCOUNT_KEY" | sudo tee -a $SMB_CREDENTIAL_FILE > /dev/null
else
    echo "The credential file $SMB_CREDENTIAL_FILE already exists, and was not modified."
fi

# Change permissions on the credential file so only root can read or modify the password file.
sudo chmod 600 $SMB_CREDENTIAL_FILE

若要自动装载文件共享,可以选择通过 /etc/fstab 实用工具使用静态装载,或者通过 autofs 实用工具使用动态装载。

通过 /etc/fstab 进行静态装载

沿用前面所述的环境,在装载文件夹下为存储帐户/文件共享创建一个文件夹。 请将 <file-share-name> 替换为你的 Azure 文件共享的相应名称。

FILE_SHARE_NAME="<file-share-name>"

MNT_PATH="$MNT_ROOT/$STORAGE_ACCOUNT_NAME/$FILE_SHARE_NAME"
sudo mkdir -p $MNT_PATH

最后,在 /etc/fstab 文件中为 Azure 文件共享创建一条记录。 在以下命令中,使用了默认的 0755 Linux 文件和文件夹权限,这表示所有者拥有读取、写入和执行权限(基于文件/目录 Linux 所有者),所有者组中的用户拥有读取和执行权限,系统中的其他用户拥有读取和执行权限。 您可能希望根据需要为挂载设置备用的 uidgiddir_modefile_mode 权限。 若要详细了解如何设置权限,请参阅 UNIX 数值表示法。 有关 SMB 装载选项的列表,请参阅装载选项

提示

如果希望运行 .NET Core 应用程序的 Docker 容器能够写入 Azure 文件共享,请在 SMB 装载选项中包含 nobrl,以避免将字节范围锁定请求发送到服务器。

HTTP_ENDPOINT=$(az storage account show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $STORAGE_ACCOUNT_NAME \
    --query "primaryEndpoints.file" --output tsv | tr -d '"')
SMB_PATH=$(echo $HTTP_ENDPOINT | cut -c7-${#HTTP_ENDPOINT})$FILE_SHARE_NAME

if [ -z "$(grep $SMB_PATH\ $MNT_PATH /etc/fstab)" ]; then
    echo "$SMB_PATH $MNT_PATH cifs _netdev,nofail,credentials=$SMB_CREDENTIAL_FILE,serverino,nosharesock,actimeo=30,mfsymlinks" | sudo tee -a /etc/fstab > /dev/null
else
    echo "/etc/fstab was not modified to avoid conflicting entries as this Azure file share was already present. You might want to double check /etc/fstab to ensure the configuration is as desired."
fi

sudo mount -a

注意

从 Linux 内核版本 5.0 开始,SMB 3.1.1 是默认的协商协议。 可以使用 vers 装载选项指定备用协议版本(协议版本为 3.1.13.02.1)。

通过 autofs 进行动态装载

若要使用 autofs 实用工具动态装载文件共享,请在你选择的 Linux 发行版上使用包管理器安装该实用工具。

在 Ubuntu 和 Debian 发行版上,使用 apt 包管理器:

sudo apt update
sudo apt install autofs

接下来,更新 autofs 配置文件。 有关 SMB 装载选项的列表,请参阅装载选项

FILE_SHARE_NAME="<file-share-name>"

HTTP_ENDPOINT=$(az storage account show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $STORAGE_ACCOUNT_NAME \
    --query "primaryEndpoints.file" --output tsv | tr -d '"')
SMB_PATH=$(echo $HTTP_ENDPOINT | cut -c7-$(expr length $HTTP_ENDPOINT))$FILE_SHARE_NAME

echo "$FILE_SHARE_NAME -fstype=cifs,credentials=$SMB_CREDENTIAL_FILE,serverino,nosharesock,actimeo=30,mfsymlinks :$SMB_PATH" > /etc/auto.fileshares

echo "/fileshares /etc/auto.fileshares --timeout=60" > /etc/auto.master

最后一步是重启 autofs 服务。

sudo systemctl restart autofs

装载选项

在 Linux 上装载 SMB Azure 文件共享时,可以使用以下装载选项。

装载选项 建议的值 说明
username= 存储帐户名称 进行 NTLMv2 身份验证时是必需的。
password= 存储帐户主密钥 进行 NTLMv2 身份验证时是必需的。
password2= 存储帐户辅助密钥 建议在需要进行无停机密钥轮换时使用。
mfsymlinks n/a 推荐。 强制此装载支持符号链接,允许 git 之类的应用程序使用符号链接克隆存储库。
actimeo= 30-60 推荐。 CIFS 客户端在向服务器请求属性信息之前缓存文件或目录的属性的时间(以秒为单位)。 使用小于 30 秒的值可能会导致性能下降,因为文件和目录的属性缓存很快就会过期。 建议将 actimeo 设置为 30 到 60 秒。
nosharesock n/a 可选。 强制客户端始终与服务器建立新连接,即使它已经有一个与 SMB 装载的现有连接。 这可以增强性能,因为每个装入点都会使用不同的 TCP 套接字。 在某些情况下,nosharesock 可能会降低性能,因为从同一客户端的两个挂载点打开文件时,同一个文件不会被缓存。
max_channels= 4 建议在使用 SMB 多通道时使用。 指定文件共享的最大通道数(网络连接数)。 如果使用的是 SMB 多通道并且通道数超过 4 个,则会导致性能不佳。
remount n/a 重新装载文件共享并更改装载选项(如果已指定)。 在你想要指定备用密码来修复进行原始装载后过期的密码时与 password2 选项配合使用。
nobrl n/a 建议在需要使用公告锁的单客户端应用场景中使用。 Azure 文件存储不支持咨询锁,此设置会阻止向服务器发送字节范围锁请求。
snapshot= 时间 装载文件共享的特定快照。 时间必须为正整数,用于标识所请求的快照(按自 1601 年 1 月 1 日起经过的时间以 100 纳秒为单位来计量,或者也可以使用 GMT 格式来指定,例如 @GMT-2024.03.27-20.52.19))。
closetimeo= 5 配置以秒为单位的延迟关闭超时(句柄缓存),或者通过设置为 0 来禁用它。 默认值为 5 秒。
nostrictsync n/a 不要让服务器在执行 fsync() 时刷新。 某些服务器默认执行非缓冲写入,在这种情况下刷新是多余的。 此选项可以提高性能,适用于客户端执行大量频繁的小型写入与fsync组合操作,并且网络延迟远高于服务器延迟的工作负荷。
multiuser n/a 在访问服务器时,将用户访问映射到单个凭据。 默认情况下,CIFS 装载仅在访问共享时使用一组用户凭据(装载凭据)。 使用此选项,每当有新用户访问挂载点时,客户端将会使用用户的凭据与服务器创建一个新的会话。 该用户的进一步的访问也将使用这些凭据。 由于内核无法提示用户输入密码,因此多用户装载仅限于使用不需要密码的 sec= 选项的装载。
cifsacl n/a 此选项用于在 CIFS/NTFS ACL 与 Linux 权限位之间来回映射、在 SID 与 UID 和 GID 之间来回映射,以及获取和设置安全描述符。 仅支持用于 NTLMv2 身份验证。
idsfromsid,modefromsid n/a 建议在客户端需要进行客户端强制授权时使用。 启用 Unix 样式权限。 仅当 UID/GID 在所有客户端中统一时才有效。 仅支持用于 NTLMv2 身份验证。
sec= krb5 Kerberos 身份验证的必需项。 若要启用 Kerberos 安全模式,请设置 sec=krb5。 使用此选项时,必须省略用户名和密码。 Linux 客户端必须已加入域。 请参阅通过 SMB 为 Linux 客户端启用 Active Directory 身份验证
uid= 0 可选。 设置一个 UID,该 UID 在服务器不提供所有权信息时会拥有已装载文件系统上的所有文件或目录。 可以将其指定为用户名或数字 UID。 在未指定的情况下,默认值为 0。
gid= 0 可选。 设置一个 GID,该 GID 在服务器不提供所有权信息时会拥有已装载文件系统上的所有文件或目录。 可以将其指定为组名或数字 GID。 在未指定的情况下,默认值为 0。
file_mode= n/a 可选。 如果服务器不支持 CIFS Unix 扩展,则会替代默认文件模式。
dir_mode= n/a 可选。 如果服务器不支持 CIFS Unix 扩展,则会替代目录的默认模式。
handletimeout= n/a 可选。 故障转移后服务器保留文件句柄以等待客户端重新连接的时间(毫秒)。

后续步骤

若要详细了解如何通过 Linux 使用 SMB Azure 文件共享,请参阅: