Skapa loggsökningsaviseringar från Container Insights

Containerinsikter övervakar prestandan för containerarbetsbelastningar som distribueras till hanterade eller självhanterade Kubernetes-kluster. Den här artikeln beskriver hur du skapar loggbaserade aviseringar för följande situationer med Azure Kubernetes Service-kluster (AKS) för att avisera om vad som är viktigt:

  • När processor- eller minnesanvändning på klusternoder överskrider ett tröskelvärde
  • När processor- eller minnesanvändning på en container i en kontrollant överskrider ett tröskelvärde jämfört med en gräns som har angetts för motsvarande resurs
  • NotReady antal statusnoder
  • Failed, Pending, Unknown, Runningeller Succeeded poddfasantal
  • När ledigt diskutrymme på klusternoder överskrider ett tröskelvärde

Om du vill varna för hög processor- eller minnesanvändning eller lågt ledigt diskutrymme på klusternoder använder du de frågor som tillhandahålls för att skapa en måttavisering eller en måttmätningsavisering. Måttaviseringar har lägre svarstid än loggsökningsaviseringar, men aviseringar för loggsökning ger avancerade frågor och större sofistikering. Aviseringsfrågor för loggsökning jämför en datetime med nutiden med hjälp av operatorn now och går tillbaka en timme. (Container insights lagrar alla datum i formatet Coordinated Universal Time [UTC].)

Viktigt!

Frågorna i den här artikeln beror på data som samlas in av Container Insights och lagras på en Log Analytics-arbetsyta. Om du har ändrat standardinställningarna för datainsamling kanske frågorna inte returnerar det förväntade resultatet. Om du har inaktiverat insamling av prestandadata eftersom du har aktiverat Prometheus-mått för klustret returnerar inte frågor som använder Perf tabellen resultat.

Se Konfigurera datainsamling i Container Insights med hjälp av datainsamlingsregeln för förinställda konfigurationer, inklusive inaktivering av insamling av prestandadata. Se Konfigurera datainsamling i Container Insights med hjälp av ConfigMap för ytterligare datainsamlingsalternativ.

Om du inte är bekant med Azure Monitor-aviseringar kan du läsa Översikt över aviseringar i Microsoft Azure innan du börjar. Mer information om aviseringar som använder loggfrågor finns i Logga sökaviseringar i Azure Monitor. Mer information om måttaviseringar finns i Måttaviseringar i Azure Monitor.

Loggfrågemått

Loggsökningsaviseringar kan mäta två olika saker, som kan användas för att övervaka virtuella datorer i olika scenarier:

  • Resultatantal: Räknar antalet rader som returneras av frågan och kan användas för att arbeta med händelser som Windows-händelseloggar, Syslog och programfel.
  • Beräkning av ett värde: Gör en beräkning baserat på en numerisk kolumn och kan användas för att inkludera valfritt antal resurser. Ett exempel är CPU-procent.

Målresurser och dimensioner

Du kan använda en regel för att övervaka värdena för flera instanser med hjälp av dimensioner. Du kan till exempel använda dimensioner om du vill övervaka CPU-användningen på flera instanser som kör din webbplats eller app och skapa en avisering för CPU-användning på över 80 %.

Om du vill skapa resurscentrerade aviseringar i stor skala för en prenumeration eller resursgrupp kan du dela efter dimensioner. När du vill övervaka samma villkor för flera Azure-resurser delas aviseringarna upp i separata aviseringar genom att gruppera unika kombinationer med hjälp av numeriska kolumner eller strängkolumner. Om du delar upp en Azure-resurs-ID-kolumn hamnar den angivna resursen i aviseringsmålet.

Du kanske också bestämmer dig för att inte dela upp när du vill ha ett villkor för flera resurser i omfånget. Du kanske till exempel vill skapa en avisering om minst fem datorer i resursgruppens omfång har processoranvändning över 80 %.

Skärmbild som visar en ny varningsregel för loggsökning med delade dimensioner.

Du kanske vill se en lista över aviseringarna från den berörda datorn. Du kan använda en anpassad arbetsbok som använder ett anpassat resursdiagram för att tillhandahålla den här vyn. Använd följande fråga för att visa aviseringar och använda datakällan Azure Resource Graph i arbetsboken.

Skapa en aviseringsregel för loggsökning

Om du vill skapa en aviseringsregel för loggsökning med hjälp av portalen kan du se det här exemplet på en loggsökningsavisering som ger en fullständig genomgång. Du kan använda samma processer för att skapa aviseringsregler för AKS-kluster med hjälp av frågor som liknar dem i den här artikeln.

Information om hur du skapar en frågeaviseringsregel med hjälp av en ARM-mall (Azure Resource Manager) finns i Resource Manager-mallexempel för aviseringsregler för loggsökning i Azure Monitor. Du kan använda samma processer för att skapa ARM-mallar för loggfrågorna i den här artikeln.

Resursutnyttjande

Genomsnittlig CPU-användning som ett genomsnitt av medlemsnodernas CPU-användning varje minut (måttmätning):

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

Genomsnittlig minnesanvändning som ett genomsnitt av medlemsnodernas minnesanvändning varje minut (måttmätning):

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

Viktigt!

Följande frågor använder platshållarvärdena <your-cluster-name> och <your-controller-name> för att representera klustret och kontrollanten. Ersätt dem med värden som är specifika för din miljö när du konfigurerar aviseringar.

Genomsnittlig processoranvändning för alla containrar i en kontrollant som ett genomsnitt av CPU-användningen för varje containerinstans i en kontrollant varje minut (måttmätning):

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

Genomsnittlig minnesanvändning för alla containrar i en kontrollant som ett genomsnitt av minnesanvändningen för varje containerinstans i en kontrollant varje minut (måttmätning):

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

Resurstillgänglighet

Noder och antal som har statusen Klar och NotReady (måttmätning):

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

Följande fråga returnerar antalet poddar baserat på alla faser: Failed, Pending, Unknown, Running, eller 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)

Kommentar

Om du vill avisera om vissa poddfaser, till exempel Pending, Failedeller Unknown, ändrar du den sista raden i frågan. Om du till exempel vill avisera om FailedCountanvänder du | summarize AggValue = avg(FailedCount) by bin(TimeGenerated, trendBinSize).

Följande fråga returnerar klusternoder diskar som överskrider 90 % ledigt utrymme som används. Hämta kluster-ID:t genom att först köra följande fråga och kopiera värdet från ClusterId egenskapen:

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

Enskilda container startar om (antal resultat) aviseringar när antalet omstarter av enskilda systemcontainer överskrider ett tröskelvärde under de senaste 10 minuterna:

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

Nästa steg