掛接 Azure 檔案共享時發生錯誤
本文提供可能導致 Azure 檔案共用掛接失敗的錯誤原因和解決方案。
徵兆
您可以在 Azure Kubernetes Service (AKS) 環境中部署 Kubernetes 資源,例如部署或 StatefulSet。 部署會建立 Pod,以掛接參考 Azure 檔案共用的 PersistentVolumeClaim (PVC)。
不過,Pod 會維持在 ContainerCreating 狀態中。 當您執行 kubectl describe pods
命令時,可能會在命令輸出中看到下列其中一個錯誤,這會導致掛接作業失敗:
請參閱下列輸出作為範例:
MountVolume.MountDevice failed for volume "\<pv-fileshare-name>"
rpc error: code = Internal desc =
volume(\<storage-account's-resource-group>#\<storage-account-name>#\<pv/fileshare-name>#) > mount "//\<storage-account-name>.file.core.windows.net/\<pv-fileshare-name>" on "/var/lib/kubelet/plugins/kubernetes.io/csi/pv/\<pv-fileshare-name>/globalmount" failed with
mount failed: exit status 32
Mounting command: mount
Mounting arguments: -t cifs -o dir_mode=0777,file_mode=0777,uid=0,gid=0,mfsymlinks,cache=strict,actimeo=30,\<masked> //\<storage-account-name>.file.core.windows.net/\<pv-name> /var/lib/kubelet/plugins/kubernetes.io/csi/pv/\<pv-name>/globalmount
Output: mount error(\<error-id>): \<error-description>
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg)
注意
- 如果可公開存取記憶體帳戶,輸出中顯示的主機名將會是 storage-account-name.file.core.windows.net>。<
- 如果記憶體帳戶是以私人連結、端點或 DNS 區域私下設定,主機名會是 storage-account-name.privatelink.file.core.windows.net>。<
疑難排解之前
根據輸出中的訊息,如下列範例所示,識別記憶體帳戶和檔案共享,這些值將在稍後的疑難解答步驟中使用。
掛接 “@storage-account-name.file.core.windows.net/<>< pv-fileshare-name”>
如需可能的原因和解決方案,請參閱下列各節。
掛接錯誤 (2):沒有這類檔案或目錄
此錯誤表示 AKS 叢集與記憶體帳戶之間沒有連線。
初始疑難排解
Azure 檔案依賴 SMB 通訊協定(埠 445)。 請確定未封鎖記憶體帳戶的埠 445 和/或 IP 位址。
若要檢查記憶體帳戶的 IP 位址,請執行網域名稱系統 (DNS) 命令,例如 nslookup
、 dig
或 host
。 例如:
nslookup <storage-account-name>.file.core.windows.net
若要檢查 AKS 叢集與記憶體帳戶之間是否有連線,請在節點或 Pod 內取得,然後執行下列nc
或telnet
命令:
nc -v -w 2 <storage-account-name>.file.core.windows.net 445
telnet <storage-account-name>.file.core.windows.net 445
掛接錯誤可能的原因(2)
注意
- 原因 1、2 和 4 適用於公用和私人記憶體帳戶案例。
- 原因 3 僅適用於公用案例。
原因 1:檔案共用不存在
若要檢查檔案共用是否存在,請遵循下列步驟:
在 Azure 入口網站 中搜尋記憶體帳戶,並存取您的記憶體帳戶。
在記憶體帳戶中的數據記憶體下選取 [檔案分享],並檢查 Pod、部署或具狀態集的 yaml 檔案中是否有相關聯的 PersistentVolumeClaim。
解決方案:確定檔案共用存在
若要解決此問題,請確定與 PV/PV 相關聯的檔案共用存在。
原因 2:網路安全組封鎖 AKS 與記憶體帳戶之間的流量
檢查初始疑難解答一節中提及的 nc
或 telnet
命令輸出。 如果顯示逾時,請檢查 網路安全組 (NSG), 並確定記憶體帳戶的IP位址未遭到封鎖。
若要檢查 NSG 是否封鎖記憶體帳戶的 IP 位址,請遵循下列步驟:
在 Azure 入口網站 中,移至 [網路監看員],然後選取 [NSG 診斷]。
使用下列值填入欄位:
- 通訊協定:任何
- 方向:輸出
- 來源類型:IPv4 位址/CIDR
- IPv4 位址/CIDR:與 AKS 節點相關聯的實例 IP 位址
- 目的地 IP 位址:記憶體帳戶的 IP 位址
- 目的地埠:445
選取 [ 檢查] 按鈕並檢查 [流量 狀態]。
流量狀態可以是 [允許] 或 [拒絕]。 拒絕狀態表示 NSG 正在封鎖 AKS 叢集與記憶體帳戶之間的流量。 如果狀態為 [拒絕],則會顯示 NSG 名稱。
解決方案:允許 AKS 與記憶體帳戶之間的連線
若要解決此問題,請據以在 NSG 層級執行變更,以允許 AKS 叢集與埠 445 上的記憶體帳戶之間的連線。
原因 3:虛擬設備會封鎖 AKS 與記憶體帳戶之間的流量
如果您使用虛擬設備(通常是防火牆)來控制 AKS 叢集的輸出流量(例如,虛擬設備在 AKS 叢集的子網上套用路由表,而路由表具有將流量傳送至虛擬設備的路由),虛擬設備可能會封鎖 AKS 叢集與記憶體帳戶之間的流量。
若要找出問題,請在路由表中為記憶體帳戶的IP位址新增路由,以將流量傳送至因特網。
若要確認哪個路由表控制 AKS 叢集的流量,請遵循下列步驟:
- 移至 Azure 入口網站 中的 AKS 叢集,然後選取 [屬性>基礎結構] 資源群組。
- 如果您使用這類 VM 集合類型,請存取可用性設定組中的虛擬機擴展集 (VMSS) 或 VM。
- 選取 [虛擬網络/子網>子網] ,並識別 AKS 叢集的子網。 在右側,您會看到路由表。
若要在路由表中新增路由,請遵循建立路由中的步驟並填入下列欄位:
- 地址前綴: <storage-account's-public-IP>/32
- 下一個躍點類型:因特網
此路由會透過公用因特網傳送 AKS 叢集與記憶體帳戶之間的所有流量。
新增路由之後,請使用 nc
或 telnet
命令測試連線能力,然後再次執行掛接作業。
解決方案:確定虛擬設備允許 AKS 與記憶體帳戶之間的流量
如果掛接作業成功,建議您諮詢網路小組,以確保虛擬設備可以允許埠 445 上的 AKS 叢集與記憶體帳戶之間的流量。
原因 4:使用已啟用 FIPS 的節點集區
如果您使用 已啟用聯邦資訊處理標準 (FIPS) 的節點集區,掛接作業將會失敗,因為 FIPS 會停用某些驗證模組,這可防止掛接 CIFS 共用。 這是預期的行為,而不是 AKS 特有的。
若要解決此問題,請使用下列其中一個解決方案:
解決方案 1:在非 FIPS 節點集區中的節點上排程 Pod
根據預設,AKS 節點集區會停用 FIPS,而且只能在使用 --enable-fips-image
參數建立節點集區期間啟用。
若要解決錯誤,您可以在非 FIPS 節點集區中的節點上排程 Pod。
解決方案 2:建立可在已啟用 FIPS 的節點上排程的 Pod
若要建立可在已啟用 FIPS 的節點上排程的 Pod,請遵循下列步驟:
使用 Azure 檔案 CSI 驅動程式來建立使用 NFS 通訊協定的自定義 StorageClass。
以下列 YAML 檔案為例:
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: azurefile-sc-fips provisioner: file.csi.azure.com reclaimPolicy: Delete volumeBindingMode: Immediate allowVolumeExpansion: true parameters: skuName: Premium_LRS protocol: nfs
SKU 會設定為 YAML 檔案中的Premium_LRS,因為 NFS 需要進階 SKU。 如需詳細資訊,請參閱 動態布建。
由於進階 SKU,檔案共用的大小下限為 100GB。 如需詳細資訊,請參閱 建立記憶體類別。
建立參考自定義 StorageClass azurefile-sc-fips 的PVC。
以下列 YAML 檔案為例:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: azurefile-pvc-fips spec: accessModes: - ReadWriteMany storageClassName: azurefile-sc-fips resources: requests: storage: 100Gi
建立裝載PVC azurefile-pv-fips 的 Pod。
以下列 YAML 檔案為例:
kind: Pod apiVersion: v1 metadata: name: azurefile-pod-fips spec: containers: - name: azurefile-pod-fips image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine resources: requests: cpu: 100m memory: 128Mi limits: cpu: 250m memory: 256Mi volumeMounts: - mountPath: "/mnt/azure" name: volume volumes: - name: volume persistentVolumeClaim: claimName: azurefile-pvc-fips
掛接錯誤 (13):使用權限被拒
以下是此錯誤的可能原因:
- 原因 1:Kubernetes 祕密不會參考正確的儲存體帳戶名稱或金鑰
- 原因 2:記憶體帳戶不允許 AKS 的 VNET 和子網
- 原因 3:連線是透過私人連結,但節點和私人端點位於不同的 VNET 中
- 原因 4:記憶體帳戶設定為要求用戶端不支援的加密
- 原因 5:不符合記憶體帳戶的最低加密需求
- 原因 6:未啟用 NTLM v2 驗證的安全性配置檔
注意
- 原因 1 適用於公用和私人案例。
- 原因 2 僅適用於公用案例。
- 原因 3 僅適用於私人案例。
- 原因 4 適用於公用和私人案例。
- 原因 5 適用於公用和私人案例。
- 原因 6 適用於公用和私人案例。
原因 1:Kubernetes 秘密未參考正確的記憶體帳戶名稱或密鑰
如果動態建立檔案共用,則會自動建立 Kubernetes 秘密資源,名稱為 “azure-storage-account-storage-account-name-secret<>”。
如果手動建立檔案共用,則應該手動建立 Kubernetes 秘密資源。
不論建立方法為何,如果 Kubernetes 秘密中所參考的記憶體帳戶名稱或密鑰與實際值不符,掛接作業將會失敗,並出現「許可權遭拒」錯誤。
不相符的可能原因
如果以手動方式建立 Kubernetes 秘密,可能會在建立期間發生錯字。
如果在記憶體帳戶層級執行「輪替密鑰」作業,變更將不會反映在 Kubernetes 秘密層級。 這會導致記憶體帳戶層級的密鑰值與 Kubernetes 秘密層級的值不符。
如果發生「輪替金鑰」作業,則會在記憶體帳戶的活動記錄中顯示名稱為 「重新產生記憶體帳戶密鑰」的作業。 請注意活動記錄的90天保留期間。
確認不相符
若要確認不相符,請遵循下列步驟:
搜尋並存取 Azure 入口網站 中的記憶體帳戶。 選取 [存取金鑰>][在記憶體帳戶中顯示金鑰]。 您會看到儲存體帳戶名稱和相關聯的金鑰。
移至 AKS 叢集,選取 [設定>秘密],然後搜尋並存取相關聯的秘密。
選取 [顯示 ](眼睛圖示),並比較記憶體帳戶名稱和相關聯密鑰的值與步驟 1 中的值。
選取 [ 顯示] 之前,儲存體帳戶名稱和相關聯密鑰的值會編碼為base64字串。 選取 [ 顯示] 之後,就會將值譯碼。
如果您沒有 Azure 入口網站 中 AKS 叢集的存取權,請在 kubectl 層級執行步驟 2:
取得 Kubernetes 秘密的 YAML 檔案,然後執行下列命令,從輸出取得記憶體帳戶名稱和密鑰的值:
kubectl get secret <secret-name> -n <secret-namespace> -o <yaml-file-name>
echo
使用 命令來譯碼記憶體帳戶名稱和金鑰的值,並將其與記憶體帳戶層級的值進行比較。以下是譯碼記憶體帳戶名稱的範例:
echo -n '<storage account name>' | base64 --decode ;echo
解決方案:調整 Kubernetes 秘密並重新建立 Pod
如果 Kubernetes 秘密中的記憶體帳戶名稱或金鑰值不符合記憶體帳戶中 存取金鑰 中的值,請執行下列命令,在 Kubernetes 秘密層級調整 Kubernetes 秘密:
kubectl edit secret <secret-name> -n <secret-namespace>
Kubernetes 秘密組態中新增的記憶體帳戶名稱或密鑰的值應該是base64編碼的值。 若要取得編碼的值,請使用 echo
命令。
以下是編碼記憶體帳戶名稱的範例:
echo -n '<storage account name>'| base64 | tr -d '\n' ; echo
如需詳細資訊,請參閱 使用 kubectl 管理秘密。
在 Kubernetes 秘密 azure-storage-account-<storage-account-name>-secret
具有正確的值之後,請重新建立 Pod。 否則,這些 Pod 會繼續使用不再有效的舊值。
原因 2:記憶體帳戶不允許 AKS 的 VNET 和子網
如果記憶體帳戶的網路僅限於選取的網路,但 AKS 叢集的 VNET 和子網不會新增至選取的網路,則掛接作業將會失敗,並出現「許可權遭拒」錯誤。
解決方案:允許 AKS 的 VNET 和子網用於記憶體帳戶
執行下列命令來識別載入錯誤 Pod 的節點:
kubectl get pod <pod-name> -n <namespace> -o wide
從指令輸出檢查節點:
移至 Azure 入口網站 中的 AKS 叢集,選取 [屬性>基礎結構] 資源群組、存取與節點相關聯的 VMSS,然後檢查 [虛擬網路/子網] 以識別 VNET 和子網。
存取 Azure 入口網站 中的記憶體帳戶。 選取 [網路功能]。 如果 [允許從 存取] 設定為 [選取的網络],請檢查是否已新增 AKS 叢集的 VNET 和子網。
如果未新增 AKS 叢集的 VNET 和子網,請選取 [ 新增現有的虛擬網络]。 在 [ 新增網络] 頁面上,輸入 AKS 叢集的 VNET 和子網,然後選取 [ 新增>儲存]。
可能需要幾分鐘的時間,變更才會生效。 新增 VNET 和子網之後,請檢查 Pod 狀態是否從 ContainerCreating 變更為 執行中。
原因 3:連線是透過私人連結,但節點和私人端點位於不同的 VNET 中
當 AKS 叢集和記憶體帳戶透過私人連結連線時,會使用已核准的私人端點連線。
在此案例中,如果私人端點和 AKS 節點位於相同的 VNET 中,您將能夠掛接 Azure 檔案共用。
如果私人端點和 AKS 叢集位於不同的 VNET 中,掛接作業將會失敗,並出現「許可權遭拒」錯誤。
解決方案:在私人 DNS 區域建立 AKS 叢集 VNET 的虛擬網路連結
取得節點 內部,並檢查完整功能變數名稱 (FQDN) 是否透過公用或私人IP位址解析。 若要這樣做,請執行下列命令:
nslookup <storage-account-name>.privatelink.file.core.windows.net
如果 FQDN 是透過公用 IP 位址解析的(請參閱下列螢幕快照),請在私人 DNS 區域 (“privatelink.file.core.windows.net”) 層級建立 AKS 叢集 VNET 的虛擬網路連結。 請注意,已為記憶體帳戶私人端點的 VNET 自動建立虛擬網路連結。
若要建立虛擬網路連結,請遵循下列步驟:
存取 私用 DNS 區域,然後選取 [新增虛擬網络連結>]。
填寫欄位,然後選取虛擬網路 AKS 叢集的 VNET。 如需如何識別 AKS 叢集的 VNET,請參閱 解決方案:允許 AKS 的 VNET 和子網用於記憶體帳戶 一節。
選取 [確定]。
新增虛擬網路連結之後,FQDN 應該透過私人IP位址解析,而且掛接作業應該會成功。 如需範例,請參閱下列螢幕快照:
原因 4:記憶體帳戶設定為要求用戶端不支援的加密
Azure 檔案儲存體 安全性設定包含一些選項,可用來控制記憶體帳戶的安全性和加密設定。 限制允許的方法和演算法可防止客戶端連線。
1.25 之前的 AKS 版本是以 Ubuntu 18.04 LTS 為基礎,其使用 Linux 5.4 核心,且僅支援 AES-128-CCM 和 AES-128-GCM 加密演算法。 最大 安全性 配置檔或 停用 AES-128-GCM 的自定義 配置檔,將會導致共用對應失敗。
AKS 1.25 版和更新版本是以 Ubuntu 22.04 為基礎,其使用 Linux 5.15 核心,並支援 AES-256-GCM。
解決方案:允許使用 AES-128-GCM 加密演算法
使用 最大相容性 配置檔或 啟用 AES-128-GCM 的自定義 配置檔來啟用 AES-128-GCM 演算法。 如需詳細資訊,請參閱 Azure 檔案儲存體 安全性設定。
原因 5:不符合記憶體帳戶的最低加密需求
解決方案:為所有記憶體帳戶啟用 AES-128-GCM 加密演算法
若要成功掛接或存取檔案共用,應為所有記憶體帳戶啟用 AES-128-GCM 加密演算法。
如果您想要只使用 AES-256-GCM 加密,請執行下列動作:
Linux
使用下列腳本來檢查用戶端是否支援 AES-256-GCM,並只在執行下列動作時才強制執行:
cifsConfPath="/etc/modprobe.d/cifs.conf"
echo "$(date) before change ${cifsConfPath}:"
cat ${cifsConfPath}
# Check if 'require_gcm_256' is already present in the configuration file
if ! grep -q "require_gcm_256" "${cifsConfPath}"; then
# Load the CIFS module
modprobe cifs
# Set the parameter at runtime
echo 1 > /sys/module/cifs/parameters/require_gcm_256
# Persist the configuration
echo "options cifs require_gcm_256=1" >> "${cifsConfPath}"
echo "$(date) after changing ${cifsConfPath}:"
cat "${cifsConfPath}"
else
echo "require_gcm_256 is already set in ${cifsConfPath}"
fi
您也可以使用 Kubernetes DaemonSet 在每個節點上強制執行 AES-256。 請參閱下列範例:
Windows
使用 Set-SmbClientConfiguration PowerShell 命令來指定 SMB 用戶端所使用的加密密碼,以及慣用的加密類型,而不需使用者確認:
Set-SmbClientConfiguration -EncryptionCiphers "AES_256_GCM" -Confirm:$false
注意
從EncryptionCiphers
適用於 x64 型系統的 2022-06 版 Windows Server 21H2 累積更新和 Windows 11 版本 22H2 的累積更新(KB5014665 KB5014668)開始,即可使用 參數。
原因 6:未啟用 NTLM v2 驗證的安全性配置檔
當您在沒有啟用NTLM v2驗證機制的情況下使用 [最大安全性配置檔] 或 [自定義安全性配置檔] 時,掛接作業將會失敗,並出現「掛接錯誤(13):許可權遭拒」錯誤。
解決方案:啟用NTLM v2驗證或使用「最大相容性」配置檔
若要在 AKS 中正確掛接它,您必須啟用自訂安全性設定檔的 NTLM v2 驗證機制,或使用相容性安全性設定檔上限。
其他相關資訊
如果您遇到其他掛接錯誤,請參閱針對Linux中的 Azure 檔案儲存體問題進行疑難解答。
與我們連絡,以取得說明
如果您有問題或需要相關協助,請建立支援要求,或詢問 Azure community 支援。 您也可以向 Azure 意見反應社群提交產品意見反應。