Partager via


Résoudre les problèmes liés à l’extension Azure pour SQL Server

S’applique à :SQL Server

Cet article décrit les façons d’identifier les extensions non saines qui ne sont pas installées correctement, s’exécutant correctement ou non connectées à Azure.

Identifier les extensions non saines

Utiliser le tableau de bord d’intégrité d’extension intégré dans le portail Azure

Vous pouvez utiliser le tableau de bord d’intégrité d’extension intégré dans le portail Azure pour afficher l’intégrité de toutes les extensions Azure déployées pour SQL Server.

Conseil

Créez votre propre tableau de bord personnalisé avec ce fichier à partir du dépôt GitHub sql-server-samples : SQL Server avec Arc Health.json.

Interroger des extensions non saines à l’aide d’Azure Resource Graph

Utilisez Azure Resource Graph pour identifier l’état de l’extension Azure pour SQL Server sur vos serveurs avec Azure Arc.

Conseil

Si vous ne le connaissez pas déjà, découvrez Azure Resource Graph :

Cette requête renvoie les instances de SQL Server sur des serveurs dont les extensions sont installées, mais qui ne sont pas saines.

resources
| where type == "microsoft.hybridcompute/machines/extensions"
| where properties.type in ("WindowsAgent.SqlServer", "LinuxAgent.SqlServer")
| extend targetMachineName = tolower(tostring(split(id, '/')[8])) // Extract the machine name from the extension's id
| join kind=leftouter (
    resources
    | where type == "microsoft.hybridcompute/machines"
    | project machineId = id, MachineName = name, subscriptionId, LowerMachineName = tolower(name), resourceGroup , MachineStatus= properties.status , MachineProvisioningStatus= properties.provisioningState, MachineErrors = properties.errorDetails //Project relevant machine health information.
) on $left.targetMachineName == $right.LowerMachineName and $left.resourceGroup == $right.resourceGroup and $left.subscriptionId == $right.subscriptionId // Join Based on MachineName in the id and the machine's name, the resource group, and the subscription. This join allows us to present the data of the machine as well as the extension in the final output.
| extend statusExpirationLengthRange = 3d // Change this value to change the acceptable range for the last time an extension should have reported its status.
| extend startDate = startofday(now() - statusExpirationLengthRange), endDate = startofday(now()) // Get the start and end position for the given range.
| extend extractedDateString = extract("timestampUTC : (\\d{4}\\W\\d{2}\\W\\d{2})", 1, tostring(properties.instanceView.status.message)) // Extracting the date string for the LastUploadTimestamp. Is empty if none is found.
| extend extractedDateStringYear = split(extractedDateString, '/')[0], extractedDateStringMonth = split(extractedDateString, '/')[1], extractedDateStringDay = split(extractedDateString, '/')[2] // Identifying each of the parts of the date that was extracted from the message.
| extend extractedDate = todatetime(strcat(extractedDateStringYear,"-",extractedDateStringMonth,"-",extractedDateStringDay,"T00:00:00Z")) // Converting to a datetime object and rewriting string into ISO format because todatetime() does not work using the previous format.
| extend isNotInDateRange = not(extractedDate >= startDate and extractedDate <= endDate) // Created bool which is true if the date we extracted from the message is not within the specified range. This bool will also be true if the date was not found in the message.
| where properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy" // Begin searching for unhealthy extensions using the following 1. Does extension report being healthy. 2. Is last upload within the given range. 3. Is the upload status in an OK state. 4. Is provisioning state not in a succeeded state.
    or isNotInDateRange
    or properties.instanceView.status.message !contains "uploadStatus : OK"
    or properties.provisioningState != "Succeeded"
    or MachineStatus != "Connected"
| extend FailureReasons = strcat( // Makes a String to list all the reason that this resource got flagged for
        iif(MachineStatus != "Connected",strcat("- Machine's status is ", MachineStatus," -"),"") ,
        iif(MachineErrors != "[]","- Machine reports errors -", ""),
        iif(properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy","- Extension reported unhealthy -",""),
        iif(isNotInDateRange,"- Last upload outside acceptable range -",""),
        iif(properties.instanceView.status.message !contains "uploadStatus : OK","- Upload status is not reported OK -",""),
        iif(properties.provisioningState != "Succeeded",strcat("- Extension provisiong state is ", properties.provisioningState," -"),"")
    )
| extend RecommendedAction = //Attempt to Identify RootCause based on information gathered, and point customer to what they should investigate first.
    iif(MachineStatus == "Disconnected", "Machine is disconnected. Please reconnect the machine.",
        iif(MachineStatus == "Expired", "Machine cert is expired. Go to the machine on the Azure portal for more information on how to resolve this issue.",
            iif(MachineStatus != "Connected", strcat("Machine status is ", MachineStatus,". Investigate and resolve this issue."),
                iif(MachineProvisioningStatus != "Succeeded", strcat("Machine provisioning status is ", MachineProvisioningStatus, ". Investigate and resolve machine provisioning status"),
                    iff(MachineErrors != "[]", "Machine is reporting errors. Investigate and resolve machine errors",
                        iif(properties.provisioningState != "Succeeded", strcat("Extension provisioning status is ", properties.provisioningState,". Investigate and resolve extension provisioning state."),
                            iff(properties.instanceView.status.message !contains "SQL Server Extension Agent:" and properties.instanceView.status.message contains "SQL Server Extension Agent Deployer", "SQL Server extension employer ran. However, SQL Server extension seems to not be running. Verify that the extension is currently running.",
                                iff(properties.instanceView.status.message !contains "uploadStatus : OK" or isNotInDateRange or properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy", "Extension reported as unhealthy. View FailureReasons and LastExtensionStatusMessage for more information as to the cause of the failure.",
                                    "Unable to recommend actions. Please view FailureReasons."
                                )
                            )
                        )
                    )
                )
            )
        )
    )
| project ID = id, MachineName, ResourceGroup = resourceGroup, SubscriptionID = subscriptionId, Location = location, RecommendedAction, FailureReasons, LicenseType = properties.settings.LicenseType,
    LastReportedExtensionHealth = iif(properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy", "Unhealthy", "Healthy"),
    LastExtensionUploadTimestamp = iif(indexof(properties.instanceView.status.message, "timestampUTC : ") > 0,
        substring(properties.instanceView.status.message, indexof(properties.instanceView.status.message, "timestampUTC : ") + 15, 10),
        "no timestamp"),
    LastExtensionUploadStatus = iif(indexof(properties.instanceView.status.message, "uploadStatus : OK") > 0, "OK", "Unhealthy"),
    ExtensionProvisioningState = properties.provisioningState,
    MachineStatus, MachineErrors, MachineProvisioningStatus,MachineId = machineId,
    LastExtensionStatusMessage = properties.instanceView.status.message

Pour identifier les problèmes potentiels, examinez la valeur dans la colonne RecommendedAction ou FailureReasons. La colonne RecommendedAction fournit les premières étapes possibles pour résoudre le problème ou des indices sur ce qu’il faut vérifier en premier. La colonne FailureReasons répertorie les raisons pour lesquelles la ressource a été considérée comme non saine. Enfin, vérifiez LastExtensionStatusMessage pour voir le dernier message signalé par l’agent.

Recommandations

Action recommandée Détails de l’action
Le certificat de la machine a expiré.

Accédez à la machine sur le portail Azure pour plus d’informations sur la façon de résoudre ce problème.
La machine avec Arc doit être réinsérée à Arc, car le certificat utilisé pour s’authentifier auprès d’Azure a expiré. L’état de l’ordinateur Arc est expiré dans le portail Azure. Vous pouvez désinstaller l’agent , puis réinscrire. Il n'est pas nécessaire de supprimer les ressources SQL Server activées par Arc dans le portail si vous vous réinscrivez. L'extension SQL est automatiquement réinstallée tant que l'intégration automatique est activée (par défaut).
La machine est déconnectée.

Reconnectez la machine.
La machine Arc est dans un état de type state = Disconnected. Cet état peut être pour diverses raisons :
L’agent d’ordinateur connecté à Arc est arrêté, désactivé ou constamment en panne
ou
La connectivité est bloquée entre l’agent et Azure.
Vérifiez l’état de ces services/démons connectés à Arc pour vous assurer qu’ils sont activés et en cours d’exécution.
Vérifier la connectivité.
Résolvez les problèmes de l'agent en utilisant le journal détaillé.
Extension signalée comme non saine.

Consultez FailureReasons et LastExtensionStatusMessage pour plus d’informations sur la cause de l’échec.
Dernier envoi de données en dehors de la période acceptable (dans les trois derniers jours).
Vérifiez la colonne LastExtensionUploadTimestamp. S’il ne s’agit pas d’un horodatage, il n’a jamais signalé de données d’inventaire ou d’utilisation dans Azure. Résolvez les problèmes de connectivité au service de traitement des données et aux points de terminaison de télémétrie.
Si le dernier chargement est en dehors de la plage acceptable (au cours des trois derniers jours) et que tout le reste semble OK, comme LastExtensionUploadStatus, ExtensionProvisioningState et MachineStatus, il est possible que l’extension Azure pour le service/démon SQL Server soit arrêtée. Découvrez pourquoi il est arrêté et recommencez-le. Vérifiez la LastExtensionStatusMessage pour obtenir d’autres indices sur le problème.
L'état de provisionnement de l'extension est Échec.

Examinez et résolvez l'état de provisionnement de l'extension.
L’installation initiale de l’extension SQL ou la mise à jour a échoué. Résoudre les problèmes liés à l’extension Azure pour le déploiement de SQL Server.
Veuillez vérifier la valeur dans LastExtensionStatusMessage.
L'état du chargement n'est pas signalé comme OK. Consultez la colonne LastExtensionMessage dans le tableau de bord et examinez la valeur uploadStatus et la valeur uploadMessage (selon la version, le cas échéant).

La valeur uploadStatus est généralement un code d’erreur HTTP. Passez en revue l'article Résoudre les problèmes de codes d'erreur.
Le uploadMessage peut avoir des informations plus spécifiques. Résolvez les problèmes de connectivité au service de traitement des données et aux points de terminaison de télémétrie.
L'état de provisionnement de l'extension est Mise à jour

ou
L'état de provisionnement de l'extension est Création
ou
L'état de provisionnement de l'extension est Échec
ou
L'état de provisionnement de l'extension est Suppression
Si une extension donnée reste dans l’un de ces états pendant plus de 30 minutes, il est probable qu’il y ait un problème d'approvisionnement. Désinstallez l’extension et réinstallez-la à l’aide de l’interface CLI ou du portail. Si le problème persiste, vérifiez les journaux d'extension et de déploiement.
Si la création de l’extension échoue, vérifiez que l’agent est connecté et que les services d’agent associés sont en cours d’exécution.
En cas d’échec de la suppression, essayez de désinstaller l’agent et de supprimer la ressource de machine Arc dans le portail si nécessaire, puis redéployez.
Vous pouvez désinstaller l’agent , puis réinscrire.

Identifier une extension non saine (PowerShell)

Cet exemple s'exécute dans PowerShell. L’exemple retourne le même résultat que la requête précédente, mais via un script PowerShell.

# PowerShell script to execute an Azure Resource Graph query using Azure CLI
# where the extension status is unhealthy or the extension last upload time isn't in this month or the previous month.

# Requires the Az.ResourceGraph PowerShell module

# Login to Azure if needed
#az login

# Define the Azure Resource Graph query
$query = @"
resources
| where type == "microsoft.hybridcompute/machines/extensions"
| where properties.type in ("WindowsAgent.SqlServer", "LinuxAgent.SqlServer")
| extend targetMachineName = tolower(tostring(split(id, '/')[8])) // Extract the machine name from the extension's id
| join kind=leftouter (
    resources
    | where type == "microsoft.hybridcompute/machines"
    | project machineId = id, MachineName = name, subscriptionId, LowerMachineName = tolower(name), resourceGroup , MachineStatus= properties.status , MachineProvisioningStatus= properties.provisioningState, MachineErrors = properties.errorDetails //Project relevant machine health information.
) on $left.targetMachineName == $right.LowerMachineName and $left.resourceGroup == $right.resourceGroup and $left.subscriptionId == $right.subscriptionId // Join Based on MachineName in the id and the machine's name, the resource group, and the subscription. This join allows us to present the data of the machine as well as the extension in the final output.
| extend statusExpirationLengthRange = 3d // Change this value to change the acceptable range for the last time an extension should have reported its status.
| extend startDate = startofday(now() - statusExpirationLengthRange), endDate = startofday(now()) // Get the start and end position for the given range.
| extend extractedDateString = extract("timestampUTC : (\\d{4}\\W\\d{2}\\W\\d{2})", 1, tostring(properties.instanceView.status.message)) // Extracting the date string for the LastUploadTimestamp. Is empty if none is found.
| extend extractedDateStringYear = split(extractedDateString, '/')[0], extractedDateStringMonth = split(extractedDateString, '/')[1], extractedDateStringDay = split(extractedDateString, '/')[2] // Identifying each of the parts of the date that was extracted from the message.
| extend extractedDate = todatetime(strcat(extractedDateStringYear,"-",extractedDateStringMonth,"-",extractedDateStringDay,"T00:00:00Z")) // Converting to a datetime object and rewriting string into ISO format because todatetime() does not work using the previous format.
| extend isNotInDateRange = not(extractedDate >= startDate and extractedDate <= endDate) // Created bool which is true if the date we extracted from the message is not within the specified range. This bool will also be true if the date was not found in the message.
| where properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy" // Begin searching for unhealthy extensions using the following 1. Does extension report being healthy. 2. Is last upload within the given range. 3. Is the upload status in an OK state. 4. Is provisioning state not in a succeeded state.
    or isNotInDateRange
    or properties.instanceView.status.message !contains "uploadStatus : OK"
    or properties.provisioningState != "Succeeded"
    or MachineStatus != "Connected"
| extend FailureReasons = strcat( // Makes a String to list all the reason that this resource got flagged for
        iif(MachineStatus != "Connected",strcat("- Machine's status is ", MachineStatus," -"),"") ,
        iif(MachineErrors != "[]","- Machine reports errors -", ""),
        iif(properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy","- Extension reported unhealthy -",""),
        iif(isNotInDateRange,"- Last upload outside acceptable range -",""),
        iif(properties.instanceView.status.message !contains "uploadStatus : OK","- Upload status is not reported OK -",""),
        iif(properties.provisioningState != "Succeeded",strcat("- Extension provisiong state is ", properties.provisioningState," -"),"")
    )
| extend RecommendedAction = //Attempt to Identify RootCause based on information gathered, and point customer to what they should investigate first.
    iif(MachineStatus == "Disconnected", "Machine is disconnected. Please reconnect the machine.",
        iif(MachineStatus == "Expired", "Machine cert is expired. Go to the machine on the Azure portal for more information on how to resolve this issue.",
            iif(MachineStatus != "Connected", strcat("Machine status is ", MachineStatus,". Investigate and resolve this issue."),
                iif(MachineProvisioningStatus != "Succeeded", strcat("Machine provisioning status is ", MachineProvisioningStatus, ". Investigate and resolve machine provisioning status"),
                    iff(MachineErrors != "[]", "Machine is reporting errors. Investigate and resolve machine errors",
                        iif(properties.provisioningState != "Succeeded", strcat("Extension provisioning status is ", properties.provisioningState,". Investigate and resolve extension provisioning state."),
                            iff(properties.instanceView.status.message !contains "SQL Server Extension Agent:" and properties.instanceView.status.message contains "SQL Server Extension Agent Deployer", "SQL Server extension employer ran. However, SQL Server extension seems to not be running. Verify that the extension is currently running.",
                                iff(properties.instanceView.status.message !contains "uploadStatus : OK" or isNotInDateRange or properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy", "Extension reported as unhealthy. View FailureReasons and LastExtensionStatusMessage for more information as to the cause of the failure.",
                                    "Unable to recommend actions. Please view FailureReasons."
                                )
                            )
                        )
                    )
                )
            )
        )
    )
| project ID = id, MachineName, ResourceGroup = resourceGroup, SubscriptionID = subscriptionId, Location = location, RecommendedAction, FailureReasons, LicenseType = properties.settings.LicenseType,
    LastReportedExtensionHealth = iif(properties.instanceView.status.message !contains "SQL Server Extension Agent: Healthy", "Unhealthy", "Healthy"),
    LastExtensionUploadTimestamp = iif(indexof(properties.instanceView.status.message, "timestampUTC : ") > 0,
        substring(properties.instanceView.status.message, indexof(properties.instanceView.status.message, "timestampUTC : ") + 15, 10),
        "no timestamp"),
    LastExtensionUploadStatus = iif(indexof(properties.instanceView.status.message, "uploadStatus : OK") > 0, "OK", "Unhealthy"),
    ExtensionProvisioningState = properties.provisioningState,
    MachineStatus, MachineErrors, MachineProvisioningStatus,MachineId = machineId,
    LastExtensionStatusMessage = properties.instanceView.status.message
"@

# Execute the Azure Resource Graph query
$result = Search-AzGraph -Query $query

# Output the results
$result | Format-Table -Property ExtensionHealth, LastUploadTimestamp, LastUploadStatus, Message

Pour identifier les problèmes potentiels, examinez la valeur dans la colonne RecommendedAction ou FailureReasons. La colonne RecommendedAction fournit les premières étapes possibles pour résoudre le problème ou des indices sur ce qu’il faut vérifier en premier. La colonne FailureReasons répertorie les raisons pour lesquelles la ressource a été considérée comme non saine. Enfin, vérifiez LastExtensionStatusMessage pour voir le dernier message signalé par l’agent.

Identifier les extensions nécessitant une mise à jour

Identifiez les extensions sans mises à jour d’état récentes. Cette requête renvoie une liste des extensions Azure pour SQL Server, classées par nombre de jours écoulés depuis la dernière mise à jour de leur statut. Une valeur égale à -1 indique que l'extension a planté et qu'une trace de pile est présente dans le statut de l'extension.

// Show the timestamp extracted
// If an extension has crashed (i.e. no heartbeat), fill timestamp with "1900/01/01, 00:00:00.000"
//
resources
| where type =~ 'microsoft.hybridcompute/machines/extensions'
| extend extensionStatus = parse_json(properties).instanceView.status.message
| extend timestampExtracted = extract(@"timestampUTC\s*:\s*(\d{4}/\d{2}/\d{2}, \d{2}:\d{2}:\d{2}\.\d{3})", 1, tostring(extensionStatus))
| extend timestampNullFilled = iff(isnull(timestampExtracted) or timestampExtracted == "", "1900/01/01, 00:00:00.000", timestampExtracted)
| extend timestampKustoFormattedString = strcat(replace(",", "", replace("/", "-", replace("/", "-", timestampNullFilled))), "Z")
| extend agentHeartbeatUtcTimestamp = todatetime(timestampKustoFormattedString)
| extend agentHeartbeatLagInDays = datetime_diff('day', now(), agentHeartbeatUtcTimestamp)
| project id, extensionStatus, agentHeartbeatUtcTimestamp, agentHeartbeatLagInDays
| limit 100
| order by ['agentHeartbeatLagInDays'] asc

Cette requête renvoie un nombre d'extensions groupées par nombre de jours écoulés depuis leur dernière mise à jour de statut. Une valeur égale à -1 indique que l'extension a planté et qu'une trace de pile est présente dans le statut de l'extension.

// Aggregate by timestamp
//
// -1: Crashed extension with no heartbeat, we got a stacktrace instead
//  0: Healthy
// >1: Stale/Offline
//
resources
| where type =~ 'microsoft.hybridcompute/machines/extensions'
| extend extensionStatus = parse_json(properties).instanceView.status.message
| extend timestampExtracted = extract(@"timestampUTC\s*:\s*(\d{4}/\d{2}/\d{2}, \d{2}:\d{2}:\d{2}\.\d{3})", 1, tostring(extensionStatus))
| extend timestampNullFilled = iff(isnull(timestampExtracted) or timestampExtracted == "", "1900/01/01, 00:00:00.000", timestampExtracted)
| extend timestampKustoFormattedString = strcat(replace(",", "", replace("/", "-", replace("/", "-", timestampNullFilled))), "Z")
| extend agentHeartbeatUtcTimestamp = todatetime(timestampKustoFormattedString)
| extend agentHeartbeatLagInDays = iff(agentHeartbeatUtcTimestamp == todatetime("1900/01/01, 00:00:00.000Z"), -1, datetime_diff('day', now(), agentHeartbeatUtcTimestamp))
| summarize numExtensions = count() by agentHeartbeatLagInDays
| order by numExtensions desc

Mettre à niveau l’extension

Pour déterminer la version de la version actuelle de l’extension, passez en revue les notes de publication.

Pour vérifier la version de votre extension, utilisez la commande PowerShell suivante :

azcmagent version

Pour simplifier les mises à niveau d’extension, veillez à activer les mises à jour automatiques. Vous pouvez également mettre à niveau manuellement l’extension à l’aide du portail Azure, de PowerShell et d’Azure CLI.

Pour mettre à niveau l’extension dans le portail Azure, procédez comme suit :

  1. Dans le portail Azure, accédez à Machines - Azure Arc.

  2. Sélectionnez le nom de l’ordinateur sur lequel SQL Server est installé pour ouvrir le volet Vue d’ensemble de votre serveur.

  3. Sous Paramètres, sélectionnez Extensions.

  4. Cochez la case pour l’extension WindowsAgent.SqlServer , puis sélectionnez Mettre à jour dans le menu de navigation.

    Capture d’écran du volet Extension pour le volet Machine - Azure Arc dans le portail Azure, avec mise à jour mise en surbrillance.

  5. Sélectionnez Oui dans la boîte de dialogue de confirmation de l’extension De mise à jour pour terminer la mise à niveau.

Pour plus d’informations sur la mise à niveau de l’extension Azure pour SQL Server, consultez Mise à niveau de l’extension.