Condividi tramite


Creare avvisi di ricerca log da Informazioni dettagliate sui contenitori

Le informazioni dettagliate sul contenitore monitorizzano le prestazioni dei carichi di lavoro dei contenitori distribuiti nei cluster Kubernetes gestiti o autogestiti. Per ricevere avvisi sugli aspetti importanti, questo articolo descrive come creare avvisi basati su log per le situazioni seguenti con i cluster del servizio Azure Kubernetes:

  • Quando l'utilizzo della CPU o della memoria nei nodi del cluster supera una soglia
  • Quando l'utilizzo della CPU o della memoria in qualsiasi contenitore all'interno di un controller supera una soglia rispetto a un limite impostato sulla risorsa corrispondente
  • NotReady conteggi dei nodi di stato
  • Failed, Pending, Unknown, Running o Succeeded conteggi delle fasi dei pod
  • Quando lo spazio libero su disco nei nodi del cluster supera una soglia

Per ricevere avvisi per un utilizzo elevato della CPU o della memoria o per uno spazio su disco insufficiente nei nodi del cluster, usare le query fornite per creare un avviso di metrica o un avviso di misurazione della metrica. Gli avvisi delle metriche hanno una latenza inferiore rispetto agli avvisi di ricerca log, ma gli avvisi di ricerca log offrono query avanzate e maggiore complessità. Le query di avviso di ricerca log confrontano un valore datetime con il presente usando l'operatore now e tornare indietro di un'ora. (Le informazioni dettagliate sui contenitori archiviano tutte le date in formato [UTC] in Coordinated Universal Time).

Importante

Le query contenute in questo articolo dipendono dai dati raccolti da Informazioni dettagliate sui contenitori e archiviati in un'area di lavoro Log Analytics. Se sono state modificate le impostazioni di raccolta dati predefinite, le query potrebbero non restituire i risultati previsti. In particolare, se è stata disabilitata la raccolta di dati sulle prestazioni perché sono state abilitate le metriche Prometheus per il cluster, le query che usano la tabella Perf non restituiranno risultati.

Vedere Configurare la raccolta dati in Informazioni dettagliate sui contenitori usando la regola di raccolta dati per le configurazioni predefinite, inclusa la disabilitazione della raccolta dei dati sulle prestazioni. Per altre opzioni di raccolta dati, vedere Configurare la raccolta dati in Informazioni dettagliate sui contenitori con ConfigMap.

Se non si ha familiarità con gli avvisi di Monitoraggio di Azure, vedere Panoramica degli avvisi in Microsoft Azure prima di iniziare. Per altre informazioni sugli avvisi che usano le query di log, vedere Avvisi di ricerca log in Monitoraggio di Azure. Per altre informazioni sugli avvisi delle metriche, vedere Avvisi delle metriche in Monitoraggio di Azure.

Misurazioni delle query di log

Gli Avvisi di ricerca log possono misurare due aspetti diversi, che possono essere usati per monitorare le macchine virtuali in scenari diversi:

  • Conteggio risultati: conta il numero di righe restituite dalla query e può essere usato per lavorare con eventi quali registri eventi di Windows, Syslog ed eccezioni dell'applicazione.
  • Calcolo di un valore: esegue un calcolo basato su una colonna numerica e può essere usato per includere un numero qualsiasi di risorse. Un esempio è la percentuale di CPU.

Risorse e dimensioni di destinazione

È possibile usare una regola per monitorare i valori di più istanze usando le dimensioni. Ad esempio, si userebbero dimensioni se si vuole monitorare l'utilizzo della CPU in più istanze che eseguono il sito Web o l'app e creare un avviso per l'utilizzo della CPU superiore all'80%.

Per creare avvisi incentrati sulle risorse su larga scala per una sottoscrizione o un gruppo di risorse, è possibile si usa la suddividere in base alle dimensioni. Quando si vuole monitorare la stessa condizione in più risorse di Azure, la suddivisione per dimensioni suddivide gli avvisi in avvisi separati raggruppando combinazioni univoche usando colonne numeriche o stringa. La suddivisione di una colonna ID risorsa di Azure rende la risorsa specificata nella destinazione dell'avviso.

È anche possibile decidere di non suddividere quando si vuole desidera una condizione a più risorse nell'ambito. Ad esempio, potrebbe essere necessario creare un avviso se almeno cinque computer nell'ambito del gruppo di risorse hanno un utilizzo della CPU superiore all'80%.

Screenshot che mostra una nuova regola di avviso di ricerca log con dimensioni suddivise.

Potrebbe essere necessario visualizzare un elenco degli avvisi da parte del computer interessato. È possibile usare una cartella di lavoro personalizzata che usa un grafico delle risorse personalizzato per fornire questa visualizzazione. Usare la query seguente per visualizzare gli avvisi e usare l'origine dati Azure Resource Graph nella cartella di lavoro.

Creare una regola di avviso di ricerca log

Per creare una regola di avviso di ricerca log usando il portale, vedere questo esempio di un avviso di ricerca log, che fornisce una procedura dettagliata completa. È possibile usare questi stessi processi per creare regole di avviso per i cluster del servizio Azure Kubernetes usando query simili a quelle contenute in questo articolo.

Per creare una regola di avviso di query usando un modello di Azure Resource Manager (ARM), vedere gli Esempi di modelli di Resource Manager per le regole di avviso di ricerca log in Monitoraggio di Azure. È possibile usare questi stessi processi per creare modelli di Resource Manager per le query di log in questo articolo.

Utilizzo della risorsa

Utilizzo medio della CPU come media dell'utilizzo della CPU dei nodi membro ogni minuto (misurazione della metrica):

let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let capacityCounterName = 'cpuCapacityNanoCores';
let usageCounterName = 'cpuUsageNanoCores';
KubeNodeInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
// cluster filter would go here if multiple clusters are reporting to the same Log Analytics workspace
| distinct ClusterName, Computer
| join hint.strategy=shuffle (
  Perf
  | where TimeGenerated < endDateTime
  | where TimeGenerated >= startDateTime
  | where ObjectName == 'K8SNode'
  | where CounterName == capacityCounterName
  | summarize LimitValue = max(CounterValue) by Computer, CounterName, bin(TimeGenerated, trendBinSize)
  | project Computer, CapacityStartTime = TimeGenerated, CapacityEndTime = TimeGenerated + trendBinSize, LimitValue
) on Computer
| join kind=inner hint.strategy=shuffle (
  Perf
  | where TimeGenerated < endDateTime + trendBinSize
  | where TimeGenerated >= startDateTime - trendBinSize
  | where ObjectName == 'K8SNode'
  | where CounterName == usageCounterName
  | project Computer, UsageValue = CounterValue, TimeGenerated
) on Computer
| where TimeGenerated >= CapacityStartTime and TimeGenerated < CapacityEndTime
| project ClusterName, Computer, TimeGenerated, UsagePercent = UsageValue * 100.0 / LimitValue
| summarize AggValue = avg(UsagePercent) by bin(TimeGenerated, trendBinSize), ClusterName

Utilizzo medio della memoria come media dell'utilizzo della memoria dei nodi membro ogni minuto (misurazione della metrica):

let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let capacityCounterName = 'memoryCapacityBytes';
let usageCounterName = 'memoryRssBytes';
KubeNodeInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
// cluster filter would go here if multiple clusters are reporting to the same Log Analytics workspace
| distinct ClusterName, Computer
| join hint.strategy=shuffle (
  Perf
  | where TimeGenerated < endDateTime
  | where TimeGenerated >= startDateTime
  | where ObjectName == 'K8SNode'
  | where CounterName == capacityCounterName
  | summarize LimitValue = max(CounterValue) by Computer, CounterName, bin(TimeGenerated, trendBinSize)
  | project Computer, CapacityStartTime = TimeGenerated, CapacityEndTime = TimeGenerated + trendBinSize, LimitValue
) on Computer
| join kind=inner hint.strategy=shuffle (
  Perf
  | where TimeGenerated < endDateTime + trendBinSize
  | where TimeGenerated >= startDateTime - trendBinSize
  | where ObjectName == 'K8SNode'
  | where CounterName == usageCounterName
  | project Computer, UsageValue = CounterValue, TimeGenerated
) on Computer
| where TimeGenerated >= CapacityStartTime and TimeGenerated < CapacityEndTime
| project ClusterName, Computer, TimeGenerated, UsagePercent = UsageValue * 100.0 / LimitValue
| summarize AggValue = avg(UsagePercent) by bin(TimeGenerated, trendBinSize), ClusterName

Importante

Le query seguenti usano i valori segnaposto <your-cluster-name> e <your-controller-name> per rappresentare il cluster e il controller. Sostituirli con valori specifici dell'ambiente quando si configurano gli avvisi.

Utilizzo medio della CPU di tutti i contenitori in un controller come media dell'utilizzo della CPU di ogni istanza del contenitore in un controller ogni minuto (misurazione della metrica):

let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let capacityCounterName = 'cpuLimitNanoCores';
let usageCounterName = 'cpuUsageNanoCores';
let clusterName = '<your-cluster-name>';
let controllerName = '<your-controller-name>';
KubePodInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| where ClusterName == clusterName
| where ControllerName == controllerName
| extend InstanceName = strcat(ClusterId, '/', ContainerName),
         ContainerName = strcat(controllerName, '/', tostring(split(ContainerName, '/')[1]))
| distinct Computer, InstanceName, ContainerName
| join hint.strategy=shuffle (
    Perf
    | where TimeGenerated < endDateTime
    | where TimeGenerated >= startDateTime
    | where ObjectName == 'K8SContainer'
    | where CounterName == capacityCounterName
    | summarize LimitValue = max(CounterValue) by Computer, InstanceName, bin(TimeGenerated, trendBinSize)
    | project Computer, InstanceName, LimitStartTime = TimeGenerated, LimitEndTime = TimeGenerated + trendBinSize, LimitValue
) on Computer, InstanceName
| join kind=inner hint.strategy=shuffle (
    Perf
    | where TimeGenerated < endDateTime + trendBinSize
    | where TimeGenerated >= startDateTime - trendBinSize
    | where ObjectName == 'K8SContainer'
    | where CounterName == usageCounterName
    | project Computer, InstanceName, UsageValue = CounterValue, TimeGenerated
) on Computer, InstanceName
| where TimeGenerated >= LimitStartTime and TimeGenerated < LimitEndTime
| project Computer, ContainerName, TimeGenerated, UsagePercent = UsageValue * 100.0 / LimitValue
| summarize AggValue = avg(UsagePercent) by bin(TimeGenerated, trendBinSize) , ContainerName

Utilizzo medio della memoria di tutti i contenitori in un controller come media dell'utilizzo della memoria di ogni istanza del contenitore in un controller ogni minuto (misurazione della metrica):

let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let capacityCounterName = 'memoryLimitBytes';
let usageCounterName = 'memoryRssBytes';
let clusterName = '<your-cluster-name>';
let controllerName = '<your-controller-name>';
KubePodInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| where ClusterName == clusterName
| where ControllerName == controllerName
| extend InstanceName = strcat(ClusterId, '/', ContainerName),
         ContainerName = strcat(controllerName, '/', tostring(split(ContainerName, '/')[1]))
| distinct Computer, InstanceName, ContainerName
| join hint.strategy=shuffle (
    Perf
    | where TimeGenerated < endDateTime
    | where TimeGenerated >= startDateTime
    | where ObjectName == 'K8SContainer'
    | where CounterName == capacityCounterName
    | summarize LimitValue = max(CounterValue) by Computer, InstanceName, bin(TimeGenerated, trendBinSize)
    | project Computer, InstanceName, LimitStartTime = TimeGenerated, LimitEndTime = TimeGenerated + trendBinSize, LimitValue
) on Computer, InstanceName
| join kind=inner hint.strategy=shuffle (
    Perf
    | where TimeGenerated < endDateTime + trendBinSize
    | where TimeGenerated >= startDateTime - trendBinSize
    | where ObjectName == 'K8SContainer'
    | where CounterName == usageCounterName
    | project Computer, InstanceName, UsageValue = CounterValue, TimeGenerated
) on Computer, InstanceName
| where TimeGenerated >= LimitStartTime and TimeGenerated < LimitEndTime
| project Computer, ContainerName, TimeGenerated, UsagePercent = UsageValue * 100.0 / LimitValue
| summarize AggValue = avg(UsagePercent) by bin(TimeGenerated, trendBinSize) , ContainerName

Disponibilità delle risorse

Nodi e conteggi con stato Ready e NotReady (misurazione metrica):

let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let clusterName = '<your-cluster-name>';
KubeNodeInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| distinct ClusterName, Computer, TimeGenerated
| summarize ClusterSnapshotCount = count() by bin(TimeGenerated, trendBinSize), ClusterName, Computer
| join hint.strategy=broadcast kind=inner (
    KubeNodeInventory
    | where TimeGenerated < endDateTime
    | where TimeGenerated >= startDateTime
    | summarize TotalCount = count(), ReadyCount = sumif(1, Status contains ('Ready'))
                by ClusterName, Computer,  bin(TimeGenerated, trendBinSize)
    | extend NotReadyCount = TotalCount - ReadyCount
) on ClusterName, Computer, TimeGenerated
| project   TimeGenerated,
            ClusterName,
            Computer,
            ReadyCount = todouble(ReadyCount) / ClusterSnapshotCount,
            NotReadyCount = todouble(NotReadyCount) / ClusterSnapshotCount
| order by ClusterName asc, Computer asc, TimeGenerated desc

La query seguente restituisce i conteggi delle fasi dei pod in base a tutte le fasi: Failed, Pending, Unknown, Running o Succeeded.

let endDateTime = now(); 
let startDateTime = ago(1h);
let trendBinSize = 1m;
let clusterName = '<your-cluster-name>';
KubePodInventory
    | where TimeGenerated < endDateTime
    | where TimeGenerated >= startDateTime
    | where ClusterName == clusterName
    | distinct ClusterName, TimeGenerated
    | summarize ClusterSnapshotCount = count() by bin(TimeGenerated, trendBinSize), ClusterName
    | join hint.strategy=broadcast (
        KubePodInventory
        | where TimeGenerated < endDateTime
        | where TimeGenerated >= startDateTime
        | summarize PodStatus=any(PodStatus) by TimeGenerated, PodUid, ClusterName
        | summarize TotalCount = count(),
                    PendingCount = sumif(1, PodStatus =~ 'Pending'),
                    RunningCount = sumif(1, PodStatus =~ 'Running'),
                    SucceededCount = sumif(1, PodStatus =~ 'Succeeded'),
                    FailedCount = sumif(1, PodStatus =~ 'Failed')
                by ClusterName, bin(TimeGenerated, trendBinSize)
    ) on ClusterName, TimeGenerated
    | extend UnknownCount = TotalCount - PendingCount - RunningCount - SucceededCount - FailedCount
    | project TimeGenerated,
              TotalCount = todouble(TotalCount) / ClusterSnapshotCount,
              PendingCount = todouble(PendingCount) / ClusterSnapshotCount,
              RunningCount = todouble(RunningCount) / ClusterSnapshotCount,
              SucceededCount = todouble(SucceededCount) / ClusterSnapshotCount,
              FailedCount = todouble(FailedCount) / ClusterSnapshotCount,
              UnknownCount = todouble(UnknownCount) / ClusterSnapshotCount
| summarize AggValue = avg(PendingCount) by bin(TimeGenerated, trendBinSize)

Nota

Per ricevere avvisi su determinate fasi del pod, ad esempio Pending, Failed o Unknown, modificare l'ultima riga della query. Ad esempio, per generare un avviso su FailedCount, usare | summarize AggValue = avg(FailedCount) by bin(TimeGenerated, trendBinSize).

La query seguente restituisce dischi dei nodi del cluster che superano il 90% dello spazio disponibile usato. Per ottenere l'ID cluster, eseguire prima di tutto la query seguente e copiare il valore dalla proprietà ClusterId:

InsightsMetrics
| extend Tags = todynamic(Tags)            
| project ClusterId = Tags['container.azm.ms/clusterId']   
| distinct tostring(ClusterId)   
let clusterId = '<cluster-id>';
let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
InsightsMetrics
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| where Origin == 'container.azm.ms/telegraf'            
| where Namespace == 'container.azm.ms/disk'            
| extend Tags = todynamic(Tags)            
| project TimeGenerated, ClusterId = Tags['container.azm.ms/clusterId'], Computer = tostring(Tags.hostName), Device = tostring(Tags.device), Path = tostring(Tags.path), DiskMetricName = Name, DiskMetricValue = Val   
| where ClusterId =~ clusterId       
| where DiskMetricName == 'used_percent'
| summarize AggValue = max(DiskMetricValue) by bin(TimeGenerated, trendBinSize)
| where AggValue >= 90

Il singolo contenitore viene riavviato (numero di risultati) quando il numero di riavvio del singolo contenitore di sistema supera una soglia per gli ultimi 10 minuti:

let _threshold = 10m; 
let _alertThreshold = 2;
let Timenow = (datetime(now) - _threshold); 
let starttime = ago(5m); 
KubePodInventory
| where TimeGenerated >= starttime
| where Namespace in ('default', 'kube-system') // the namespace filter goes here
| where ContainerRestartCount > _alertThreshold
| extend Tags = todynamic(ContainerLastStatus)
| extend startedAt = todynamic(Tags.startedAt)
| where startedAt >= Timenow
| summarize arg_max(TimeGenerated, *) by Name

Passaggi successivi