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
`,
},
}