Cara membuat kueri log dari wawasan Kontainer

Wawasan kontainer mengumpulkan metrik performa, data inventaris, dan informasi status kesehatan dari host kontainer dan kontainer. Data dikumpulkan setiap tiga menit dan dialihkan ke ruang kerja Log Analytics di Azure Monitor jika tersedia untuk kueri log menggunakan Log Analytics di Azure Monitor. Anda dapat menerapkan data ini ke skenario yang mencakup perencanaan migrasi, analisis kapasitas, penemuan, dan pemecahan masalah performa sesuai permintaan. Azure Monitor Logs dapat membantu Anda mencari tren, mendiagnosis penyempitan, memperkirakan, atau menghubungkan data yang dapat membantu Anda menentukan apakah konfigurasi kluster saat ini berkinerja optimal.

Lihat Menggunakan kueri di Azure Monitor Log Analytics untuk mengetahui informasi tentang cara menggunakan kueri ini dan tutorial Log Analytics untuk tutorial selengkapnya terkait menggunakan Log Analytics untuk menjalankan kueri dan mendapatkan hasilnya.

Buka Analitik Log

Ada beberapa opsi untuk memulai Log Analytics, masing-masing dimulai dengan lingkup yang berbeda. Untuk mengakses semua data di ruang kerja, pilih Log dari menu Monitor. Untuk membatasi data ke satu kluster Kubernetes, pilih Log dari menu kluster tersebut.

Start Log Analytics

Kueri log yang ada

Anda tidak perlu memahami cara menulis kueri log untuk menggunakan Log Analytics. Ada beberapa kueri bawaan yang dapat Anda pilih dan jalankan tanpa modifikasi atau gunakan sebagai awal untuk kueri khusus. Klik Kueri di bagian atas layar Log Analytics dan lihat kueri dengan Jenis sumber dayaLayanan Kubernetes.

Log Analytics queries for Kubernetes

Tabel kontainer

Lihat Referensi tabel Azure Monitor untuk daftar tabel dan deskripsi terperinci yang digunakan oleh wawasan Kontainer. Semua tabel ini tersedia untuk kueri log.

Kueri log sampel

Sering kali berguna untuk membuat kueri yang dimulai dengan satu atau dua contoh dan kemudian memodifikasinya agar sesuai dengan kebutuhan Anda. Untuk membantu membuat kueri tingkat lanjut, Anda dapat bereksperimen dengan kueri contoh berikut:

Mencantumkan semua informasi siklus hidup kontainer

ContainerInventory
| project Computer, Name, Image, ImageTag, ContainerState, CreatedTime, StartedTime, FinishedTime
| render table

Peristiwa Kube

KubeEvents
| where not(isempty(Namespace))
| sort by TimeGenerated desc
| render table

CPU kontainer

Perf
| where ObjectName == "K8SContainer" and CounterName == "cpuUsageNanoCores" 
| summarize AvgCPUUsageNanoCores = avg(CounterValue) by bin(TimeGenerated, 30m), InstanceName 

Memori kontainer

Perf
| where ObjectName == "K8SContainer" and CounterName == "memoryRssBytes"
| summarize AvgUsedRssMemoryBytes = avg(CounterValue) by bin(TimeGenerated, 30m), InstanceName

Permintaan Per Menit dengan Metrik Kustom

InsightsMetrics
| where Name == "requests_count"
| summarize Val=any(Val) by TimeGenerated=bin(TimeGenerated, 1m)
| sort by TimeGenerated asc
| project RequestsPerMinute = Val - prev(Val), TimeGenerated
| render barchart 

Pod menurut nama dan namespace

let startTimestamp = ago(1h);
KubePodInventory
| where TimeGenerated > startTimestamp
| project ContainerID, PodName=Name, Namespace
| where PodName contains "name" and Namespace startswith "namespace"
| distinct ContainerID, PodName
| join
(
    ContainerLog
    | where TimeGenerated > startTimestamp
)
on ContainerID
// at this point before the next pipe, columns from both tables are available to be "projected". Due to both
// tables having a "Name" column, we assign an alias as PodName to one column which we actually want
| project TimeGenerated, PodName, LogEntry, LogEntrySource
| summarize by TimeGenerated, LogEntry
| order by TimeGenerated desc

Pod scale-out (HPA)

Mengembalikan jumlah replika yang diperkecil di setiap penyebaran. Menghitung persentase skala-out dengan jumlah maksimum replika dikonfigurasi dalam HPA.

let _minthreshold = 70; // minimum threshold goes here if you want to setup as an alert
let _maxthreshold = 90; // maximum threshold goes here if you want to setup as an alert
let startDateTime = ago(60m);
KubePodInventory
| where TimeGenerated >= startDateTime 
| where Namespace !in('default', 'kube-system') // List of non system namespace filter goes here.
| extend labels = todynamic(PodLabel)
| extend deployment_hpa = reverse(substring(reverse(ControllerName), indexof(reverse(ControllerName), "-") + 1))
| distinct tostring(deployment_hpa)
| join kind=inner (InsightsMetrics 
    | where TimeGenerated > startDateTime 
    | where Name == 'kube_hpa_status_current_replicas'
    | extend pTags = todynamic(Tags) //parse the tags for values
    | extend ns = todynamic(pTags.k8sNamespace) //parse namespace value from tags
    | extend deployment_hpa = todynamic(pTags.targetName) //parse HPA target name from tags
    | extend max_reps = todynamic(pTags.spec_max_replicas) // Parse maximum replica settings from HPA deployment
    | extend desired_reps = todynamic(pTags.status_desired_replicas) // Parse desired replica settings from HPA deployment
    | summarize arg_max(TimeGenerated, *) by tostring(ns), tostring(deployment_hpa), Cluster=toupper(tostring(split(_ResourceId, '/')[8])), toint(desired_reps), toint(max_reps), scale_out_percentage=(desired_reps * 100 / max_reps)
    //| where scale_out_percentage > _minthreshold and scale_out_percentage <= _maxthreshold
    )
    on deployment_hpa

Nodepool scale-out

Mengembalikan jumlah node aktif di setiap kumpulan node. Menghitung jumlah node aktif yang tersedia dan konfigurasi node maks dalam pengaturan skala otomatis untuk menentukan persentase scale-out. Lihat baris yang dikomentari di kueri untuk menggunakannya sebanyak jumlah hasil aturan pemberitahuan.

let nodepoolMaxnodeCount = 10; // the maximum number of nodes in your auto scale setting goes here.
let _minthreshold = 20;
let _maxthreshold = 90;
let startDateTime = 60m;
KubeNodeInventory
| where TimeGenerated >= ago(startDateTime)
| extend nodepoolType = todynamic(Labels) //Parse the labels to get the list of node pool types
| extend nodepoolName = todynamic(nodepoolType[0].agentpool) // parse the label to get the nodepool name or set the specific nodepool name (like nodepoolName = 'agentpool)'
| summarize nodeCount = count(Computer) by ClusterName, tostring(nodepoolName), TimeGenerated
//(Uncomment the below two lines to set this as an log search alert)
//| extend scaledpercent = iff(((nodeCount * 100 / nodepoolMaxnodeCount) >= _minthreshold and (nodeCount * 100 / nodepoolMaxnodeCount) < _maxthreshold), "warn", "normal")
//| where scaledpercent == 'warn'
| summarize arg_max(TimeGenerated, *) by nodeCount, ClusterName, tostring(nodepoolName)
| project ClusterName, 
    TotalNodeCount= strcat("Total Node Count: ", nodeCount),
    ScaledOutPercentage = (nodeCount * 100 / nodepoolMaxnodeCount),  
    TimeGenerated, 
    nodepoolName

Ketersediaan kontainer sistem (replicaset)

Mengembalikan wadah sistem (replicaset) dan melaporkan persentase yang tidak tersedia. Lihat baris yang dikomentari di kueri untuk menggunakannya sebanyak jumlah hasil aturan pemberitahuan.

let startDateTime = 5m; // the minimum time interval goes here
let _minalertThreshold = 50; //Threshold for minimum and maximum unavailable or not running containers
let _maxalertThreshold = 70;
KubePodInventory
| where TimeGenerated >= ago(startDateTime)
| distinct ClusterName, TimeGenerated
| summarize Clustersnapshot = count() by ClusterName
| join kind=inner (
    KubePodInventory
    | where TimeGenerated >= ago(startDateTime)
    | where Namespace in('default', 'kube-system') and ControllerKind == 'ReplicaSet' // the system namespace filter goes here
    | distinct ClusterName, Computer, PodUid, TimeGenerated, PodStatus, ServiceName, PodLabel, Namespace, ContainerStatus
    | summarize arg_max(TimeGenerated, *), TotalPODCount = count(), podCount = sumif(1, PodStatus == 'Running' or PodStatus != 'Running'), containerNotrunning = sumif(1, ContainerStatus != 'running')
        by ClusterName, TimeGenerated, ServiceName, PodLabel, Namespace
    )
    on ClusterName
| project ClusterName, ServiceName, podCount, containerNotrunning, containerNotrunningPercent = (containerNotrunning * 100 / podCount), TimeGenerated, PodStatus, PodLabel, Namespace, Environment = tostring(split(ClusterName, '-')[3]), Location = tostring(split(ClusterName, '-')[4]), ContainerStatus
//Uncomment the below line to set for automated alert
//| where PodStatus == "Running" and containerNotrunningPercent > _minalertThreshold and containerNotrunningPercent < _maxalertThreshold
| summarize arg_max(TimeGenerated, *), c_entry=count() by PodLabel, ServiceName, ClusterName
//Below lines are to parse the labels to identify the impacted service/component name
| extend parseLabel = replace(@'k8s-app', @'k8sapp', PodLabel)
| extend parseLabel = replace(@'app.kubernetes.io/component', @'appkubernetesiocomponent', parseLabel)
| extend parseLabel = replace(@'app.kubernetes.io/instance', @'appkubernetesioinstance', parseLabel)
| extend tags = todynamic(parseLabel)
| extend tag01 = todynamic(tags[0].app)
| extend tag02 = todynamic(tags[0].k8sapp)
| extend tag03 = todynamic(tags[0].appkubernetesiocomponent)
| extend tag04 = todynamic(tags[0].aadpodidbinding)
| extend tag05 = todynamic(tags[0].appkubernetesioinstance)
| extend tag06 = todynamic(tags[0].component)
| project ClusterName, TimeGenerated,
    ServiceName = strcat( ServiceName, tag01, tag02, tag03, tag04, tag05, tag06),
    ContainerUnavailable = strcat("Unavailable Percentage: ", containerNotrunningPercent),
    PodStatus = strcat("PodStatus: ", PodStatus), 
    ContainerStatus = strcat("Container Status: ", ContainerStatus)

Ketersediaan kontainer sistem (daemonset)

Mengembalikan wadah sistem (daemonset) dan melaporkan persentase yang tidak tersedia. Lihat baris yang dikomentari di kueri untuk menggunakannya sebanyak jumlah hasil aturan pemberitahuan.

let startDateTime = 5m; // the minimum time interval goes here
let _minalertThreshold = 50; //Threshold for minimum and maximum unavailable or not running containers
let _maxalertThreshold = 70;
KubePodInventory
| where TimeGenerated >= ago(startDateTime)
| distinct ClusterName, TimeGenerated
| summarize Clustersnapshot = count() by ClusterName
| join kind=inner (
    KubePodInventory
    | where TimeGenerated >= ago(startDateTime)
    | where Namespace in('default', 'kube-system') and ControllerKind == 'DaemonSet' // the system namespace filter goes here
    | distinct ClusterName, Computer, PodUid, TimeGenerated, PodStatus, ServiceName, PodLabel, Namespace, ContainerStatus
    | summarize arg_max(TimeGenerated, *), TotalPODCount = count(), podCount = sumif(1, PodStatus == 'Running' or PodStatus != 'Running'), containerNotrunning = sumif(1, ContainerStatus != 'running')
        by ClusterName, TimeGenerated, ServiceName, PodLabel, Namespace
    )
    on ClusterName
| project ClusterName, ServiceName, podCount, containerNotrunning, containerNotrunningPercent = (containerNotrunning * 100 / podCount), TimeGenerated, PodStatus, PodLabel, Namespace, Environment = tostring(split(ClusterName, '-')[3]), Location = tostring(split(ClusterName, '-')[4]), ContainerStatus
//Uncomment the below line to set for automated alert
//| where PodStatus == "Running" and containerNotrunningPercent > _minalertThreshold and containerNotrunningPercent < _maxalertThreshold
| summarize arg_max(TimeGenerated, *), c_entry=count() by PodLabel, ServiceName, ClusterName
//Below lines are to parse the labels to identify the impacted service/component name
| extend parseLabel = replace(@'k8s-app', @'k8sapp', PodLabel)
| extend parseLabel = replace(@'app.kubernetes.io/component', @'appkubernetesiocomponent', parseLabel)
| extend parseLabel = replace(@'app.kubernetes.io/instance', @'appkubernetesioinstance', parseLabel)
| extend tags = todynamic(parseLabel)
| extend tag01 = todynamic(tags[0].app)
| extend tag02 = todynamic(tags[0].k8sapp)
| extend tag03 = todynamic(tags[0].appkubernetesiocomponent)
| extend tag04 = todynamic(tags[0].aadpodidbinding)
| extend tag05 = todynamic(tags[0].appkubernetesioinstance)
| extend tag06 = todynamic(tags[0].component)
| project ClusterName, TimeGenerated,
    ServiceName = strcat( ServiceName, tag01, tag02, tag03, tag04, tag05, tag06),
    ContainerUnavailable = strcat("Unavailable Percentage: ", containerNotrunningPercent),
    PodStatus = strcat("PodStatus: ", PodStatus), 
    ContainerStatus = strcat("Container Status: ", ContainerStatus)

Log sumber daya

Log sumber daya untuk AKS disimpan di tabel AzureDiagnostics. Anda dapat membedakan log yang berbeda dengan kolom Kategori. Lihat log sumber daya AKS untuk mengetahui deskripsi tiap kategori. Contoh berikut memerlukan ekstensi diagnostik untuk mengirim log sumber daya untuk kluster AKS ke ruang kerja Log Analytics. Lihat Konfigurasi pemantauan untuk mengetahui detailnya.

Log server API

AzureDiagnostics 
| where Category == "kube-apiserver"

Menghitung log untuk setiap kategori

AzureDiagnostics
| where ResourceType == "MANAGEDCLUSTERS"
| summarize count() by Category

Kueri data metrik Prometheus

Contoh berikut adalah kueri metrik Prometheus yang menunjukkan pembacaan disk per detik per disk per simpul.

InsightsMetrics
| where Namespace == 'container.azm.ms/diskio'
| where TimeGenerated > ago(1h)
| where Name == 'reads'
| extend Tags = todynamic(Tags)
| extend HostName = tostring(Tags.hostName), Device = Tags.name
| extend NodeDisk = strcat(Device, "/", HostName)
| order by NodeDisk asc, TimeGenerated asc
| serialize
| extend PrevVal = iif(prev(NodeDisk) != NodeDisk, 0.0, prev(Val)), PrevTimeGenerated = iif(prev(NodeDisk) != NodeDisk, datetime(null), prev(TimeGenerated))
| where isnotnull(PrevTimeGenerated) and PrevTimeGenerated != TimeGenerated
| extend Rate = iif(PrevVal > Val, Val / (datetime_diff('Second', TimeGenerated, PrevTimeGenerated) * 1), iif(PrevVal == Val, 0.0, (Val - PrevVal) / (datetime_diff('Second', TimeGenerated, PrevTimeGenerated) * 1)))
| where isnotnull(Rate)
| project TimeGenerated, NodeDisk, Rate
| render timechart

Untuk menampilkan metrik Prometheus yang diekstraksi oleh Azure Monitor yang difilter oleh Namespace, tentukan "prometheus". Berikut ini sampel kueri untuk melihat metrik Prometheus dari namespace layanan kubernetes default.

InsightsMetrics 
| where Namespace == "prometheus"
| extend tags=parse_json(Tags)
| summarize count() by Name

Data Prometheus juga dapat langsung dikueri berdasarkan nama.

InsightsMetrics 
| where Namespace == "prometheus"
| where Name contains "some_prometheus_metric"

Konfigurasi kueri atau kesalahan ekstraksi

Untuk menyelidiki konfigurasi atau kesalahan ekstraksi, contoh kueri berikut mengembalikan peristiwa informasi dari tabel KubeMonAgentEvents.

KubeMonAgentEvents | where Level != "Info" 

Output menunjukkan hasil yang mirip dengan contoh berikut:

Log query results of informational events from agent

Langkah berikutnya

Wawasan kontainer tidak menyertakan kumpulan pemberitahuan yang telah ditentukan sebelumnya. Tinjau Buat pemberitahuan performa dengan wawasan Kontainer untuk mempelajari cara membuat pemberitahuan yang disarankan untuk penggunaan CPU dan memori yang tinggi guna mendukung Azure DevOps atau proses dan prosedur operasional Anda.