github.com/netdata/go.d.plugin@v0.58.1/modules/k8s_state/charts.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package k8s_state 4 5 import ( 6 "fmt" 7 "regexp" 8 "strings" 9 10 "github.com/netdata/go.d.plugin/agent/module" 11 ) 12 13 // NETDATA_CHART_PRIO_CGROUPS_CONTAINERS 40000 14 const prioDiscoveryDiscovererState = 50999 15 16 const ( 17 prioNodeAllocatableCPURequestsUtil = 50100 + iota 18 prioNodeAllocatableCPURequestsUsed 19 prioNodeAllocatableCPULimitsUtil 20 prioNodeAllocatableCPULimitsUsed 21 prioNodeAllocatableMemRequestsUtil 22 prioNodeAllocatableMemRequestsUsed 23 prioNodeAllocatableMemLimitsUtil 24 prioNodeAllocatableMemLimitsUsed 25 prioNodeAllocatablePodsUtil 26 prioNodeAllocatablePodsUsage 27 prioNodeConditions 28 prioNodeSchedulability 29 prioNodePodsReadiness 30 prioNodePodsReadinessState 31 prioNodePodsCondition 32 prioNodePodsPhase 33 prioNodeContainersCount 34 prioNodeContainersState 35 prioNodeInitContainersState 36 prioNodeAge 37 ) 38 39 const ( 40 prioPodCPURequestsUsed = 50300 + iota 41 prioPodCPULimitsUsed 42 prioPodMemRequestsUsed 43 prioPodMemLimitsUsed 44 prioPodCondition 45 prioPodPhase 46 prioPodAge 47 prioPodContainersCount 48 prioPodContainersState 49 prioPodInitContainersState 50 prioPodContainerReadinessState 51 prioPodContainerRestarts 52 prioPodContainerState 53 prioPodContainerWaitingStateReason 54 prioPodContainerTerminatedStateReason 55 ) 56 57 const ( 58 labelKeyPrefix = "k8s_" 59 //labelKeyLabelPrefix = labelKeyPrefix + "label_" 60 //labelKeyAnnotationPrefix = labelKeyPrefix + "annotation_" 61 labelKeyClusterID = labelKeyPrefix + "cluster_id" 62 labelKeyClusterName = labelKeyPrefix + "cluster_name" 63 labelKeyNamespace = labelKeyPrefix + "namespace" 64 labelKeyKind = labelKeyPrefix + "kind" 65 labelKeyPodName = labelKeyPrefix + "pod_name" 66 labelKeyNodeName = labelKeyPrefix + "node_name" 67 labelKeyPodUID = labelKeyPrefix + "pod_uid" 68 labelKeyControllerKind = labelKeyPrefix + "controller_kind" 69 labelKeyControllerName = labelKeyPrefix + "controller_name" 70 labelKeyContainerName = labelKeyPrefix + "container_name" 71 labelKeyContainerID = labelKeyPrefix + "container_id" 72 labelKeyQoSClass = labelKeyPrefix + "qos_class" 73 ) 74 75 var baseCharts = module.Charts{ 76 discoveryStatusChart.Copy(), 77 } 78 79 var nodeChartsTmpl = module.Charts{ 80 nodeAllocatableCPURequestsUtilChartTmpl.Copy(), 81 nodeAllocatableCPURequestsUsedChartTmpl.Copy(), 82 nodeAllocatableCPULimitsUtilChartTmpl.Copy(), 83 nodeAllocatableCPULimitsUsedChartTmpl.Copy(), 84 nodeAllocatableMemRequestsUtilChartTmpl.Copy(), 85 nodeAllocatableMemRequestsUsedChartTmpl.Copy(), 86 nodeAllocatableMemLimitsUtilChartTmpl.Copy(), 87 nodeAllocatableMemLimitsUsedChartTmpl.Copy(), 88 nodeAllocatablePodsUtilizationChartTmpl.Copy(), 89 nodeAllocatablePodsUsageChartTmpl.Copy(), 90 nodeConditionsChartTmpl.Copy(), 91 nodeSchedulabilityChartTmpl.Copy(), 92 nodePodsReadinessChartTmpl.Copy(), 93 nodePodsReadinessStateChartTmpl.Copy(), 94 nodePodsConditionChartTmpl.Copy(), 95 nodePodsPhaseChartTmpl.Copy(), 96 nodeContainersChartTmpl.Copy(), 97 nodeContainersStateChartTmpl.Copy(), 98 nodeInitContainersStateChartTmpl.Copy(), 99 nodeAgeChartTmpl.Copy(), 100 } 101 102 var podChartsTmpl = module.Charts{ 103 podCPURequestsUsedChartTmpl.Copy(), 104 podCPULimitsUsedChartTmpl.Copy(), 105 podMemRequestsUsedChartTmpl.Copy(), 106 podMemLimitsUsedChartTmpl.Copy(), 107 podConditionChartTmpl.Copy(), 108 podPhaseChartTmpl.Copy(), 109 podAgeChartTmpl.Copy(), 110 podContainersCountChartTmpl.Copy(), 111 podContainersStateChartTmpl.Copy(), 112 podInitContainersStateChartTmpl.Copy(), 113 } 114 115 var containerChartsTmpl = module.Charts{ 116 containerReadinessStateChartTmpl.Copy(), 117 containerRestartsChartTmpl.Copy(), 118 containersStateChartTmpl.Copy(), 119 containersStateWaitingChartTmpl.Copy(), 120 containersStateTerminatedChartTmpl.Copy(), 121 } 122 123 var ( 124 // CPU resource 125 nodeAllocatableCPURequestsUtilChartTmpl = module.Chart{ 126 IDSep: true, 127 ID: "node_%s.allocatable_cpu_requests_utilization", 128 Title: "CPU requests utilization", 129 Units: "%", 130 Fam: "node cpu resource", 131 Ctx: "k8s_state.node_allocatable_cpu_requests_utilization", 132 Priority: prioNodeAllocatableCPURequestsUtil, 133 Dims: module.Dims{ 134 {ID: "node_%s_alloc_cpu_requests_util", Name: "requests", Div: precision}, 135 }, 136 } 137 nodeAllocatableCPURequestsUsedChartTmpl = module.Chart{ 138 IDSep: true, 139 ID: "node_%s.allocatable_cpu_requests_used", 140 Title: "CPU requests used", 141 Units: "millicpu", 142 Fam: "node cpu resource", 143 Ctx: "k8s_state.node_allocatable_cpu_requests_used", 144 Priority: prioNodeAllocatableCPURequestsUsed, 145 Dims: module.Dims{ 146 {ID: "node_%s_alloc_cpu_requests_used", Name: "requests"}, 147 }, 148 } 149 nodeAllocatableCPULimitsUtilChartTmpl = module.Chart{ 150 IDSep: true, 151 ID: "node_%s.allocatable_cpu_limits_utilization", 152 Title: "CPU limits utilization", 153 Units: "%", 154 Fam: "node cpu resource", 155 Ctx: "k8s_state.node_allocatable_cpu_limits_utilization", 156 Priority: prioNodeAllocatableCPULimitsUtil, 157 Dims: module.Dims{ 158 {ID: "node_%s_alloc_cpu_limits_util", Name: "limits", Div: precision}, 159 }, 160 } 161 nodeAllocatableCPULimitsUsedChartTmpl = module.Chart{ 162 IDSep: true, 163 ID: "node_%s.allocatable_cpu_limits_used", 164 Title: "CPU limits used", 165 Units: "millicpu", 166 Fam: "node cpu resource", 167 Ctx: "k8s_state.node_allocatable_cpu_limits_used", 168 Priority: prioNodeAllocatableCPULimitsUsed, 169 Dims: module.Dims{ 170 {ID: "node_%s_alloc_cpu_limits_used", Name: "limits"}, 171 }, 172 } 173 // memory resource 174 nodeAllocatableMemRequestsUtilChartTmpl = module.Chart{ 175 IDSep: true, 176 ID: "node_%s.allocatable_mem_requests_utilization", 177 Title: "Memory requests utilization", 178 Units: "%", 179 Fam: "node mem resource", 180 Ctx: "k8s_state.node_allocatable_mem_requests_utilization", 181 Priority: prioNodeAllocatableMemRequestsUtil, 182 Dims: module.Dims{ 183 {ID: "node_%s_alloc_mem_requests_util", Name: "requests", Div: precision}, 184 }, 185 } 186 nodeAllocatableMemRequestsUsedChartTmpl = module.Chart{ 187 IDSep: true, 188 ID: "node_%s.allocatable_mem_requests_used", 189 Title: "Memory requests used", 190 Units: "bytes", 191 Fam: "node mem resource", 192 Ctx: "k8s_state.node_allocatable_mem_requests_used", 193 Priority: prioNodeAllocatableMemRequestsUsed, 194 Dims: module.Dims{ 195 {ID: "node_%s_alloc_mem_requests_used", Name: "requests"}, 196 }, 197 } 198 nodeAllocatableMemLimitsUtilChartTmpl = module.Chart{ 199 IDSep: true, 200 ID: "node_%s.allocatable_mem_limits_utilization", 201 Title: "Memory limits utilization", 202 Units: "%", 203 Fam: "node mem resource", 204 Ctx: "k8s_state.node_allocatable_mem_limits_utilization", 205 Priority: prioNodeAllocatableMemLimitsUtil, 206 Dims: module.Dims{ 207 {ID: "node_%s_alloc_mem_limits_util", Name: "limits", Div: precision}, 208 }, 209 } 210 nodeAllocatableMemLimitsUsedChartTmpl = module.Chart{ 211 IDSep: true, 212 ID: "node_%s.allocatable_mem_limits_used", 213 Title: "Memory limits used", 214 Units: "bytes", 215 Fam: "node mem resource", 216 Ctx: "k8s_state.node_allocatable_mem_limits_used", 217 Priority: prioNodeAllocatableMemLimitsUsed, 218 Dims: module.Dims{ 219 {ID: "node_%s_alloc_mem_limits_used", Name: "limits"}, 220 }, 221 } 222 // pods resource 223 nodeAllocatablePodsUtilizationChartTmpl = module.Chart{ 224 IDSep: true, 225 ID: "node_%s.allocatable_pods_utilization", 226 Title: "Pods resource utilization", 227 Units: "%", 228 Fam: "node pods resource", 229 Ctx: "k8s_state.node_allocatable_pods_utilization", 230 Priority: prioNodeAllocatablePodsUtil, 231 Dims: module.Dims{ 232 {ID: "node_%s_alloc_pods_util", Name: "allocated", Div: precision}, 233 }, 234 } 235 nodeAllocatablePodsUsageChartTmpl = module.Chart{ 236 IDSep: true, 237 ID: "node_%s.allocated_pods_usage", 238 Title: "Pods resource usage", 239 Units: "pods", 240 Fam: "node pods resource", 241 Ctx: "k8s_state.node_allocatable_pods_usage", 242 Type: module.Stacked, 243 Priority: prioNodeAllocatablePodsUsage, 244 Dims: module.Dims{ 245 {ID: "node_%s_alloc_pods_available", Name: "available"}, 246 {ID: "node_%s_alloc_pods_allocated", Name: "allocated"}, 247 }, 248 } 249 // condition 250 nodeConditionsChartTmpl = module.Chart{ 251 IDSep: true, 252 ID: "node_%s.condition_status", 253 Title: "Condition status", 254 Units: "status", 255 Fam: "node condition", 256 Ctx: "k8s_state.node_condition", 257 Priority: prioNodeConditions, 258 } 259 nodeSchedulabilityChartTmpl = module.Chart{ 260 IDSep: true, 261 ID: "node_%s.schedulability", 262 Title: "Schedulability", 263 Units: "state", 264 Fam: "node schedulability", 265 Ctx: "k8s_state.node_schedulability", 266 Priority: prioNodeSchedulability, 267 Dims: module.Dims{ 268 {ID: "node_%s_schedulability_schedulable", Name: "schedulable"}, 269 {ID: "node_%s_schedulability_unschedulable", Name: "unschedulable"}, 270 }, 271 } 272 // pods readiness 273 nodePodsReadinessChartTmpl = module.Chart{ 274 IDSep: true, 275 ID: "node_%s.pods_readiness", 276 Title: "Pods readiness", 277 Units: "%", 278 Fam: "node pods readiness", 279 Ctx: "k8s_state.node_pods_readiness", 280 Priority: prioNodePodsReadiness, 281 Dims: module.Dims{ 282 {ID: "node_%s_pods_readiness", Name: "ready", Div: precision}, 283 }, 284 } 285 nodePodsReadinessStateChartTmpl = module.Chart{ 286 IDSep: true, 287 ID: "node_%s.pods_readiness_state", 288 Title: "Pods readiness state", 289 Units: "pods", 290 Fam: "node pods readiness", 291 Ctx: "k8s_state.node_pods_readiness_state", 292 Type: module.Stacked, 293 Priority: prioNodePodsReadinessState, 294 Dims: module.Dims{ 295 {ID: "node_%s_pods_readiness_ready", Name: "ready"}, 296 {ID: "node_%s_pods_readiness_unready", Name: "unready"}, 297 }, 298 } 299 // pods condition 300 nodePodsConditionChartTmpl = module.Chart{ 301 IDSep: true, 302 ID: "node_%s.pods_condition", 303 Title: "Pods condition", 304 Units: "pods", 305 Fam: "node pods condition", 306 Ctx: "k8s_state.node_pods_condition", 307 Priority: prioNodePodsCondition, 308 Dims: module.Dims{ 309 {ID: "node_%s_pods_cond_podready", Name: "pod_ready"}, 310 {ID: "node_%s_pods_cond_podscheduled", Name: "pod_scheduled"}, 311 {ID: "node_%s_pods_cond_podinitialized", Name: "pod_initialized"}, 312 {ID: "node_%s_pods_cond_containersready", Name: "containers_ready"}, 313 }, 314 } 315 // pods phase 316 nodePodsPhaseChartTmpl = module.Chart{ 317 IDSep: true, 318 ID: "node_%s.pods_phase", 319 Title: "Pods phase", 320 Units: "pods", 321 Fam: "node pods phase", 322 Ctx: "k8s_state.node_pods_phase", 323 Type: module.Stacked, 324 Priority: prioNodePodsPhase, 325 Dims: module.Dims{ 326 {ID: "node_%s_pods_phase_running", Name: "running"}, 327 {ID: "node_%s_pods_phase_failed", Name: "failed"}, 328 {ID: "node_%s_pods_phase_succeeded", Name: "succeeded"}, 329 {ID: "node_%s_pods_phase_pending", Name: "pending"}, 330 }, 331 } 332 // containers 333 nodeContainersChartTmpl = module.Chart{ 334 IDSep: true, 335 ID: "node_%s.containers", 336 Title: "Containers", 337 Units: "containers", 338 Fam: "node containers", 339 Ctx: "k8s_state.node_containers", 340 Priority: prioNodeContainersCount, 341 Dims: module.Dims{ 342 {ID: "node_%s_containers", Name: "containers"}, 343 {ID: "node_%s_init_containers", Name: "init_containers"}, 344 }, 345 } 346 nodeContainersStateChartTmpl = module.Chart{ 347 IDSep: true, 348 ID: "node_%s.containers_state", 349 Title: "Containers state", 350 Units: "containers", 351 Fam: "node containers", 352 Ctx: "k8s_state.node_containers_state", 353 Type: module.Stacked, 354 Priority: prioNodeContainersState, 355 Dims: module.Dims{ 356 {ID: "node_%s_containers_state_running", Name: "running"}, 357 {ID: "node_%s_containers_state_waiting", Name: "waiting"}, 358 {ID: "node_%s_containers_state_terminated", Name: "terminated"}, 359 }, 360 } 361 nodeInitContainersStateChartTmpl = module.Chart{ 362 IDSep: true, 363 ID: "node_%s.init_containers_state", 364 Title: "Init containers state", 365 Units: "containers", 366 Fam: "node containers", 367 Ctx: "k8s_state.node_init_containers_state", 368 Type: module.Stacked, 369 Priority: prioNodeInitContainersState, 370 Dims: module.Dims{ 371 {ID: "node_%s_init_containers_state_running", Name: "running"}, 372 {ID: "node_%s_init_containers_state_waiting", Name: "waiting"}, 373 {ID: "node_%s_init_containers_state_terminated", Name: "terminated"}, 374 }, 375 } 376 // age 377 nodeAgeChartTmpl = module.Chart{ 378 IDSep: true, 379 ID: "node_%s.age", 380 Title: "Age", 381 Units: "seconds", 382 Fam: "node age", 383 Ctx: "k8s_state.node_age", 384 Priority: prioNodeAge, 385 Dims: module.Dims{ 386 {ID: "node_%s_age", Name: "age"}, 387 }, 388 } 389 ) 390 391 func (ks *KubeState) newNodeCharts(ns *nodeState) *module.Charts { 392 cs := nodeChartsTmpl.Copy() 393 for _, c := range *cs { 394 c.ID = fmt.Sprintf(c.ID, replaceDots(ns.id())) 395 c.Labels = ks.newNodeChartLabels(ns) 396 for _, d := range c.Dims { 397 d.ID = fmt.Sprintf(d.ID, ns.id()) 398 } 399 } 400 return cs 401 } 402 403 func (ks *KubeState) newNodeChartLabels(ns *nodeState) []module.Label { 404 labels := []module.Label{ 405 {Key: labelKeyNodeName, Value: ns.name, Source: module.LabelSourceK8s}, 406 {Key: labelKeyClusterID, Value: ks.kubeClusterID, Source: module.LabelSourceK8s}, 407 {Key: labelKeyClusterName, Value: ks.kubeClusterName, Source: module.LabelSourceK8s}, 408 } 409 return labels 410 } 411 412 func (ks *KubeState) addNodeCharts(ns *nodeState) { 413 cs := ks.newNodeCharts(ns) 414 if err := ks.Charts().Add(*cs...); err != nil { 415 ks.Warning(err) 416 } 417 } 418 419 func (ks *KubeState) removeNodeCharts(ns *nodeState) { 420 prefix := fmt.Sprintf("node_%s", replaceDots(ns.id())) 421 for _, c := range *ks.Charts() { 422 if strings.HasPrefix(c.ID, prefix) { 423 c.MarkRemove() 424 c.MarkNotCreated() 425 } 426 } 427 } 428 429 func (ks *KubeState) addNodeConditionToCharts(ns *nodeState, cond string) { 430 id := fmt.Sprintf(nodeConditionsChartTmpl.ID, replaceDots(ns.id())) 431 c := ks.Charts().Get(id) 432 if c == nil { 433 ks.Warningf("chart '%s' does not exist", id) 434 return 435 } 436 dim := &module.Dim{ 437 ID: fmt.Sprintf("node_%s_cond_%s", ns.id(), strings.ToLower(cond)), 438 Name: cond, 439 } 440 if err := c.AddDim(dim); err != nil { 441 ks.Warning(err) 442 return 443 } 444 c.MarkNotCreated() 445 } 446 447 var ( 448 podCPURequestsUsedChartTmpl = module.Chart{ 449 IDSep: true, 450 ID: "pod_%s.cpu_requests_used", 451 Title: "CPU requests used", 452 Units: "millicpu", 453 Fam: "pod allocated cpu", 454 Ctx: "k8s_state.pod_cpu_requests_used", 455 Priority: prioPodCPURequestsUsed, 456 Dims: module.Dims{ 457 {ID: "pod_%s_cpu_requests_used", Name: "requests"}, 458 }, 459 } 460 podCPULimitsUsedChartTmpl = module.Chart{ 461 IDSep: true, 462 ID: "pod_%s.cpu_limits_used", 463 Title: "CPU limits used", 464 Units: "millicpu", 465 Fam: "pod allocated cpu", 466 Ctx: "k8s_state.pod_cpu_limits_used", 467 Priority: prioPodCPULimitsUsed, 468 Dims: module.Dims{ 469 {ID: "pod_%s_cpu_limits_used", Name: "limits"}, 470 }, 471 } 472 podMemRequestsUsedChartTmpl = module.Chart{ 473 IDSep: true, 474 ID: "pod_%s.mem_requests_used", 475 Title: "Memory requests used", 476 Units: "bytes", 477 Fam: "pod allocated mem", 478 Ctx: "k8s_state.pod_mem_requests_used", 479 Priority: prioPodMemRequestsUsed, 480 Dims: module.Dims{ 481 {ID: "pod_%s_mem_requests_used", Name: "requests"}, 482 }, 483 } 484 podMemLimitsUsedChartTmpl = module.Chart{ 485 IDSep: true, 486 ID: "pod_%s.mem_limits_used", 487 Title: "Memory limits used", 488 Units: "bytes", 489 Fam: "pod allocated mem", 490 Ctx: "k8s_state.pod_mem_limits_used", 491 Priority: prioPodMemLimitsUsed, 492 Dims: module.Dims{ 493 {ID: "pod_%s_mem_limits_used", Name: "limits"}, 494 }, 495 } 496 podConditionChartTmpl = module.Chart{ 497 IDSep: true, 498 ID: "pod_%s.condition", 499 Title: "Condition", 500 Units: "state", 501 Fam: "pod condition", 502 Ctx: "k8s_state.pod_condition", 503 Priority: prioPodCondition, 504 Dims: module.Dims{ 505 {ID: "pod_%s_cond_podready", Name: "pod_ready"}, 506 {ID: "pod_%s_cond_podscheduled", Name: "pod_scheduled"}, 507 {ID: "pod_%s_cond_podinitialized", Name: "pod_initialized"}, 508 {ID: "pod_%s_cond_containersready", Name: "containers_ready"}, 509 }, 510 } 511 podPhaseChartTmpl = module.Chart{ 512 IDSep: true, 513 ID: "pod_%s.phase", 514 Title: "Phase", 515 Units: "state", 516 Fam: "pod phase", 517 Ctx: "k8s_state.pod_phase", 518 Priority: prioPodPhase, 519 Dims: module.Dims{ 520 {ID: "pod_%s_phase_running", Name: "running"}, 521 {ID: "pod_%s_phase_failed", Name: "failed"}, 522 {ID: "pod_%s_phase_succeeded", Name: "succeeded"}, 523 {ID: "pod_%s_phase_pending", Name: "pending"}, 524 }, 525 } 526 podAgeChartTmpl = module.Chart{ 527 IDSep: true, 528 ID: "pod_%s.age", 529 Title: "Age", 530 Units: "seconds", 531 Fam: "pod age", 532 Ctx: "k8s_state.pod_age", 533 Priority: prioPodAge, 534 Dims: module.Dims{ 535 {ID: "pod_%s_age", Name: "age"}, 536 }, 537 } 538 podContainersCountChartTmpl = module.Chart{ 539 IDSep: true, 540 ID: "pod_%s.containers_count", 541 Title: "Containers", 542 Units: "containers", 543 Fam: "pod containers", 544 Ctx: "k8s_state.pod_containers", 545 Priority: prioPodContainersCount, 546 Dims: module.Dims{ 547 {ID: "pod_%s_containers", Name: "containers"}, 548 {ID: "pod_%s_init_containers", Name: "init_containers"}, 549 }, 550 } 551 podContainersStateChartTmpl = module.Chart{ 552 IDSep: true, 553 ID: "pod_%s.containers_state", 554 Title: "Containers state", 555 Units: "containers", 556 Fam: "pod containers", 557 Ctx: "k8s_state.pod_containers_state", 558 Type: module.Stacked, 559 Priority: prioPodContainersState, 560 Dims: module.Dims{ 561 {ID: "pod_%s_containers_state_running", Name: "running"}, 562 {ID: "pod_%s_containers_state_waiting", Name: "waiting"}, 563 {ID: "pod_%s_containers_state_terminated", Name: "terminated"}, 564 }, 565 } 566 podInitContainersStateChartTmpl = module.Chart{ 567 IDSep: true, 568 ID: "pod_%s.init_containers_state", 569 Title: "Init containers state", 570 Units: "containers", 571 Fam: "pod containers", 572 Ctx: "k8s_state.pod_init_containers_state", 573 Type: module.Stacked, 574 Priority: prioPodInitContainersState, 575 Dims: module.Dims{ 576 {ID: "pod_%s_init_containers_state_running", Name: "running"}, 577 {ID: "pod_%s_init_containers_state_waiting", Name: "waiting"}, 578 {ID: "pod_%s_init_containers_state_terminated", Name: "terminated"}, 579 }, 580 } 581 ) 582 583 func (ks *KubeState) newPodCharts(ps *podState) *module.Charts { 584 charts := podChartsTmpl.Copy() 585 for _, c := range *charts { 586 c.ID = fmt.Sprintf(c.ID, replaceDots(ps.id())) 587 c.Labels = ks.newPodChartLabels(ps) 588 for _, d := range c.Dims { 589 d.ID = fmt.Sprintf(d.ID, ps.id()) 590 } 591 } 592 return charts 593 } 594 595 func (ks *KubeState) newPodChartLabels(ps *podState) []module.Label { 596 labels := []module.Label{ 597 {Key: labelKeyNamespace, Value: ps.namespace, Source: module.LabelSourceK8s}, 598 {Key: labelKeyPodName, Value: ps.name, Source: module.LabelSourceK8s}, 599 {Key: labelKeyNodeName, Value: ps.nodeName, Source: module.LabelSourceK8s}, 600 {Key: labelKeyQoSClass, Value: ps.qosClass, Source: module.LabelSourceK8s}, 601 {Key: labelKeyControllerKind, Value: ps.controllerKind, Source: module.LabelSourceK8s}, 602 {Key: labelKeyControllerName, Value: ps.controllerName, Source: module.LabelSourceK8s}, 603 {Key: labelKeyClusterID, Value: ks.kubeClusterID, Source: module.LabelSourceK8s}, 604 {Key: labelKeyClusterName, Value: ks.kubeClusterName, Source: module.LabelSourceK8s}, 605 } 606 return labels 607 } 608 609 func (ks *KubeState) addPodCharts(ps *podState) { 610 charts := ks.newPodCharts(ps) 611 if err := ks.Charts().Add(*charts...); err != nil { 612 ks.Warning(err) 613 } 614 } 615 616 func (ks *KubeState) updatePodChartsNodeLabel(ps *podState) { 617 prefix := fmt.Sprintf("pod_%s", replaceDots(ps.id())) 618 for _, c := range *ks.Charts() { 619 if strings.HasPrefix(c.ID, prefix) { 620 updateNodeLabel(c, ps.nodeName) 621 c.MarkNotCreated() 622 } 623 } 624 } 625 626 func updateNodeLabel(c *module.Chart, nodeName string) { 627 for i, l := range c.Labels { 628 if l.Key == labelKeyNodeName { 629 c.Labels[i].Value = nodeName 630 break 631 } 632 } 633 } 634 635 func (ks *KubeState) removePodCharts(ps *podState) { 636 prefix := fmt.Sprintf("pod_%s", replaceDots(ps.id())) 637 for _, c := range *ks.Charts() { 638 if strings.HasPrefix(c.ID, prefix) { 639 c.MarkRemove() 640 c.MarkNotCreated() 641 } 642 } 643 } 644 645 var ( 646 containerReadinessStateChartTmpl = module.Chart{ 647 IDSep: true, 648 ID: "pod_%s_container_%s.readiness_state", 649 Title: "Readiness state", 650 Units: "state", 651 Fam: "container readiness", 652 Ctx: "k8s_state.pod_container_readiness_state", 653 Priority: prioPodContainerReadinessState, 654 Dims: module.Dims{ 655 {ID: "pod_%s_container_%s_readiness", Name: "ready"}, 656 }, 657 } 658 containerRestartsChartTmpl = module.Chart{ 659 IDSep: true, 660 ID: "pod_%s_container_%s.restarts", 661 Title: "Restarts", 662 Units: "restarts", 663 Fam: "container restarts", 664 Ctx: "k8s_state.pod_container_restarts", 665 Priority: prioPodContainerRestarts, 666 Dims: module.Dims{ 667 {ID: "pod_%s_container_%s_restarts", Name: "restarts"}, 668 }, 669 } 670 containersStateChartTmpl = module.Chart{ 671 IDSep: true, 672 ID: "pod_%s_container_%s.state", 673 Title: "Container state", 674 Units: "state", 675 Fam: "container state", 676 Ctx: "k8s_state.pod_container_state", 677 Priority: prioPodContainerState, 678 Dims: module.Dims{ 679 {ID: "pod_%s_container_%s_state_running", Name: "running"}, 680 {ID: "pod_%s_container_%s_state_waiting", Name: "waiting"}, 681 {ID: "pod_%s_container_%s_state_terminated", Name: "terminated"}, 682 }, 683 } 684 containersStateWaitingChartTmpl = module.Chart{ 685 IDSep: true, 686 ID: "pod_%s_container_%s.state_waiting_reason", 687 Title: "Container waiting state reason", 688 Units: "state", 689 Fam: "container waiting reason", 690 Ctx: "k8s_state.pod_container_waiting_state_reason", 691 Priority: prioPodContainerWaitingStateReason, 692 } 693 containersStateTerminatedChartTmpl = module.Chart{ 694 IDSep: true, 695 ID: "pod_%s_container_%s.state_terminated_reason", 696 Title: "Container terminated state reason", 697 Units: "state", 698 Fam: "container terminated reason", 699 Ctx: "k8s_state.pod_container_terminated_state_reason", 700 Priority: prioPodContainerTerminatedStateReason, 701 } 702 ) 703 704 func (ks *KubeState) newContainerCharts(ps *podState, cs *containerState) *module.Charts { 705 charts := containerChartsTmpl.Copy() 706 for _, c := range *charts { 707 c.ID = fmt.Sprintf(c.ID, replaceDots(ps.id()), cs.name) 708 c.Labels = ks.newContainerChartLabels(ps, cs) 709 for _, d := range c.Dims { 710 d.ID = fmt.Sprintf(d.ID, ps.id(), cs.name) 711 } 712 } 713 return charts 714 } 715 716 func (ks *KubeState) newContainerChartLabels(ps *podState, cs *containerState) []module.Label { 717 labels := ks.newPodChartLabels(ps) 718 labels = append( 719 labels, module.Label{Key: labelKeyContainerName, Value: cs.name, Source: module.LabelSourceK8s}, 720 ) 721 return labels 722 } 723 724 func (ks *KubeState) addContainerCharts(ps *podState, cs *containerState) { 725 charts := ks.newContainerCharts(ps, cs) 726 if err := ks.Charts().Add(*charts...); err != nil { 727 ks.Warning(err) 728 } 729 } 730 731 func (ks *KubeState) addContainerWaitingStateReasonToChart(ps *podState, cs *containerState, reason string) { 732 id := fmt.Sprintf(containersStateWaitingChartTmpl.ID, replaceDots(ps.id()), cs.name) 733 c := ks.Charts().Get(id) 734 if c == nil { 735 ks.Warningf("chart '%s' does not exist", id) 736 return 737 } 738 dim := &module.Dim{ 739 ID: fmt.Sprintf("pod_%s_container_%s_state_waiting_reason_%s", ps.id(), cs.name, reason), 740 Name: reason, 741 } 742 if err := c.AddDim(dim); err != nil { 743 ks.Warning(err) 744 return 745 } 746 c.MarkNotCreated() 747 } 748 749 func (ks *KubeState) addContainerTerminatedStateReasonToChart(ps *podState, cs *containerState, reason string) { 750 id := fmt.Sprintf(containersStateTerminatedChartTmpl.ID, replaceDots(ps.id()), cs.name) 751 c := ks.Charts().Get(id) 752 if c == nil { 753 ks.Warningf("chart '%s' does not exist", id) 754 return 755 } 756 dim := &module.Dim{ 757 ID: fmt.Sprintf("pod_%s_container_%s_state_terminated_reason_%s", ps.id(), cs.name, reason), 758 Name: reason, 759 } 760 if err := c.AddDim(dim); err != nil { 761 ks.Warning(err) 762 return 763 } 764 c.MarkNotCreated() 765 } 766 767 var discoveryStatusChart = module.Chart{ 768 ID: "discovery_discoverers_state", 769 Title: "Running discoverers state", 770 Units: "state", 771 Fam: "discovery", 772 Ctx: "k8s_state.discovery_discoverers_state", 773 Priority: prioDiscoveryDiscovererState, 774 Opts: module.Opts{Hidden: true}, 775 Dims: module.Dims{ 776 {ID: "discovery_node_discoverer_state", Name: "node"}, 777 {ID: "discovery_pod_discoverer_state", Name: "pod"}, 778 }, 779 } 780 781 var reDots = regexp.MustCompile(`\.`) 782 783 func replaceDots(v string) string { 784 return reDots.ReplaceAllString(v, "-") 785 }