diff --git a/docs/metrics/workload/deployment-metrics.md b/docs/metrics/workload/deployment-metrics.md index 94f515901..6b07e50b9 100644 --- a/docs/metrics/workload/deployment-metrics.md +++ b/docs/metrics/workload/deployment-metrics.md @@ -9,7 +9,7 @@ | kube_deployment_status_replicas_unavailable | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | | kube_deployment_status_replicas_updated | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | | kube_deployment_status_observed_generation | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | -| kube_deployment_status_condition | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`condition`=<deployment-condition>
`status`=<true\|false\|unknown> | STABLE | +| kube_deployment_status_condition | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`reason`=<deployment-transition-reason>
`condition`=<deployment-condition>
`status`=<true\|false\|unknown> | STABLE | | kube_deployment_spec_replicas | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | | kube_deployment_spec_paused | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | | kube_deployment_spec_strategy_rollingupdate_max_unavailable | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | diff --git a/internal/store/deployment.go b/internal/store/deployment.go index 7f902b0c1..7b6c71afa 100644 --- a/internal/store/deployment.go +++ b/internal/store/deployment.go @@ -41,6 +41,22 @@ var ( descDeploymentLabelsDefaultLabels = []string{"namespace", "deployment"} ) +// Reasons copied from kubernetes/pkg/controller/deployment/deployment_utils.go. +var ( + allowedDeploymentReasons = map[string]struct{}{ + "ReplicaSetUpdated": {}, + "ReplicaSetCreateError": {}, + "NewReplicaSetCreated": {}, + "FoundNewReplicaSet": {}, + "NewReplicaSetAvailable": {}, + "ProgressDeadlineExceeded": {}, + "DeploymentPaused": {}, + "DeploymentResumed": {}, + "MinimumReplicasAvailable": {}, + "MinimumReplicasUnavailable": {}, + } +) + func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { return []generator.FamilyGenerator{ *generator.NewFamilyGeneratorWithStability( @@ -174,8 +190,13 @@ func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) [] for j, m := range conditionMetrics { metric := m - metric.LabelKeys = []string{"condition", "status"} - metric.LabelValues = append([]string{string(c.Type)}, metric.LabelValues...) + reason := c.Reason + if _, ok := allowedDeploymentReasons[reason]; !ok { + reason = "unknown" + } + + metric.LabelKeys = []string{"reason", "condition", "status"} + metric.LabelValues = append([]string{reason, string(c.Type)}, metric.LabelValues...) ms[i*len(conditionStatuses)+j] = metric } } diff --git a/internal/store/deployment_test.go b/internal/store/deployment_test.go index 31be4a17d..662a44cb5 100644 --- a/internal/store/deployment_test.go +++ b/internal/store/deployment_test.go @@ -31,6 +31,7 @@ import ( var ( depl1Replicas int32 = 200 depl2Replicas int32 = 5 + depl3Replicas int32 = 1 depl1MaxUnavailable = intstr.FromInt(10) depl2MaxUnavailable = intstr.FromString("25%") @@ -98,8 +99,8 @@ func TestDeploymentStore(t *testing.T) { UpdatedReplicas: 2, ObservedGeneration: 111, Conditions: []v1.DeploymentCondition{ - {Type: v1.DeploymentAvailable, Status: corev1.ConditionTrue}, - {Type: v1.DeploymentProgressing, Status: corev1.ConditionTrue}, + {Type: v1.DeploymentAvailable, Status: corev1.ConditionTrue, Reason: "MinimumReplicasAvailable"}, + {Type: v1.DeploymentProgressing, Status: corev1.ConditionTrue, Reason: "NewReplicaSetAvailable"}, }, }, Spec: v1.DeploymentSpec{ @@ -126,12 +127,12 @@ func TestDeploymentStore(t *testing.T) { kube_deployment_status_replicas_updated{deployment="depl1",namespace="ns1"} 2 kube_deployment_status_replicas{deployment="depl1",namespace="ns1"} 15 kube_deployment_status_replicas_ready{deployment="depl1",namespace="ns1"} 10 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Available",status="true"} 1 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Progressing",status="true"} 1 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Available",status="false"} 0 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Progressing",status="false"} 0 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Available",status="unknown"} 0 - kube_deployment_status_condition{deployment="depl1",namespace="ns1",condition="Progressing",status="unknown"} 0 + kube_deployment_status_condition{condition="Available",deployment="depl1",namespace="ns1",reason="MinimumReplicasAvailable",status="true"} 1 + kube_deployment_status_condition{condition="Available",deployment="depl1",namespace="ns1",reason="MinimumReplicasAvailable",status="false"} 0 + kube_deployment_status_condition{condition="Available",deployment="depl1",namespace="ns1",reason="MinimumReplicasAvailable",status="unknown"} 0 + kube_deployment_status_condition{condition="Progressing",deployment="depl1",namespace="ns1",reason="NewReplicaSetAvailable",status="true"} 1 + kube_deployment_status_condition{condition="Progressing",deployment="depl1",namespace="ns1",reason="NewReplicaSetAvailable",status="false"} 0 + kube_deployment_status_condition{condition="Progressing",deployment="depl1",namespace="ns1",reason="NewReplicaSetAvailable",status="unknown"} 0 `, }, { @@ -152,9 +153,9 @@ func TestDeploymentStore(t *testing.T) { UpdatedReplicas: 1, ObservedGeneration: 1111, Conditions: []v1.DeploymentCondition{ - {Type: v1.DeploymentAvailable, Status: corev1.ConditionFalse}, - {Type: v1.DeploymentProgressing, Status: corev1.ConditionFalse}, - {Type: v1.DeploymentReplicaFailure, Status: corev1.ConditionTrue}, + {Type: v1.DeploymentAvailable, Status: corev1.ConditionFalse, Reason: "MinimumReplicasUnavailable"}, + {Type: v1.DeploymentProgressing, Status: corev1.ConditionFalse, Reason: "ProgressDeadlineExceeded"}, + {Type: v1.DeploymentReplicaFailure, Status: corev1.ConditionTrue, Reason: "ReplicaSetCreateError"}, }, }, Spec: v1.DeploymentSpec{ @@ -180,15 +181,45 @@ func TestDeploymentStore(t *testing.T) { kube_deployment_status_replicas_updated{deployment="depl2",namespace="ns2"} 1 kube_deployment_status_replicas{deployment="depl2",namespace="ns2"} 10 kube_deployment_status_replicas_ready{deployment="depl2",namespace="ns2"} 5 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Available",status="true"} 0 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Progressing",status="true"} 0 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="ReplicaFailure",status="true"} 1 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Available",status="false"} 1 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Progressing",status="false"} 1 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="ReplicaFailure",status="false"} 0 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Available",status="unknown"} 0 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="Progressing",status="unknown"} 0 - kube_deployment_status_condition{deployment="depl2",namespace="ns2",condition="ReplicaFailure",status="unknown"} 0 + kube_deployment_status_condition{condition="Available",deployment="depl2",namespace="ns2",reason="MinimumReplicasUnavailable",status="true"} 0 + kube_deployment_status_condition{condition="Available",deployment="depl2",namespace="ns2",reason="MinimumReplicasUnavailable",status="false"} 1 + kube_deployment_status_condition{condition="Available",deployment="depl2",namespace="ns2",reason="MinimumReplicasUnavailable",status="unknown"} 0 + kube_deployment_status_condition{condition="Progressing",deployment="depl2",namespace="ns2",reason="ProgressDeadlineExceeded",status="true"} 0 + kube_deployment_status_condition{condition="Progressing",deployment="depl2",namespace="ns2",reason="ProgressDeadlineExceeded",status="false"} 1 + kube_deployment_status_condition{condition="Progressing",deployment="depl2",namespace="ns2",reason="ProgressDeadlineExceeded",status="unknown"} 0 + kube_deployment_status_condition{condition="ReplicaFailure",deployment="depl2",namespace="ns2",reason="ReplicaSetCreateError",status="true"} 1 + kube_deployment_status_condition{condition="ReplicaFailure",deployment="depl2",namespace="ns2",reason="ReplicaSetCreateError",status="false"} 0 + kube_deployment_status_condition{condition="ReplicaFailure",deployment="depl2",namespace="ns2",reason="ReplicaSetCreateError",status="unknown"} 0 +`, + }, + { + Obj: &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "depl3", + Namespace: "ns3", + }, + Status: v1.DeploymentStatus{ + Conditions: []v1.DeploymentCondition{ + {Type: v1.DeploymentAvailable, Status: corev1.ConditionFalse, Reason: "ThisReasonIsNotAllowed"}, + }, + }, + Spec: v1.DeploymentSpec{ + Replicas: &depl3Replicas, + }, + }, + Want: metadata + ` + kube_deployment_metadata_generation{deployment="depl3",namespace="ns3"} 0 + kube_deployment_spec_paused{deployment="depl3",namespace="ns3"} 0 + kube_deployment_spec_replicas{deployment="depl3",namespace="ns3"} 1 + kube_deployment_status_condition{condition="Available",deployment="depl3",namespace="ns3",reason="unknown",status="true"} 0 + kube_deployment_status_condition{condition="Available",deployment="depl3",namespace="ns3",reason="unknown",status="false"} 1 + kube_deployment_status_condition{condition="Available",deployment="depl3",namespace="ns3",reason="unknown",status="unknown"} 0 + kube_deployment_status_observed_generation{deployment="depl3",namespace="ns3"} 0 + kube_deployment_status_replicas{deployment="depl3",namespace="ns3"} 0 + kube_deployment_status_replicas_available{deployment="depl3",namespace="ns3"} 0 + kube_deployment_status_replicas_ready{deployment="depl3",namespace="ns3"} 0 + kube_deployment_status_replicas_unavailable{deployment="depl3",namespace="ns3"} 0 + kube_deployment_status_replicas_updated{deployment="depl3",namespace="ns3"} 0 `, }, }