1. 问题现象与初步诊断
上周五凌晨2点37分,我负责维护的Azure App Service生产环境突然触发了警报。日志中赫然出现"not enough space on the disk"错误,导致应用完全无法写入新数据。这个看似简单的磁盘空间问题,背后却隐藏着Azure PaaS服务的特殊运行机制。
不同于传统虚拟机,App Service采用共享存储架构。即使选择P2v3这样的高级定价层,默认分配的临时存储空间也只有250GB(Windows)或100GB(Linux)。当应用日志暴增、文件上传失控或缓存未清理时,很容易突破这个隐形天花板。更棘手的是,Azure门户的监控图表默认只显示应用代码占用空间,需要手动开启"Filesystem usage"指标才能看到真实磁盘消耗。
关键提示:Azure的磁盘空间告警阈值默认为90%,但实际达到95%时就会开始拒绝写入操作。建议在85%时就建立预警机制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 磁盘空间占用分析实战
2.1 快速获取空间使用详情
通过Kudu控制台(访问路径:https://<app-name>.scm.azurewebsites.net/DebugConsole)可以执行以下诊断命令:
bash复制# Windows容器
dir /s D:\home
dir /s D:\local
# Linux容器
du -h --max-depth=1 /home
du -h --max-depth=1 /tmp
典型的高占用场景包括:
/home/site/wwwroot/App_Data/LogFiles(应用日志)/home/data/Docker(容器层缓存)/tmp(临时文件)/home/site/repository(Git部署残留)
2.2 空间占用TOP5排查案例
在我的实践中,磁盘爆满的元凶通常集中在以下几个场景:
| 问题类型 | 典型路径 | 解决方案 |
|---|---|---|
| 失控日志 | /home/LogFiles/Application | 配置日志自动轮转 |
| 未压缩上传 | /home/site/wwwroot/uploads | 启用Blob存储分流 |
| 内存转储 | /home/dumps | 禁用故障转储或设置上限 |
| Node_modules | /home/site/wwwroot/node_modules | 使用.npmrc优化安装 |
| 部署残留 | /home/site/deployments | 清理旧部署版本 |
3. 根治方案设计与实施
3.1 临时应急清理
当空间已满导致应用崩溃时,可通过ARM API强制清理:
powershell复制Invoke-AzResourceAction -ResourceGroupName $RG -ResourceType Microsoft.Web/sites -ResourceName $AppName -Action recycle -ApiVersion 2019-08-01 -Force
此操作会重启应用并清空D:\local临时目录(Linux则为/tmp),但不会影响持久化存储(D:\home)。
3.2 长期治理策略
3.2.1 日志管理黄金法则
xml复制<!-- Web.config配置示例 -->
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="AzureDiagnostics"
type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics"
traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId">
<filter type="" />
</add>
</listeners>
</trace>
</system.diagnostics>
配合Application Insights实现:
- 日志级别动态调整
- 采样率控制
- 自动日志轮转(单个文件不超过50MB)
3.2.2 存储架构优化
对于文件密集型应用,必须实施"冷热分离":
- 热数据:使用Azure Files挂载(SMB协议)
- 冷数据:通过Blob存储SDK直传
- 临时数据:定期清理Job(推荐使用WebJobs)
csharp复制// Blob存储分流示例
var blobClient = new BlobServiceClient(connectionString);
var container = blobClient.GetBlobContainerClient("uploads");
await container.UploadBlobAsync(fileName, stream);
4. 高级监控与预警体系
4.1 自定义指标采集
在应用启动时注入以下代码,实时监控关键目录:
csharp复制public class DiskMonitor : IHostedService
{
public Task StartAsync(CancellationToken token)
{
_ = Task.Run(async () => {
while (!token.IsCancellationRequested)
{
var drive = new DriveInfo("D");
TelemetryClient.TrackMetric("DiskFreeSpace", drive.AvailableFreeSpace / 1024 / 1024);
await Task.Delay(TimeSpan.FromMinutes(5), token);
}
});
return Task.CompletedTask;
}
}
4.2 预警规则配置
在Azure Monitor中创建复合指标规则:
- 文件系统使用率 > 85% 持续10分钟
- 每秒写入IOPS > 500
- 日志错误率突增
建议采用动态阈值而非固定值,以适应业务波动。
5. 特殊场景深度解析
5.1 Docker镜像膨胀问题
当使用自定义容器时,常见陷阱包括:
- 未使用多阶段构建导致包含编译工具链
- 未清理apt/yum缓存
- 日志未配置--log-opt max-size
优化后的Dockerfile示例:
dockerfile复制FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /app .
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
5.2 部署包优化技巧
对于Zip部署方式,务必在打包时排除:
**/bin/**/obj/**/.git/**/node_modules/
推荐使用.deploymentignore文件:
code复制.git/
.vscode/
node_modules/
*.pdb
*.zip
6. 灾备与自动化处理
建立自动化处理流水线:
- 当磁盘使用率>90%时自动触发清理脚本
- 连续3次触发后自动扩容App Service Plan
- 发送详细诊断报告到Teams频道
ARM模板关键片段:
json复制{
"resources": [{
"type": "Microsoft.Insights/scheduledQueryRules",
"apiVersion": "2018-04-16",
"name": "DiskCleanupTrigger",
"properties": {
"action": {
"odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.Microsoft.AppInsights.Nexus.DataContracts.Resources.ScheduledQueryRules.AzureFunctionAction",
"functionAppResourceId": "[resourceId('Microsoft.Web/sites', 'cleanup-func')]",
"functionName": "EmergencyCleanup",
"httpTriggerUrl": "https://cleanup-func.azurewebsites.net/api/EmergencyCleanup"
}
}
}]
}
在实际运维中,我发现约70%的磁盘空间问题源于未配置日志轮转机制。特别是使用NLog或log4net等框架时,务必显式设置maxArchiveFiles和archiveAboveSize参数。曾经有个电商网站在大促期间因为未限制日志大小,30分钟内生成了47GB的日志文件,直接导致支付服务瘫痪。
