This commit is contained in:
Bernie White 2024-06-19 00:06:28 +10:00 коммит произвёл GitHub
Родитель 9f9b5ea492
Коммит 5095d47322
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
8 изменённых файлов: 511 добавлений и 0 удалений

Просмотреть файл

@ -39,6 +39,9 @@ What's changed since pre-release v1.38.0-B0011:
- Azure Kubernetes Service:
- Added check to automatically upgrade AKS cluster node image by @sharmilamusunuru.
[#2445](https://github.com/Azure/PSRule.Rules.Azure/issues/2445)
- Azure Virtual Desktop:
- Added check for scheduled agent updates on host pools by @BernieWhite.
[#2946](https://github.com/Azure/PSRule.Rules.Azure/issues/2946)
- Engineering:
- Quality updates to rule documentation by @BernieWhite.
[#2570](https://github.com/Azure/PSRule.Rules.Azure/issues/2570)

Просмотреть файл

@ -0,0 +1,113 @@
---
reviewed: 2024-06-18
severity: Important
pillar: Reliability
category: RE:04 Target metrics
resource: Azure Virtual Desktop
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.AVD.ScheduleAgentUpdate/
---
# Schedule agent updates for host pools
## SYNOPSIS
Define a windows for agent updates to minimize disruptions to users.
## DESCRIPTION
Azure Virtual Desktop (AVD) regularly provide updates to the agent software that runs on host pools.
The agent software is responsible for managing user sessions and providing access to resources.
These updates provide new functionality and fixes.
While the update process is designed to minimize disruptions, updates should be applied outside of peak load times.
By default, agent updates are applied automatically when they become available.
If you have configured a maintenance window, updates are only applied during the maintenance window that you specify.
Each host pool can configure up to two maintenance windows per week.
## RECOMMENDATION
Consider defining a maintenance window for agent updates to minimize disruptions to users on AVD host pools.
## EXAMPLES
### Configure with Azure template
To deploy host pools that pass this rule:
- Set the `properties.agentUpdate.type` property to `Scheduled`. _AND_
- Configure one or more maintenance windows in the `properties.agentUpdate.maintenanceWindows` property.
For example:
```json
{
"type": "Microsoft.DesktopVirtualization/hostPools",
"apiVersion": "2024-04-03",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"hostPoolType": "Pooled",
"loadBalancerType": "DepthFirst",
"preferredAppGroupType": "Desktop",
"maxSessionLimit": 10,
"agentUpdate": {
"type": "Scheduled",
"maintenanceWindowTimeZone": "AUS Eastern Standard Time",
"maintenanceWindows": [
{
"dayOfWeek": "Sunday",
"hour": 1
}
]
}
}
}
```
### Configure with Bicep
To deploy host pools that pass this rule:
- Set the `properties.agentUpdate.type` property to `Scheduled`. _AND_
- Configure one or more maintenance windows in the `properties.agentUpdate.maintenanceWindows` property.
For example:
```bicep
resource pool 'Microsoft.DesktopVirtualization/hostPools@2024-04-03' = {
name: name
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
hostPoolType: 'Pooled'
loadBalancerType: 'DepthFirst'
preferredAppGroupType: 'Desktop'
maxSessionLimit: 10
agentUpdate: {
type: 'Scheduled'
maintenanceWindowTimeZone: 'AUS Eastern Standard Time'
maintenanceWindows: [
{
dayOfWeek: 'Sunday'
hour: 1
}
]
}
}
}
```
<!-- external:avm avm/res/desktop-virtualization/host-pool agentUpdate -->
## LINKS
- [RE:04 Target metrics](https://learn.microsoft.com/azure/well-architected/reliability/metrics)
- [Get started with the Azure Virtual Desktop Agent](https://learn.microsoft.com/azure/virtual-desktop/agent-overview#agent-update-process)
- [Scheduled Agent Updates for Azure Virtual Desktop host pools](https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates)
- [What's new in the Azure Virtual Desktop Agent?](https://learn.microsoft.com/azure/virtual-desktop/whats-new-agent)
- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.desktopvirtualization/hostpools)

89
docs/examples-avd.bicep Normal file
Просмотреть файл

@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
@description('The name of the resource.')
param name string
@description('The location resources will be deployed.')
param location string = resourceGroup().location
// An example pooled desktop host pool using depth first load balancing.
resource pool 'Microsoft.DesktopVirtualization/hostPools@2024-04-03' = {
name: name
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
hostPoolType: 'Pooled'
loadBalancerType: 'DepthFirst'
preferredAppGroupType: 'Desktop'
maxSessionLimit: 10
agentUpdate: {
type: 'Scheduled'
maintenanceWindowTimeZone: 'AUS Eastern Standard Time'
maintenanceWindows: [
{
dayOfWeek: 'Sunday'
hour: 1
}
]
}
}
}
// An example scaling plan for a host pool.
resource scaling 'Microsoft.DesktopVirtualization/scalingPlans@2024-04-03' = {
name: name
location: location
properties: {
timeZone: 'E. Australia Standard Time'
hostPoolType: 'Pooled'
hostPoolReferences: [
{
hostPoolArmPath: pool.id
scalingPlanEnabled: true
}
]
schedules: [
{
rampUpStartTime: {
hour: 8
minute: 0
}
peakStartTime: {
hour: 9
minute: 0
}
rampDownStartTime: {
hour: 18
minute: 0
}
offPeakStartTime: {
hour: 22
minute: 0
}
name: 'weekdays_schedule'
daysOfWeek: [
'Monday'
'Tuesday'
'Wednesday'
'Thursday'
'Friday'
]
rampUpLoadBalancingAlgorithm: 'BreadthFirst'
rampUpMinimumHostsPct: 20
rampUpCapacityThresholdPct: 60
peakLoadBalancingAlgorithm: 'DepthFirst'
rampDownLoadBalancingAlgorithm: 'DepthFirst'
rampDownMinimumHostsPct: 10
rampDownCapacityThresholdPct: 90
rampDownForceLogoffUsers: true
rampDownWaitTimeMinutes: 30
rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.'
rampDownStopHostsWhen: 'ZeroSessions'
offPeakLoadBalancingAlgorithm: 'DepthFirst'
}
]
}
}

112
docs/examples-avd.json Normal file
Просмотреть файл

@ -0,0 +1,112 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.28.1.47646",
"templateHash": "18117889941546285249"
}
},
"parameters": {
"name": {
"type": "string",
"metadata": {
"description": "The name of the resource."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The location resources will be deployed."
}
}
},
"resources": [
{
"type": "Microsoft.DesktopVirtualization/hostPools",
"apiVersion": "2024-04-03",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"hostPoolType": "Pooled",
"loadBalancerType": "DepthFirst",
"preferredAppGroupType": "Desktop",
"maxSessionLimit": 10,
"agentUpdate": {
"type": "Scheduled",
"maintenanceWindowTimeZone": "AUS Eastern Standard Time",
"maintenanceWindows": [
{
"dayOfWeek": "Sunday",
"hour": 1
}
]
}
}
},
{
"type": "Microsoft.DesktopVirtualization/scalingPlans",
"apiVersion": "2024-04-03",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"properties": {
"timeZone": "E. Australia Standard Time",
"hostPoolType": "Pooled",
"hostPoolReferences": [
{
"hostPoolArmPath": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]",
"scalingPlanEnabled": true
}
],
"schedules": [
{
"rampUpStartTime": {
"hour": 8,
"minute": 0
},
"peakStartTime": {
"hour": 9,
"minute": 0
},
"rampDownStartTime": {
"hour": 18,
"minute": 0
},
"offPeakStartTime": {
"hour": 22,
"minute": 0
},
"name": "weekdays_schedule",
"daysOfWeek": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday"
],
"rampUpLoadBalancingAlgorithm": "BreadthFirst",
"rampUpMinimumHostsPct": 20,
"rampUpCapacityThresholdPct": 60,
"peakLoadBalancingAlgorithm": "DepthFirst",
"rampDownLoadBalancingAlgorithm": "DepthFirst",
"rampDownMinimumHostsPct": 10,
"rampDownCapacityThresholdPct": 90,
"rampDownForceLogoffUsers": true,
"rampDownWaitTimeMinutes": 30,
"rampDownNotificationMessage": "You will be logged off in 30 min. Make sure to save your work.",
"rampDownStopHostsWhen": "ZeroSessions",
"offPeakLoadBalancingAlgorithm": "DepthFirst"
}
]
},
"dependsOn": [
"[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]"
]
}
]
}

Просмотреть файл

@ -345,6 +345,7 @@ task Rules Dependencies, {
As = 'Summary'
Outcome = 'Problem'
}
Import-Module PSRule -RequiredVersion 2.9.0;
Import-Module (Join-Path -Path $PWD -ChildPath out/modules/PSRule.Rules.Azure) -Force;
Assert-PSRule @assertParams -InputPath $PWD -Module PSRule.Rules.MSFT.OSS -Format File -OutputPath reports/ps-rule-file.xml;

Просмотреть файл

@ -0,0 +1,32 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# Validation rules for Azure Virtual Desktop
#
#region Rules
---
# Synopsis: Define a windows for agent updates to minimize disruptions to users.
apiVersion: github.com/microsoft/PSRule/v1
kind: Rule
metadata:
name: Azure.AVD.ScheduleAgentUpdate
ref: AZR-000437
tags:
release: GA
ruleSet: 2024_06
Azure.WAF/pillar: Reliability
spec:
type:
- Microsoft.DesktopVirtualization/hostPools
condition:
allOf:
- field: properties.agentUpdate.type
equals: Scheduled
- field: properties.agentUpdate.maintenanceWindows
greaterOrEquals: 1
#endregion Rules

Просмотреть файл

@ -0,0 +1,58 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# Unit tests for Azure Virtual Desktop (AVD) rules
#
[CmdletBinding()]
param ()
BeforeAll {
# Setup error handling
$ErrorActionPreference = 'Stop';
Set-StrictMode -Version latest;
if ($Env:SYSTEM_DEBUG -eq 'true') {
$VerbosePreference = 'Continue';
}
# Setup tests paths
$rootPath = $PWD;
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Azure) -Force;
$here = (Resolve-Path $PSScriptRoot).Path;
}
Describe 'Azure.AVD' -Tag 'AVD' {
Context 'Conditions' {
BeforeAll {
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$dataPath = Join-Path -Path $here -ChildPath 'Resources.AVD.json';
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
}
It 'Azure.AVD.ScheduleAgentUpdate' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AVD.ScheduleAgentUpdate' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'pool-A', 'pool-C';
$ruleResult[0].Reason | Should -BeExactly "Path properties.agentUpdate.type: The field 'properties.agentUpdate.type' does not exist.";
$ruleResult[1].Reason | Should -BeExactly "Path properties.agentUpdate.type: Is set to 'Default'.";
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -BeIn 'pool-B';
}
}
}

Просмотреть файл

@ -0,0 +1,103 @@
[
{
"name": "pool-A",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/hostpools/pool-A",
"type": "Microsoft.DesktopVirtualization/hostpools",
"location": "region",
"properties": {
"managedPrivateUDP": "Default",
"directUDP": "Default",
"publicUDP": "Default",
"relayUDP": "Default",
"managementType": "Standard",
"appAttachPackageReferences": [],
"agentUpdate": null,
"friendlyName": null,
"description": "Created through the Azure Virtual Desktop extension",
"hostPoolType": "Pooled",
"personalDesktopAssignmentType": null,
"applicationGroupReferences": [
"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/applicationgroups/pool-A-DAG"
],
"customRdpProperty": "drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;",
"maxSessionLimit": 10,
"loadBalancerType": "BreadthFirst",
"validationEnvironment": false,
"preferredAppGroupType": "Desktop"
}
},
{
"name": "pool-B",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/hostpools/pool-B",
"type": "Microsoft.DesktopVirtualization/hostpools",
"location": "region",
"properties": {
"managedPrivateUDP": "Default",
"directUDP": "Default",
"publicUDP": "Default",
"relayUDP": "Default",
"managementType": "Standard",
"appAttachPackageReferences": [],
"agentUpdate": {
"type": "Scheduled",
"useSessionHostLocalTime": false,
"maintenanceWindowTimeZone": "E. Australia Standard Time",
"maintenanceWindows": [
{
"hour": 1,
"dayOfWeek": "Sunday"
}
]
},
"friendlyName": null,
"description": "Created through the Azure Virtual Desktop extension",
"hostPoolType": "Pooled",
"personalDesktopAssignmentType": null,
"applicationGroupReferences": [
"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/applicationgroups/pool-B-DAG"
],
"customRdpProperty": "drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;",
"maxSessionLimit": 10,
"loadBalancerType": "BreadthFirst",
"validationEnvironment": false,
"preferredAppGroupType": "Desktop"
}
},
{
"name": "pool-C",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/hostpools/pool-C",
"type": "Microsoft.DesktopVirtualization/hostpools",
"location": "region",
"properties": {
"managedPrivateUDP": "Default",
"directUDP": "Default",
"publicUDP": "Default",
"relayUDP": "Default",
"managementType": "Standard",
"appAttachPackageReferences": [],
"agentUpdate": {
"type": "Default",
"useSessionHostLocalTime": false,
"maintenanceWindowTimeZone": "E. Australia Standard Time",
"maintenanceWindows": [
{
"hour": 1,
"dayOfWeek": "Sunday"
}
]
},
"friendlyName": null,
"description": "Created through the Azure Virtual Desktop extension",
"hostPoolType": "Pooled",
"personalDesktopAssignmentType": null,
"applicationGroupReferences": [
"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-test/providers/Microsoft.DesktopVirtualization/applicationgroups/pool-C-DAG"
],
"customRdpProperty": "drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;",
"maxSessionLimit": 10,
"loadBalancerType": "BreadthFirst",
"validationEnvironment": false,
"preferredAppGroupType": "Desktop"
}
}
]