最終更新 1742359572

FixBatch.md Raw

这部分内容是通用的用于诊断 Substrate 数据中心机器部署失败的方法。可以从宏观上找到核心问题。

  1. 准备工作区:立刻打开两个DMS,两个OSP和一个Kusto Explorer。

  2. 识别:识别有故障的范围,是版本还是Ring。在OSP检查此Ring趋势图。检查Substrate版本历史,确认其版本类型(Dogfood、Daily)。

我正在检查 ________ 版本,范围是 Deploy Ring _________,其部署状况是 ______,版本类型是 ______。
  1. 检查Override:

不要跳过这一步!很多问题都是由于Override引起的。或许你完全可以发现已经有人在Override这个问题了。

OSP Overrides 页面搜索:

  • 这个版本本身的信息
  • 包含 999 的 override
  • 最近的 10 个 override

检查是否被Halt,以及相关Override的修改时间。检查相关Incident。

  • 如果有相关Override,找到正确责任组。结束
  • 如果没有相关Override,转到步骤4

特别注意:如果调查的环境是 Gallatin 或 Itar,不要相信 OSP Overrides 页面的信息。这两个环境的 OSP Overrides 页面是不准确的!要手工在目标环境运行下面的命令来检查Override:

Set-MyServiceInstance -ServiceInstanceName Multitenant
Get-DeploymentOverrideNew -ShowDeleted $true | Sort-Object Id -Descending | Select-Object -First 100 | Format-Table -Property Id, DeploymentOverrideType, CreatedBy, Deleted, Data1
  1. 进一步识别+验证:在DMS里使用gcam命令检查这个版本是否真的没有被部署。
$machines = gcam -ShowAll -Filter "DeployRing -eq 'MSIT'" # 取出要调查的整个范围。

$machines | Where-Object { $_.DesiredMachineDefinition -eq 'BE' } | Group-Object ActualVersion | Sort-Object { $_.Name }
$machines | Where-Object { $_.DesiredMachineDefinition -eq 'FE' } | Group-Object ActualVersion | Sort-Object { $_.Name }
$machines | Where-Object { $_.DesiredMachineDefinition -eq 'AD' } | Group-Object ActualVersion | Sort-Object { $_.Name }

如果没有 DMS,可以使用 CADW 数据库: CADW

SubstrateMachine
| where DeployRing == "SDFV2"
| where DesiredMachineDefinition == "BE"
| where DesiredVersion contains "15.20.8495"
| where ProvisioningState != "Provisioned"
| project Name, ActualVersion, DesiredVersion, Dag, Forest, DesiredMachineDefinition, ProvisioningState, ActivityState
| sort by Dag
  • 在这一步:确定不能部署的机器的Role
  1. 检查期待性:在DMS里将机器按DesiredVersion Group,检查是否有机器试图部署这个版本。
$machines | Where-Object { $_.DesiredMachineDefinition -eq 'BE' } | Group-Object DesiredVersion | Sort-Object { $_.Name }
  • 如果有机器,证明机器正在Deploy但是失败了,前往步骤6。
  • 如果没有机器,证明机器根本就没打算部署这个版本,前往步骤9。
  1. 检查机器错误情况。抽样几台。检查其最近Workitem,观察错误

  2. 使用Dots App交叉验证6。找到除了无法BeginMM以外最多的错误。

如果需要查看一个Ring一个Role一个版本的升级发生的所有错误,按出错数量排序,使用下面的Kusto:

APSFailedWorkitemEvent_Global
| where env_time > ago(10h)
| where prioritizer contains "Sweeper:CapacityDeploymentSweeper"
| where targetIntention contains "15.20.8032"
| where requestorMeta has 'TDF'
| where requestorMeta has 'BE'
| where requestorMeta has "DotBuildUpgrade"
| where failureMessage !has "forcing ReimageMode to WinPE"
| project failureTagId, resourceName, targetResourceUnit, targetIntention, deployRing,
          failureWorkflowName, workflowId, workflowStartTime, failureTagWords, 
          failureMessage, workflowEndTime, sku
| summarize Count = count(), 
            ExampleErrorMessage = take_any(failureMessage), 
            ExampleWorkflowId = take_any(workflowId),
            ExampleFailureTagId = take_any(failureTagId)
  by targetIntention, failureWorkflowName
| where Count > 3
| order by targetIntention asc, Count desc

如果输出了大量 DownloadComponent 的错误,可以使用这个 Query 查询它的分布:

ComponentReplicationCogsEvent_Global()
| where deployRing == "TDF" and env_time > ago(100h)
| summarize
    Failed = countif(result == 'Failed'),
    Succeeded = countif(result == 'Succeeded') by bin(env_time, 30min)
| render timechart

上面的查询会输出一些机器示例。请参考第二章以进一步诊断这些机器。

  1. 找到错误的信息,检查日志,找到正确的责任人。

(注意:CAMgt3 的机器天生不跑 FastTrain,只装 Dogfood,就不再管了,而且只有Reimage能成功)

结束

  1. 如果整个Ring都有这个问题,则在Email中搜索 Ringbot \ Stagebot 相关的告警,检查是否 Ringbot \ Stagebot 工作异常:(TODO:这里要讨论并非整个Ring有问题的情况)

gwrc (Get-OrchestrationScopeWorkflow (Get-LatestOrchestration StageBOT_ValidateWorkflow_Substrate_V2).QualifiedId).QualifiedWorkflowId

  • 如果有,检查Ringbot的异常:Get-ScheduledWorkflow ringbot* | ft name, lastoperationid, isenabled 或 Invoke-RingbotValidateProdRings.ps1
  • 如果没有,继续
  1. 打开OSP的Ring Promo信息,观察是否这个版本被Promo

可以运行下面的引擎手工重启命令以强制触发它们重新评估。

Request-ElevatedAccess_V2.ps1 -Role "ManagementDestructiveAccess" -Reason "Manual control deployment workflows" -DurationHours 12
Request-ElevatedAccess_V2.ps1 -Role "ManagementChangeAccess" -Reason "Manual control deployment workflows" -DurationHours 12

Start-DeploymentEngine.ps1
Start-BuildComponentListHandler.ps1
Start-Camgt2DeploymentHandler.ps1
Start-DotBuildValidationHandler.ps1
Start-EopStatefulDbHandler.ps1
Start-IngressRingBotPromotionHandler.ps1
Start-PrepareAdHandler.ps1
Start-SaturationHandler.ps1
Start-SeedComponentsHandler.ps1
Start-SeedPavcComponentsHandler.ps1
Start-WorkflowPairingHandler.ps1
  • 如果有 Ring Promo,检查其欠缺的条件。如果有欠缺,则诊断欠缺的条件。如果全部满足,前往步骤14。
  • 如果没有 Ring Promo,转到步骤11
  1. 使用DMS See-Version,检查相关的
  • deployment config workitem
  • deployment config version
  • deployment config approved version
  • config prerequisite versions
Get-DeploymentConfigWorkItem            -DeployRing WW -ApprovedVersion 15.20.7472.030 | ft -a
Get-DeploymentConfigVersion             -DeployRing WW -ApprovedVersion 15.20.7472.030 | ft -a
Get-DeploymentConfigApprovedVersion                    -ApprovedVersion 15.20.7472.030 | ft -a
Get-DeploymentConfigPrerequisiteVersion -EntityName BE -ApprovedVersion 15.20.7472.030 | ft -a

在没有 DMS 时,使用下面的 Kusto 应急:

SubstrateConfigWorkItem
| where DeployRing contains "TDF" and ApprovedVersion contains "8374" and ServerRole contains "BE"
| project HandlerType, HandlerStatus, WhenChanged

是否完整

  1. 检查其前一个 Ring 有没有 config version 创建出来
  • 如果有,转到步骤14
  • 如果没有,转到步骤13
  1. 考虑手工创建前一个Ring的Config Version,然后手工创建当前 Ring的 Config Workitem
 Get-DeploymentConfigWorkItem -DeployRing MSIT -ApprovedVersion 15.20.7091.005 | ft -a

For: DeploymentEngine, SeedComponents, Saturation, BuildComponentList, PrepareAD, SeedPavcComponents, WorkflowPairing

New-DeploymentConfigWorkItem `
  -DeployRing MSIT `
  -ApprovedVersion 15.20.7091.005 `
  -ServerRole BE `
  -HandlerType <-EACH-> `
  -DeploymentTrainType RegularTrain `
  -HandlerStatus Pending `
  -UserComments "Rerun PrepareAD with new build" `
  -CreatedBy xuef
  • 然后等待大约20分钟,重新执行此检查单
  1. 检查相关的Deployment Config Workitem 是否执行完整
 Get-DeploymentConfigWorkItem -DeployRing MSIT -ApprovedVersion 15.20.7091.005 | ft -a
  1. 找到几台示例机器,检查APSPrioritizerLog,观察Message得知为何机器明明可以Deploy这个版本却为何不Deploy这个版本

在完成检查单后,使用下面的命令以检查是否有机器开始部署了:

$msitUpgradingBe = gcam -ShowAll -Filter "DeployRing -eq 'MSIT' -and DesiredMachineDefinition -eq 'BE' -and DesiredVersion -like '15.20.7091.*' -and AutopilotMode -eq 'ApClient'"

结束

FixMachine.md Raw

第二章 - 诊断少量机器无法部署的问题

  1. 运行下面的查询来查看机器的基本信息。
$machineObject = Get-CentralAdminMachine $machine
$machineObject | Format-List Name, *Definition, Dag, Nag, DesiredDefinition, DeployRing, AutopilotMode, *Version*, ProvisioningState, ActivityState, Forest, When*, City, ServiceInstanceType

这些基本信息帮助快速了解机器的当前状态。

我们也可能还需要知道机器所在单位的上下文信息,可以运行下面的命令:

if (-not [string]::IsNullOrEmpty($machineObject.Dag)) {
    Write-Host "Downloading DAG context..." -ForegroundColor Yellow;
    Write-Host "You are $machine and you are viewing DAG: $($machineObject.Dag)";
    Get-CentralAdminMachine -Filter "Dag -eq '$($machineObject.Dag)'" -ShowAll | Sort-Object ProvisioningState | Format-Table -AutoSize Name, ActivityState, ProvisioningState, *Definition, ActualVersion, Location, AutopilotMode
}

if (-not [string]::IsNullOrEmpty($machineObject.CapacityUnit)) {
    Write-Host "Downloading CapacityUnit context..." -ForegroundColor Yellow;
    Write-Host "You are $machine and you are viewing CapacityUnit: $($machineObject.CapacityUnit) .";
    Get-CentralAdminMachine -Filter "CapacityUnit -eq '$($machineObject.CapacityUnit)'" -ShowAll | Sort-Object ProvisioningState | Format-Table -AutoSize Name, ActivityState, ProvisioningState, *Definition, ActualVersion, Location, AutopilotMode
}
  1. 查看机器的历史部署记录,以了解机器的部署历史。

如果需要针对一台机器,查查它历史上都是如何被Deploy的, 使用下面的Kusto:

DeploymentCogsEvent_Global
| where machineName == '$machine'
| where timestamp >= ago(3d)
| sort by timestamp desc
| project timestamp, machineName, actionType, requestor, provisioningState, deployMode, activityId, forest, actionStatus, deployVersion, SourceVersion, workflowId

上面的 Kusto 可以在 DMS 里交叉验证:

Get-DeploymentAPSWorkitem -Machines $machine -ShowAll `
| Sort-Object WorkflowStartTime -Descending `
| Select-Object -First 20 `
| Format-Table -AutoSize Status, WorkflowId, TargetIntention, WorkflowStartTime

一定要检查机器的部署历史。从而判断机器是真的部署失败了,还是根本没有尝试部署,亦或是可重试而恢复的错误,还是根本性的错误。是应该部署还是不应该部署。

  1. 了解一台机器为什么不部署或者部署了(可选):

在 Kusto 中运行下面的查询,以查看机器的部署期待性。这有助于诊断为什么机器迟迟没有部署。

ApsEvaluatorTraceEvent_Global
| where Message has "GV2PEPF0000385A" and env_time > ago(12h)
| where Message has "Failed with rule:"
| parse Message with * "Failed with rule:" FailRule:string "||" *
| project env_time, FailRule, PolicyIdentifier, MessageId, Message
| sort by env_time desc
| limit 200
  1. 了解机器为什么一定要部署一个版本(可选):

有的时候,机器可能会被强制部署一个意外版本(例如过老的版本)。在 Kusto 中运行下面的查询,以查看机器被强制部署的原因:

ApsPrioritizerTraceEvent_Global
| where Message has "GV2PEPF0000385A" and env_time > ago(12h)
| where Message has ""
| where PrioritizerIdentifier startswith 'Sweeper:CapacityDeploymentSweeper'
| sort by env_time desc
| project PrioritizerIdentifier,Message,env_time
| limit 200
  1. 诊断机器的部署错误:

对于第二步的输出,我们可以看到 WorkflowId。我们可以使用这个 WorkflowId 来查看机器的部署错误。

Enable-SeeAnything
See-Workflow $workflowId

如果没有 DMS,则考虑使用下面的 Kusto:

CentralAdminWorkflows_Global
| where RootWorkflowId == '$guid'
| extend WorkflowId = strcat("\\\\", ManagementUnit, "\\", Id)
| project ClassName, Result, CreateTimeUtc, EndTimeUtc, WorkflowId, Exception, LastGoodKnownState, UserContext, TenantVersion,RootWorkflowId
| sort by CreateTimeUtc asc

对于 Itar,则使用 Jarvis.

一般到这里,我们已经可以知道机器为什么部署失败了。如果还不清楚,可以继续下面的步骤。

  1. 将部署的错误按原因分类:

有的时候,我们只检查一两条错误对于诊断机器为什么部署失败是没有说服力的。我们可以使用下面的 Kusto 查询来将错误按原因分类:

APSFailedWorkitemEvent_Global
| where env_time > ago(200h)
| where resourceName == "GV2PEPF0000385A"
| where prioritizer contains "Sweeper:CapacityDeploymentSweeper"
| where failureMessage !has "forcing ReimageMode to WinPE"
| project failureTagId, resourceName, targetResourceUnit, targetIntention, deployRing,
          failureWorkflowName, workflowId, workflowStartTime, failureTagWords, 
          failureMessage, workflowEndTime, sku
| summarize Count = count(), 
            ExampleErrorMessage = take_any(failureMessage), 
            ExampleWorkflowId = take_any(workflowId),
            ExampleFailureTagId = take_any(failureTagId)
  by targetIntention, failureWorkflowName
| where Count > 3
| order by targetIntention asc, Count desc

这样,出现较多的错误就是我们需要关注的根本性错误。

  1. 诊断 ExchangeSetup 的错误:

如果机器是 ExchangeSetup 的错误,我们可以使用下面的 DMS 查询来诊断:

Get-MachineLog C_ExchangeSetup -Target "GV2PEPF0000385A" -Download
  1. 进行缓解措施:

机器的情况可能分为两类:

  • 机器是可以部署的,但是由于某些原因没有部署。这种情况下,我们可以手动触发机器的部署和修复手段。转到步骤 9 。
  • 大范围的问题或版本本身的问题。这种情况下,即使这一台机器可以部署,它也会失败。转到步骤 10 。
  1. 手动触发机器的部署:

如果机器是可以部署的,我们可以手动触发机器的部署。有一系列命令可以针对一台机器进行修复:

文件操作类

  1. 列出目标机器上的文件夹内容
    命令:Get-ChildItem.ps1 -Target "GV2PEPF0000385A" -Path "C:\"

  2. 下载目标机器上的文件
    命令:Get-TorusFile -Path "C:\program files\microsoft\exchange server\v15\config\AntiMalware.settings.ini" -Machine "GV2PEPF0000385A"

  3. 查看目标机器上文件的属性
    命令:Get-ItemProperty.ps1 -Path "C:\program files\microsoft\exchange server\v15\config\AntiMalware.settings.ini" -Target "GV2PEPF0000385A" | Format-List

  4. 下载Exchange安装日志
    命令:Get-MachineLog C_ExchangeSetup -Target "GV2PEPF0000385A" -Download

状态诊断类

  1. 检查机器性能
    命令:Measure-Performance -Machine GV2PEPF0000385A

  2. 检查机器磁盘使用情况
    命令:Get-WmiObject.ps1 -Target GV2PEPF0000385A -Class Win32_LogicalDisk -NoFormatting | Foreach-Object { 'Disk {0}({4}) has free space: {1:0.0}GB/{2:0.0}GB ({3:0.0}%)\n' -f .Caption, (.FreeSpace / 1024MB), (.Size / 1024MB), (.FreeSpace / .Size * 100), .VolumeName }

  3. 测试网络连接
    命令:Test-MachineNetworkConnectivity.ps1 -TargetMachine GV2PEPF0000385A

  4. 诊断WinPE启动失败问题
    命令:Invoke-WinPEFailureDiagnose.ps1 -TargetMachine "GV2PEPF0000385A"

  5. 检查机器组件信息
    命令:Get-MachineComponentV2 -Filter "MachineName -eq 'GV2PEPF0000385A'" | Format-Table -AutoSize

  6. 检查机器服务信息
    命令:Get-ServiceInfo.ps1.dms -RemoteFQDNs GV2PEPF0000385A

  7. 查看机器部署能力
    命令:See-MachineDeployAbility -MachineName GV2PEPF0000385A

缓解修复类

  1. 进入维护模式
    命令:Request-MachineBeginMaintenance_V2.ps1 -TargetMachine "GV2PEPF0000385A" -Reason "Bring the machine to maintainance to reimage it."

  2. 重启目标机器
    命令:Request-SetMachinePowerStateV2.ps1 -TargetMachine "GV2PEPF0000385A" -DesiredState "Restart" -Reason "Machine stacked."

  3. 清理机器缓存
    命令:Invoke-ComponentReplicationWorkflow.ps1 -TargetMachine GV2PEPF0000385A -ComponentIds 'WipeCache'

  4. 优先分配备用机器
    命令:New-MachineDeploymentControl.ps1 -MachineName "GV2PEPF0000385A" -MachineDeploymentControlType PrioritizeSpareAssignment -Justification "GV2PEPF0000385A has a bad disk, we need to replace it"

  5. 优先修复目标机器
    命令:Request-RepairByDeployment.ps1 -MachineName GV2PEPF0000385A -ReimageMode "<ForceNextOS|ForceWinPE|ForceFlatten>" -Justification "Try to repair this machine."

  6. 立即尝试修复机器
    命令:Invoke-RepairOnDemandWorkflow.ps1 -TargetMachine GV2PEPF0000385A

使用合理的指令,触发机器部署即可。

结束

  1. 大范围问题或版本本身的问题:

参考第一章的诊断步骤,诊断大范围问题或版本本身的问题。

FixStruggler.md Raw

第三章 - 诊断剩余机器不部署的问题

  1. 运行下面的查询来查看剩余机器信息

使用 CADW 数据库: CADW

SubstrateMachine
| where ActivityState == "DotBuildUpgrade" and DesiredMachineDefinition == "BE"
| where ActualExchangeVersion contains "15.20.8534"
| where DeployRing in ('SIP', 'WW')
| extend unpatched = strcmp(ActualExchangeVersion, "15.20.8534.031") < 0
| summarize TotalCount=count(), unpatchedCount = countif(unpatched) by Forest
| extend UnPatchedPercentage = round(100.0 * unpatchedCount / TotalCount, 2)
| order by UnPatchedPercentage desc