diff --git a/docs/metrics/workload/deployment-metrics.md b/docs/metrics/workload/deployment-metrics.md
index e8d0fdb42a..b1f513ae8e 100644
--- a/docs/metrics/workload/deployment-metrics.md
+++ b/docs/metrics/workload/deployment-metrics.md
@@ -1,20 +1,21 @@
# Deployment Metrics
-| Metric name | Metric type | Description | Labels/tags | Status |
-| ----------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
-| kube_deployment_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`annotation_DEPLOYMENT_ANNOTATION`=<DEPLOYMENT_ANNOTATION> | EXPERIMENTAL |
-| kube_deployment_status_replicas | Gauge | The number of replicas per deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_replicas_ready | Gauge | The number of ready replicas per deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_replicas_available | Gauge | The number of available replicas per deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_replicas_unavailable | Gauge | The number of unavailable replicas per deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_replicas_updated | Gauge | The number of updated replicas per deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_observed_generation | Gauge | The generation observed by the deployment controller. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_status_condition | Gauge | The current status conditions of a deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`reason`=<deployment-transition-reason>
`condition`=<deployment-condition>
`status`=<true\|false\|unknown> | STABLE |
-| kube_deployment_spec_replicas | Gauge | Number of desired pods for a deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_spec_paused | Gauge | Whether the deployment is paused and will not be processed by the deployment controller. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_spec_strategy_rollingupdate_max_unavailable | Gauge | Maximum number of unavailable replicas during a rolling update of a deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_spec_strategy_rollingupdate_max_surge | Gauge | Maximum number of replicas that can be scheduled above the desired number of replicas during a rolling update of a deployment. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_metadata_generation | Gauge | Sequence number representing a specific generation of the desired state. | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`label_DEPLOYMENT_LABEL`=<DEPLOYMENT_LABEL> | STABLE |
-| kube_deployment_created | Gauge | Unix creation timestamp | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
-| kube_deployment_deletion_timestamp | Gauge | Unix deletion timestamp | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | EXPIREMENTAL |
+| Metric name | Metric type | Description | Labels/tags | Status |
+| ----------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
+| kube_deployment_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`annotation_DEPLOYMENT_ANNOTATION`=<DEPLOYMENT_ANNOTATION> | EXPERIMENTAL |
+| kube_deployment_status_replicas | Gauge | The number of replicas per deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_replicas_ready | Gauge | The number of ready replicas per deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_replicas_available | Gauge | The number of available replicas per deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_replicas_unavailable | Gauge | The number of unavailable replicas per deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_replicas_updated | Gauge | The number of updated replicas per deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_observed_generation | Gauge | The generation observed by the deployment controller | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_status_condition | Gauge | The current status conditions of a deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`reason`=<deployment-transition-reason>
`condition`=<deployment-condition>
`status`=<true\|false\|unknown> | STABLE |
+| kube_deployment_spec_replicas | Gauge | Number of desired pods for a deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_spec_paused | Gauge | Whether the deployment is paused and will not be processed by the deployment controller | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_spec_strategy_rollingupdate_max_unavailable | Gauge | Maximum number of unavailable replicas during a rolling update of a deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_spec_strategy_rollingupdate_max_surge | Gauge | Maximum number of replicas that can be scheduled above the desired number of replicas during a rolling update of a deployment | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_spec_topology_spread_constraint | Gauge | Explicit details of each topology spread constraint in the deployment's pod template | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`topology_key`=<topology-key>
`max_skew`=<max-skew-value>
`when_unsatisfiable`=<DoNotSchedule\|ScheduleAnyway>
`min_domains`=<min-domains-value>
`label_selector`=<label-selector-string> | ALPHA |
+| kube_deployment_metadata_generation | Gauge | Sequence number representing a specific generation of the desired state | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `deployment`=<deployment-name>
`namespace`=<deployment-namespace>
`label_DEPLOYMENT_LABEL`=<DEPLOYMENT_LABEL> | STABLE |
+| kube_deployment_created | Gauge | Unix creation timestamp | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE |
+| kube_deployment_deletion_timestamp | Gauge | Unix deletion timestamp | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | EXPERIMENTAL |
diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml
index 6e9ff89892..0f621f18c5 100644
--- a/examples/autosharding/cluster-role.yaml
+++ b/examples/autosharding/cluster-role.yaml
@@ -125,4 +125,4 @@ rules:
- roles
verbs:
- list
- - watch
+ - watch
\ No newline at end of file
diff --git a/examples/autosharding/role-binding.yaml b/examples/autosharding/role-binding.yaml
index af4d794d66..113ce64761 100644
--- a/examples/autosharding/role-binding.yaml
+++ b/examples/autosharding/role-binding.yaml
@@ -12,5 +12,5 @@ roleRef:
kind: Role
name: kube-state-metrics
subjects:
-- kind: ServiceAccount
- name: kube-state-metrics
+ - kind: ServiceAccount
+ name: kube-state-metrics
diff --git a/examples/autosharding/role.yaml b/examples/autosharding/role.yaml
index b93e99d254..257fc99d9c 100644
--- a/examples/autosharding/role.yaml
+++ b/examples/autosharding/role.yaml
@@ -21,4 +21,4 @@ rules:
resources:
- statefulsets
verbs:
- - get
+ - get
\ No newline at end of file
diff --git a/examples/autosharding/service.yaml b/examples/autosharding/service.yaml
index b0d74c182f..7b4ffb0074 100644
--- a/examples/autosharding/service.yaml
+++ b/examples/autosharding/service.yaml
@@ -15,6 +15,6 @@ spec:
targetPort: http-metrics
- name: telemetry
port: 8081
- targetPort: telemetry
+ targetPort: telemetry
selector:
app.kubernetes.io/name: kube-state-metrics
diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml
index 6e9ff89892..12cef1ab06 100644
--- a/examples/standard/cluster-role.yaml
+++ b/examples/standard/cluster-role.yaml
@@ -125,4 +125,4 @@ rules:
- roles
verbs:
- list
- - watch
+ - watch
\ No newline at end of file
diff --git a/examples/standard/service.yaml b/examples/standard/service.yaml
index b0d74c182f..7b4ffb0074 100644
--- a/examples/standard/service.yaml
+++ b/examples/standard/service.yaml
@@ -15,6 +15,6 @@ spec:
targetPort: http-metrics
- name: telemetry
port: 8081
- targetPort: telemetry
+ targetPort: telemetry
selector:
app.kubernetes.io/name: kube-state-metrics
diff --git a/internal/store/deployment.go b/internal/store/deployment.go
index 31e3b200a6..08a9e314e0 100644
--- a/internal/store/deployment.go
+++ b/internal/store/deployment.go
@@ -1,17 +1,25 @@
/*
+
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
+
you may not use this file except in compliance with the License.
+
You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
+
distributed under the License is distributed on an "AS IS" BASIS,
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+
See the License for the specific language governing permissions and
+
limitations under the License.
+
*/
package store
@@ -19,25 +27,38 @@ package store
import (
"context"
+ "strconv"
+
basemetrics "k8s.io/component-base/metrics"
"k8s.io/kube-state-metrics/v2/pkg/metric"
+
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
v1 "k8s.io/api/apps/v1"
+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
"k8s.io/apimachinery/pkg/runtime"
+
"k8s.io/apimachinery/pkg/util/intstr"
+
"k8s.io/apimachinery/pkg/watch"
+
clientset "k8s.io/client-go/kubernetes"
+
"k8s.io/client-go/tools/cache"
)
var (
- descDeploymentAnnotationsName = "kube_deployment_annotations"
- descDeploymentAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
- descDeploymentLabelsName = "kube_deployment_labels"
- descDeploymentLabelsHelp = "Kubernetes labels converted to Prometheus labels."
+ descDeploymentAnnotationsName = "kube_deployment_annotations"
+
+ descDeploymentAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels."
+
+ descDeploymentLabelsName = "kube_deployment_labels"
+
+ descDeploymentLabelsHelp = "Kubernetes labels converted to Prometheus labels."
+
descDeploymentLabelsDefaultLabels = []string{"namespace", "deployment"}
)
@@ -59,136 +80,232 @@ var (
)
func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator {
+
return []generator.FamilyGenerator{
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_created",
+
"Unix creation timestamp",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
ms := []*metric.Metric{}
if !d.CreationTimestamp.IsZero() {
+
ms = append(ms, &metric.Metric{
+
Value: float64(d.CreationTimestamp.Unix()),
})
+
}
return &metric.Family{
+
Metrics: ms,
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_replicas",
+
"The number of replicas per deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.Replicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_replicas_ready",
+
"The number of ready replicas per deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.ReadyReplicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_replicas_available",
+
"The number of available replicas per deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.AvailableReplicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_replicas_unavailable",
+
"The number of unavailable replicas per deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.UnavailableReplicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_replicas_updated",
+
"The number of updated replicas per deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.UpdatedReplicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_observed_generation",
+
"The generation observed by the deployment controller.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Status.ObservedGeneration),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_status_condition",
+
"The current status conditions of a deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
ms := make([]*metric.Metric, len(d.Status.Conditions)*len(conditionStatuses))
for i, c := range d.Status.Conditions {
+
conditionMetrics := addConditionMetrics(c.Status)
for j, m := range conditionMetrics {
+
metric := m
reason := c.Reason
@@ -197,204 +314,380 @@ func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
}
metric.LabelKeys = []string{"reason", "condition", "status"}
+
metric.LabelValues = append([]string{reason, string(c.Type)}, metric.LabelValues...)
+
ms[i*len(conditionStatuses)+j] = metric
+
}
+
}
return &metric.Family{
+
Metrics: ms,
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_spec_replicas",
+
"Number of desired pods for a deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(*d.Spec.Replicas),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_spec_paused",
+
"Whether the deployment is paused and will not be processed by the deployment controller.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: boolFloat64(d.Spec.Paused),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_spec_strategy_rollingupdate_max_unavailable",
+
"Maximum number of unavailable replicas during a rolling update of a deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
if d.Spec.Strategy.RollingUpdate == nil {
+
return &metric.Family{}
+
}
maxUnavailable, err := intstr.GetScaledValueFromIntOrPercent(d.Spec.Strategy.RollingUpdate.MaxUnavailable, int(*d.Spec.Replicas), false)
+
if err != nil {
+
panic(err)
+
}
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(maxUnavailable),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_spec_strategy_rollingupdate_max_surge",
+
"Maximum number of replicas that can be scheduled above the desired number of replicas during a rolling update of a deployment.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
if d.Spec.Strategy.RollingUpdate == nil {
+
return &metric.Family{}
+
}
maxSurge, err := intstr.GetScaledValueFromIntOrPercent(d.Spec.Strategy.RollingUpdate.MaxSurge, int(*d.Spec.Replicas), true)
+
if err != nil {
+
panic(err)
+
}
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(maxSurge),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
+ "kube_deployment_spec_topology_spread_constraint",
+
+ "Explicit details of each topology spread constraint in the deployment's pod template.",
+
+ metric.Gauge,
+
+ basemetrics.ALPHA,
+
+ "",
+
+ wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
+ ms := []*metric.Metric{}
+ for _, constraint := range d.Spec.Template.Spec.TopologySpreadConstraints {
+ labelSelectorStr, err := metav1.LabelSelectorAsSelector(constraint.LabelSelector)
+ if err != nil {
+ // Skip invalid label selectors
+ continue
+ }
+ minDomainsStr := "1"
+ if constraint.MinDomains != nil {
+ minDomainsStr = strconv.Itoa(int(*constraint.MinDomains))
+ }
+ ms = append(ms, &metric.Metric{
+ LabelKeys: []string{"topology_key", "max_skew", "when_unsatisfiable", "min_domains", "label_selector"},
+ LabelValues: []string{constraint.TopologyKey, strconv.Itoa(int(constraint.MaxSkew)), string(constraint.WhenUnsatisfiable), minDomainsStr, labelSelectorStr.String()},
+ Value: 1,
+ })
+ }
+ return &metric.Family{Metrics: ms}
+
+ }),
+ ),
+
+ *generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_metadata_generation",
+
"Sequence number representing a specific generation of the desired state.",
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
+
Value: float64(d.Generation),
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
"kube_deployment_deletion_timestamp",
+
"Unix deletion timestamp",
+
metric.Gauge,
+
basemetrics.ALPHA,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
ms := []*metric.Metric{}
if !d.DeletionTimestamp.IsZero() {
+
ms = append(ms, &metric.Metric{
+
Value: float64(d.DeletionTimestamp.Unix()),
})
+
}
return &metric.Family{
+
Metrics: ms,
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
descDeploymentAnnotationsName,
+
descDeploymentAnnotationsHelp,
+
metric.Gauge,
basemetrics.ALPHA,
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
if len(allowAnnotationsList) == 0 {
+
return &metric.Family{}
+
}
+
annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", d.Annotations, allowAnnotationsList)
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
- LabelKeys: annotationKeys,
+
+ LabelKeys: annotationKeys,
+
LabelValues: annotationValues,
- Value: 1,
+
+ Value: 1,
},
},
}
+
}),
),
+
*generator.NewFamilyGeneratorWithStability(
+
descDeploymentLabelsName,
+
descDeploymentLabelsHelp,
+
metric.Gauge,
+
basemetrics.STABLE,
+
"",
+
wrapDeploymentFunc(func(d *v1.Deployment) *metric.Family {
+
if len(allowLabelsList) == 0 {
+
return &metric.Family{}
+
}
+
labelKeys, labelValues := createPrometheusLabelKeysValues("label", d.Labels, allowLabelsList)
+
return &metric.Family{
+
Metrics: []*metric.Metric{
+
{
- LabelKeys: labelKeys,
+
+ LabelKeys: labelKeys,
+
LabelValues: labelValues,
- Value: 1,
+
+ Value: 1,
},
},
}
+
}),
),
}
+
}
func wrapDeploymentFunc(f func(*v1.Deployment) *metric.Family) func(interface{}) *metric.Family {
+
return func(obj interface{}) *metric.Family {
+
deployment := obj.(*v1.Deployment)
metricFamily := f(deployment)
for _, m := range metricFamily.Metrics {
+
m.LabelKeys, m.LabelValues = mergeKeyValues(descDeploymentLabelsDefaultLabels, []string{deployment.Namespace, deployment.Name}, m.LabelKeys, m.LabelValues)
+
}
return metricFamily
+
}
+
}
func createDeploymentListWatch(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher {
+
return &cache.ListWatch{
+
ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) {
+
opts.FieldSelector = fieldSelector
+
return kubeClient.AppsV1().Deployments(ns).List(context.TODO(), opts)
+
},
+
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
+
opts.FieldSelector = fieldSelector
+
return kubeClient.AppsV1().Deployments(ns).Watch(context.TODO(), opts)
+
},
}
+
}
diff --git a/internal/store/deployment_test.go b/internal/store/deployment_test.go
index a0e3f4aa17..40129d407b 100644
--- a/internal/store/deployment_test.go
+++ b/internal/store/deployment_test.go
@@ -31,8 +31,6 @@ import (
var (
depl1Replicas int32 = 200
depl2Replicas int32 = 5
- depl3Replicas int32 = 1
- depl4Replicas int32 = 10
depl1MaxUnavailable = intstr.FromInt(10)
depl2MaxUnavailable = intstr.FromString("25%")
@@ -73,6 +71,8 @@ func TestDeploymentStore(t *testing.T) {
# TYPE kube_deployment_spec_strategy_rollingupdate_max_unavailable gauge
# HELP kube_deployment_spec_strategy_rollingupdate_max_surge [STABLE] Maximum number of replicas that can be scheduled above the desired number of replicas during a rolling update of a deployment.
# TYPE kube_deployment_spec_strategy_rollingupdate_max_surge gauge
+ # HELP kube_deployment_spec_topology_spread_constraint Explicit details of each topology spread constraint in the deployment's pod template.
+ # TYPE kube_deployment_spec_topology_spread_constraint gauge
# HELP kube_deployment_labels [STABLE] Kubernetes labels converted to Prometheus labels.
# TYPE kube_deployment_labels gauge
# HELP kube_deployment_deletion_timestamp Unix deletion timestamp
@@ -114,6 +114,14 @@ func TestDeploymentStore(t *testing.T) {
MaxSurge: &depl1MaxSurge,
},
},
+ Template: corev1.PodTemplateSpec{
+ Spec: corev1.PodSpec{
+ TopologySpreadConstraints: []corev1.TopologySpreadConstraint{
+ {MaxSkew: 1, TopologyKey: "kubernetes.io/zone", WhenUnsatisfiable: corev1.DoNotSchedule},
+ {MaxSkew: 1, TopologyKey: "kubernetes.io/hostname", WhenUnsatisfiable: corev1.ScheduleAnyway},
+ },
+ },
+ },
},
},
Want: metadata + `
@@ -124,6 +132,8 @@ func TestDeploymentStore(t *testing.T) {
kube_deployment_spec_replicas{deployment="depl1",namespace="ns1"} 200
kube_deployment_spec_strategy_rollingupdate_max_surge{deployment="depl1",namespace="ns1"} 10
kube_deployment_spec_strategy_rollingupdate_max_unavailable{deployment="depl1",namespace="ns1"} 10
+ kube_deployment_spec_topology_spread_constraint{deployment="depl1",namespace="ns1",topology_key="kubernetes.io/zone",max_skew="1",when_unsatisfiable="DoNotSchedule",min_domains="1",label_selector=""} 1
+ kube_deployment_spec_topology_spread_constraint{deployment="depl1",namespace="ns1",topology_key="kubernetes.io/hostname",max_skew="1",when_unsatisfiable="ScheduleAnyway",min_domains="1",label_selector=""} 1
kube_deployment_status_observed_generation{deployment="depl1",namespace="ns1"} 111
kube_deployment_status_replicas_available{deployment="depl1",namespace="ns1"} 10
kube_deployment_status_replicas_unavailable{deployment="depl1",namespace="ns1"} 5
@@ -195,64 +205,8 @@ func TestDeploymentStore(t *testing.T) {
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"},
- {Type: v1.DeploymentProgressing, Status: corev1.ConditionTrue},
- },
- },
- 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
- kube_deployment_status_condition{condition="Progressing",deployment="depl3",namespace="ns3",reason="",status="false"} 0
- kube_deployment_status_condition{condition="Progressing",deployment="depl3",namespace="ns3",reason="",status="true"} 1
- kube_deployment_status_condition{condition="Progressing",deployment="depl3",namespace="ns3",reason="",status="unknown"} 0
-`,
- },
- {
- Obj: &v1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Name: "deployment-terminating",
- Namespace: "ns4",
- CreationTimestamp: metav1.Time{Time: time.Unix(1600000000, 0)},
- DeletionTimestamp: &metav1.Time{Time: time.Unix(1800000000, 0)},
- Labels: map[string]string{
- "app": "example4",
- },
- Generation: 22,
- },
- Spec: v1.DeploymentSpec{
- Paused: true,
- Replicas: &depl4Replicas,
- },
- },
- Want: `
- # HELP kube_deployment_deletion_timestamp Unix deletion timestamp
- # TYPE kube_deployment_deletion_timestamp gauge
- kube_deployment_deletion_timestamp{deployment="deployment-terminating",namespace="ns4"} 1.8e+09`,
- MetricNames: []string{"kube_deployment_deletion_timestamp"},
- },
}
+
for i, c := range cases {
c.Func = generator.ComposeMetricGenFuncs(deploymentMetricFamilies(c.AllowAnnotationsList, nil))
c.Headers = generator.ExtractMetricFamilyHeaders(deploymentMetricFamilies(c.AllowAnnotationsList, nil))
diff --git a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
index bbf44adb77..a2115a8470 100644
--- a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
+++ b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet
@@ -192,7 +192,7 @@
},
livenessProbe: { timeoutSeconds: 5, initialDelaySeconds: 5, httpGet: {
port: 'http-metrics',
- path: '/livez',
+ path: '/healthz',
} },
readinessProbe: { timeoutSeconds: 5, initialDelaySeconds: 5, httpGet: {
port: 'telemetry',
diff --git a/test_output.txt b/test_output.txt
new file mode 100644
index 0000000000..e75578f6ec
--- /dev/null
+++ b/test_output.txt
@@ -0,0 +1,4 @@
+=== RUN TestDeploymentStore
+--- PASS: TestDeploymentStore (0.00s)
+PASS
+ok k8s.io/kube-state-metrics/v2/internal/store (cached)