Web Deployで発生するWindows Azureディスク容量不足への対応

Not enough space on the disk – Windows Azure | Matias Woloski」をざっくり意訳した投稿です。

ローカルストレージ容量が容量が少なくて、Windows Azureで容量不足が発生します。ServiceDefで容量増加をすることで簡単に解決することができます。WebDeployを使用すると度々この問題に直面します。解決方法について情報共有したいと思います。

問題

パッケージを作成する時、WebDeployがディスク容量不足の例外が発生します。

There is not enough space on the disk. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count) at System.IO.BinaryWriter.Write(Byte[] buffer, Int32 index, Int32 count) at Microsoft.Web.Deployment.ZipEntry.ReadFromFile(String path, Boolean shouldCompress, BinaryWriter tempWriter, Stream stream, FileAttributes attr, DateTime lastModifiedTime, String descriptor, Int64 size) at Microsoft.Web.Deployment.ZipEntry..ctor(String path, DeploymentObject source, ZipFile zipFile)

分析

パッケージを作成している間、WebDeployは一時ファイルを作成するためにtempパスを使用します。このフォルダーは、MSDNによると100MBです。パッケージが100MB以上必要な場合、”disk is full”が原因で、IO例外が発生します。Azure Web Role上で、Process Monitorのトレースを見ると、CreateFileからDISK FULLを返します。

image2

image

Reflectorで見ると、WebDeployはPath.GetTempPathを使用します。

image1

解決策

異なるパスを使用するのに、WebDeployコードを変更する必要はありません。TEMP/TMP環境設定を変更します。詳細は、General Troubleshooting in Windows Azureを参照して下さい。

TEMP/TMPのディレクトリを十分な容量を持っているディレクトリに変更することができます。

TEMPとTMPは、最大サイズ100MBのディレクトリに設定さています。このディレクトリに保存されたデータは、ホストサービスのライフサイクルの中で永続化されません。ロールインスタンスがリサイクルすると、ディレクトリはクリアされます。

もしホストサービス用の一時ディレクトリが容量不足になるか、一時ディレクトリのデータを永続化させる必要があるなら、それらを解決することができます。

ローカルストレージのリソースを設定することで、TEMP又はTMPを使用する代わりに直接アクセスできるようになります。ローカルストレージリソースにアクセスする為に、アプリケーションからRoleEnvironment.GetLocalResource Method (Microsoft.WindowsAzure.ServiceRuntime)メソッドを呼び出します。詳細については、How to Configure Local Storage Resourcesを参照してください。

ローカルストレージリソースを設定し、TEMPとTMPディレクトリをローカルストレージリソースに指定します。この変更は、RoleEntryPoint.OnStart Method (Microsoft.WindowsAzure.ServiceRuntime)メソッド内で処理すべきです。次のコードは、OnStartメソッドからTEMPとTMPの対象ディレクトリを変更する方法です。

using System;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WorkerRole1
{
public class WorkerRole : RoleEntryPoint
{
public override bool OnStart()
{
string customTempLocalResourcePath =
RoleEnvironment.GetLocalResource("tempdir").RootPath;
Environment.SetEnvironmentVariable("TMP",
customTempLocalResourcePath);
Environment.SetEnvironmentVariable("TEMP",
customTempLocalResourcePath);

// The rest of your startup code goes here…

return base.OnStart();
}
}
}