improvement(go.d/k8sstate): add deployment conditions (#19662)
Ilya Mashchenko committed
Feb 17, 2025 at 22:26 UTC
b62aac1ef3cb73a70118bcab317b4e57d1ed5233
6 files changed
+64
-17
src/go/plugin/go.d/collector/k8s_state/charts.go
+17
-1
@@ -56,7 +56,8 @@ const (
56
)
57
58
const (
59
- prioDeploymentReplicas = 50500 + iota
59
+ prioDeploymentConditions = 50500 + iota
60
+ prioDeploymentReplicas
61
prioDeploymentAge
62
)
63
@@ -129,6 +130,7 @@ var containerChartsTmpl = module.Charts{
130
}
131
132
var deploymentChartsTmpl = module.Charts{
133
+ deploymentConditionStatusChartTmpl.Copy(),
134
deploymentReplicasChartTmpl.Copy(),
135
deploymentAgeChartTmpl.Copy(),
136
}
@@ -759,6 +761,20 @@ func (c *Collector) addContainerCharts(ps *podState, cs *containerState) {
761
}
762
763
var (
764
+ deploymentConditionStatusChartTmpl = module.Chart{
765
+ IDSep: true,
766
+ ID: "deployment_%s.conditions",
767
+ Title: "Deployment Conditions",
768
+ Units: "status",
769
+ Fam: "deployment conditions",
770
+ Ctx: "k8s_state.deployment_conditions",
771
+ Priority: prioDeploymentConditions,
772
+ Dims: module.Dims{
773
+ {ID: "deploy_%s_condition_available", Name: "available"},
774
+ {ID: "deploy_%s_condition_replica_failure", Name: "replica_failure"},
775
+ {ID: "deploy_%s_condition_progressing", Name: "progressing"},
776
+ },
777
+ }
778
deploymentReplicasChartTmpl = module.Chart{
779
IDSep: true,
780
ID: "deployment_%s.replicas",
src/go/plugin/go.d/collector/k8s_state/collect.go
+21
-12
@@ -9,10 +9,11 @@ import (
9
"slices"
10
"time"
11
12
+ appsv1 "k8s.io/api/apps/v1"
13
+ corev1 "k8s.io/api/core/v1"
14
+
15
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
16
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/metrix"
14
-
15
- corev1 "k8s.io/api/core/v1"
17
)
18
19
const precision = 1000
@@ -331,21 +332,29 @@ func (c *Collector) collectDeploymentState(mx map[string]int64) {
332
mx[px+"current_replicas"] = ds.availableReplicas
333
mx[px+"ready_replicas"] = ds.readyReplicas
334
335
+ mx[px+"condition_available"] = 0
336
+ mx[px+"condition_progressing"] = 0
337
+ mx[px+"condition_replica_failure"] = 0
338
+
339
+ for _, cond := range ds.conditions {
340
+ v := metrix.Bool(cond.Status == corev1.ConditionTrue)
341
+ switch cond.Type {
342
+ case appsv1.DeploymentAvailable:
343
+ // https://github.com/kubernetes/kubernetes/blob/2b3da7dfc846fec7c4044a320f8f38b4a45367a3/pkg/controller/deployment/sync.go#L518-L525
344
+ mx[px+"condition_available"] = v
345
+ case appsv1.DeploymentProgressing:
346
+ mx[px+"condition_available"] = v
347
+ case appsv1.DeploymentReplicaFailure:
348
+ mx[px+"condition_replica_failure"] = v
349
+ }
350
+ }
351
+
352
return false
353
})
354
}
355
356
func condStatusToInt(cs corev1.ConditionStatus) int64 {
339
- switch cs {
340
- case corev1.ConditionFalse:
341
- return 0
342
- case corev1.ConditionTrue:
343
- return 1
344
- case corev1.ConditionUnknown:
345
- return 0
346
- default:
347
- return 0
348
- }
357
+ return metrix.Bool(cs == corev1.ConditionTrue)
358
}
359
360
func calcPercentage(value, total int64) int64 {
src/go/plugin/go.d/collector/k8s_state/collector_test.go
+13
-4
@@ -371,6 +371,13 @@ func TestCollector_Collect(t *testing.T) {
371
step1 := func(t *testing.T, collr *Collector) {
372
mx := collr.Collect(context.Background())
373
expected := map[string]int64{
374
+ "deploy_default_replicaset01_age": 3,
375
+ "deploy_default_replicaset01_condition_available": 1,
376
+ "deploy_default_replicaset01_condition_progressing": 0,
377
+ "deploy_default_replicaset01_condition_replica_failure": 0,
378
+ "deploy_default_replicaset01_current_replicas": 1,
379
+ "deploy_default_replicaset01_desired_replicas": 2,
380
+ "deploy_default_replicaset01_ready_replicas": 3,
381
"discovery_node_discoverer_state": 1,
382
"discovery_pod_discoverer_state": 1,
383
"node_node01_age": 3,
@@ -480,10 +487,6 @@ func TestCollector_Collect(t *testing.T) {
487
"pod_default_pod01_status_reason_Other": 0,
488
"pod_default_pod01_status_reason_Shutdown": 0,
489
"pod_default_pod01_status_reason_UnexpectedAdmissionError": 0,
483
- "deploy_default_replicaset01_age": 3,
484
- "deploy_default_replicaset01_current_replicas": 1,
485
- "deploy_default_replicaset01_desired_replicas": 2,
486
- "deploy_default_replicaset01_ready_replicas": 3,
490
}
491
492
copyAge(expected, mx)
@@ -986,6 +989,12 @@ func newDeployment(name string) *appsv1.Deployment {
989
CreationTimestamp: metav1.Time{Time: time.Now()},
990
},
991
Status: appsv1.DeploymentStatus{
992
+ Conditions: []appsv1.DeploymentCondition{
993
+ {
994
+ Type: appsv1.DeploymentAvailable,
995
+ Status: corev1.ConditionTrue,
996
+ },
997
+ },
998
AvailableReplicas: 1,
999
Replicas: 2,
1000
ReadyReplicas: 3,
src/go/plugin/go.d/collector/k8s_state/metadata.yaml
+8
@@ -225,6 +225,14 @@ modules:
225
- name: k8s_namespace
226
description: Namespace.
227
metrics:
228
+ - name: k8s_state.deployment_conditions
229
+ description: Deployment Conditions
230
+ unit: 'status'
231
+ chart_type: line
232
+ dimensions:
233
+ - name: available
234
+ - name: replica_failure
235
+ - name: progressing
236
- name: k8s_state.deployment_replicas
237
description: Deployment Replicas
238
unit: 'replicas'
src/go/plugin/go.d/collector/k8s_state/state.go
+3
@@ -6,6 +6,7 @@ import (
6
"sync"
7
"time"
8
9
+ appsv1 "k8s.io/api/apps/v1"
10
corev1 "k8s.io/api/core/v1"
11
)
12
@@ -166,6 +167,8 @@ type deploymentState struct {
167
name string
168
namespace string
169
170
+ conditions []appsv1.DeploymentCondition
171
+
172
creationTime time.Time
173
replicas int64 // desired
174
availableReplicas int64 // current
src/go/plugin/go.d/collector/k8s_state/update_deployment_state.go
+2
@@ -29,6 +29,8 @@ func (c *Collector) updateDeploymentState(r resource) {
29
ds.creationTime = deploy.CreationTimestamp.Time
30
}
31
32
+ ds.conditions = deploy.Status.Conditions
33
+
34
ds.replicas = int64(deploy.Status.Replicas)
35
ds.availableReplicas = int64(deploy.Status.AvailableReplicas)
36
ds.readyReplicas = int64(deploy.Status.ReadyReplicas)