Tworzenie alertów przeszukiwania dzienników na podstawie usługi Container Insights

Usługa Container Insights monitoruje wydajność obciążeń kontenerów wdrożonych w zarządzanych lub samodzielnie zarządzanych klastrach Kubernetes. Aby otrzymywać alerty dotyczące tego, co ma znaczenie, w tym artykule opisano sposób tworzenia alertów opartych na dziennikach w następujących sytuacjach z klastrami usługi Azure Kubernetes Service (AKS):

  • Gdy użycie procesora CPU lub pamięci w węzłach klastra przekracza próg
  • Gdy użycie procesora CPU lub pamięci w dowolnym kontenerze w kontrolerze przekracza próg w porównaniu z limitem ustawionym dla odpowiedniego zasobu
  • NotReady liczba węzłów stanu
  • Failed, Pending, Unknown, Runninglub Succeeded liczba faz zasobników
  • Gdy wolne miejsce na dysku w węzłach klastra przekracza próg

Aby otrzymywać alerty dotyczące wysokiego użycia procesora CPU lub pamięci lub niskiego wolnego miejsca na dysku w węzłach klastra, użyj zapytań udostępnianych do utworzenia alertu dotyczącego metryki lub alertu pomiaru metryki. Alerty metryk mają mniejsze opóźnienie niż alerty przeszukiwania dzienników, ale alerty wyszukiwania dzienników zapewniają zaawansowane zapytania i większe wyrafinowanie. Zapytania dotyczące przeszukiwania dzienników porównują datę/godzinę z bieżącą przy użyciu now operatora i wracają o jedną godzinę. (Usługa Container Insights przechowuje wszystkie daty w formacie uniwersalnego czasu koordynowanego [UTC].

Ważne

Zapytania w tym artykule zależą od danych zebranych przez usługę Container Insights i przechowywanych w obszarze roboczym usługi Log Analytics. Jeśli zmodyfikowano domyślne ustawienia zbierania danych, zapytania mogą nie zwracać oczekiwanych wyników. W szczególności, jeśli kolekcja danych wydajności została wyłączona od włączenia metryk rozwiązania Prometheus dla klastra, wszystkie zapytania korzystające z Perf tabeli nie będą zwracać wyników.

Zobacz Konfigurowanie zbierania danych w usłudze Container Insights przy użyciu reguły zbierania danych, aby uzyskać wstępne konfiguracje, w tym wyłączanie zbierania danych wydajności. Aby uzyskać więcej opcji zbierania danych, zobacz Konfigurowanie zbierania danych w usłudze Container Insights przy użyciu narzędzia ConfigMap .

Jeśli nie znasz alertów usługi Azure Monitor, zobacz Omówienie alertów na platformie Microsoft Azure przed rozpoczęciem. Aby dowiedzieć się więcej na temat alertów korzystających z zapytań dzienników, zobacz Alerty przeszukiwania dzienników w usłudze Azure Monitor. Aby uzyskać więcej informacji na temat alertów metryk, zobacz Alerty metryk w usłudze Azure Monitor.

Pomiary zapytań dzienników

Alerty przeszukiwania dzienników mogą mierzyć dwie różne rzeczy, które mogą służyć do monitorowania maszyn wirtualnych w różnych scenariuszach:

  • Liczba wyników: zlicza liczbę wierszy zwracanych przez zapytanie i może służyć do pracy ze zdarzeniami, takimi jak dzienniki zdarzeń systemu Windows, dziennik syslog i wyjątki aplikacji.
  • Obliczanie wartości: tworzy obliczenie na podstawie kolumny liczbowej i może służyć do uwzględnienia dowolnej liczby zasobów. Przykładem jest procent procesora CPU.

Zasoby docelowe i wymiary

Jedną regułę można użyć do monitorowania wartości wielu wystąpień przy użyciu wymiarów. Można na przykład użyć wymiarów, jeśli chcesz monitorować użycie procesora CPU w wielu wystąpieniach z uruchomioną witryną internetową lub aplikacją, i utworzyć alert dotyczący użycia procesora CPU powyżej 80%.

Aby utworzyć alerty skoncentrowane na zasobach na dużą skalę dla subskrypcji lub grupy zasobów, można podzielić według wymiarów. Jeśli chcesz monitorować ten sam warunek dla wielu zasobów platformy Azure, dzielenie według wymiarów dzieli alerty na oddzielne alerty, grupując unikatowe kombinacje przy użyciu kolumn liczbowych lub kolumn ciągu. Podzielenie kolumny identyfikatora zasobu platformy Azure powoduje, że określony zasób jest przeznaczony dla elementu docelowego alertu.

Możesz również zdecydować, że nie chcesz dzielić warunku dla wielu zasobów w zakresie. Na przykład możesz utworzyć alert, jeśli co najmniej pięć maszyn w zakresie grupy zasobów ma użycie procesora CPU powyżej 80%.

Zrzut ekranu przedstawiający nową regułę alertu przeszukiwania dzienników z podziałem według wymiarów.

Może być konieczne wyświetlenie listy alertów przez komputer, którego dotyczy problem. Do udostępnienia tego widoku można użyć skoroszytu niestandardowego, który używa wykresu zasobów niestandardowych. Użyj następującego zapytania, aby wyświetlić alerty i użyć źródła danych usługi Azure Resource Graph w skoroszycie.

Tworzenie reguły alertu przeszukiwania dzienników

Aby utworzyć regułę alertu przeszukiwania dzienników przy użyciu portalu, zobacz ten przykład alertu wyszukiwania dzienników, który zawiera kompletny przewodnik. Te same procesy umożliwiają tworzenie reguł alertów dla klastrów usługi AKS przy użyciu zapytań podobnych do tych w tym artykule.

Aby utworzyć regułę alertu zapytania przy użyciu szablonu usługi Azure Resource Manager (ARM), zobacz Przykłady szablonów usługi Resource Manager dla reguł alertów przeszukiwania dzienników w usłudze Azure Monitor. Te same procesy umożliwiają tworzenie szablonów usługi ARM dla zapytań dzienników w tym artykule.

Wykorzystanie zasobów

Średnie wykorzystanie procesora CPU jako średnie wykorzystanie procesora CPU węzłów członkowskich co minutę (pomiar metryki):

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

Średnie wykorzystanie pamięci jako średnie wykorzystanie pamięci węzłów członkowskich co minutę (pomiar metryki):

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

Ważne

Poniższe zapytania używają wartości <zastępczych your-cluster-name i <your-controller-name>> do reprezentowania klastra i kontrolera. Zastąp je wartościami specyficznymi dla środowiska podczas konfigurowania alertów.

Średnie wykorzystanie procesora CPU wszystkich kontenerów w kontrolerze jako średnie wykorzystanie procesora CPU każdego wystąpienia kontenera w kontrolerze co minutę (pomiar metryki):

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

Średnie wykorzystanie pamięci wszystkich kontenerów w kontrolerze jako średnie wykorzystanie pamięci każdego wystąpienia kontenera w kontrolerze co minutę (pomiar metryki):

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

Dostępność zasobów

Węzły i liczby, które mają stan Gotowe i NotReady (pomiar metryki):

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

Następujące zapytanie zwraca liczby faz zasobników na podstawie wszystkich faz: Failed, , PendingUnknown, lub RunningSucceeded.

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)

Uwaga

Aby otrzymywać alerty dotyczące niektórych faz zasobników, takich jak Pending, Failedlub Unknown, zmodyfikuj ostatni wiersz zapytania. Aby na przykład otrzymywać alerty dotyczące FailedCountpolecenia , użyj polecenia | summarize AggValue = avg(FailedCount) by bin(TimeGenerated, trendBinSize).

Poniższe zapytanie zwraca dyski węzłów klastra, które przekraczają 90% wolnego miejsca. Aby uzyskać identyfikator klastra, najpierw uruchom następujące zapytanie i skopiuj wartość z ClusterId właściwości :

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

Alert pojedynczego kontenera jest uruchamiany ponownie (liczba wyników), gdy liczba ponownych uruchomień pojedynczego kontenera systemu przekracza próg dla ostatnich 10 minut:

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

Następne kroki

  • Wyświetl przykłady zapytań dzienników , aby wyświetlić wstępnie zdefiniowane zapytania i przykłady do oceny lub dostosowywania alertów, wizualizacji lub analizowania klastrów.
  • Aby dowiedzieć się więcej o usłudze Azure Monitor i sposobie monitorowania innych aspektów klastra Kubernetes, zobacz Wyświetlanie wydajności klastra Kubernetes i Wyświetlanie kondycji klastra Kubernetes.