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)