Skip to content

Commit

Permalink
Use labels instead of separate metrics (#127)
Browse files Browse the repository at this point in the history
Signed-off-by: Antony Dovgal <[email protected]>
  • Loading branch information
tony2001 authored Feb 5, 2024
1 parent 18857bd commit 59a2759
Show file tree
Hide file tree
Showing 4 changed files with 399 additions and 60 deletions.
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,21 +232,21 @@ Usage of k8s-image-availability-exporter:

The following metrics for Prometheus are provided:

* `k8s_image_availability_exporter_<TYPE>_available` — non-zero indicates *successful* image check.
* `k8s_image_availability_exporter_<TYPE>_bad_image_format` — non-zero indicates incorrect `image` field format.
* `k8s_image_availability_exporter_<TYPE>_absent` — non-zero indicates an image's manifest absence from container registry.
* `k8s_image_availability_exporter_<TYPE>_registry_unavailable` — non-zero indicates general registry unavailiability, perhaps, due to network outage.
* `k8s_image_availability_exporter_deployment_registry_v1_api_not_supported` — non-zero indicates v1 Docker Registry API, these images are best ignored with `--ignored-images` cmdline parameter.
* `k8s_image_availability_exporter_<TYPE>_authentication_failure` — non-zero indicates authentication error to container registry, verify imagePullSecrets.
* `k8s_image_availability_exporter_<TYPE>_authorization_failure` — non-zero indicates authorization error to container registry, verify imagePullSecrets.
* `k8s_image_availability_exporter_<TYPE>_unknown_error` — non-zero indicates an error that failed to be classified, consult exporter's logs for additional information.

Each `<TYPE>` in the exporter's metrics name is replaced with the following values:

* `deployment`
* `statefulset`
* `daemonset`
* `cronjob`
* `k8s_image_availability_exporter_available` — non-zero indicates *successful* image check.
* `k8s_image_availability_exporter_absent` — non-zero indicates an image's manifest absence from container registry.
* `k8s_image_availability_exporter_bad_image_format` — non-zero indicates incorrect `image` field format.
* `k8s_image_availability_exporter_registry_unavailable` — non-zero indicates general registry unavailiability, perhaps, due to network outage.
* `k8s_image_availability_exporter_authentication_failure` — non-zero indicates authentication error to container registry, verify imagePullSecrets.
* `k8s_image_availability_exporter_authorization_failure` — non-zero indicates authorization error to container registry, verify imagePullSecrets.
* `k8s_image_availability_exporter_unknown_error` — non-zero indicates an error that failed to be classified, consult exporter's logs for additional information.

Each metric has the following labels:

* `namespace` - namespace name
* `container` - container name
* `image` - image URL in the registry
* `kind` - Kubernetes controller kind, namely `deployment`, `statefulset`, `daemonset` or `cronjob`
* `name` - controller name

## Compatibility

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,52 @@ spec:
rules:
- alert: DeploymentImageUnavailable
expr: |
max by (namespace, deployment, container, image) (
k8s_image_availability_exporter_deployment_available == 0
max by (namespace, name, container, image) (
k8s_image_availability_exporter_available{kind="deployment"} == 0
)
annotations:
message: >
Image {{`{{ $labels.image }}`}} from container {{`{{ $labels.container }}`}}
in deployment {{`{{ $labels.deployment }}`}}
in deployment {{`{{ $labels.name }}`}}
from namespace {{`{{ $labels.namespace }}`}}
is not available in docker registry.
labels:
severity: critical
- alert: StatefulSetImageUnavailable
expr: |
max by (namespace, statefulset, container, image) (
k8s_image_availability_exporter_statefulset_available == 0
max by (namespace, name, container, image) (
k8s_image_availability_exporter_available{kind="statefulset"} == 0
)
annotations:
message: >
Image {{`{{ $labels.image }}`}} from container {{`{{ $labels.container }}`}}
in statefulSet {{`{{ $labels.statefulset }}`}}
in statefulSet {{`{{ $labels.name }}`}}
from namespace {{`{{ $labels.namespace }}`}}
is not available in docker registry.
labels:
severity: critical
- alert: DaemonSetImageUnavailable
expr: |
max by (namespace, daemonset, container, image) (
k8s_image_availability_exporter_daemonset_available == 0
max by (namespace, name, container, image) (
k8s_image_availability_exporter_available{kind="daemonset"} == 0
)
annotations:
message: >
Image {{`{{ $labels.image }}`}} from container {{`{{ $labels.container }}`}}
in daemonSet {{`{{ $labels.daemonset }}`}}
in daemonSet {{`{{ $labels.name }}`}}
from namespace {{`{{ $labels.namespace }}`}}
is not available in docker registry.
labels:
severity: critical
- alert: CronJobImageUnavailable
expr: |
max by (namespace, cronjob, container, image) (
k8s_image_availability_exporter_cronjob_available == 0
max by (namespace, name, container, image) (
k8s_image_availability_exporter_available{kind="cronjob"} == 0
)
annotations:
message: >
Image {{`{{ $labels.image }}`}} from container {{`{{ $labels.container }}`}}
in cronJob {{`{{ $labels.cronjob }}`}}
in cronJob {{`{{ $labels.name }}`}}
from namespace {{`{{ $labels.namespace }}`}}
is not available in docker registry.
labels:
Expand Down
24 changes: 5 additions & 19 deletions pkg/store/image_store.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package store

import (
"fmt"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -217,35 +216,22 @@ func newNamedConstMetrics(ownerKind, ownerName, namespace, container, image stri
"namespace": namespace,
"container": container,
"image": image,
"kind": strings.ToLower(ownerKind),
"name": ownerName,
}

switch ownerKind {
case "Deployment":
labels["deployment"] = ownerName
return getMetricByControllerKind(ownerKind, labels, avalMode)
case "StatefulSet":
labels["statefulset"] = ownerName
return getMetricByControllerKind(ownerKind, labels, avalMode)
case "DaemonSet":
labels["daemonset"] = ownerName
return getMetricByControllerKind(ownerKind, labels, avalMode)
case "CronJob":
labels["cronjob"] = ownerName
return getMetricByControllerKind(ownerKind, labels, avalMode)
default:
panic(fmt.Sprintf("received unknown metric name: %s", ownerKind))
}
return getMetric(labels, avalMode)
}

func getMetricByControllerKind(controllerKind string, labels map[string]string, mode AvailabilityMode) (ret []prometheus.Metric) {
func getMetric(labels map[string]string, mode AvailabilityMode) (ret []prometheus.Metric) {
for availMode, desc := range AvailabilityModeDescMap {
var value float64
if availMode == mode {
value = 1
}

ret = append(ret, prometheus.MustNewConstMetric(
prometheus.NewDesc("k8s_image_availability_exporter_"+strings.ToLower(controllerKind)+"_"+desc, "", nil, labels),
prometheus.NewDesc("k8s_image_availability_exporter_"+desc, "", nil, labels),
prometheus.GaugeValue,
value,
))
Expand Down
Loading

0 comments on commit 59a2759

Please sign in to comment.