Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/metrics/workload/deployment-metrics.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 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`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; <br> `annotation_DEPLOYMENT_ANNOTATION`=&lt;DEPLOYMENT_ANNOTATION&gt; | EXPERIMENTAL |
| kube_deployment_status_replicas | Gauge | The number of replicas per deployment. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_status_replicas_ready | Gauge | The number of ready replicas per deployment. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
Expand All @@ -12,9 +12,10 @@
| kube_deployment_status_condition | Gauge | The current status conditions of a deployment. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; <br> `reason`=&lt;deployment-transition-reason&gt; <br> `condition`=&lt;deployment-condition&gt; <br> `status`=&lt;true\|false\|unknown&gt; | STABLE |
| kube_deployment_spec_replicas | Gauge | Number of desired pods for a deployment. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_spec_paused | Gauge | Whether the deployment is paused and will not be processed by the deployment controller. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_spec_affinity | Gauge | Pod affinity and anti-affinity rules defined in the deployment's pod template specification | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; <br> `affinity`=&lt;podaffinity\|podantiaffinity&gt; <br> `type`=&lt;requiredDuringSchedulingIgnoredDuringExecution\|preferredDuringSchedulingIgnoredDuringExecution&gt; <br> `topology_key`=&lt;topology-key&gt; <br> `label_selector`=&lt;selector-string&gt; <br> `namespace_selector`=&lt;namespace-selector-string&gt; <br> `namespaces`=&lt;comma-separated-namespaces&gt; | ALPHA |
| kube_deployment_spec_strategy_rollingupdate_max_unavailable | Gauge | Maximum number of unavailable replicas during a rolling update of a deployment. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | 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`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_metadata_generation | Gauge | Sequence number representing a specific generation of the desired state. | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; <br> `label_DEPLOYMENT_LABEL`=&lt;DEPLOYMENT_LABEL&gt; | STABLE |
| kube_deployment_created | Gauge | Unix creation timestamp | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | STABLE |
| kube_deployment_deletion_timestamp | Gauge | Unix deletion timestamp | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | EXPIREMENTAL |
| kube_deployment_deletion_timestamp | Gauge | Unix deletion timestamp | `deployment`=&lt;deployment-name&gt; <br> `namespace`=&lt;deployment-namespace&gt; | EXPERIMENTAL |
81 changes: 81 additions & 0 deletions internal/store/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package store

import (
"context"
"strings"

basemetrics "k8s.io/component-base/metrics"

Expand Down Expand Up @@ -289,6 +290,15 @@ func deploymentMetricFamilies(allowAnnotationsList, allowLabelsList []string) []
}
}),
),
*generator.NewFamilyGeneratorWithStability(
"kube_deployment_spec_affinity",
"Pod affinity and anti-affinity rules defined in the deployment's pod template specification.",
metric.Gauge,
basemetrics.ALPHA,
"",
wrapDeploymentFunc(generateDeploymentAffinityMetrics),
),

*generator.NewFamilyGeneratorWithStability(
"kube_deployment_metadata_generation",
"Sequence number representing a specific generation of the desired state.",
Expand Down Expand Up @@ -398,3 +408,74 @@ func createDeploymentListWatch(kubeClient clientset.Interface, ns string, fieldS
},
}
}
func generateDeploymentAffinityMetrics(d *v1.Deployment) *metric.Family {
var metrics []*metric.Metric

if d.Spec.Template.Spec.Affinity == nil {
return &metric.Family{Metrics: metrics}
}

// Handle pod affinity rules
if d.Spec.Template.Spec.Affinity.PodAffinity != nil {
// Required affinity rules
for _, rule := range d.Spec.Template.Spec.Affinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
labelSelector := formatLabelSelector(rule.LabelSelector)
namespaceSelector := formatLabelSelector(rule.NamespaceSelector)
namespaces := strings.Join(rule.Namespaces, ",")
metrics = append(metrics, &metric.Metric{
LabelKeys: []string{"affinity", "type", "topology_key", "label_selector", "namespace_selector", "namespaces"},
LabelValues: []string{"podaffinity", "requiredDuringSchedulingIgnoredDuringExecution", rule.TopologyKey, labelSelector, namespaceSelector, namespaces},
Value: 1,
})
}

// Preferred affinity rules
for _, rule := range d.Spec.Template.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution {
labelSelector := formatLabelSelector(rule.PodAffinityTerm.LabelSelector)
namespaceSelector := formatLabelSelector(rule.PodAffinityTerm.NamespaceSelector)
namespaces := strings.Join(rule.PodAffinityTerm.Namespaces, ",")
metrics = append(metrics, &metric.Metric{
LabelKeys: []string{"affinity", "type", "topology_key", "label_selector", "namespace_selector", "namespaces"},
LabelValues: []string{"podaffinity", "preferredDuringSchedulingIgnoredDuringExecution", rule.PodAffinityTerm.TopologyKey, labelSelector, namespaceSelector, namespaces},
Value: 1,
})
}
}

// Handle pod anti-affinity rules
if d.Spec.Template.Spec.Affinity.PodAntiAffinity != nil {
// Required anti-affinity rules
for _, rule := range d.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
labelSelector := formatLabelSelector(rule.LabelSelector)
namespaceSelector := formatLabelSelector(rule.NamespaceSelector)
namespaces := strings.Join(rule.Namespaces, ",")
metrics = append(metrics, &metric.Metric{
LabelKeys: []string{"affinity", "type", "topology_key", "label_selector", "namespace_selector", "namespaces"},
LabelValues: []string{"podantiaffinity", "requiredDuringSchedulingIgnoredDuringExecution", rule.TopologyKey, labelSelector, namespaceSelector, namespaces},
Value: 1,
})
}

// Preferred anti-affinity rules
for _, rule := range d.Spec.Template.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution {
labelSelector := formatLabelSelector(rule.PodAffinityTerm.LabelSelector)
namespaceSelector := formatLabelSelector(rule.PodAffinityTerm.NamespaceSelector)
namespaces := strings.Join(rule.PodAffinityTerm.Namespaces, ",")
metrics = append(metrics, &metric.Metric{
LabelKeys: []string{"affinity", "type", "topology_key", "label_selector", "namespace_selector", "namespaces"},
LabelValues: []string{"podantiaffinity", "preferredDuringSchedulingIgnoredDuringExecution", rule.PodAffinityTerm.TopologyKey, labelSelector, namespaceSelector, namespaces},
Value: 1,
})
}
}

return &metric.Family{Metrics: metrics}
}

// formatLabelSelector converts a LabelSelector to a string representation
func formatLabelSelector(selector *metav1.LabelSelector) string {
if selector == nil {
return ""
}
return metav1.FormatLabelSelector(selector)
}
Loading