Compartilhar via


Criar alertas de pesquisa de log a partir do Container insights

As informações do contentor monitorizam o desempenho de grupos de funcionalidades do contentor instaladas em clusters Kubernetes geridos ou geridos autonomamente. Para alertar sobre o que importa, este artigo descreve como criar alertas baseados em log para as seguintes situações com clusters do Serviço Kubernetes do Azure (AKS):

  • Quando a utilização da CPU ou da memória em nós de cluster excede um limite
  • Quando a utilização da CPU ou da memória em qualquer contêiner dentro de um controlador excede um limite em comparação com um limite definido no recurso correspondente
  • NotReady contagens de nós de status
  • Failed, Pending, Unknown, Running, ou Succeeded contagens de fase pod
  • Quando o espaço livre em disco nos nós do cluster excede um limite

Para alertar sobre alta utilização de CPU ou memória, ou pouco espaço livre em disco nos nós do cluster, use as consultas fornecidas para criar um alerta de métrica ou um alerta de medição métrica. Os alertas de métricas têm latência menor do que os alertas de pesquisa de log, mas os alertas de pesquisa de log fornecem consultas avançadas e maior sofisticação. As consultas de alerta de pesquisa de log comparam uma data/hora com o presente usando o now operador e voltando uma hora. (O Container insights armazena todas as datas no formato Tempo Universal Coordenado [UTC].)

Importante

As consultas neste artigo dependem dos dados coletados pelo Container insights e armazenados em um espaço de trabalho do Log Analytics. Se você tiver modificado as configurações padrão de coleta de dados, as consultas podem não retornar os resultados esperados. Mais notavelmente, se você tiver desabilitado a coleta de dados de desempenho desde que ativou as métricas do Prometheus para o cluster, todas as consultas usando a Perf tabela não retornarão resultados.

Consulte Configurar a coleta de dados em Insights de contêiner usando a regra de coleta de dados para configurações predefinidas, incluindo a desativação da coleta de dados de desempenho. Consulte Configurar a coleta de dados no Container insights usando o ConfigMap para obter mais opções de coleta de dados.

Se você não estiver familiarizado com os alertas do Azure Monitor, consulte Visão geral dos alertas no Microsoft Azure antes de começar. Para saber mais sobre alertas que usam consultas de log, consulte Alertas de pesquisa de log no Azure Monitor. Para saber mais sobre alertas de métrica, consulte Alertas de métrica no Azure Monitor.

Medições de consulta de log

Os alertas de pesquisa de log podem medir duas coisas diferentes, que podem ser usadas para monitorar máquinas virtuais em diferentes cenários:

  • Contagem de resultados: Conta o número de linhas retornadas pela consulta e pode ser usada para trabalhar com eventos como logs de eventos do Windows, Syslog e exceções de aplicativos.
  • Cálculo de um valor: faz um cálculo com base em uma coluna numérica e pode ser usado para incluir qualquer número de recursos. Um exemplo é a percentagem de CPU.

Recursos e dimensões de destino

Você pode usar uma regra para monitorar os valores de várias instâncias usando dimensões. Por exemplo, você usaria dimensões se quisesse monitorar o uso da CPU em várias instâncias executando seu site ou aplicativo e criar um alerta para o uso da CPU de mais de 80%.

Para criar alertas centrados em recursos em escala para uma assinatura ou grupo de recursos, você pode dividir por dimensões. Quando você deseja monitorar a mesma condição em vários recursos do Azure, a divisão por dimensões divide os alertas em alertas separados agrupando combinações exclusivas usando colunas numéricas ou de cadeia de caracteres. Dividir uma coluna de ID de recurso do Azure torna o recurso especificado no destino do alerta.

Você também pode decidir não dividir quando quiser uma condição em vários recursos no escopo. Por exemplo, talvez você queira criar um alerta se pelo menos cinco máquinas no escopo do grupo de recursos tiverem uso de CPU superior a 80%.

Captura de tela que mostra uma nova regra de alerta de pesquisa de log com divisão por dimensões.

Talvez você queira ver uma lista dos alertas do computador afetado. Você pode usar uma pasta de trabalho personalizada que usa um gráfico de recursos personalizado para fornecer esse modo de exibição. Use a consulta a seguir para exibir alertas e use a fonte de dados Azure Resource Graph na pasta de trabalho.

Criar uma regra de alerta de pesquisa de log

Para criar uma regra de alerta de pesquisa de log usando o portal, consulte este exemplo de um alerta de pesquisa de log, que fornece um passo a passo completo. Você pode usar esses mesmos processos para criar regras de alerta para clusters AKS usando consultas semelhantes às deste artigo.

Para criar uma regra de alerta de consulta usando um modelo do Azure Resource Manager (ARM), consulte Exemplos de modelo do Resource Manager para regras de alerta de pesquisa de log no Azure Monitor. Você pode usar esses mesmos processos para criar modelos ARM para as consultas de log neste artigo.

Utilização de recursos

Utilização média da CPU como uma média da utilização da CPU dos nós membros a cada minuto (medição métrica):

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

Utilização média da memória como uma média da utilização da memória dos nós membros a cada minuto (medição métrica):

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

As consultas a seguir usam os valores <de espaço reservado your-cluster-name> e <your-controller-name> para representar o cluster e o controlador. Substitua-os por valores específicos do seu ambiente ao configurar alertas.

Utilização média da CPU de todos os contêineres em um controlador como uma média da utilização da CPU de cada instância de contêiner em um controlador a cada minuto (medição métrica):

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

Utilização média de memória de todos os contêineres em um controlador como uma média de utilização de memória de cada instância de contêiner em um controlador a cada minuto (medição métrica):

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

Disponibilidade do recurso

Nós e contagens que têm um status de Ready e NotReady (medição métrica):

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

A consulta a seguir retorna contagens de fase pod com base em todas as fases: Failed, Pending, Unknown, Running, ou 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

Para alertar em determinadas fases do pod, como Pending, Failed, ou Unknown, modifique a última linha da consulta. Por exemplo, para alertar sobre FailedCount, use | summarize AggValue = avg(FailedCount) by bin(TimeGenerated, trendBinSize).

A consulta a seguir retorna discos de nós de cluster que excedem 90% de espaço livre usado. Para obter a ID do cluster, primeiro execute a seguinte consulta e copie o ClusterId valor da propriedade:

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

Alerta de reinicializações de contêiner individuais (número de resultados) quando a contagem de reinicialização de contêiner individual do sistema exceder um limite nos últimos 10 minutos:

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

Próximos passos

  • Exiba exemplos de consulta de log para ver consultas predefinidas e exemplos para avaliar ou personalizar para alertar, visualizar ou analisar seus clusters.
  • Para saber mais sobre o Azure Monitor e como monitorar outros aspetos do seu cluster Kubernetes, consulte Exibir o desempenho do cluster Kubernetes e Exibir a integridade do cluster Kubernetes.