diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b4cebad1f..f305704827 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,8 @@ env: E2E_SETUP_KIND: yes E2E_SETUP_KUBECTL: yes SUDO: sudo - GO_VERSION: "^1.21" - GOLANGCI_LINT_VERSION: "v1.54.2" + GO_VERSION: "^1.22" + GOLANGCI_LINT_VERSION: "v1.56.2" jobs: ci-go-lint: @@ -29,10 +29,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -51,10 +51,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -72,10 +72,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -93,10 +93,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -114,10 +114,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -135,7 +135,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup promtool run: | @@ -150,10 +150,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -171,10 +171,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go @@ -192,10 +192,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} id: go diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index 58ad384559..5ed80784e4 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -6,7 +6,7 @@ on: - cron: '0 0 * * 1' env: - GO_VERSION: "^1.21" + GO_VERSION: "^1.22" permissions: contents: read @@ -15,10 +15,10 @@ jobs: ci-security-checks: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 name: Checkout code - name: Set up Go 1.x - uses: actions/setup-go@v5 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ env.GO_VERSION }} - name: Install govulncheck binary diff --git a/.github/workflows/openvex.yml b/.github/workflows/openvex.yml index c76c425d38..5b80fa92b2 100644 --- a/.github/workflows/openvex.yml +++ b/.github/workflows/openvex.yml @@ -3,17 +3,35 @@ name: openvex on: workflow_dispatch: release: - types: [published] + types: + - released + +permissions: + contents: read + jobs: vexctl: runs-on: ubuntu-latest + + permissions: + contents: write + steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Set environment variables run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - uses: openvex/generate-vex@c59881b41451d7ccba5c3b74cd195382b8971fcd # Refer: https://github.com/openvex/vexctl#operational-model name: Run vexctl with: product: pkg:golang/k8s.io/kube-state-metrics/v2@${{ env.RELEASE_VERSION }} + file: kube-state-metrics.openvex.json + + - name: Upload OpenVEX document to GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ env.RELEASE_VERSION }} kube-state-metrics.openvex.json diff --git a/.github/workflows/sbom.yaml b/.github/workflows/sbom.yaml new file mode 100644 index 0000000000..73949a0204 --- /dev/null +++ b/.github/workflows/sbom.yaml @@ -0,0 +1,41 @@ +name: Generate SBOM with Kubernetes BOM + +on: + release: + types: + - released + +permissions: + contents: read + +jobs: + sbom: + runs-on: ubuntu-latest + + permissions: + contents: write + + env: + OUTPUT: sbom.spdx + TAG: ${{ github.event.release.tag_name }} + + steps: + - name: Fetch source code into GITHUB_WORKSPACE + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Install Kubernetes BOM + uses: kubernetes-sigs/release-actions/setup-bom@2f8b9ec22aedc9ce15039b6c7716aa6c2907df1c # v0.2.0 + + - name: Generate SBOM + run: | + bom generate \ + --dirs=. \ + --image=registry.k8s.io/kube-state-metrics/kube-state-metrics:$TAG \ + --namespace=https://github.com/kubernetes/kube-state-metrics/releases/download/$TAG/$OUTPUT + --output=$OUTPUT + + - name: Upload SBOM to GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload $TAG $OUTPUT diff --git a/.github/workflows/semantic.yml b/.github/workflows/semantic.yml index c2f6094adb..ad62ec05d3 100644 --- a/.github/workflows/semantic.yml +++ b/.github/workflows/semantic.yml @@ -18,6 +18,6 @@ jobs: name: Validate PR title for semantic commit message runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v5 + - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.golangci.yml b/.golangci.yml index d7acc58f39..edbd40a820 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ run: - deadline: 5m + deadline: 10m linters: disable-all: true diff --git a/CHANGELOG.md b/CHANGELOG.md index fb8e66c011..97397f9ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## v2.13.0 / 2024-07-18 + +### Note + +* This release builds with Golang `v1.22.5`. +* This release builds with `k8s.io/client-go`: `v0.30.3`. +* This release adds read and write timeouts for requests. The defaults might have an impact on scrapes that take a long time. + +* [BUGFIX] Pod autosharding: transition from labelselector to fieldselector by @pkoutsovasilis in +* [ENHANCEMENT] Add automatic detection of memory limits by @SuperQ in +* [FEATURE] Add `readyz` endpoint by @rexagod in +* [FEATURE] Add `livez` endpoint by @rexagod in +* [FEATURE] Add kube_persistentvolume_volume_mode metric by @ricardoapl in +* [FEATURE] Add read and write timeouts by @Pokom in + ## v2.12.0 / 2024-04-02 ### Note diff --git a/Dockerfile b/Dockerfile index 798ac7e656..d8899a7ae3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG GOVERSION=1.21 +ARG GOVERSION=1.22 ARG GOARCH FROM golang:${GOVERSION} as builder ARG GOARCH diff --git a/Makefile b/Makefile index 61736eaf5f..467b73e6b0 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,9 @@ FLAGS = TESTENVVAR = REGISTRY ?= gcr.io/k8s-staging-kube-state-metrics TAG_PREFIX = v -VERSION = $(shell cat VERSION) +VERSION = $(shell gomplate -d config=./data.yaml --in '{{ (datasource "config").version }}') TAG ?= $(TAG_PREFIX)$(VERSION) -LATEST_RELEASE_BRANCH := release-$(shell grep -ohE "[0-9]+.[0-9]+" VERSION) +LATEST_RELEASE_BRANCH := release-$(shell echo $(VERSION) | grep -ohE "[0-9]+.[0-9]+") BRANCH = $(strip $(shell git rev-parse --abbrev-ref HEAD)) DOCKER_CLI ?= docker PROMTOOL_CLI ?= promtool @@ -15,13 +15,13 @@ GIT_COMMIT ?= $(shell git rev-parse --short HEAD) OS ?= $(shell uname -s | tr A-Z a-z) ALL_ARCH = amd64 arm arm64 ppc64le s390x PKG = github.com/prometheus/common -PROMETHEUS_VERSION = 2.46.0 -GO_VERSION = 1.21.8 +PROMETHEUS_VERSION = 2.53.1 +GO_VERSION = 1.22.5 IMAGE = $(REGISTRY)/kube-state-metrics MULTI_ARCH_IMG = $(IMAGE)-$(ARCH) USER ?= $(shell id -u -n) HOST ?= $(shell hostname) -MARKDOWNLINT_CLI2_VERSION = 0.9.2 +MARKDOWNLINT_CLI2_VERSION = 0.13.0 export DOCKER_CLI_EXPERIMENTAL=enabled @@ -48,19 +48,19 @@ lint: shellcheck licensecheck lint-markdown-format lint-fix: fix-markdown-format golangci-lint run --fix -v - + doccheck: generate validate-template @echo "- Checking if the generated documentation is up to date..." @git diff --exit-code @echo "- Checking if the documentation is in sync with the code..." - @grep -hoE -d skip '\| kube_[^ |]+' docs/* --exclude=README.md | sed -E 's/\| //g' | sort -u > documented_metrics + @grep -rhoE '\| kube_[^ |]+' docs/metrics/* --exclude=README.md | sed -E 's/\| //g' | sort -u > documented_metrics @find internal/store -type f -not -name '*_test.go' -exec sed -nE 's/.*"(kube_[^"]+)".*/\1/p' {} \; | sort -u > code_metrics @diff -u0 code_metrics documented_metrics || (echo "ERROR: Metrics with - are present in code but missing in documentation, metrics with + are documented but not found in code."; exit 1) @echo OK @rm -f code_metrics documented_metrics @echo "- Checking for orphan documentation files" - @cd docs; for doc in *.md; do if [ "$$doc" != "README.md" ] && ! grep -q "$$doc" *.md; then echo "ERROR: No link to documentation file $${doc} detected"; exit 1; fi; done + @cd docs; for doc in $$(find metrics/* -name '*.md' | sed 's/.*\///'); do if [ "$$doc" != "README.md" ] && ! grep -q "$$doc" *.md; then echo "ERROR: No link to documentation file $${doc} detected"; exit 1; fi; done @echo OK build-local: @@ -151,17 +151,17 @@ examples/prometheus-alerting-rules/alerts.yaml: jsonnet $(shell find jsonnet | g examples: examples/standard examples/autosharding examples/daemonsetsharding mixin -examples/standard: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/standard.jsonnet scripts/vendor VERSION +examples/standard: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/standard.jsonnet scripts/vendor mkdir -p examples/standard jsonnet -J scripts/vendor -m examples/standard --ext-str version="$(VERSION)" scripts/standard.jsonnet | xargs -I{} sh -c 'cat {} | gojsontoyaml > `echo {} | sed "s/\(.\)\([A-Z]\)/\1-\2/g" | tr "[:upper:]" "[:lower:]"`.yaml' -- {} find examples -type f ! -name '*.yaml' -delete -examples/autosharding: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/autosharding.jsonnet scripts/vendor VERSION +examples/autosharding: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/autosharding.jsonnet scripts/vendor mkdir -p examples/autosharding jsonnet -J scripts/vendor -m examples/autosharding --ext-str version="$(VERSION)" scripts/autosharding.jsonnet | xargs -I{} sh -c 'cat {} | gojsontoyaml > `echo {} | sed "s/\(.\)\([A-Z]\)/\1-\2/g" | tr "[:upper:]" "[:lower:]"`.yaml' -- {} find examples -type f ! -name '*.yaml' -delete -examples/daemonsetsharding: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/daemonsetsharding.jsonnet scripts/vendor VERSION +examples/daemonsetsharding: jsonnet $(shell find jsonnet | grep ".libsonnet") scripts/daemonsetsharding.jsonnet scripts/vendor mkdir -p examples/daemonsetsharding jsonnet -J scripts/vendor -m examples/daemonsetsharding --ext-str version="$(VERSION)" scripts/daemonsetsharding.jsonnet | xargs -I{} sh -c 'cat {} | gojsontoyaml > `echo {} | sed "s/\(.\)\([A-Z]\)/\1-\2/g" | tr "[:upper:]" "[:lower:]"`.yaml' -- {} find examples -type f ! -name '*.yaml' -delete diff --git a/OWNERS b/OWNERS index 68b33e94dd..c7dcbf11c7 100644 --- a/OWNERS +++ b/OWNERS @@ -1,17 +1,17 @@ -approvers: -- dislbenn -- marcolan018 -- subbarao-meduri -- bjoydeep -- saswatamcode -- philipgough -- douglascamata -- coleenquadros -- thibaultmg -- moadz -- jacobbaungard reviewers: -- clyang82 -- haoqing0110 -- morvencao -- ngraham20 + - CatherineF-dev + - dgrisonnet + - logicalhan + - mrueg + - rexagod +approvers: + - dgrisonnet + - mrueg + - rexagod +emeritus_approvers: + - LiliC + - andyxning + - brancz + - tariq1890 + - zouyee + - fpetkovski diff --git a/README.md b/README.md index 21e5499343..762ea413ab 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/kube-state-metrics)](https://goreportcard.com/report/github.com/kubernetes/kube-state-metrics) [![Go Reference](https://pkg.go.dev/badge/github.com/kubernetes/kube-state-metrics.svg)](https://pkg.go.dev/github.com/kubernetes/kube-state-metrics) [![govulncheck](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml/badge.svg)](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8696/badge)](https://www.bestpractices.dev/projects/8696) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/kubernetes/kube-state-metrics/badge)](https://api.securityscorecards.dev/projects/github.com/kubernetes/kube-state-metrics) kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API @@ -59,6 +60,7 @@ are deleted they are no longer visible on the `/metrics` endpoint. * [Helm Chart](#helm-chart) * [Development](#development) * [Developer Contributions](#developer-contributions) + * [Community](#community) ### Versioning @@ -77,12 +79,12 @@ Generally, it is recommended to use the latest release of kube-state-metrics. If | kube-state-metrics | Kubernetes client-go Version | |--------------------|:----------------------------:| -| **v2.8.2** | v1.26 | | **v2.9.2** | v1.26 | | **v2.10.1** | v1.27 | | **v2.11.0** | v1.28 | | **v2.12.0** | v1.29 | -| **main** | v1.29 | +| **v2.13.0** | v1.30 | +| **main** | v1.30 | #### Resource group version compatibility @@ -94,8 +96,8 @@ release. The latest container image can be found at: -* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) -* View all multi-architecture images at [here](https://explore.ggcr.dev/?image=registry.k8s.io%2Fkube-state-metrics%2Fkube-state-metrics:v2.12.0) +* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) +* View all multi-architecture images at [here](https://explore.ggcr.dev/?image=registry.k8s.io%2Fkube-state-metrics%2Fkube-state-metrics:v2.13.0) ### Metrics Documentation @@ -204,7 +206,7 @@ In a 100 node cluster scaling test the latency numbers were as follows: ### A note on costing -By default, kube-state-metrics exposes several metrics for events across your cluster. If you have a large number of frequently-updating resources on your cluster, you may find that a lot of data is ingested into these metrics. This can incur high costs on some cloud providers. Please take a moment to [configure what metrics you'd like to expose](docs/cli-arguments.md), as well as consult the documentation for your Kubernetes environment in order to avoid unexpectedly high costs. +By default, kube-state-metrics exposes several metrics for events across your cluster. If you have a large number of frequently-updating resources on your cluster, you may find that a lot of data is ingested into these metrics. This can incur high costs on some cloud providers. Please take a moment to [configure what metrics you'd like to expose](docs/developer/cli-arguments.md), as well as consult the documentation for your Kubernetes environment in order to avoid unexpectedly high costs. ### kube-state-metrics vs. metrics-server @@ -342,6 +344,16 @@ Note that your GCP identity is case sensitive but `gcloud info` as of Google Clo After running the above, if you see `Clusterrolebinding "cluster-admin-binding" created`, then you are able to continue with the setup of this service. +#### Healthcheck Endpoints + +The following healthcheck endpoints are available (`self` refers to the telemetry port, while `main` refers to the exposition port): + +* `/healthz` (exposed on `main`): Returns a 200 status code if the application is running. We recommend to use this for the startup probe. +* `/livez` (exposed on `main`): Returns a 200 status code if the application is not affected by an outage of the Kubernetes API Server. We recommend to using this for the liveness probe. +* `/readyz` (exposed on `self`): Returns a 200 status code if the application is ready to accept requests and expose metrics. We recommend using this for the readiness probe. + +Note that it is discouraged to use the telemetry metrics endpoint for any probe when proxying the exposition data. + #### Limited privileges environment If you want to run kube-state-metrics in an environment where you don't have cluster-reader role, you can: @@ -387,7 +399,11 @@ spec: - '--namespaces=project1' ``` -For the full list of arguments available, see the documentation in [docs/cli-arguments.md](./docs/cli-arguments.md) +For the full list of arguments available, see the documentation in [docs/developer/cli-arguments.md](./docs/developer/cli-arguments.md) + +#### Helm Chart + +Starting from the kube-state-metrics chart `v2.13.3` (kube-state-metrics image `v1.9.8`), the official [Helm chart](https://artifacthub.io/packages/helm/prometheus-community/kube-state-metrics/) is maintained in [prometheus-community/helm-charts](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics). Starting from kube-state-metrics chart `v3.0.0` only kube-state-metrics images of `v2.0.0 +` are supported. #### Helm Chart @@ -412,3 +428,15 @@ To run the e2e tests locally see the documentation in [tests/README.md](./tests/ #### Developer Contributions When developing, there are certain code patterns to follow to better your contributing experience and likelihood of e2e and other ci tests to pass. To learn more about them, see the documentation in [docs/developer/guide.md](./docs/developer/guide.md). + +#### Community + +This project is sponsored by [SIG Instrumentation](https://github.com/kubernetes/community/tree/master/sig-instrumentation). + +There is also a channel for [#kube-state-metrics](https://kubernetes.slack.com/archives/CJJ529RUY) on Kubernetes' Slack. + +You can also join the SIG Instrumentation [mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-instrumentation). +This will typically add invites for the following meetings to your calendar, in which topics around kube-state-metrics can be discussed. + +* Regular SIG Meeting: [Thursdays at 9:30 PT (Pacific Time)](https://zoom.us/j/5342565819?pwd=RlVsK21NVnR1dmE3SWZQSXhveHZPdz09) (biweekly). [Convert to your timezone](http://www.thetimezoneconverter.com/?t=9:30&tz=PT%20%28Pacific%20Time%29). +* Regular Triage Meeting: [Thursdays at 9:30 PT (Pacific Time)](https://zoom.us/j/5342565819?pwd=RlVsK21NVnR1dmE3SWZQSXhveHZPdz09) (biweekly - alternating with regular meeting). [Convert to your timezone](http://www.thetimezoneconverter.com/?t=9:30&tz=PT%20%28Pacific%20Time%29). diff --git a/README.md.tpl b/README.md.tpl index 18d498d521..5548b022f5 100644 --- a/README.md.tpl +++ b/README.md.tpl @@ -4,6 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/kube-state-metrics)](https://goreportcard.com/report/github.com/kubernetes/kube-state-metrics) [![Go Reference](https://pkg.go.dev/badge/github.com/kubernetes/kube-state-metrics.svg)](https://pkg.go.dev/github.com/kubernetes/kube-state-metrics) [![govulncheck](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml/badge.svg)](https://github.com/kubernetes/kube-state-metrics/actions/workflows/govulncheck.yml) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8696/badge)](https://www.bestpractices.dev/projects/8696) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/kubernetes/kube-state-metrics/badge)](https://api.securityscorecards.dev/projects/github.com/kubernetes/kube-state-metrics) kube-state-metrics (KSM) is a simple service that listens to the Kubernetes API @@ -59,6 +60,7 @@ are deleted they are no longer visible on the `/metrics` endpoint. * [Helm Chart](#helm-chart) * [Development](#development) * [Developer Contributions](#developer-contributions) + * [Community](#community) ### Versioning @@ -205,7 +207,7 @@ In a 100 node cluster scaling test the latency numbers were as follows: ### A note on costing -By default, kube-state-metrics exposes several metrics for events across your cluster. If you have a large number of frequently-updating resources on your cluster, you may find that a lot of data is ingested into these metrics. This can incur high costs on some cloud providers. Please take a moment to [configure what metrics you'd like to expose](docs/cli-arguments.md), as well as consult the documentation for your Kubernetes environment in order to avoid unexpectedly high costs. +By default, kube-state-metrics exposes several metrics for events across your cluster. If you have a large number of frequently-updating resources on your cluster, you may find that a lot of data is ingested into these metrics. This can incur high costs on some cloud providers. Please take a moment to [configure what metrics you'd like to expose](docs/developer/cli-arguments.md), as well as consult the documentation for your Kubernetes environment in order to avoid unexpectedly high costs. ### kube-state-metrics vs. metrics-server @@ -343,6 +345,16 @@ Note that your GCP identity is case sensitive but `gcloud info` as of Google Clo After running the above, if you see `Clusterrolebinding "cluster-admin-binding" created`, then you are able to continue with the setup of this service. +#### Healthcheck Endpoints + +The following healthcheck endpoints are available (`self` refers to the telemetry port, while `main` refers to the exposition port): + +* `/healthz` (exposed on `main`): Returns a 200 status code if the application is running. We recommend to use this for the startup probe. +* `/livez` (exposed on `main`): Returns a 200 status code if the application is not affected by an outage of the Kubernetes API Server. We recommend to using this for the liveness probe. +* `/readyz` (exposed on `self`): Returns a 200 status code if the application is ready to accept requests and expose metrics. We recommend using this for the readiness probe. + +Note that it is discouraged to use the telemetry metrics endpoint for any probe when proxying the exposition data. + #### Limited privileges environment If you want to run kube-state-metrics in an environment where you don't have cluster-reader role, you can: @@ -388,7 +400,7 @@ spec: - '--namespaces=project1' ``` -For the full list of arguments available, see the documentation in [docs/cli-arguments.md](./docs/cli-arguments.md) +For the full list of arguments available, see the documentation in [docs/developer/cli-arguments.md](./docs/developer/cli-arguments.md) #### Helm Chart @@ -413,3 +425,15 @@ To run the e2e tests locally see the documentation in [tests/README.md](./tests/ #### Developer Contributions When developing, there are certain code patterns to follow to better your contributing experience and likelihood of e2e and other ci tests to pass. To learn more about them, see the documentation in [docs/developer/guide.md](./docs/developer/guide.md). + +#### Community + +This project is sponsored by [SIG Instrumentation](https://github.com/kubernetes/community/tree/master/sig-instrumentation). + +There is also a channel for [#kube-state-metrics](https://kubernetes.slack.com/archives/CJJ529RUY) on Kubernetes' Slack. + +You can also join the SIG Instrumentation [mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-instrumentation). +This will typically add invites for the following meetings to your calendar, in which topics around kube-state-metrics can be discussed. + +* Regular SIG Meeting: [Thursdays at 9:30 PT (Pacific Time)](https://zoom.us/j/5342565819?pwd=RlVsK21NVnR1dmE3SWZQSXhveHZPdz09) (biweekly). [Convert to your timezone](http://www.thetimezoneconverter.com/?t=9:30&tz=PT%20%28Pacific%20Time%29). +* Regular Triage Meeting: [Thursdays at 9:30 PT (Pacific Time)](https://zoom.us/j/5342565819?pwd=RlVsK21NVnR1dmE3SWZQSXhveHZPdz09) (biweekly - alternating with regular meeting). [Convert to your timezone](http://www.thetimezoneconverter.com/?t=9:30&tz=PT%20%28Pacific%20Time%29). diff --git a/RELEASE.md b/RELEASE.md index 968c3be8b5..97e4419a68 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -14,10 +14,11 @@ Maintaining the release branches for older minor releases happens on a best effo ## Prepare your release -* Bump the version in the `VERSION` file in the root of the repository. +* Update the [data.yaml](data.yaml) + * Update the compat list + * Update the version key to refer to your new release * Run `make examples`, which will re-generate all example manifests to use the new version. * Make a PR to update: - * Update the [[`data.yaml`](data.yaml) * Run `make generate`, which will update the compatibility matrix in README.md * Changelog entry * Only include user relevant changes diff --git a/SECURITY-INSIGHTS.yml b/SECURITY-INSIGHTS.yml index 619041dc6b..0750830c69 100644 --- a/SECURITY-INSIGHTS.yml +++ b/SECURITY-INSIGHTS.yml @@ -32,6 +32,8 @@ dependencies: dependencies-lists: - https://github.com/kubernetes/kube-state-metrics/blob/main/go.mod - https://github.com/kubernetes/kube-state-metrics/blob/main/Dockerfile + env-dependencies-policy: + policy-url: https://github.com/kubernetes/kube-state-metrics/blob/main/docs/dependencies-policy.md documentation: - https://github.com/kubernetes/kube-state-metrics/tree/main/docs security-testing: diff --git a/data.yaml b/data.yaml index 7b1bcf9a30..a5876cd726 100644 --- a/data.yaml +++ b/data.yaml @@ -1,7 +1,10 @@ +# The purpose of this config is to keep all versions in a single file and make them machine accessible + +# Marks the latest release +version: "2.13.0" + # List at max 5 releases here + the main branch compat: - - version: "v2.8.2" - kubernetes: "1.26" - version: "v2.9.2" kubernetes: "1.26" - version: "v2.10.1" @@ -10,5 +13,7 @@ compat: kubernetes: "1.28" - version: "v2.12.0" kubernetes: "1.29" + - version: "v2.13.0" + kubernetes: "1.30" - version: "main" - kubernetes: "1.29" + kubernetes: "1.30" diff --git a/docs/README.md b/docs/README.md index e871e09c78..08d3f91118 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,44 +32,44 @@ See each file for specific documentation about the exposed metrics: ### Default Resources -* [CertificateSigningRequest Metrics](certificatesigningrequest-metrics.md) -* [ConfigMap Metrics](configmap-metrics.md) -* [CronJob Metrics](cronjob-metrics.md) -* [DaemonSet Metrics](daemonset-metrics.md) -* [Deployment Metrics](deployment-metrics.md) -* [Endpoint Metrics](endpoint-metrics.md) -* [Horizontal Pod Autoscaler Metrics](horizontalpodautoscaler-metrics.md) -* [Ingress Metrics](ingress-metrics.md) -* [Job Metrics](job-metrics.md) -* [Lease Metrics](lease-metrics.md) -* [LimitRange Metrics](limitrange-metrics.md) -* [MutatingWebhookConfiguration Metrics](mutatingwebhookconfiguration-metrics.md) -* [Namespace Metrics](namespace-metrics.md) -* [NetworkPolicy Metrics](networkpolicy-metrics.md) -* [Node Metrics](node-metrics.md) -* [PersistentVolume Metrics](persistentvolume-metrics.md) -* [PersistentVolumeClaim Metrics](persistentvolumeclaim-metrics.md) -* [Pod Disruption Budget Metrics](poddisruptionbudget-metrics.md) -* [Pod Metrics](pod-metrics.md) -* [ReplicaSet Metrics](replicaset-metrics.md) -* [ReplicationController Metrics](replicationcontroller-metrics.md) -* [ResourceQuota Metrics](resourcequota-metrics.md) -* [Secret Metrics](secret-metrics.md) -* [Service Metrics](service-metrics.md) -* [StatefulSet Metrics](statefulset-metrics.md) -* [StorageClass Metrics](storageclass-metrics.md) -* [ValidatingWebhookConfiguration Metrics](validatingwebhookconfiguration-metrics.md) -* [VolumeAttachment Metrics](volumeattachment-metrics.md) +* [CertificateSigningRequest Metrics](metrics/auth/certificatesigningrequest-metrics.md) +* [ConfigMap Metrics](metrics/storage/configmap-metrics.md) +* [CronJob Metrics](metrics/workload/cronjob-metrics.md) +* [DaemonSet Metrics](metrics/workload/daemonset-metrics.md) +* [Deployment Metrics](metrics/workload/deployment-metrics.md) +* [Endpoint Metrics](metrics/service/endpoint-metrics.md) +* [Horizontal Pod Autoscaler Metrics](metrics/workload/horizontalpodautoscaler-metrics.md) +* [Ingress Metrics](metrics/service/ingress-metrics.md) +* [Job Metrics](metrics/workload/job-metrics.md) +* [Lease Metrics](metrics/cluster/lease-metrics.md) +* [LimitRange Metrics](metrics/policy/limitrange-metrics.md) +* [MutatingWebhookConfiguration Metrics](metrics/extend/mutatingwebhookconfiguration-metrics.md) +* [Namespace Metrics](metrics/cluster/namespace-metrics.md) +* [NetworkPolicy Metrics](metrics/policy/networkpolicy-metrics.md) +* [Node Metrics](metrics/cluster/node-metrics.md) +* [PersistentVolume Metrics](metrics/storage/persistentvolume-metrics.md) +* [PersistentVolumeClaim Metrics](metrics/storage/persistentvolumeclaim-metrics.md) +* [Pod Disruption Budget Metrics](metrics/policy/poddisruptionbudget-metrics.md) +* [Pod Metrics](metrics/workload/pod-metrics.md) +* [ReplicaSet Metrics](metrics/workload/replicaset-metrics.md) +* [ReplicationController Metrics](metrics/workload/replicationcontroller-metrics.md) +* [ResourceQuota Metrics](metrics/policy/resourcequota-metrics.md) +* [Secret Metrics](metrics/storage/secret-metrics.md) +* [Service Metrics](metrics/service/service-metrics.md) +* [StatefulSet Metrics](metrics/workload/statefulset-metrics.md) +* [StorageClass Metrics](metrics/storage/storageclass-metrics.md) +* [ValidatingWebhookConfiguration Metrics](metrics/extend/validatingwebhookconfiguration-metrics.md) +* [VolumeAttachment Metrics](metrics/storage/volumeattachment-metrics.md) ### Optional Resources -* [ClusterRole Metrics](clusterrole-metrics.md) -* [ClusterRoleBinding Metrics](clusterrolebinding-metrics.md) -* [EndpointSlice Metrics](endpointslice-metrics.md) -* [IngressClass Metrics](ingressclass-metrics.md) -* [Role Metrics](role-metrics.md) -* [RoleBinding Metrics](rolebinding-metrics.md) -* [ServiceAccount Metrics](serviceaccount-metrics.md) +* [ClusterRole Metrics](metrics/cluster/clusterrole-metrics.md) +* [ClusterRoleBinding Metrics](metrics/cluster/clusterrolebinding-metrics.md) +* [EndpointSlice Metrics](metrics/service/endpointslice-metrics.md) +* [IngressClass Metrics](metrics/service/ingressclass-metrics.md) +* [Role Metrics](metrics/auth/role-metrics.md) +* [RoleBinding Metrics](metrics/auth/rolebinding-metrics.md) +* [ServiceAccount Metrics](metrics/auth/serviceaccount-metrics.md) ## Join Metrics @@ -92,8 +92,8 @@ sum(kube_pod_container_resource_requests{resource="memory"}) by (namespace, pod, ## Metrics from Custom Resources -See [Custom Resource State Metrics](customresourcestate-metrics.md) for experimental support for custom resources. +See [Custom Resource State Metrics](metrics/extend/customresourcestate-metrics.md) for experimental support for custom resources. ## CLI Arguments -Additionally, options for `kube-state-metrics` can be passed when executing as a CLI, or in a kubernetes / openshift environment. More information can be found here: [CLI Arguments](cli-arguments.md) +Additionally, options for `kube-state-metrics` can be passed when executing as a CLI, or in a kubernetes / openshift environment. More information can be found here: [CLI Arguments](developer/cli-arguments.md) diff --git a/docs/dependencies-policy.md b/docs/dependencies-policy.md new file mode 100644 index 0000000000..d1e0d5e945 --- /dev/null +++ b/docs/dependencies-policy.md @@ -0,0 +1,43 @@ +# Dependencies Policy + +## Purpose + +This policy describes how kube-state-metrics maintainers consume third-party packages. + +## Scope + +This policy applies to all kube-state-metrics maintainers and all third-party packages used in the kube-state-metrics project. + +## Policy + +kube-state-metrics maintainers must follow these guidelines when consuming third-party packages: + +* Only use third-party packages that are necessary for the functionality of kube-state-metrics. +* Use the latest version of all third-party packages whenever possible. +* Avoid using third-party packages that are known to have security vulnerabilities. +* Pin all third-party packages to specific versions in the kube-state-metrics codebase. +* Use a dependency management tool, such as Go modules, to manage third-party dependencies. + +## Procedure + +When adding a new third-party package to kube-state-metrics, maintainers must follow these steps: + +1. Evaluate the need for the package. Is it necessary for the functionality of kube-state-metrics? +2. Research the package. Is it actively maintained? Does it have a good reputation? +3. Choose a version of the package. Use the latest version whenever possible. +4. Pin the package to the specific version in the kube-state-metrics codebase. +5. Update the kube-state-metrics documentation to reflect the new dependency. + +## Enforcement + +This policy is enforced by the kube-state-metrics maintainers. + +Maintainers are expected to review each other's code changes to ensure that they comply with this policy. + +## Exceptions + +Exceptions to this policy may be granted by the kube-state-metrics project owners on a case-by-case basis. + +## Credits + +This policy was adapted from Kubescape's [Environment Dependencies Policy](https://github.com/kubescape/kubescape/blob/master/docs/environment-dependencies-policy.md). diff --git a/docs/developer/cli-arguments.md b/docs/developer/cli-arguments.md new file mode 100644 index 0000000000..7f4996a645 --- /dev/null +++ b/docs/developer/cli-arguments.md @@ -0,0 +1,91 @@ +# Command line arguments + +kube-state-metrics can be configured through command line arguments. + +Those arguments can be passed during startup when running locally: + +`kube-state-metrics --telemetry-port=8081 --kubeconfig= --apiserver= ...` + +Or configured in the `args` section of your deployment configuration in a Kubernetes / Openshift context: + +```yaml +spec: + template: + spec: + containers: + - args: + - '--telemetry-port=8081' + - '--kubeconfig=' + - '--apiserver=' +``` + +## Available options + + + +[embedmd]:# (../../help.txt) +```txt +$ kube-state-metrics -h +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. + +Usage: + kube-state-metrics [flags] + kube-state-metrics [command] + +Available Commands: + completion Generate completion script for kube-state-metrics. + help Help about any command + version Print version information. + +Flags: + --add_dir_header If true, adds the file directory to the header of the log messages + --alsologtostderr log to standard error as well as files (no effect when -logtostderr=true) + --apiserver string The URL of the apiserver to use as a master + --auto-gomemlimit Automatically set GOMEMLIMIT to match container or system memory limit. (experimental) + --auto-gomemlimit-ratio float The ratio of reserved GOMEMLIMIT memory to the detected maximum container or system memory. (experimental) (default 0.9) + --config string Path to the kube-state-metrics options config file + --custom-resource-state-config string Inline Custom Resource State Metrics config YAML (experimental) + --custom-resource-state-config-file string Path to a Custom Resource State Metrics config file (experimental) + --custom-resource-state-only Only provide Custom Resource State metrics (experimental) + --enable-gzip-encoding Gzip responses when requested by clients via 'Accept-Encoding: gzip' header. + -h, --help Print Help text + --host string Host to expose metrics on. (default "::") + --kubeconfig string Absolute path to the kubeconfig file + --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) + --log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true) + --log_file string If non-empty, use this log file (no effect when -logtostderr=true) + --log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + --logtostderr log to standard error instead of files (default true) + --metric-allowlist string Comma-separated list of metrics to be exposed. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive. + --metric-annotations-allowlist string Comma-separated list of Kubernetes annotations keys that will be used in the resource' labels metric. By default the annotations metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. A single '*' can be provided per resource instead to allow any annotations, but that has severe performance implications (Example: '=pods=[*]'). + --metric-denylist string Comma-separated list of metrics not to be enabled. This list comprises of exact metric names and/or regex patterns. The allowlist and denylist are mutually exclusive. + --metric-labels-allowlist string Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the labels metrics are not exposed. To include them, provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (Example: '=pods=[*]'). Additionally, an asterisk (*) can be provided as a key, which will resolve to all resources, i.e., assuming '--resources=deployments,pods', '=*=[*]' will resolve to '=deployments=[*],pods=[*]'. + --metric-opt-in-list string Comma-separated list of metrics which are opt-in and not enabled by default. This is in addition to the metric allow- and denylists + --namespaces string Comma-separated list of namespaces to be enabled. Defaults to "" + --namespaces-denylist string Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, only namespaces that are excluded in namespaces-denylist will be used. + --node string Name of the node that contains the kube-state-metrics pod. Most likely it should be passed via the downward API. This is used for daemonset sharding. Only available for resources (pod metrics) that support spec.nodeName fieldSelector. This is experimental. + --one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) + --pod string Name of the pod that contains the kube-state-metrics container. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. + --pod-namespace string Name of the namespace of the pod specified by --pod. When set, it is expected that --pod and --pod-namespace are both set. Most likely this should be passed via the downward API. This is used for auto-detecting sharding. If set, this has preference over statically configured sharding. This is experimental, it may be removed without notice. + --port int Port to expose metrics on. (default 8080) + --resources string Comma-separated list of Resources to be enabled. Defaults to "certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments" + --server-idle-timeout duration The maximum amount of time to wait for the next request when keep-alives are enabled. Align with the idletimeout of your scrape clients. (default 5m0s) + --server-read-header-timeout duration The maximum duration for reading the header of requests. (default 5s) + --server-read-timeout duration The maximum duration for reading the entire request, including the body. Align with the scrape interval or timeout of scraping clients. (default 1m0s) + --server-write-timeout duration The maximum duration before timing out writes of the response. Align with the scrape interval or timeout of scraping clients.. (default 1m0s) + --shard int32 The instances shard nominal (zero indexed) within the total number of shards. (default 0) + --skip_headers If true, avoid header prefixes in the log messages + --skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true) + --stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true) (default 2) + --telemetry-host string Host to expose kube-state-metrics self metrics on. (default "::") + --telemetry-port int Port to expose kube-state-metrics self metrics on. (default 8081) + --tls-config string Path to the TLS configuration file + --total-shards int The total number of shards. Sharding is disabled when total shards is set to 1. (default 1) + --use-apiserver-cache Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read. + -v, --v Level number for the log level verbosity + --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging + +Use "kube-state-metrics [command] --help" for more information about a command. +``` + + diff --git a/docs/developer/guide.md b/docs/developer/guide.md index b93f715001..276a676874 100644 --- a/docs/developer/guide.md +++ b/docs/developer/guide.md @@ -12,15 +12,15 @@ Any contribution to improving this documentation will be appreciated. The following steps are needed to introduce a new resource and its respective resource metrics. -* Reference your new resource(s) to the [docs/README.md](https://github.com/kubernetes/kube-state-metrics/blob/main/docs/README.md#exposed-metrics). -* Reference your new resource(s) in the [docs/cli-arguments.md](https://github.com/kubernetes/kube-state-metrics/blob/main/docs/cli-arguments.md#available-options) as part of the `--resources` flag. -* Create a new `.md` in the [docs](https://github.com/kubernetes/kube-state-metrics/tree/main/docs) directory to provide documentation on the resource(s) and metrics you implemented. Follow the formatting of all other resources. -* Add the resource(s) you are representing to the [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/main/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet) under the appropriate `apiGroup` using the `verbs`: `list` and `watch`. -* Run `make examples/standard`, this should re-generate [examples/standard/cluster-role.yaml](https://github.com/kubernetes/kube-state-metrics/blob/main/examples/standard/cluster-role.yaml) with the resource(s) added to [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](https://github.com/kubernetes/kube-state-metrics/blob/main/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet). -* Reference and add build functions for the new resource(s) in [internal/store/builder.go](https://github.com/kubernetes/kube-state-metrics/blob/main/internal/store/builder.go). -* Reference the new resource in [pkg/options/resource.go](https://github.com/kubernetes/kube-state-metrics/blob/main/pkg/options/resource.go). -* Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](https://github.com/kubernetes/kube-state-metrics/tree/main/tests/manifests) directory. -* Lastly, and most importantly, actually implement your new resource(s) and its test binary in [internal/store](https://github.com/kubernetes/kube-state-metrics/tree/main/internal/store). Follow the formatting and structure of other resources. +* Reference your new resource(s) to the [docs/README.md](./../README.md#exposed-metrics). +* Reference your new resource(s) in the [docs/developer/cli-arguments.md](./cli-arguments.md#available-options) as part of the `--resources` flag. +* Create a new `.md` in the [docs](./../docs) directory to provide documentation on the resource(s) and metrics you implemented. Follow the formatting of all other resources. +* Add the resource(s) you are representing to the [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](./../../jsonnet/kube-state-metrics/kube-state-metrics.libsonnet) under the appropriate `apiGroup` using the `verbs`: `list` and `watch`. +* Run `make examples/standard`, this should re-generate [examples/standard/cluster-role.yaml](./../../examples/standard/cluster-role.yaml) with the resource(s) added to [jsonnet/kube-state-metrics/kube-state-metrics.libsonnet](./../../jsonnet/kube-state-metrics/kube-state-metrics.libsonnet). +* Reference and add build functions for the new resource(s) in [internal/store/builder.go](./../../internal/store/builder.go). +* Reference the new resource in [pkg/options/resource.go](./../../pkg/options/resource.go). +* Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](./../../tests/manifests) directory. +* Lastly, and most importantly, actually implement your new resource(s) and its test binary in [internal/store](./../../internal/store). Follow the formatting and structure of other resources. ### Add New Metrics diff --git a/docs/metrics/auth/certificatesigningrequest-metrics.md b/docs/metrics/auth/certificatesigningrequest-metrics.md new file mode 100644 index 0000000000..ffc013db8a --- /dev/null +++ b/docs/metrics/auth/certificatesigningrequest-metrics.md @@ -0,0 +1,9 @@ +# CertificateSigningRequest Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_certificatesigningrequest_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | EXPERIMENTAL | +| kube_certificatesigningrequest_created | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | STABLE | +| kube_certificatesigningrequest_condition | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name>
`condition`=<approved\|denied> | STABLE | +| kube_certificatesigningrequest_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | STABLE | +| kube_certificatesigningrequest_cert_length | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | STABLE | diff --git a/docs/metrics/auth/role-metrics.md b/docs/metrics/auth/role-metrics.md new file mode 100644 index 0000000000..1c9e4be2af --- /dev/null +++ b/docs/metrics/auth/role-metrics.md @@ -0,0 +1,9 @@ +# Role Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ----------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------ | +| kube_role_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | +| kube_role_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | +| kube_role_info | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | +| kube_role_created | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | +| kube_role_metadata_resource_version | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/auth/rolebinding-metrics.md b/docs/metrics/auth/rolebinding-metrics.md new file mode 100644 index 0000000000..cf67bc05a7 --- /dev/null +++ b/docs/metrics/auth/rolebinding-metrics.md @@ -0,0 +1,9 @@ +# RoleBinding Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_rolebinding_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | +| kube_rolebinding_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | +| kube_rolebinding_info | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace>
`roleref_kind`=<role-kind>
`roleref_name`=<role-name> | EXPERIMENTAL | +| kube_rolebinding_created | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | +| kube_rolebinding_metadata_resource_version | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/auth/serviceaccount-metrics.md b/docs/metrics/auth/serviceaccount-metrics.md new file mode 100644 index 0000000000..a7ec4704b6 --- /dev/null +++ b/docs/metrics/auth/serviceaccount-metrics.md @@ -0,0 +1,11 @@ +# ServiceAccount Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | +| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_serviceaccount_info | Gauge | Information about a service account | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`automount_token`=<serviceaccount-automount-token> | EXPERIMENTAL | +| kube_serviceaccount_created | Gauge | Unix creation timestamp | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid> | EXPERIMENTAL | +| kube_serviceaccount_deleted | Gauge | Unix deletion timestamp | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid> | EXPERIMENTAL | +| kube_serviceaccount_secret | Gauge | Secret being referenced by a service account | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`name`=<secret-name> | EXPERIMENTAL | +| kube_serviceaccount_image_pull_secret | Gauge | Secret being referenced by a service account for the purpose of pulling images | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`name`=<secret-name> | EXPERIMENTAL | +| kube_serviceaccount_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`annotation_SERVICE_ACCOUNT_ANNOTATION`=<SERVICE_ACCOUNT_ANNOTATION> | EXPERIMENTAL | +| kube_serviceaccount_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`label_SERVICE_ACCOUNT_LABEL`=<SERVICE_ACCOUNT_LABEL> | EXPERIMENTAL | diff --git a/docs/metrics/cluster/clusterrole-metrics.md b/docs/metrics/cluster/clusterrole-metrics.md new file mode 100644 index 0000000000..ef930a5960 --- /dev/null +++ b/docs/metrics/cluster/clusterrole-metrics.md @@ -0,0 +1,9 @@ +# ClusterRole Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------ | +| kube_clusterrole_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | +| kube_clusterrole_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | +| kube_clusterrole_info | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | +| kube_clusterrole_created | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | +| kube_clusterrole_metadata_resource_version | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | diff --git a/docs/metrics/cluster/clusterrolebinding-metrics.md b/docs/metrics/cluster/clusterrolebinding-metrics.md new file mode 100644 index 0000000000..07020f1b5f --- /dev/null +++ b/docs/metrics/cluster/clusterrolebinding-metrics.md @@ -0,0 +1,9 @@ +# ClusterRoleBinding Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_clusterrolebinding_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | +| kube_clusterrolebinding_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | +| kube_clusterrolebinding_info | Gauge | | `clusterrolebinding`=<clusterrolebinding-name>
`roleref_kind`=<role-kind>
`roleref_name`=<role-name> | EXPERIMENTAL | +| kube_clusterrolebinding_created | Gauge | | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | +| kube_clusterrolebinding_metadata_resource_version | Gauge | | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | diff --git a/docs/metrics/cluster/lease-metrics.md b/docs/metrics/cluster/lease-metrics.md new file mode 100644 index 0000000000..f90cfe8eaf --- /dev/null +++ b/docs/metrics/cluster/lease-metrics.md @@ -0,0 +1,6 @@ +# Lease Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| --------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| kube_lease_owner | Gauge | | `lease`=<lease-name>
`owner_kind`=<onwer kind>
`owner_name`=<owner name>
`namespace` = <namespace>
`lease_holder`=<lease holder name> | EXPERIMENTAL | +| kube_lease_renew_time | Gauge | | `lease`=<lease-name>
`namespace` = <namespace> | EXPERIMENTAL | diff --git a/docs/metrics/cluster/namespace-metrics.md b/docs/metrics/cluster/namespace-metrics.md new file mode 100644 index 0000000000..d5dac41506 --- /dev/null +++ b/docs/metrics/cluster/namespace-metrics.md @@ -0,0 +1,9 @@ +# Namespace Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_namespace_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `namespace`=<namespace-name>
`label_NS_ANNOTATION`=<NS_ANNOTATION> | EXPERIMENTAL | +| kube_namespace_created | Gauge | | `namespace`=<namespace-name> | STABLE | +| kube_namespace_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `namespace`=<namespace-name>
`label_NS_LABEL`=<NS_LABEL> | STABLE | +| kube_namespace_status_condition | Gauge | | `namespace`=<namespace-name>
`condition`=<NamespaceDeletionDiscoveryFailure\|NamespaceDeletionContentFailure\|NamespaceDeletionGroupVersionParsingFailure>
`status`=<true\|false\|unknown> | EXPERIMENTAL | +| kube_namespace_status_phase | Gauge | | `namespace`=<namespace-name>
`phase`=<Active\|Terminating> | STABLE | diff --git a/docs/metrics/cluster/node-metrics.md b/docs/metrics/cluster/node-metrics.md new file mode 100644 index 0000000000..ac1085bf8e --- /dev/null +++ b/docs/metrics/cluster/node-metrics.md @@ -0,0 +1,16 @@ +# Node Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | +| ---------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_node_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `node`=<node-address>
`annotation_NODE_ANNOTATION`=<NODE_ANNOTATION> | EXPERIMENTAL | +| kube_node_info | Gauge | Information about a cluster node | | `node`=<node-address>
`kernel_version`=<kernel-version>
`os_image`=<os-image-name>
`container_runtime_version`=<container-runtime-and-version-combination>
`kubelet_version`=<kubelet-version>
`kubeproxy_version`=<kubeproxy-version>
`pod_cidr`=<pod-cidr>
`provider_id`=<provider-id>
`system_uuid`=<system-uuid>
`internal_ip`=<internal-ip> | STABLE | +| kube_node_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `node`=<node-address>
`label_NODE_LABEL`=<NODE_LABEL> | STABLE | +| kube_node_role | Gauge | The role of a cluster node | | `node`=<node-address>
`role`=<NODE_ROLE> | EXPERIMENTAL | +| kube_node_spec_unschedulable | Gauge | Whether a node can schedule new pods | | `node`=<node-address> | STABLE | +| kube_node_spec_taint | Gauge | The taint of a cluster node. | | `node`=<node-address>
`key`=<taint-key>
`value=`<taint-value>
`effect=`<taint-effect> | STABLE | +| kube_node_status_capacity | Gauge | The total amount of resources available for a node | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> | `node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit> | STABLE | +| kube_node_status_addresses | Gauge | The addresses of a node | | `node`=<node-address>
`type`=<address-type>
`address`=<address-value> | EXPERIMENTAL | +| kube_node_status_allocatable | Gauge | The amount of resources allocatable for pods (after reserving some for system daemons) | `cpu`=<core>
`ephemeral_storage`=<byte>
`pods`=<integer>
`attachable_volumes_*`=<byte>
`hugepages_*`=<byte>
`memory`=<byte> | `node`=<node-address>
`resource`=<resource-name>
`unit`=<resource-unit> | STABLE | +| kube_node_status_condition | Gauge | The condition of a cluster node | | `node`=<node-address>
`condition`=<node-condition>
`status`=<true\|false\|unknown> | STABLE | +| kube_node_created | Gauge | Unix creation timestamp | seconds | `node`=<node-address> | STABLE | +| kube_node_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | `node`=<node-address> | EXPERIMENTAL | diff --git a/docs/metrics/extend/customresourcestate-metrics.md b/docs/metrics/extend/customresourcestate-metrics.md new file mode 100644 index 0000000000..9330478b8e --- /dev/null +++ b/docs/metrics/extend/customresourcestate-metrics.md @@ -0,0 +1,572 @@ +# Custom Resource State Metrics + +This section describes how to add metrics based on the state of a custom resource without writing a custom resource +registry and running your own build of KSM. + +## Configuration + +A YAML configuration file described below is required to define your custom resources and the fields to turn into metrics. + +Two flags can be used: + +* `--custom-resource-state-config "inline yaml (see example)"` or +* `--custom-resource-state-config-file /path/to/config.yaml` + +If both flags are provided, the inline configuration will take precedence. +When multiple entries for the same resource exist, kube-state-metrics will exit with an error. +This includes configuration which refers to a different API version. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kube-state-metrics + namespace: kube-system +spec: + template: + spec: + containers: + - name: kube-state-metrics + args: + - --custom-resource-state-config + # in YAML files, | allows a multi-line string to be passed as a flag value + # see https://yaml-multiline.info + - | + spec: + resources: + - groupVersionKind: + group: myteam.io + version: "v1" + kind: Foo + metrics: + - name: active_count + help: "Count of active Foo" + each: + type: Gauge + ... +``` + +It's also possible to configure kube-state-metrics to run in a `custom-resource-mode` only. In addition to specifying one of `--custom-resource-state-config*` flags, you could set `--custom-resource-state-only` to `true`. +With this configuration only the known custom resources configured in `--custom-resource-state-config*` will be taken into account by kube-state-metrics. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kube-state-metrics + namespace: kube-system +spec: + template: + spec: + containers: + - name: kube-state-metrics + args: + - --custom-resource-state-config + # in YAML files, | allows a multi-line string to be passed as a flag value + # see https://yaml-multiline.info + - | + spec: + resources: + - groupVersionKind: + group: myteam.io + version: "v1" + kind: Foo + metrics: + - name: active_count + help: "Count of active Foo" + each: + type: Gauge + ... + - --custom-resource-state-only=true +``` + +NOTE: The `customresource_group`, `customresource_version`, and `customresource_kind` common labels are reserved, and will be overwritten by the values from the `groupVersionKind` field. + +### RBAC-enabled Clusters + +Please be aware that kube-state-metrics needs list and watch permissions granted to `customresourcedefinitions.apiextensions.k8s.io` as well as to the resources you want to gather metrics from. + +### Examples + +The examples in this section will use the following custom resource: + +```yaml +kind: Foo +apiVersion: myteam.io/vl +metadata: + annotations: + bar: baz + qux: quxx + labels: + foo: bar + name: foo +spec: + version: v1.2.3 + order: + - id: 1 + value: true + - id: 3 + value: false + replicas: 1 + refs: + - my_other_foo + - foo_2 + - foo_with_extensions +status: + phase: Pending + active: + type-a: 1 + type-b: 3 + conditions: + - name: a + value: 45 + - name: b + value: 66 + sub: + type-a: + active: 1 + ready: 2 + type-b: + active: 3 + ready: 4 + uptime: 43.21 +``` + +#### Single Values + +The config: + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + metrics: + - name: "uptime" + help: "Foo uptime" + each: + type: Gauge + gauge: + path: [status, uptime] +``` + +Produces the metric: + +```prometheus +kube_customresource_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21 +``` + +#### Multiple Metrics/Kitchen Sink + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + # labels can be added to all metrics from a resource + commonLabels: + crd_type: "foo" + labelsFromPath: + name: [metadata, name] + metrics: + - name: "ready_count" + help: "Number Foo Bars ready" + each: + type: Gauge + gauge: + # targeting an object or array will produce a metric for each element + # labelsFromPath and value are relative to this path + path: [status, sub] + + # if path targets an object, the object key will be used as label value + # This is not supported for StateSet type as all values will be truthy, which is redundant. + labelFromKey: type + # label values can be resolved specific to this path + labelsFromPath: + active: [active] + # The actual field to use as metric value. Should be a number, boolean or RFC3339 timestamp string. + valueFrom: [ready] + commonLabels: + custom_metric: "yes" + labelsFromPath: + # whole objects may be copied into labels by prefixing with "*" + # *anything will be copied into labels, with the highest sorted * strings first + "*": [metadata, labels] + # a prefix before the asterisk will be used as a label prefix + "lorem_*": [metadata, annotations] + "**": [metadata, annotations] + + # or specific fields may be copied. these fields will always override values from *s + name: [metadata, name] + foo: [metadata, labels, foo] +``` + +Produces the following metrics: + +```prometheus +kube_customresource_ready_count{customresource_group="myteam.io", customresource_kind="Foo", +customresource_version="v1", active="1",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-a", +lorem_bar="baz",lorem_qux="quxx",} 2 +kube_customresource_ready_count{customresource_group="myteam.io", customresource_kind="Foo", +customresource_version="v1", active="3",custom_metric="yes",foo="bar",name="foo",bar="baz",qux="quxx",type="type-b", +lorem_bar="baz",lorem_qux="quxx",} 4 +``` + +#### Non-map Arrays + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + labelsFromPath: + name: [metadata, name] + metrics: + - name: "ref_info" + help: "Reference to other Foo" + each: + type: Info + info: + # targeting an array will produce a metric for each element + # labelsFromPath and value are relative to this path + path: [spec, refs] + + # if path targets a list of values (e.g. strings or numbers, not objects or maps), individual values can + # referenced by a label using this syntax + labelsFromPath: + ref: [] +``` + +Produces the following metrics: + +```prometheus +kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="my_other_foo"} 1 +kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="foo_2"} 1 +kube_customresource_ref_info{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", name="foo",ref="foo_with_extensions"} 1 +``` + +#### VerticalPodAutoscaler + +In v2.9.0 the `vericalpodautoscalers` resource was removed from the list of default resources. In order to generate metrics for `verticalpodautoscalers`, you can use the following Custom Resource State config: + +```yaml +# Using --resource=verticalpodautoscalers, we get the following output: +# HELP kube_verticalpodautoscaler_annotations Kubernetes annotations converted to Prometheus labels. +# TYPE kube_verticalpodautoscaler_annotations gauge +# kube_verticalpodautoscaler_annotations{namespace="default",verticalpodautoscaler="hamster-vpa",target_api_version="apps/v1",target_kind="Deployment",target_name="hamster"} 1 +# A similar result can be achieved by specifying the following in --custom-resource-state-config: +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: autoscaling.k8s.io + kind: "VerticalPodAutoscaler" + version: "v1" + labelsFromPath: + verticalpodautoscaler: [metadata, name] + namespace: [metadata, namespace] + target_api_version: [apiVersion] + target_kind: [spec, targetRef, kind] + target_name: [spec, targetRef, name] + metrics: + - name: "annotations" + help: "Kubernetes annotations converted to Prometheus labels." + each: + type: Gauge + gauge: + path: [metadata, annotations] +# This will output the following metric: +# HELP kube_customresource_autoscaling_annotations Kubernetes annotations converted to Prometheus labels. +# TYPE kube_customresource_autoscaling_annotations gauge +# kube_customresource_autoscaling_annotations{customresource_group="autoscaling.k8s.io", customresource_kind="VerticalPodAutoscaler", customresource_version="v1", namespace="default",target_api_version="autoscaling.k8s.io/v1",target_kind="Deployment",target_name="hamster",verticalpodautoscaler="hamster-vpa"} 123 +``` + +The above configuration was tested on [this](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/examples/hamster.yaml) VPA configuration, with an added annotation (`foo: 123`). + +### Metric types + +The configuration supports three kind of metrics from the [OpenMetrics specification](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md). + +The metric type is specified by the `type` field and its specific configuration at the types specific struct. + +#### Gauge + +> Gauges are current measurements, such as bytes of memory currently used or the number of items in a queue. For gauges the absolute value is what is of interest to a user. [[0]](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#gauge) + +Example: + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + metrics: + - name: "uptime" + help: "Foo uptime" + each: + type: Gauge + gauge: + path: [status, uptime] +``` + +Produces the metric: + +```prometheus +kube_customresource_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21 +``` + +##### Type conversion and special handling + +Gauges produce values of type float64 but custom resources can be of all kinds of types. +Kube-state-metrics performs implicit type conversions for a lot of type. +Supported types are: + +* (u)int32/64, int, float32 and byte are cast to float64 +* `nil` is generally mapped to `0.0` if NilIsZero is `true`, otherwise it will throw an error +* for bool `true` is mapped to `1.0` and `false` is mapped to `0.0` +* for string the following logic applies + * `"true"` and `"yes"` are mapped to `1.0` and `"false"` and `"no"` are mapped to `0.0` (all case-insensitive) + * RFC3339 times are parsed to float timestamp + * Quantities like "250m" or "512Gi" are parsed to float using + * Percentages ending with a "%" are parsed to float + * finally the string is parsed to float using which should support all common number formats. If that fails an error is yielded + +##### Example for status conditions on Kubernetes Controllers + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "foo_status" + help: "status condition " + each: + type: Gauge + gauge: + path: [status, conditions] + labelsFromPath: + type: ["type"] + valueFrom: ["status"] +``` + +This will work for kubernetes controller CRs which expose status conditions according to the kubernetes api (): + +```yaml +status: + conditions: + - lastTransitionTime: "2019-10-22T16:29:31Z" + status: "True" + type: Ready +``` + +kube_customresource_foo_status{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", type="Ready"} 1.0 + +#### StateSet + +> StateSets represent a series of related boolean values, also called a bitset. If ENUMs need to be encoded this MAY be done via StateSet. [[1]](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#stateset) + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + metrics: + - name: "status_phase" + help: "Foo status_phase" + each: + type: StateSet + stateSet: + labelName: phase + path: [status, phase] + list: [Pending, Bar, Baz] +``` + +Metrics of type `StateSet` will generate a metric for each value defined in `list` for each resource. +The value will be 1, if the value matches the one in list. + +Produces the metric: + +```prometheus +kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Pending"} 1 +kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Bar"} 0 +kube_customresource_status_phase{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", phase="Baz"} 0 +``` + +#### Info + +> Info metrics are used to expose textual information which SHOULD NOT change during process lifetime. Common examples are an application's version, revision control commit, and the version of a compiler. [[2]](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#info) + +Metrics of type `Info` will always have a value of 1. + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: myteam.io + kind: "Foo" + version: "v1" + metrics: + - name: "version" + help: "Foo version" + each: + type: Info + info: + labelsFromPath: + version: [spec, version] +``` + +Produces the metric: + +```prometheus +kube_customresource_version{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1", version="v1.2.3"} 1 +``` + +### Naming + +The default metric names are prefixed to avoid collisions with other metrics. +By default, a metric prefix of `kube_` concatenated with your custom resource's group+version+kind is used. +You can override this behavior with the `metricNamePrefix` field. + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: ... + metricNamePrefix: myteam_foos + metrics: + - name: uptime + # ... +``` + +Produces: + +```prometheus +myteam_foos_uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21 +``` + +To omit namespace and/or subsystem altogether, set them to the empty string: + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: ... + metricNamePrefix: "" + metrics: + - name: uptime + # ... +``` + +Produces: + +```prometheus +uptime{customresource_group="myteam.io", customresource_kind="Foo", customresource_version="v1"} 43.21 +``` + +### Logging + +If a metric path is registered but not found on a custom resource, an error will be logged. For some resources, +this may produce a lot of noise. The error log [verbosity][vlog] for a metric or resource can be set with `errorLogV` on +the resource or metric: + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: ... + errorLogV: 0 # 0 = default for errors + metrics: + - name: uptime + errorLogV: 10 # only log at high verbosity +``` + +[vlog]: https://github.com/go-logr/logr#why-v-levels + +### Path Syntax + +Paths are specified as a list of strings. Each string is a path segment, resolved dynamically against the data of the custom resource. +If any part of a path is missing, the result is nil. + +Examples: + +```yaml +# simple path lookup +[spec, replicas] # spec.replicas == 1 + +# indexing an array +[spec, order, "0", value] # spec.order[0].value = true + +# finding an element in a list by key=value +[status, conditions, "[name=a]", value] # status.conditions[0].value = 45 + +# if the value to be matched is a number or boolean, the value is compared as a number or boolean +[status, conditions, "[value=66]", name] # status.conditions[1].name = "b" + +# For generally matching against a field in an object schema, use the following syntax: +[metadata, "name=foo"] # if v, ok := metadata[name]; ok && v == "foo" { return v; } else { /* ignore */ } +``` + +### Wildcard matching of version and kind fields + +The Custom Resource State (CRS hereon) configuration also allows you to monitor all versions and/or kinds that come under a group. It watches +the installed CRDs for this purpose. Taking the aforementioned `Foo` object as reference, the configuration below allows +you to monitor all objects under all versions *and* all kinds that come under the `myteam.io` group. + +```yaml +kind: CustomResourceStateMetrics +spec: + resources: + - groupVersionKind: + group: "myteam.io" + version: "*" # Set to `v1 to monitor all kinds under `myteam.io/v1`. Wildcard matches all installed versions that come under this group. + kind: "*" # Set to `Foo` to monitor all `Foo` objects under the `myteam.io` group (under all versions). Wildcard matches all installed kinds that come under this group (and version, if specified). + metrics: + - name: "myobject_info" + help: "Foo Bar Baz" + each: + type: Info + info: + path: [metadata] + labelsFromPath: + object: [name] + namespace: [namespace] +``` + +The configuration above produces these metrics. + +```yaml +kube_customresource_myobject_info{customresource_group="myteam.io",customresource_kind="Foo",customresource_version="v1",namespace="ns",object="foo"} 1 +kube_customresource_myobject_info{customresource_group="myteam.io",customresource_kind="Bar",customresource_version="v1",namespace="ns",object="bar"} 1 +``` + +#### Note + +* For cases where the GVKs defined in a CRD have multiple versions under a single group for the same kind, as expected, the wildcard value will resolve to *all* versions, but a query for any specific version will return all resources under all versions, in that versions' representation. This basically means that for two such versions `A` and `B`, if a resource exists under `B`, it will reflect in the metrics generated for `A` as well, in addition to any resources of itself, and vice-versa. This logic is based on the [current `list`ing behavior](https://github.com/kubernetes/client-go/issues/1251#issuecomment-1544083071) of the client-go library. +* The introduction of this feature further discourages (and discontinues) the use of native objects in the CRS featureset, since these do not have an explicit CRD associated with them, and conflict with internal stores defined specifically for such native resources. Please consider opening an issue or raising a PR if you'd like to expand on the current metric labelsets for them. Also, any such configuration will be ignored, and no metrics will be generated for the same. diff --git a/docs/metrics/extend/mutatingwebhookconfiguration-metrics.md b/docs/metrics/extend/mutatingwebhookconfiguration-metrics.md new file mode 100644 index 0000000000..10ddb0682b --- /dev/null +++ b/docs/metrics/extend/mutatingwebhookconfiguration-metrics.md @@ -0,0 +1,8 @@ +# MutatingWebhookConfiguration Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| -------------------------------------------------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_mutatingwebhookconfiguration_info | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_mutatingwebhookconfiguration_created | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_mutatingwebhookconfiguration_metadata_resource_version | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_mutatingwebhookconfiguration_webhook_clientconfig_service | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace>
`webhook_name`=<webhook-name>
`service_name`=<webhook-service-name>
`service_namespace`=<webhook-service-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/extend/validatingwebhookconfiguration-metrics.md b/docs/metrics/extend/validatingwebhookconfiguration-metrics.md new file mode 100644 index 0000000000..f41627a685 --- /dev/null +++ b/docs/metrics/extend/validatingwebhookconfiguration-metrics.md @@ -0,0 +1,8 @@ +# ValidatingWebhookConfiguration Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ---------------------------------------------------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_validatingwebhookconfiguration_info | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_validatingwebhookconfiguration_created | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_validatingwebhookconfiguration_metadata_resource_version | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | +| kube_validatingwebhookconfiguration_webhook_clientconfig_service | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace>
`webhook_name`=<webhook-name>
`service_name`=<webhook-service-name>
`service_namespace`=<webhook-service-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/policy/limitrange-metrics.md b/docs/metrics/policy/limitrange-metrics.md new file mode 100644 index 0000000000..fe2cfb08f9 --- /dev/null +++ b/docs/metrics/policy/limitrange-metrics.md @@ -0,0 +1,6 @@ +# LimitRange Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ----------------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| kube_limitrange | Gauge | | `limitrange`=<limitrange-name>
`namespace`=<namespace>
`resource`=<ResourceName>
`type`=<Pod\|Container\|PersistentVolumeClaim>
`constraint`=<constraint> | STABLE | +| kube_limitrange_created | Gauge | | `limitrange`=<limitrange-name>
`namespace`=<namespace> | STABLE | diff --git a/docs/metrics/policy/networkpolicy-metrics.md b/docs/metrics/policy/networkpolicy-metrics.md new file mode 100644 index 0000000000..8ed494350e --- /dev/null +++ b/docs/metrics/policy/networkpolicy-metrics.md @@ -0,0 +1,9 @@ +# Network Policy Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ | +| kube_networkpolicy_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | +| kube_networkpolicy_created | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | +| kube_networkpolicy_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | +| kube_networkpolicy_spec_egress_rules | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | +| kube_networkpolicy_spec_ingress_rules | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | diff --git a/docs/metrics/policy/poddisruptionbudget-metrics.md b/docs/metrics/policy/poddisruptionbudget-metrics.md new file mode 100644 index 0000000000..2e8fb1179a --- /dev/null +++ b/docs/metrics/policy/poddisruptionbudget-metrics.md @@ -0,0 +1,12 @@ +# PodDisruptionBudget Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_poddisruptionbudget_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `poddisruptionbudget`=<poddisruptionbudget-name>
`namespace`=<poddisruptionbudget-namespace>
`annotation_PODDISRUPTIONBUDGET_ANNOTATION`=<PODDISRUPTIONBUDGET_ANNOATION> | EXPERIMENTAL | +| kube_poddisruptionbudget_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `poddisruptionbudget`=<poddisruptionbudget-name>
`namespace`=<poddisruptionbudget-namespace>
`label_PODDISRUPTIONBUDGET_LABEL`=<PODDISRUPTIONBUDGET_ANNOATION> | EXPERIMENTAL | +| kube_poddisruptionbudget_created | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | +| kube_poddisruptionbudget_status_current_healthy | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | +| kube_poddisruptionbudget_status_desired_healthy | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | +| kube_poddisruptionbudget_status_pod_disruptions_allowed | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | +| kube_poddisruptionbudget_status_expected_pods | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | +| kube_poddisruptionbudget_status_observed_generation | Gauge | | `poddisruptionbudget`=<pdb-name>
`namespace`=<pdb-namespace> | STABLE | diff --git a/docs/metrics/policy/resourcequota-metrics.md b/docs/metrics/policy/resourcequota-metrics.md new file mode 100644 index 0000000000..3a68fdae29 --- /dev/null +++ b/docs/metrics/policy/resourcequota-metrics.md @@ -0,0 +1,8 @@ +# ResourceQuota Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_resourcequota | Gauge | | `resourcequota`=<quota-name>
`namespace`=<namespace>
`resource`=<ResourceName>
`type`=<quota-type> | STABLE | +| kube_resourcequota_created | Gauge | | `resourcequota`=<quota-name>
`namespace`=<namespace> | STABLE | +| kube_resourcequota_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `resourcequota`=<quota-name>
`namespace`=<namespace>
`annotation_RESOURCE_QUOTA_ANNOTATION`=<RESOURCE_QUOTA_ANNOTATION> | EXPERIMENTAL | +| kube_resourcequota_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `resourcequota`=<quota-name>
`namespace`=<namespace>
`label_RESOURCE_QUOTA_LABEL`=<RESOURCE_QUOTA_LABEL> | EXPERIMENTAL | diff --git a/docs/metrics/service/endpoint-metrics.md b/docs/metrics/service/endpoint-metrics.md new file mode 100644 index 0000000000..4845988bdd --- /dev/null +++ b/docs/metrics/service/endpoint-metrics.md @@ -0,0 +1,12 @@ +# Endpoint Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_endpoint_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace>
`annotation_ENDPOINT_ANNOTATION`=<ENDPOINT_ANNOTATION> | EXPERIMENTAL | +| kube_endpoint_address_not_ready | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | DEPRECATED | +| kube_endpoint_address_available | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | DEPRECATED | +| kube_endpoint_info | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | STABLE | +| kube_endpoint_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace>
`label_ENDPOINT_LABEL`=<ENDPOINT_LABEL> | STABLE | +| kube_endpoint_created | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | STABLE | +| kube_endpoint_ports | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace>
`port_name`=<endpoint-port-name>
`port_protocol`=<endpoint-port-protocol>
`port_number`=<endpoint-port-number> | STABLE | +| kube_endpoint_address | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace>
`ip`=<endpoint-ip>
`ready`=<true if available, false if unavailalbe> | STABLE | diff --git a/docs/metrics/service/endpointslice-metrics.md b/docs/metrics/service/endpointslice-metrics.md new file mode 100644 index 0000000000..e54014ed4e --- /dev/null +++ b/docs/metrics/service/endpointslice-metrics.md @@ -0,0 +1,11 @@ +# Endpoint Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_endpointslice_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`annotation_ENDPOINTSLICE_ANNOTATION`=<ENDPOINTSLICE_ANNOTATION> | EXPERIMENTAL | +| kube_endpointslice_info | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | +| kube_endpointslice_ports | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`port_name`=<endpointslice-port-name>
`port_protocol`=<endpointslice-port-protocol>
`port_number`=<endpointslice-port-number> | EXPERIMENTAL | +| kube_endpointslice_endpoints | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`ready`=<endpointslice-ready>
`serving`=<endpointslice-serving>
`terminating`=<endpointslice-terminating>
`hostname`=<endpointslice-hostname>
`targetref_kind`=<endpointslice-targetref-kind>
`targetref_name`=<endpointslice-targetref-name>
`targetref_namespace`=<endpointslice-targetref-namespace>
`nodename`=<endpointslice-nodename>
`endpoint_zone`=<endpointslice-zone> | EXPERIMENTAL | +| kube_endpointslice_endpoints_hints | Gauge | Each line is a hint applied to an endpoint-slice | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`address`=<endpointslice-address[0]>
`for_zone`=<endpointslice-hint> | EXPERIMENTAL | +| kube_endpointslice_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`label_ENDPOINTSLICE_LABEL`=<ENDPOINTSLICE_LABEL> | EXPERIMENTAL | +| kube_endpointslice_created | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/service/ingress-metrics.md b/docs/metrics/service/ingress-metrics.md new file mode 100644 index 0000000000..61faf115d3 --- /dev/null +++ b/docs/metrics/service/ingress-metrics.md @@ -0,0 +1,11 @@ +# Ingress Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| -------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_ingress_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `ingress`=<ingress-name>
`namespace`=<ingress-namespace>
`annotation_INGRESS_ANNOTATION`=<ANNOTATION_LABEL> | EXPERIMENTAL | +| kube_ingress_info | Gauge | | `ingress`=<ingress-name>
`namespace`=<ingress-namespace>
`ingressclass`=<ingress-class> or `_default` if not set | STABLE | +| kube_ingress_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `ingress`=<ingress-name>
`namespace`=<ingress-namespace>
`label_INGRESS_LABEL`=<INGRESS_LABEL> | STABLE | +| kube_ingress_created | Gauge | | `ingress`=<ingress-name>
`namespace`=<ingress-namespace> | STABLE | +| kube_ingress_metadata_resource_version | Gauge | | `ingress`=<ingress-name>
`namespace`=<ingress-namespace> | EXPERIMENTAL | +| kube_ingress_path | Gauge | | `ingress`=<ingress-name>
`namespace`=<ingress-namespace>
`host`=<ingress-host>
`path`=<ingress-path>
If path served by Service Backend
`service_name`=<service name for the path>
`service_port`=<service port for the path>
If path served by Resource Backend
`resource_api_group`=<resource backend api group>
`resource_kind`=<resource backend kind>
`resource_name`=<resource backend name> | STABLE | +| kube_ingress_tls | Gauge | | `ingress`=<ingress-name>
`namespace`=<ingress-namespace>
`tls_host`=<tls hostname>
`secret`=<tls secret name> | STABLE | diff --git a/docs/metrics/service/ingressclass-metrics.md b/docs/metrics/service/ingressclass-metrics.md new file mode 100644 index 0000000000..fbb6097db4 --- /dev/null +++ b/docs/metrics/service/ingressclass-metrics.md @@ -0,0 +1,8 @@ +# IngressClass Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------ | +| kube_ingressclass_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `ingressclass`=<ingressclass-name>
`annotation_INGRESSCLASS_ANNOTATION`=<INGRESSCLASS_ANNOTATION> | EXPERIMENTAL | +| kube_ingressclass_info | Gauge | | `ingressclass`=<ingressclass-name>
`controller`=<ingress-controller-name>
| EXPERIMENTAL | +| kube_ingressclass_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `ingressclass`=<ingressclass-name>
`label_INGRESSCLASS_LABEL`=<INGRESSCLASS_LABEL> | EXPERIMENTAL | +| kube_ingressclass_created | Gauge | | `ingressclass`=<ingressclass-name> | EXPERIMENTAL | diff --git a/docs/metrics/service/service-metrics.md b/docs/metrics/service/service-metrics.md new file mode 100644 index 0000000000..fc68d3b409 --- /dev/null +++ b/docs/metrics/service/service-metrics.md @@ -0,0 +1,11 @@ +# Service Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | +| ----------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_service_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`annotation_SERVICE_ANNOTATION`=<SERVICE_ANNOTATION> | EXPERIMENTAL | +| kube_service_info | Gauge | Information about service | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`cluster_ip`=<service cluster ip>
`external_name`=<service external name>
`load_balancer_ip`=<service load balancer ip> | STABLE | +| kube_service_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`label_SERVICE_LABEL`=<SERVICE_LABEL> | STABLE | +| kube_service_created | Gauge | Unix creation timestamp | seconds | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid> | STABLE | +| kube_service_spec_type | Gauge | Type about service | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`type`=<ClusterIP\|NodePort\|LoadBalancer\|ExternalName> | STABLE | +| kube_service_spec_external_ip | Gauge | Service external ips. One series for each ip | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`external_ip`=<external-ip> | STABLE | +| kube_service_status_load_balancer_ingress | Gauge | Service load balancer ingress status | | `service`=<service-name>
`namespace`=<service-namespace>
`uid`=<service-uid>
`ip`=<load-balancer-ingress-ip>
`hostname`=<load-balancer-ingress-hostname> | STABLE | diff --git a/docs/metrics/storage/configmap-metrics.md b/docs/metrics/storage/configmap-metrics.md new file mode 100644 index 0000000000..063af2c4b3 --- /dev/null +++ b/docs/metrics/storage/configmap-metrics.md @@ -0,0 +1,9 @@ +# ConfigMap Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ---------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_configmap_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `configmap`=<configmap-name>
`namespace`=<configmap-namespace>
`annotation_CONFIGMAP_ANNOTATION`=<CONFIGMAP_ANNOTATION> | EXPERIMENTAL | +| kube_configmap_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `configmap`=<configmap-name>
`namespace`=<configmap-namespace>
`label_CONFIGMAP_LABEL`=<CONFIGMAP_LABEL> | STABLE | +| kube_configmap_info | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | STABLE | +| kube_configmap_created | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | STABLE | +| kube_configmap_metadata_resource_version | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/storage/persistentvolume-metrics.md b/docs/metrics/storage/persistentvolume-metrics.md new file mode 100644 index 0000000000..d6e9b08ddf --- /dev/null +++ b/docs/metrics/storage/persistentvolume-metrics.md @@ -0,0 +1,37 @@ +# PersistentVolume Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | +|------------------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| +| kube_persistentvolume_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `persistentvolume`=<persistentvolume-name>
`annotation_PERSISTENTVOLUME_ANNOTATION`=<PERSISTENTVOLUME_ANNOTATION> | EXPERIMENTAL | +| kube_persistentvolume_capacity_bytes | Gauge | | | `persistentvolume`=<pv-name> | STABLE | +| kube_persistentvolume_status_phase | Gauge | | | `persistentvolume`=<pv-name>
`phase`=<Bound\|Failed\|Pending\|Available\|Released> | STABLE | +| kube_persistentvolume_claim_ref | Gauge | | | `persistentvolume`=<pv-name>
`claim_namespace`=<>
`name`=<> | STABLE | +| kube_persistentvolume_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `persistentvolume`=<persistentvolume-name>
`label_PERSISTENTVOLUME_LABEL`=<PERSISTENTVOLUME_LABEL> | STABLE | +| kube_persistentvolume_info | Gauge | Information about Persistent Volumes | | `persistentvolume`=<pv-name>
`storageclass`=<storageclass-name>
`gce_persistent_disk_name`=<pd-name>
`host_path`=<path-of-a-host-volume>
`host_path_type`=<host-mount-type>
`ebs_volume_id`=<ebs-volume-id>
`azure_disk_name`=<azure-disk-name>
`fc_wwids`=<fc-wwids-comma-separated>
`fc_lun`=<fc-lun>
`fc_target_wwns`=<fc-target-wwns-comma-separated>
`iscsi_target_portal`=<iscsi-target-portal>
`iscsi_iqn`=<iscsi-iqn>
`iscsi_lun`=<iscsi-lun>
`iscsi_initiator_name`=<iscsi-initiator-name>
`local_path`=<path-of-a-local-volume>
`local_fs`=<local-volume-fs-type>
`nfs_server`=<nfs-server>
`nfs_path`=<nfs-path>
`csi_driver`=<csi-driver>
`csi_volume_handle`=<csi-volume-handle> | STABLE | +| kube_persistentvolume_created | Gauge | Unix creation timestamp | seconds | `persistentvolume`=<persistentvolume-name>
| EXPERIMENTAL | +| kube_persistentvolume_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | `persistentvolume`=<persistentvolume-name>
| EXPERIMENTAL | +| kube_persistentvolume_csi_attributes | Gauge | CSI attributes of the Persistent Volume, disabled by default, manage with [--metric-opt-in-list](../../developer/cli-arguments.md)) | | `persistentvolume`=<persistentvolume-name>
`csi_mounter`=<csi-mounter>
`csi_map_options`=<csi-map-options> | EXPERIMENTAL | +| kube_persistentvolume_volume_mode | Gauge | Volume Mode information for the PersistentVolume. | | `persistentvolume`=<persistentvolume-name>
`volumemode`=<volumemode> | EXPERIMENTAL | + +## Useful metrics queries + +### How to retrieve non-standard PV state + +It is not straightforward to get the PV states for certain cases like "Terminating" since it is not stored behind a field in the `PersistentVolume.Status`. + +So to mimic the [logic](https://github.com/kubernetes/kubernetes/blob/v1.27.2/pkg/printers/internalversion/printers.go#L1838) used by the `kubectl` command line, you will need to compose multiple metrics. + +Here is an example of a Prometheus rule that can be used to alert on a PV that has been in the `Terminating` state for more than `5m`. + +```yaml +groups: +- name: PV state + rules: + - alert: PVBlockedInTerminatingState + expr: kube_persistentvolume_deletion_timestamp * on(persistentvolume) group_left() (kube_persistentvolume_status_phase{phase="Bound"} == 1) > 0 + for: 5m + labels: + severity: warning + annotations: + summary: PV {{$labels.persistentvolume}} blocked in Terminating state. +``` diff --git a/docs/metrics/storage/persistentvolumeclaim-metrics.md b/docs/metrics/storage/persistentvolumeclaim-metrics.md new file mode 100644 index 0000000000..ecd075e46e --- /dev/null +++ b/docs/metrics/storage/persistentvolumeclaim-metrics.md @@ -0,0 +1,40 @@ +# PersistentVolumeClaim Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | +| ---------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | +| kube_persistentvolumeclaim_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `persistentvolumeclaim`=<persistentvolumeclaim-name>
`namespace`=<persistentvolumeclaim-namespace>
`annotation_PERSISTENTVOLUMECLAIM_ANNOTATION`=<PERSISTENTVOLUMECLAIM_ANNOATION> | EXPERIMENTAL | +| kube_persistentvolumeclaim_access_mode | Gauge | | | `access_mode`=<persistentvolumeclaim-access-mode>
`namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name> | STABLE | +| kube_persistentvolumeclaim_info | Gauge | | | `namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name>
`storageclass`=<persistentvolumeclaim-storageclassname>
`volumename`=<volumename>
`volumemode`=<volumemode> | STABLE | +| kube_persistentvolumeclaim_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `persistentvolumeclaim`=<persistentvolumeclaim-name>
`namespace`=<persistentvolumeclaim-namespace>
`label_PERSISTENTVOLUMECLAIM_LABEL`=<PERSISTENTVOLUMECLAIM_LABEL> | STABLE | +| kube_persistentvolumeclaim_resource_requests_storage_bytes | Gauge | | | `namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name> | STABLE | +| kube_persistentvolumeclaim_status_condition | Gauge | | | `namespace` =<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name>
`type`=<persistentvolumeclaim-condition-type>
`status`=<true\false\unknown> | EXPERIMENTAL | +| kube_persistentvolumeclaim_status_phase | Gauge | | | `namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name>
`phase`=<Pending\Bound\Lost> | STABLE | +| kube_persistentvolumeclaim_created | Gauge | Unix creation timestamp | seconds | `namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name> | EXPERIMENTAL | +| kube_persistentvolumeclaim_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | `namespace`=<persistentvolumeclaim-namespace>
`persistentvolumeclaim`=<persistentvolumeclaim-name> | EXPERIMENTAL | + +Note: + +* An empty string will be used if PVC has no storage class. + +## Useful metrics queries + +### How to retrieve non-standard PVC state + +It is not straightforward to get the PVC states for certain cases like "Terminating" since it is not stored behind a field in the `PersistentVolumeClaim.Status`. + +So to mimic the [logic](https://github.com/kubernetes/kubernetes/blob/v1.27.2/pkg/printers/internalversion/printers.go#L1883) used by the `kubectl` command line, you will need to compose multiple metrics. + +Here is an example of a Prometheus rule that can be used to alert on a PVC that has been in the `Terminating` state for more than `5m`. + +```yaml +groups: +- name: PVC state + rules: + - alert: PVCBlockedInTerminatingState + expr: kube_persistentvolumeclaim_deletion_timestamp * on(namespace, persistentvolumeclaim) group_left() (kube_persistentvolumeclaim_status_phase{phase="Bound"} == 1) > 0 + for: 5m + labels: + severity: warning + annotations: + summary: PVC {{$labels.namespace}}/{{$labels.persistentvolumeclaim}} blocked in Terminating state. +``` diff --git a/docs/metrics/storage/secret-metrics.md b/docs/metrics/storage/secret-metrics.md new file mode 100644 index 0000000000..1cc579e25d --- /dev/null +++ b/docs/metrics/storage/secret-metrics.md @@ -0,0 +1,11 @@ +# Secret Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_secret_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `secret`=<secret-name>
`namespace`=<secret-namespace>
`annotations_SECRET_ANNOTATION`=<SECRET_ANNOTATION> | EXPERIMENTAL | +| kube_secret_info | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | STABLE | +| kube_secret_type | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace>
`type`=<secret-type> | STABLE | +| kube_secret_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `secret`=<secret-name>
`namespace`=<secret-namespace>
`label_SECRET_LABEL`=<SECRET_LABEL> | STABLE | +| kube_secret_created | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | STABLE | +| kube_secret_metadata_resource_version | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | EXPERIMENTAL | +| kube_secret_owner | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller> | EXPERIMENTAL | diff --git a/docs/metrics/storage/storageclass-metrics.md b/docs/metrics/storage/storageclass-metrics.md new file mode 100644 index 0000000000..e1e3dd5441 --- /dev/null +++ b/docs/metrics/storage/storageclass-metrics.md @@ -0,0 +1,8 @@ +# StorageClass Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_storageclass_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `storageclass`=<storageclass-name>
`annotation_STORAGECLASS_ANNOTATION`=<STORAGECLASS_ANNOTATION> | EXPERIMENTAL | +| kube_storageclass_info | Gauge | | `storageclass`=<storageclass-name>
`provisioner`=<storageclass-provisioner>
`reclaim_policy`=<storageclass-reclaimPolicy>
`volume_binding_mode`=<storageclass-volumeBindingMode> | STABLE | +| kube_storageclass_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `storageclass`=<storageclass-name>
`label_STORAGECLASS_LABEL`=<STORAGECLASS_LABEL> | STABLE | +| kube_storageclass_created | Gauge | | `storageclass`=<storageclass-name> | STABLE | diff --git a/docs/metrics/storage/volumeattachment-metrics.md b/docs/metrics/storage/volumeattachment-metrics.md new file mode 100644 index 0000000000..b56be11a1f --- /dev/null +++ b/docs/metrics/storage/volumeattachment-metrics.md @@ -0,0 +1,10 @@ +# VolumeAttachment Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| -------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_volumeattachment_info | Gauge | | `volumeattachment`=<volumeattachment-name>
`attacher`=<attacher-name>
`node`=<node-name> | EXPERIMENTAL | +| kube_volumeattachment_created | Gauge | | `volumeattachment`=<volumeattachment-name> | EXPERIMENTAL | +| kube_volumeattachment_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `volumeattachment`=<volumeattachment-name>
`label_VOLUMEATTACHMENT_LABEL`=<VOLUMEATTACHMENT_LABEL> | EXPERIMENTAL | +| kube_volumeattachment_spec_source_persistentvolume | Gauge | | `volumeattachment`=<volumeattachment-name>
`volumename`=<persistentvolume-name> | EXPERIMENTAL | +| kube_volumeattachment_status_attached | Gauge | | `volumeattachment`=<volumeattachment-name> | EXPERIMENTAL | +| kube_volumeattachment_status_attachment_metadata | Gauge | | `volumeattachment`=<volumeattachment-name>
`metadata_METADATA_KEY`=<METADATA_VALUE> | EXPERIMENTAL | diff --git a/docs/metrics/workload/cronjob-metrics.md b/docs/metrics/workload/cronjob-metrics.md new file mode 100644 index 0000000000..ae32dc65d8 --- /dev/null +++ b/docs/metrics/workload/cronjob-metrics.md @@ -0,0 +1,17 @@ +# CronJob Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_cronjob_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace>
`annotation_CRONJOB_ANNOTATION`=<CRONJOB_ANNOTATION> | EXPERIMENTAL | +| kube_cronjob_info | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace>
`schedule`=<schedule>
`concurrency_policy`=<concurrency-policy> | STABLE | +| kube_cronjob_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace>
`label_CRONJOB_LABEL`=<CRONJOB_LABEL> | STABLE | +| kube_cronjob_created | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_next_schedule_time | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_status_active | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_status_last_schedule_time | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_status_last_successful_time | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | EXPERIMENTAL | +| kube_cronjob_spec_suspend | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_spec_starting_deadline_seconds | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_metadata_resource_version | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | STABLE | +| kube_cronjob_spec_successful_job_history_limit | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | EXPERIMENTAL | +| kube_cronjob_spec_failed_job_history_limit | Gauge | | `cronjob`=<cronjob-name>
`namespace`=<cronjob-namespace> | EXPERIMENTAL | diff --git a/docs/metrics/workload/daemonset-metrics.md b/docs/metrics/workload/daemonset-metrics.md new file mode 100644 index 0000000000..04c5edf4e0 --- /dev/null +++ b/docs/metrics/workload/daemonset-metrics.md @@ -0,0 +1,16 @@ +# DaemonSet Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_daemonset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace>
`annotation_DAEMONSET_ANNOTATION`=<DAEMONSET_ANNOTATION> | EXPERIMENTAL | +| kube_daemonset_created | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_current_number_scheduled | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_desired_number_scheduled | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_number_available | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_number_misscheduled | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_number_ready | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_number_unavailable | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_observed_generation | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_status_updated_number_scheduled | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_metadata_generation | Gauge | | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace> | STABLE | +| kube_daemonset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `daemonset`=<daemonset-name>
`namespace`=<daemonset-namespace>
`label_DAEMONSET_LABEL`=<DAEMONSET_LABEL> | STABLE | diff --git a/docs/metrics/workload/deployment-metrics.md b/docs/metrics/workload/deployment-metrics.md new file mode 100644 index 0000000000..94f5159015 --- /dev/null +++ b/docs/metrics/workload/deployment-metrics.md @@ -0,0 +1,19 @@ +# 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 | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | +| kube_deployment_status_replicas_ready | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | +| kube_deployment_status_replicas_available | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | +| 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_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 | +| kube_deployment_spec_strategy_rollingupdate_max_surge | Gauge | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | +| kube_deployment_metadata_generation | Gauge | | `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 | | `deployment`=<deployment-name>
`namespace`=<deployment-namespace> | STABLE | diff --git a/docs/metrics/workload/horizontalpodautoscaler-metrics.md b/docs/metrics/workload/horizontalpodautoscaler-metrics.md new file mode 100644 index 0000000000..383bdca13f --- /dev/null +++ b/docs/metrics/workload/horizontalpodautoscaler-metrics.md @@ -0,0 +1,15 @@ +# Horizontal Pod Autoscaler Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ---------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_horizontalpodautoscaler_info | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace>
`scaletargetref_api_version`=<hpa-target-api-version>
`scaletargetref_kind`=<hpa-target-kind>
`scaletargetref_name`=<hpa-target-name> | EXPERIMENTAL | +| kube_horizontalpodautoscaler_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | EXPERIMENTAL | +| kube_horizontalpodautoscaler_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | +| kube_horizontalpodautoscaler_metadata_generation | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | +| kube_horizontalpodautoscaler_spec_max_replicas | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | +| kube_horizontalpodautoscaler_spec_min_replicas | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | +| kube_horizontalpodautoscaler_spec_target_metric | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace>
`metric_name`=<metric-name>
`metric_target_type`=<value\|utilization\|average> | EXPERIMENTAL | +| kube_horizontalpodautoscaler_status_target_metric | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace>
`metric_name`=<metric-name>
`metric_target_type`=<value\|utilization\|average> | EXPERIMENTAL | +| kube_horizontalpodautoscaler_status_condition | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace>
`condition`=<hpa-condition>
`status`=<true\|false\|unknown> | STABLE | +| kube_horizontalpodautoscaler_status_current_replicas | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | +| kube_horizontalpodautoscaler_status_desired_replicas | Gauge | | `horizontalpodautoscaler`=<hpa-name>
`namespace`=<hpa-namespace> | STABLE | diff --git a/docs/metrics/workload/job-metrics.md b/docs/metrics/workload/job-metrics.md new file mode 100644 index 0000000000..d5959c4dd7 --- /dev/null +++ b/docs/metrics/workload/job-metrics.md @@ -0,0 +1,19 @@ +# Job Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_job_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `job_name`=<job-name>
`namespace`=<job-namespace>
`annotation_JOB_ANNOTATION`=<JOB_ANNOTATION> | EXPERIMENTAL | +| kube_job_info | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `job_name`=<job-name>
`namespace`=<job-namespace>
`label_JOB_LABEL`=<JOB_LABEL> | STABLE | +| kube_job_owner | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller> | STABLE | +| kube_job_spec_parallelism | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_spec_completions | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_spec_active_deadline_seconds | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_status_active | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_status_succeeded | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_status_failed | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace>
`reason`=<failure reason> | STABLE | +| kube_job_status_start_time | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_status_completion_time | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | +| kube_job_complete | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace>
`condition`=<true\|false\|unknown> | STABLE | +| kube_job_failed | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace>
`condition`=<true\|false\|unknown> | STABLE | +| kube_job_created | Gauge | | `job_name`=<job-name>
`namespace`=<job-namespace> | STABLE | diff --git a/docs/metrics/workload/pod-metrics.md b/docs/metrics/workload/pod-metrics.md new file mode 100644 index 0000000000..8b8ed9116a --- /dev/null +++ b/docs/metrics/workload/pod-metrics.md @@ -0,0 +1,87 @@ +# Pod Metrics + +| Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | Opt-in | +| ----------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------ | +| kube_pod_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`annotation_POD_ANNOTATION`=<POD_ANNOTATION>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_info | Gauge | Information about pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`host_ip`=<host-ip>
`pod_ip`=<pod-ip>
`node`=<node-name>
`created_by_kind`=<created_by_kind>
`created_by_name`=<created_by_name>
`uid`=<pod-uid>
`priority_class`=<priority_class>
`host_network`=<host_network> | STABLE | - | +| kube_pod_ips | Gauge | Pod IP addresses | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`ip`=<pod-ip-address>
`ip_family`=<4 OR 6>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_start_time | Gauge | Start time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_completion_time | Gauge | Completion time in unix timestamp for a pod | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_owner | Gauge | Information about the Pod's owner | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`label_POD_LABEL`=<POD_LABEL>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_nodeselectors | Gauge | Describes the Pod nodeSelectors | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`nodeselector_NODE_SELECTOR`=<NODE_SELECTOR>
`uid`=<pod-uid> | EXPERIMENTAL | Opt-in | +| kube_pod_status_phase | Gauge | The pods current phase | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`phase`=<Pending\|Running\|Succeeded\|Failed\|Unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_qos_class | Gauge | The pods current qosClass | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`qos_class`=<BestEffort\|Burstable\|Guaranteed>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_status_ready | Gauge | Describes whether the pod is ready to serve requests | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_scheduled | Gauge | Describes the status of the scheduling process for the pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`condition`=<true\|false\|unknown>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_info | Gauge | Information about a container in a pod | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_waiting | Gauge | Describes whether the container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_waiting_reason | Gauge | Describes the reason the container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-waiting-reason>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_running | Gauge | Describes whether the container is currently in running state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_state_started | Gauge | Start time in unix timestamp for a pod container | seconds | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_terminated | Gauge | Describes whether the container is currently in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_status_terminated_reason | Gauge | Describes the reason the container is currently in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_last_terminated_timestamp | Gauge | Last terminated time for a pod container in unix timestamp. | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_initialized_time | Gauge | Time when the pod is initialized. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_status_ready_time | Gauge | Time when pod passed readiness probes. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_status_container_ready_time | Gauge | Time when the container of the pod entered Ready state. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | `container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_container_resource_requests | Gauge | The number of requested request resource by a container. It is recommended to use the `kube_pod_resource_requests` metric exposed by kube-scheduler instead, as it is more precise. | `cpu`=<core>
`memory`=<bytes> | `resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_container_resource_limits | Gauge | The number of requested limit resource by a container. It is recommended to use the `kube_pod_resource_limits` metric exposed by kube-scheduler instead, as it is more precise. | `cpu`=<core>
`memory`=<bytes> | `resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_overhead_cpu_cores | Gauge | The pod overhead in regards to cpu cores associated with running a pod | core | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_overhead_memory_bytes | Gauge | The pod overhead in regards to memory associated with running a pod | bytes | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_runtimeclass_name_info | Gauge | The runtimeclass associated with the pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_created | Gauge | Unix creation timestamp | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_restart_policy | Gauge | Describes the restart policy in use by this pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`type`=<Always\|Never\|OnFailure>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_info | Gauge | Information about an init container in a pod | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`image`=<image-name>
`image_id`=<image-id>
`image_spec`=<image-spec>
`container_id`=<containerid>
`uid`=<pod-uid>
`restart_policy`=<restart-policy> | STABLE | - | +| kube_pod_init_container_status_waiting | Gauge | Describes whether the init container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_waiting_reason | Gauge | Describes the reason the init container is currently in waiting state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-waiting-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_status_running | Gauge | Describes whether the init container is currently in running state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_terminated | Gauge | Describes whether the init container is currently in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_terminated_reason | Gauge | Describes the reason the init container is currently in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<container-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_status_last_terminated_reason | Gauge | Describes the last reason the init container was in terminated state | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_status_ready | Gauge | Describes whether the init containers readiness check succeeded | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_status_restarts_total | Counter | The number of restarts for the init container | integer | `container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_init_container_resource_limits | Gauge | The number of CPU cores requested limit by an init container | `cpu`=<core>
`memory`=<bytes> | `resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_init_container_resource_requests | Gauge | The number of CPU cores requested by an init container | `cpu`=<core>
`memory`=<bytes> | `resource`=<resource-name>
`unit`=<resource-unit>
`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`node`=< node-name>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_spec_volumes_persistentvolumeclaims_info | Gauge | Information about persistentvolumeclaim volumes in a pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_spec_volumes_persistentvolumeclaims_readonly | Gauge | Describes whether a persistentvolumeclaim is mounted read only | bool | `pod`=<pod-name>
`namespace`=<pod-namespace>
`volume`=<volume-name>
`persistentvolumeclaim`=<persistentvolumeclaim-claimname>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_reason | Gauge | The pod status reasons | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<Evicted\|NodeAffinity\|NodeLost\|Shutdown\|UnexpectedAdmissionError>
`uid`=<pod-uid> | EXPERIMENTAL | - | +| kube_pod_status_scheduled_time | Gauge | Unix timestamp when pod moved into scheduled status | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_unschedulable | Gauge | Describes the unschedulable status for the pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_tolerations | Gauge | Information about the pod tolerations | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid>
`key`=<toleration-key>
`operator`=<toleration-operator>
`value`=<toleration-value>
`effect`=<toleration-effect> `toleration_seconds`=<toleration-seconds> | EXPERIMENTAL | - | +| kube_pod_service_account | Gauge | The service account for a pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid>
`service_account`=<service_account> | EXPERIMENTAL | - | +| kube_pod_scheduler | Gauge | The scheduler for a pod | | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid>
`name`=<scheduler-name> | EXPERIMENTAL | - | + +## Useful metrics queries + +### How to retrieve non-standard Pod state + +It is not straightforward to get the Pod states for certain cases like "Terminating" and "Unknown" since it is not stored behind a field in the `Pod.Status`. + +So to mimic the [logic](https://github.com/kubernetes/kubernetes/blob/v1.17.3/pkg/printers/internalversion/printers.go#L624) used by the `kubectl` command line, you will need to compose multiple metrics. + +For example: + +* To get the list of pods that are in the `Unknown` state, you can run the following PromQL query: `sum(kube_pod_status_phase{phase="Unknown"}) by (namespace, pod) or (count(kube_pod_deletion_timestamp) by (namespace, pod) * sum(kube_pod_status_reason{reason="NodeLost"}) by(namespace, pod))` + +* For Pods in `Terminating` state: `count(kube_pod_deletion_timestamp) by (namespace, pod) * count(kube_pod_status_reason{reason="NodeLost"} == 0) by (namespace, pod)` + +Here is an example of a Prometheus rule that can be used to alert on a Pod that has been in the `Terminating` state for more than `5m`. + +```yaml +groups: +- name: Pod state + rules: + - alert: PodsBlockedInTerminatingState + expr: count(kube_pod_deletion_timestamp) by (namespace, pod) * count(kube_pod_status_reason{reason="NodeLost"} == 0) by (namespace, pod) > 0 + for: 5m + labels: + severity: page + annotations: + summary: Pod {{$labels.namespace}}/{{$labels.pod}} blocked in Terminating state. +``` diff --git a/docs/metrics/workload/replicaset-metrics.md b/docs/metrics/workload/replicaset-metrics.md new file mode 100644 index 0000000000..cf3f8e6e10 --- /dev/null +++ b/docs/metrics/workload/replicaset-metrics.md @@ -0,0 +1,14 @@ +# ReplicaSet metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| --------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_replicaset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace>
`annotation_REPLICASET_ANNOTATION`=<REPLICASET_ANNOTATION> | EXPERIMENTAL | +| kube_replicaset_status_replicas | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_status_fully_labeled_replicas | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_status_ready_replicas | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_status_observed_generation | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_spec_replicas | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_metadata_generation | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace>
`label_REPLICASET_LABEL`=<REPLICASET_LABEL> | STABLE | +| kube_replicaset_created | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace> | STABLE | +| kube_replicaset_owner | Gauge | | `replicaset`=<replicaset-name>
`namespace`=<replicaset-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller> | STABLE | diff --git a/docs/metrics/workload/replicationcontroller-metrics.md b/docs/metrics/workload/replicationcontroller-metrics.md new file mode 100644 index 0000000000..afa4e5eec8 --- /dev/null +++ b/docs/metrics/workload/replicationcontroller-metrics.md @@ -0,0 +1,13 @@ +# ReplicationController metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| -------------------------------------------------------- | ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | +| kube_replicationcontroller_status_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_status_fully_labeled_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_status_ready_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_status_available_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_status_observed_generation | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_spec_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_metadata_generation | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_created | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | +| kube_replicationcontroller_owner | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace>
`owner_kind`=<owner kind>
`owner_name`=<owner name>
`owner_is_controller`=<whether owner is controller> | EXPERIMENTAL | diff --git a/docs/metrics/workload/statefulset-metrics.md b/docs/metrics/workload/statefulset-metrics.md new file mode 100644 index 0000000000..b3a47fd125 --- /dev/null +++ b/docs/metrics/workload/statefulset-metrics.md @@ -0,0 +1,19 @@ +# Stateful Set Metrics + +| Metric name | Metric type | Description | Labels/tags | Status | +| ------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| kube_statefulset_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`annotation_STATEFULSET_ANNOTATION`=<STATEFULSET_ANNOTATION> | EXPERIMENTAL | +| kube_statefulset_status_replicas | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_status_replicas_current | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_status_replicas_ready | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_status_replicas_available | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | EXPERIMENTAL | +| kube_statefulset_status_replicas_updated | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_status_observed_generation | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_replicas | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_ordinals_start | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | ALPHA | +| kube_statefulset_metadata_generation | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_persistentvolumeclaim_retention_policy | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`when_deleted`=<statefulset-when-deleted-pvc-policy>
`when_scaled`=<statefulset-when-scaled-pvc-policy> | EXPERIMENTAL | +| kube_statefulset_created | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace> | STABLE | +| kube_statefulset_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`label_STATEFULSET_LABEL`=<STATEFULSET_LABEL> | STABLE | +| kube_statefulset_status_current_revision | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`revision`=<statefulset-current-revision> | STABLE | +| kube_statefulset_status_update_revision | Gauge | | `statefulset`=<statefulset-name>
`namespace`=<statefulset-namespace>
`revision`=<statefulset-update-revision> | STABLE | diff --git a/examples/autosharding/cluster-role-binding.yaml b/examples/autosharding/cluster-role-binding.yaml index 917460705c..11cdc294a8 100644 --- a/examples/autosharding/cluster-role-binding.yaml +++ b/examples/autosharding/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml index 39b6cdc73a..d330803f9b 100644 --- a/examples/autosharding/cluster-role.yaml +++ b/examples/autosharding/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/autosharding/role-binding.yaml b/examples/autosharding/role-binding.yaml index 2bf840aa54..a8bc73d9c1 100644 --- a/examples/autosharding/role-binding.yaml +++ b/examples/autosharding/role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system roleRef: diff --git a/examples/autosharding/role.yaml b/examples/autosharding/role.yaml index e3c0201e40..464e44658c 100644 --- a/examples/autosharding/role.yaml +++ b/examples/autosharding/role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system rules: diff --git a/examples/autosharding/service-account.yaml b/examples/autosharding/service-account.yaml index 3f37231919..8107dcf62c 100644 --- a/examples/autosharding/service-account.yaml +++ b/examples/autosharding/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/autosharding/service.yaml b/examples/autosharding/service.yaml index 279e867735..f32d1001bb 100644 --- a/examples/autosharding/service.yaml +++ b/examples/autosharding/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/examples/autosharding/statefulset.yaml b/examples/autosharding/statefulset.yaml index 37dd37153f..a0ccaad8d2 100644 --- a/examples/autosharding/statefulset.yaml +++ b/examples/autosharding/statefulset.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: @@ -18,7 +18,7 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 spec: automountServiceAccountToken: true containers: @@ -34,11 +34,11 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0 livenessProbe: httpGet: - path: /healthz - port: 8080 + path: /livez + port: http-metrics initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics @@ -49,8 +49,8 @@ spec: name: telemetry readinessProbe: httpGet: - path: / - port: 8081 + path: /readyz + port: telemetry initialDelaySeconds: 5 timeoutSeconds: 5 securityContext: diff --git a/examples/daemonsetsharding/cluster-role-binding.yaml b/examples/daemonsetsharding/cluster-role-binding.yaml index 917460705c..11cdc294a8 100644 --- a/examples/daemonsetsharding/cluster-role-binding.yaml +++ b/examples/daemonsetsharding/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/daemonsetsharding/cluster-role.yaml b/examples/daemonsetsharding/cluster-role.yaml index 39b6cdc73a..d330803f9b 100644 --- a/examples/daemonsetsharding/cluster-role.yaml +++ b/examples/daemonsetsharding/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/daemonsetsharding/daemonset-service.yaml b/examples/daemonsetsharding/daemonset-service.yaml index 35560e4354..82bbc568bb 100644 --- a/examples/daemonsetsharding/daemonset-service.yaml +++ b/examples/daemonsetsharding/daemonset-service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics-shard namespace: kube-system spec: diff --git a/examples/daemonsetsharding/daemonset.yaml b/examples/daemonsetsharding/daemonset.yaml index 7a4ea43d87..f0d78d6fd7 100644 --- a/examples/daemonsetsharding/daemonset.yaml +++ b/examples/daemonsetsharding/daemonset.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics-shard namespace: kube-system spec: @@ -16,7 +16,7 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 spec: automountServiceAccountToken: true containers: @@ -29,11 +29,11 @@ spec: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0 livenessProbe: httpGet: - path: /healthz - port: 8080 + path: /livez + port: http-metrics initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics-shard @@ -44,8 +44,8 @@ spec: name: telemetry readinessProbe: httpGet: - path: / - port: 8081 + path: /readyz + port: telemetry initialDelaySeconds: 5 timeoutSeconds: 5 securityContext: diff --git a/examples/daemonsetsharding/deployment-no-node-pods.yaml b/examples/daemonsetsharding/deployment-no-node-pods.yaml index a4b4032214..6bea075af7 100644 --- a/examples/daemonsetsharding/deployment-no-node-pods.yaml +++ b/examples/daemonsetsharding/deployment-no-node-pods.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-pods - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics-pods namespace: kube-system spec: @@ -17,18 +17,18 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 spec: automountServiceAccountToken: true containers: - args: - --resources=pods - --node="" - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0 livenessProbe: httpGet: - path: /healthz - port: 8080 + path: /livez + port: http-metrics initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics @@ -39,8 +39,8 @@ spec: name: telemetry readinessProbe: httpGet: - path: / - port: 8081 + path: /readyz + port: telemetry initialDelaySeconds: 5 timeoutSeconds: 5 securityContext: diff --git a/examples/daemonsetsharding/deployment-service.yaml b/examples/daemonsetsharding/deployment-service.yaml index 279e867735..f32d1001bb 100644 --- a/examples/daemonsetsharding/deployment-service.yaml +++ b/examples/daemonsetsharding/deployment-service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/examples/daemonsetsharding/deployment.yaml b/examples/daemonsetsharding/deployment.yaml index cbd6d7dd8d..fcc95bceb5 100644 --- a/examples/daemonsetsharding/deployment.yaml +++ b/examples/daemonsetsharding/deployment.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: @@ -17,17 +17,17 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 spec: automountServiceAccountToken: true containers: - args: - --resources=certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0 livenessProbe: httpGet: - path: /healthz - port: 8080 + path: /livez + port: http-metrics initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics @@ -38,8 +38,8 @@ spec: name: telemetry readinessProbe: httpGet: - path: / - port: 8081 + path: /readyz + port: telemetry initialDelaySeconds: 5 timeoutSeconds: 5 securityContext: diff --git a/examples/daemonsetsharding/service-account.yaml b/examples/daemonsetsharding/service-account.yaml index 3f37231919..8107dcf62c 100644 --- a/examples/daemonsetsharding/service-account.yaml +++ b/examples/daemonsetsharding/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/standard/cluster-role-binding.yaml b/examples/standard/cluster-role-binding.yaml index 917460705c..11cdc294a8 100644 --- a/examples/standard/cluster-role-binding.yaml +++ b/examples/standard/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml index 39b6cdc73a..d330803f9b 100644 --- a/examples/standard/cluster-role.yaml +++ b/examples/standard/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/standard/deployment.yaml b/examples/standard/deployment.yaml index 85c3cec3e4..85539fc1d4 100644 --- a/examples/standard/deployment.yaml +++ b/examples/standard/deployment.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: @@ -17,15 +17,15 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 spec: automountServiceAccountToken: true containers: - - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.12.0 + - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0 livenessProbe: httpGet: - path: /healthz - port: 8080 + path: /livez + port: http-metrics initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics @@ -36,8 +36,8 @@ spec: name: telemetry readinessProbe: httpGet: - path: / - port: 8081 + path: /readyz + port: telemetry initialDelaySeconds: 5 timeoutSeconds: 5 securityContext: diff --git a/examples/standard/kustomization.yaml b/examples/standard/kustomization.yaml new file mode 100644 index 0000000000..2090c7fd94 --- /dev/null +++ b/examples/standard/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: kube-system + +resources: +- cluster-role.yaml +- cluster-role-binding.yaml +- service-account.yaml +- deployment.yaml +- service.yaml diff --git a/examples/standard/service-account.yaml b/examples/standard/service-account.yaml index 3f37231919..8107dcf62c 100644 --- a/examples/standard/service-account.yaml +++ b/examples/standard/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/standard/service.yaml b/examples/standard/service.yaml index 279e867735..f32d1001bb 100644 --- a/examples/standard/service.yaml +++ b/examples/standard/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.12.0 + app.kubernetes.io/version: 2.13.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/go.mod b/go.mod index d8b545f64a..f51bc6d30a 100644 --- a/go.mod +++ b/go.mod @@ -1,37 +1,43 @@ module k8s.io/kube-state-metrics/v2 -go 1.21 +go 1.22.0 + +toolchain go1.22.5 require ( + github.com/KimMachineGun/automemlimit v0.6.1 github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 github.com/fsnotify/fsnotify v1.7.0 github.com/gobuffalo/flect v1.0.2 github.com/google/go-cmp v0.6.0 github.com/oklog/run v1.1.0 - github.com/prometheus/client_golang v1.19.0 - github.com/prometheus/client_model v0.6.0 - github.com/prometheus/common v0.51.1 + github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.55.0 github.com/prometheus/exporter-toolkit v0.11.0 github.com/robfig/cron/v3 v3.0.1 - github.com/spf13/cobra v1.8.0 - github.com/spf13/viper v1.18.2 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/client-go v0.29.3 - k8s.io/component-base v0.29.3 - k8s.io/klog/v2 v2.120.1 - k8s.io/sample-controller v0.29.3 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/api v0.30.3 + k8s.io/apimachinery v0.30.3 + k8s.io/client-go v0.30.3 + k8s.io/component-base v0.30.3 + k8s.io/klog/v2 v2.130.1 + k8s.io/sample-controller v0.30.3 + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cilium/ebpf v0.9.1 // indirect + github.com/containerd/cgroups/v3 v3.0.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/docker/go-units v0.4.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/go-kit/log v0.2.1 // indirect @@ -40,6 +46,7 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/godbus/dbus/v5 v5.0.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect @@ -58,12 +65,15 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -73,18 +83,17 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index e82c87c95a..d22a722d59 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,18 @@ +github.com/KimMachineGun/automemlimit v0.6.1 h1:ILa9j1onAAMadBsyyUJv5cack8Y1WT26yLj/V+ulKp8= +github.com/KimMachineGun/automemlimit v0.6.1/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= +github.com/containerd/cgroups/v3 v3.0.1 h1:4hfGvu8rfGIwVIDd+nLzn/B9ZXx4BcCjzt5ToenJRaE= +github.com/containerd/cgroups/v3 v3.0.1/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -14,6 +20,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0 h1:0wH6nO9QEa02Qx8sIQGw6ieKdz+BXjpccSOo9vXNl4U= github.com/dgryski/go-jump v0.0.0-20211018200510-ba001c3ffce0/go.mod h1:4hKCXuwrJoYvHZxJ86+bRVTOMyJ0Ej+RqfSm8mHi6KA= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= @@ -38,10 +46,10 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= +github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -94,27 +102,31 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= +github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4DsQCw= -github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -124,21 +136,25 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -150,6 +166,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -162,14 +180,13 @@ golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqR golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -177,13 +194,13 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= @@ -199,10 +216,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -216,22 +231,22 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= -k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= -k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/sample-controller v0.29.3 h1:1g96iu1sH9zFaZ4Nq7s10R1eq1cNgiM9l/F4ttEURJI= -k8s.io/sample-controller v0.29.3/go.mod h1:zjhfoVX5Bcf7G4yNUoUmhXbVMMqM+TUoz3pILzH0OLo= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= +k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04= +k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc= +k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= +k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= +k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s= +k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/sample-controller v0.30.3 h1:oZTxERF8U3gANT2H5VxpkW32asgmW0IYGyUv9Opspvs= +k8s.io/sample-controller v0.30.3/go.mod h1:yhy/cWCzevQLa2+7Gvj0J9+xzmNExypunffSNANBy7o= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/internal/store/clusterrole.go b/internal/store/clusterrole.go index 86642ab229..127d513a7f 100644 --- a/internal/store/clusterrole.go +++ b/internal/store/clusterrole.go @@ -91,7 +91,7 @@ func clusterRoleMetricFamilies(allowAnnotationsList, allowLabelsList []string) [ metric.Gauge, basemetrics.ALPHA, "", - wrapClusterRoleFunc(func(r *rbacv1.ClusterRole) *metric.Family { + wrapClusterRoleFunc(func(_ *rbacv1.ClusterRole) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{{ LabelKeys: []string{}, diff --git a/internal/store/configmap.go b/internal/store/configmap.go index 90e6029ac3..dff11ea513 100644 --- a/internal/store/configmap.go +++ b/internal/store/configmap.go @@ -87,7 +87,7 @@ func configMapMetricFamilies(allowAnnotationsList, allowLabelsList []string) []g metric.Gauge, basemetrics.STABLE, "", - wrapConfigMapFunc(func(c *v1.ConfigMap) *metric.Family { + wrapConfigMapFunc(func(_ *v1.ConfigMap) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{{ LabelKeys: []string{}, diff --git a/internal/store/endpoint.go b/internal/store/endpoint.go index fb527eeb63..482eb98e2c 100644 --- a/internal/store/endpoint.go +++ b/internal/store/endpoint.go @@ -48,7 +48,7 @@ func endpointMetricFamilies(allowAnnotationsList, allowLabelsList []string) []ge metric.Gauge, basemetrics.STABLE, "", - wrapEndpointFunc(func(e *v1.Endpoints) *metric.Family { + wrapEndpointFunc(func(_ *v1.Endpoints) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{ { diff --git a/internal/store/job.go b/internal/store/job.go index d778212bbd..6e0e97b218 100644 --- a/internal/store/job.go +++ b/internal/store/job.go @@ -94,7 +94,7 @@ func jobMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat metric.Gauge, basemetrics.STABLE, "", - wrapJobFunc(func(j *v1batch.Job) *metric.Family { + wrapJobFunc(func(_ *v1batch.Job) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{ { diff --git a/internal/store/mutatingwebhookconfiguration.go b/internal/store/mutatingwebhookconfiguration.go index c09df4773f..394fd8483e 100644 --- a/internal/store/mutatingwebhookconfiguration.go +++ b/internal/store/mutatingwebhookconfiguration.go @@ -41,7 +41,7 @@ var ( metric.Gauge, basemetrics.ALPHA, "", - wrapMutatingWebhookConfigurationFunc(func(mwc *admissionregistrationv1.MutatingWebhookConfiguration) *metric.Family { + wrapMutatingWebhookConfigurationFunc(func(_ *admissionregistrationv1.MutatingWebhookConfiguration) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{ { diff --git a/internal/store/persistentvolume.go b/internal/store/persistentvolume.go index 53f21bdd6e..33d8ca0038 100644 --- a/internal/store/persistentvolume.go +++ b/internal/store/persistentvolume.go @@ -34,9 +34,8 @@ import ( ) var ( - descPersistentVolumeClaimRefName = "kube_persistentvolume_claim_ref" - descPersistentVolumeClaimRefHelp = "Information about the Persistent Volume Claim Reference." - descPersistentVolumeClaimRefDefaultLabels = []string{"persistentvolume"} + descPersistentVolumeClaimRefName = "kube_persistentvolume_claim_ref" + descPersistentVolumeClaimRefHelp = "Information about the Persistent Volume Claim Reference." descPersistentVolumeAnnotationsName = "kube_persistentvolume_annotations" descPersistentVolumeAnnotationsHelp = "Kubernetes annotations converted to Prometheus labels." @@ -50,372 +49,436 @@ var ( func persistentVolumeMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generator.FamilyGenerator { return []generator.FamilyGenerator{ - *generator.NewFamilyGeneratorWithStability( - descPersistentVolumeClaimRefName, - descPersistentVolumeClaimRefHelp, - metric.Gauge, - basemetrics.STABLE, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - claimRef := p.Spec.ClaimRef - - if claimRef == nil { - return &metric.Family{ - Metrics: []*metric.Metric{}, - } - } + createPersistentVolumeClaimRef(), + createPersistentVolumeAnnotations(allowAnnotationsList), + createPersistentVolumeLabels(allowLabelsList), + createPersistentVolumeStatusPhase(), + createPersistentVolumeInfo(), + createPersistentVolumeCapacityBytes(), + createPersistentVolumeCreated(), + createPersistentVolumeDeletionTimestamp(), + createPersistentVolumeCSIAttributes(), + createPersistentVolumeMode(), + } +} + +func wrapPersistentVolumeFunc(f func(*v1.PersistentVolume) *metric.Family) func(interface{}) *metric.Family { + return func(obj interface{}) *metric.Family { + persistentVolume := obj.(*v1.PersistentVolume) + + metricFamily := f(persistentVolume) + + for _, m := range metricFamily.Metrics { + m.LabelKeys, m.LabelValues = mergeKeyValues(descPersistentVolumeLabelsDefaultLabels, []string{persistentVolume.Name}, m.LabelKeys, m.LabelValues) + } + + return metricFamily + } +} + +func createPersistentVolumeListWatch(kubeClient clientset.Interface, _ string, _ string) cache.ListerWatcher { + return &cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { + return kubeClient.CoreV1().PersistentVolumes().List(context.TODO(), opts) + }, + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { + return kubeClient.CoreV1().PersistentVolumes().Watch(context.TODO(), opts) + }, + } +} + +func createPersistentVolumeClaimRef() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + descPersistentVolumeClaimRefName, + descPersistentVolumeClaimRefHelp, + metric.Gauge, + basemetrics.STABLE, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + claimRef := p.Spec.ClaimRef + + if claimRef == nil { return &metric.Family{ - Metrics: []*metric.Metric{ - { - LabelKeys: []string{ - "name", - "claim_namespace", - }, - LabelValues: []string{ - p.Spec.ClaimRef.Name, - p.Spec.ClaimRef.Namespace, - }, - Value: 1, - }, - }, + Metrics: []*metric.Metric{}, } - }), - ), - *generator.NewFamilyGeneratorWithStability( - descPersistentVolumeAnnotationsName, - descPersistentVolumeAnnotationsHelp, - metric.Gauge, - basemetrics.ALPHA, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - if len(allowAnnotationsList) == 0 { - return &metric.Family{} - } - annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList) - return &metric.Family{ - Metrics: []*metric.Metric{ - { - LabelKeys: annotationKeys, - LabelValues: annotationValues, - Value: 1, + } + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: []string{ + "name", + "claim_namespace", }, - }, - } - }), - ), - *generator.NewFamilyGeneratorWithStability( - descPersistentVolumeLabelsName, - descPersistentVolumeLabelsHelp, - metric.Gauge, - basemetrics.STABLE, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - if len(allowLabelsList) == 0 { - return &metric.Family{} - } - labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList) - return &metric.Family{ - Metrics: []*metric.Metric{ - { - LabelKeys: labelKeys, - LabelValues: labelValues, - Value: 1, + LabelValues: []string{ + p.Spec.ClaimRef.Name, + p.Spec.ClaimRef.Namespace, }, + Value: 1, }, - } - }), - ), - *generator.NewFamilyGeneratorWithStability( - "kube_persistentvolume_status_phase", - "The phase indicates if a volume is available, bound to a claim, or released by a claim.", - metric.Gauge, - basemetrics.STABLE, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - phase := p.Status.Phase - - if phase == "" { - return &metric.Family{ - Metrics: []*metric.Metric{}, - } - } + }, + } + }), + ) +} - // Set current phase to 1, others to 0 if it is set. - ms := []*metric.Metric{ - { - LabelValues: []string{string(v1.VolumePending)}, - Value: boolFloat64(phase == v1.VolumePending), - }, +func createPersistentVolumeAnnotations(allowAnnotationsList []string) generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + descPersistentVolumeAnnotationsName, + descPersistentVolumeAnnotationsHelp, + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + if len(allowAnnotationsList) == 0 { + return &metric.Family{} + } + annotationKeys, annotationValues := createPrometheusLabelKeysValues("annotation", p.Annotations, allowAnnotationsList) + return &metric.Family{ + Metrics: []*metric.Metric{ { - LabelValues: []string{string(v1.VolumeAvailable)}, - Value: boolFloat64(phase == v1.VolumeAvailable), - }, - { - LabelValues: []string{string(v1.VolumeBound)}, - Value: boolFloat64(phase == v1.VolumeBound), - }, - { - LabelValues: []string{string(v1.VolumeReleased)}, - Value: boolFloat64(phase == v1.VolumeReleased), + LabelKeys: annotationKeys, + LabelValues: annotationValues, + Value: 1, }, + }, + } + }), + ) +} + +func createPersistentVolumeLabels(allowLabelsList []string) generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + descPersistentVolumeLabelsName, + descPersistentVolumeLabelsHelp, + metric.Gauge, + basemetrics.STABLE, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + if len(allowLabelsList) == 0 { + return &metric.Family{} + } + labelKeys, labelValues := createPrometheusLabelKeysValues("label", p.Labels, allowLabelsList) + return &metric.Family{ + Metrics: []*metric.Metric{ { - LabelValues: []string{string(v1.VolumeFailed)}, - Value: boolFloat64(phase == v1.VolumeFailed), + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, }, - } + }, + } + }), + ) +} - for _, m := range ms { - m.LabelKeys = []string{"phase"} - } +func createPersistentVolumeStatusPhase() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_status_phase", + "The phase indicates if a volume is available, bound to a claim, or released by a claim.", + metric.Gauge, + basemetrics.STABLE, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + phase := p.Status.Phase + if phase == "" { return &metric.Family{ - Metrics: ms, + Metrics: []*metric.Metric{}, } - }), - ), - *generator.NewFamilyGeneratorWithStability( - "kube_persistentvolume_info", - "Information about persistentvolume.", - metric.Gauge, - basemetrics.STABLE, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - var ( - gcePDDiskName, - ebsVolumeID, - azureDiskName, - fcWWIDs, fcLun, fcTargetWWNs, - iscsiTargetPortal, iscsiIQN, iscsiLun, iscsiInitiatorName, - nfsServer, nfsPath, - csiDriver, csiVolumeHandle, - localFS, localPath, - hostPath, hostPathType string - ) - - switch { - case p.Spec.PersistentVolumeSource.GCEPersistentDisk != nil: - gcePDDiskName = p.Spec.PersistentVolumeSource.GCEPersistentDisk.PDName - case p.Spec.PersistentVolumeSource.AWSElasticBlockStore != nil: - ebsVolumeID = p.Spec.PersistentVolumeSource.AWSElasticBlockStore.VolumeID - case p.Spec.PersistentVolumeSource.AzureDisk != nil: - azureDiskName = p.Spec.PersistentVolumeSource.AzureDisk.DiskName - case p.Spec.PersistentVolumeSource.FC != nil: - if p.Spec.PersistentVolumeSource.FC.Lun != nil { - fcLun = strconv.FormatInt(int64(*p.Spec.PersistentVolumeSource.FC.Lun), 10) - } - for _, wwn := range p.Spec.PersistentVolumeSource.FC.TargetWWNs { - if len(fcTargetWWNs) != 0 { - fcTargetWWNs += "," - } - fcTargetWWNs += wwn - } - for _, wwid := range p.Spec.PersistentVolumeSource.FC.WWIDs { - if len(fcWWIDs) != 0 { - fcWWIDs += "," - } - fcWWIDs += wwid - } - case p.Spec.PersistentVolumeSource.ISCSI != nil: - iscsiTargetPortal = p.Spec.PersistentVolumeSource.ISCSI.TargetPortal - iscsiIQN = p.Spec.PersistentVolumeSource.ISCSI.IQN - iscsiLun = strconv.FormatInt(int64(p.Spec.PersistentVolumeSource.ISCSI.Lun), 10) - if p.Spec.PersistentVolumeSource.ISCSI.InitiatorName != nil { - iscsiInitiatorName = *p.Spec.PersistentVolumeSource.ISCSI.InitiatorName - } - case p.Spec.PersistentVolumeSource.NFS != nil: - nfsServer = p.Spec.PersistentVolumeSource.NFS.Server - nfsPath = p.Spec.PersistentVolumeSource.NFS.Path - case p.Spec.PersistentVolumeSource.CSI != nil: - csiDriver = p.Spec.PersistentVolumeSource.CSI.Driver - csiVolumeHandle = p.Spec.PersistentVolumeSource.CSI.VolumeHandle - case p.Spec.PersistentVolumeSource.Local != nil: - localPath = p.Spec.PersistentVolumeSource.Local.Path - if p.Spec.PersistentVolumeSource.Local.FSType != nil { - localFS = *p.Spec.PersistentVolumeSource.Local.FSType + } + + // Set current phase to 1, others to 0 if it is set. + ms := []*metric.Metric{ + { + LabelValues: []string{string(v1.VolumePending)}, + Value: boolFloat64(phase == v1.VolumePending), + }, + { + LabelValues: []string{string(v1.VolumeAvailable)}, + Value: boolFloat64(phase == v1.VolumeAvailable), + }, + { + LabelValues: []string{string(v1.VolumeBound)}, + Value: boolFloat64(phase == v1.VolumeBound), + }, + { + LabelValues: []string{string(v1.VolumeReleased)}, + Value: boolFloat64(phase == v1.VolumeReleased), + }, + { + LabelValues: []string{string(v1.VolumeFailed)}, + Value: boolFloat64(phase == v1.VolumeFailed), + }, + } + + for _, m := range ms { + m.LabelKeys = []string{"phase"} + } + + return &metric.Family{ + Metrics: ms, + } + }), + ) +} + +func createPersistentVolumeInfo() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_info", + "Information about persistentvolume.", + metric.Gauge, + basemetrics.STABLE, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + var ( + gcePDDiskName, + ebsVolumeID, + azureDiskName, + fcWWIDs, fcLun, fcTargetWWNs, + iscsiTargetPortal, iscsiIQN, iscsiLun, iscsiInitiatorName, + nfsServer, nfsPath, + csiDriver, csiVolumeHandle, + localFS, localPath, + hostPath, hostPathType string + ) + + switch { + case p.Spec.PersistentVolumeSource.GCEPersistentDisk != nil: + gcePDDiskName = p.Spec.PersistentVolumeSource.GCEPersistentDisk.PDName + case p.Spec.PersistentVolumeSource.AWSElasticBlockStore != nil: + ebsVolumeID = p.Spec.PersistentVolumeSource.AWSElasticBlockStore.VolumeID + case p.Spec.PersistentVolumeSource.AzureDisk != nil: + azureDiskName = p.Spec.PersistentVolumeSource.AzureDisk.DiskName + case p.Spec.PersistentVolumeSource.FC != nil: + if p.Spec.PersistentVolumeSource.FC.Lun != nil { + fcLun = strconv.FormatInt(int64(*p.Spec.PersistentVolumeSource.FC.Lun), 10) + } + for _, wwn := range p.Spec.PersistentVolumeSource.FC.TargetWWNs { + if len(fcTargetWWNs) != 0 { + fcTargetWWNs += "," } - case p.Spec.PersistentVolumeSource.HostPath != nil: - hostPath = p.Spec.PersistentVolumeSource.HostPath.Path - if p.Spec.PersistentVolumeSource.HostPath.Type != nil { - hostPathType = string(*p.Spec.PersistentVolumeSource.HostPath.Type) + fcTargetWWNs += wwn + } + for _, wwid := range p.Spec.PersistentVolumeSource.FC.WWIDs { + if len(fcWWIDs) != 0 { + fcWWIDs += "," } + fcWWIDs += wwid + } + case p.Spec.PersistentVolumeSource.ISCSI != nil: + iscsiTargetPortal = p.Spec.PersistentVolumeSource.ISCSI.TargetPortal + iscsiIQN = p.Spec.PersistentVolumeSource.ISCSI.IQN + iscsiLun = strconv.FormatInt(int64(p.Spec.PersistentVolumeSource.ISCSI.Lun), 10) + if p.Spec.PersistentVolumeSource.ISCSI.InitiatorName != nil { + iscsiInitiatorName = *p.Spec.PersistentVolumeSource.ISCSI.InitiatorName + } + case p.Spec.PersistentVolumeSource.NFS != nil: + nfsServer = p.Spec.PersistentVolumeSource.NFS.Server + nfsPath = p.Spec.PersistentVolumeSource.NFS.Path + case p.Spec.PersistentVolumeSource.CSI != nil: + csiDriver = p.Spec.PersistentVolumeSource.CSI.Driver + csiVolumeHandle = p.Spec.PersistentVolumeSource.CSI.VolumeHandle + case p.Spec.PersistentVolumeSource.Local != nil: + localPath = p.Spec.PersistentVolumeSource.Local.Path + if p.Spec.PersistentVolumeSource.Local.FSType != nil { + localFS = *p.Spec.PersistentVolumeSource.Local.FSType + } + case p.Spec.PersistentVolumeSource.HostPath != nil: + hostPath = p.Spec.PersistentVolumeSource.HostPath.Path + if p.Spec.PersistentVolumeSource.HostPath.Type != nil { + hostPathType = string(*p.Spec.PersistentVolumeSource.HostPath.Type) } + } - return &metric.Family{ - Metrics: []*metric.Metric{ - { - LabelKeys: []string{ - "storageclass", - "gce_persistent_disk_name", - "ebs_volume_id", - "azure_disk_name", - "fc_wwids", - "fc_lun", - "fc_target_wwns", - "iscsi_target_portal", - "iscsi_iqn", - "iscsi_lun", - "iscsi_initiator_name", - "nfs_server", - "nfs_path", - "csi_driver", - "csi_volume_handle", - "local_path", - "local_fs", - "host_path", - "host_path_type", - }, - LabelValues: []string{ - p.Spec.StorageClassName, - gcePDDiskName, - ebsVolumeID, - azureDiskName, - fcWWIDs, - fcLun, - fcTargetWWNs, - iscsiTargetPortal, - iscsiIQN, - iscsiLun, - iscsiInitiatorName, - nfsServer, - nfsPath, - csiDriver, - csiVolumeHandle, - localPath, - localFS, - hostPath, - hostPathType, - }, - Value: 1, + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: []string{ + "storageclass", + "gce_persistent_disk_name", + "ebs_volume_id", + "azure_disk_name", + "fc_wwids", + "fc_lun", + "fc_target_wwns", + "iscsi_target_portal", + "iscsi_iqn", + "iscsi_lun", + "iscsi_initiator_name", + "nfs_server", + "nfs_path", + "csi_driver", + "csi_volume_handle", + "local_path", + "local_fs", + "host_path", + "host_path_type", }, - }, - } - }), - ), - *generator.NewFamilyGeneratorWithStability( - "kube_persistentvolume_capacity_bytes", - "Persistentvolume capacity in bytes.", - metric.Gauge, - basemetrics.STABLE, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - storage := p.Spec.Capacity[v1.ResourceStorage] - return &metric.Family{ - Metrics: []*metric.Metric{ - { - Value: float64(storage.Value()), + LabelValues: []string{ + p.Spec.StorageClassName, + gcePDDiskName, + ebsVolumeID, + azureDiskName, + fcWWIDs, + fcLun, + fcTargetWWNs, + iscsiTargetPortal, + iscsiIQN, + iscsiLun, + iscsiInitiatorName, + nfsServer, + nfsPath, + csiDriver, + csiVolumeHandle, + localPath, + localFS, + hostPath, + hostPathType, }, + Value: 1, }, - } - }), - ), - *generator.NewFamilyGeneratorWithStability( - "kube_persistentvolume_created", - "Unix creation timestamp", - metric.Gauge, - basemetrics.ALPHA, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - ms := []*metric.Metric{} - - if !p.CreationTimestamp.IsZero() { - ms = append(ms, &metric.Metric{ - LabelKeys: []string{}, - LabelValues: []string{}, - Value: float64(p.CreationTimestamp.Unix()), - }) - } + }, + } + }), + ) +} - return &metric.Family{ - Metrics: ms, - } - }), - ), - *generator.NewFamilyGeneratorWithStability( - "kube_persistentvolume_deletion_timestamp", - "Unix deletion timestamp", - metric.Gauge, - basemetrics.ALPHA, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - ms := []*metric.Metric{} - - if p.DeletionTimestamp != nil && !p.DeletionTimestamp.IsZero() { - ms = append(ms, &metric.Metric{ - LabelKeys: []string{}, - LabelValues: []string{}, - Value: float64(p.DeletionTimestamp.Unix()), - }) - } +func createPersistentVolumeCapacityBytes() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_capacity_bytes", + "Persistentvolume capacity in bytes.", + metric.Gauge, + basemetrics.STABLE, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + storage := p.Spec.Capacity[v1.ResourceStorage] + return &metric.Family{ + Metrics: []*metric.Metric{ + { + Value: float64(storage.Value()), + }, + }, + } + }), + ) +} + +func createPersistentVolumeCreated() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_created", + "Unix creation timestamp", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + ms := []*metric.Metric{} + + if !p.CreationTimestamp.IsZero() { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64(p.CreationTimestamp.Unix()), + }) + } + return &metric.Family{ + Metrics: ms, + } + }), + ) +} + +func createPersistentVolumeDeletionTimestamp() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_deletion_timestamp", + "Unix deletion timestamp", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + ms := []*metric.Metric{} + + if p.DeletionTimestamp != nil && !p.DeletionTimestamp.IsZero() { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64(p.DeletionTimestamp.Unix()), + }) + } + + return &metric.Family{ + Metrics: ms, + } + }), + ) +} + +func createPersistentVolumeCSIAttributes() generator.FamilyGenerator { + return *generator.NewOptInFamilyGenerator( + descPersistentVolumeCSIAttributesName, + descPersistentVolumeCSIAttributesHelp, + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + if p.Spec.CSI == nil { return &metric.Family{ - Metrics: ms, - } - }), - ), - *generator.NewOptInFamilyGenerator( - descPersistentVolumeCSIAttributesName, - descPersistentVolumeCSIAttributesHelp, - metric.Gauge, - basemetrics.ALPHA, - "", - wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { - if p.Spec.CSI == nil { - return &metric.Family{ - Metrics: []*metric.Metric{}, - } + Metrics: []*metric.Metric{}, } + } - var csiMounter, csiMapOptions string - for k, v := range p.Spec.PersistentVolumeSource.CSI.VolumeAttributes { - // storage attributes handled by external CEPH CSI driver - if k == "mapOptions" { - csiMapOptions = v - } else if k == "mounter" { - csiMounter = v - } + var csiMounter, csiMapOptions string + for k, v := range p.Spec.PersistentVolumeSource.CSI.VolumeAttributes { + // storage attributes handled by external CEPH CSI driver + if k == "mapOptions" { + csiMapOptions = v + } else if k == "mounter" { + csiMounter = v } + } - return &metric.Family{ - Metrics: []*metric.Metric{ - { - LabelKeys: []string{ - "csi_mounter", - "csi_map_options", - }, - LabelValues: []string{ - csiMounter, - csiMapOptions, - }, - Value: 1, + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: []string{ + "csi_mounter", + "csi_map_options", }, + LabelValues: []string{ + csiMounter, + csiMapOptions, + }, + Value: 1, }, - } - }), - ), - } + }, + } + }), + ) } -func wrapPersistentVolumeFunc(f func(*v1.PersistentVolume) *metric.Family) func(interface{}) *metric.Family { - return func(obj interface{}) *metric.Family { - persistentVolume := obj.(*v1.PersistentVolume) - - metricFamily := f(persistentVolume) - - for _, m := range metricFamily.Metrics { - m.LabelKeys, m.LabelValues = mergeKeyValues(descPersistentVolumeLabelsDefaultLabels, []string{persistentVolume.Name}, m.LabelKeys, m.LabelValues) - } +func createPersistentVolumeMode() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_persistentvolume_volume_mode", + "Volume Mode information for the PersistentVolume.", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPersistentVolumeFunc(func(p *v1.PersistentVolume) *metric.Family { + volumeMode := "" + if p.Spec.VolumeMode != nil { + volumeMode = string(*p.Spec.VolumeMode) + } else { + volumeMode = string("Filesystem") // Filesystem is the default mode used when volumeMode parameter is omitted. + } - return metricFamily - } -} - -func createPersistentVolumeListWatch(kubeClient clientset.Interface, _ string, _ string) cache.ListerWatcher { - return &cache.ListWatch{ - ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { - return kubeClient.CoreV1().PersistentVolumes().List(context.TODO(), opts) - }, - WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { - return kubeClient.CoreV1().PersistentVolumes().Watch(context.TODO(), opts) - }, - } + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: []string{"volumemode"}, + LabelValues: []string{volumeMode}, + Value: 1, + }, + }} + }), + ) } diff --git a/internal/store/persistentvolume_test.go b/internal/store/persistentvolume_test.go index d704686fbe..e4e6847ca2 100644 --- a/internal/store/persistentvolume_test.go +++ b/internal/store/persistentvolume_test.go @@ -30,6 +30,7 @@ import ( func TestPersistentVolumeStore(t *testing.T) { iscsiInitiatorName := "iqn.my.test.initiator:112233" + volumeMode := v1.PersistentVolumeBlock cases := []generateMetricsTestCase{ // Verify phase enumerations. { @@ -743,6 +744,38 @@ func TestPersistentVolumeStore(t *testing.T) { `, MetricNames: []string{"kube_persistentvolume_csi_attributes"}, }, + { + Obj: &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-default-volumemode", + }, + Spec: v1.PersistentVolumeSpec{ + VolumeMode: nil, + }, + }, + Want: ` + # HELP kube_persistentvolume_volume_mode Volume Mode information for the PersistentVolume. + # TYPE kube_persistentvolume_volume_mode gauge + kube_persistentvolume_volume_mode{persistentvolume="test-default-volumemode",volumemode="Filesystem"} 1 + `, + MetricNames: []string{"kube_persistentvolume_volume_mode"}, + }, + { + Obj: &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-block-volumemode", + }, + Spec: v1.PersistentVolumeSpec{ + VolumeMode: &volumeMode, + }, + }, + Want: ` + # HELP kube_persistentvolume_volume_mode Volume Mode information for the PersistentVolume. + # TYPE kube_persistentvolume_volume_mode gauge + kube_persistentvolume_volume_mode{persistentvolume="test-block-volumemode",volumemode="Block"} 1 + `, + MetricNames: []string{"kube_persistentvolume_volume_mode"}, + }, } for i, c := range cases { c.Func = generator.ComposeMetricGenFuncs(persistentVolumeMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) diff --git a/internal/store/role.go b/internal/store/role.go index 3d2e801607..02bfb0d338 100644 --- a/internal/store/role.go +++ b/internal/store/role.go @@ -91,7 +91,7 @@ func roleMetricFamilies(allowAnnotationsList, allowLabelsList []string) []genera metric.Gauge, basemetrics.ALPHA, "", - wrapRoleFunc(func(r *rbacv1.Role) *metric.Family { + wrapRoleFunc(func(_ *rbacv1.Role) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{{ LabelKeys: []string{}, diff --git a/internal/store/secret.go b/internal/store/secret.go index 79b9f7afae..36d115c034 100644 --- a/internal/store/secret.go +++ b/internal/store/secret.go @@ -48,7 +48,7 @@ func secretMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gene metric.Gauge, basemetrics.STABLE, "", - wrapSecretFunc(func(s *v1.Secret) *metric.Family { + wrapSecretFunc(func(_ *v1.Secret) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{ { diff --git a/internal/store/validatingwebhookconfiguration.go b/internal/store/validatingwebhookconfiguration.go index 5084e8dd3e..c740598c29 100644 --- a/internal/store/validatingwebhookconfiguration.go +++ b/internal/store/validatingwebhookconfiguration.go @@ -41,7 +41,7 @@ var ( metric.Gauge, basemetrics.ALPHA, "", - wrapValidatingWebhookConfigurationFunc(func(vwc *admissionregistrationv1.ValidatingWebhookConfiguration) *metric.Family { + wrapValidatingWebhookConfigurationFunc(func(_ *admissionregistrationv1.ValidatingWebhookConfiguration) *metric.Family { return &metric.Family{ Metrics: []*metric.Metric{ { diff --git a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet index a7c2904123..1b2a157dca 100644 --- a/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet +++ b/jsonnet/kube-state-metrics/kube-state-metrics.libsonnet @@ -192,12 +192,12 @@ seccompProfile: { type: 'RuntimeDefault' }, }, livenessProbe: { timeoutSeconds: 5, initialDelaySeconds: 5, httpGet: { - port: 8080, - path: '/healthz', + port: "http-metrics", + path: '/livez', } }, readinessProbe: { timeoutSeconds: 5, initialDelaySeconds: 5, httpGet: { - port: 8081, - path: '/', + port: "telemetry", + path: '/readyz', } }, }; diff --git a/main.go b/main.go index 5bdfaecaf8..da948a1982 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ import ( func main() { opts := options.NewOptions() cmd := options.InitCommand - cmd.Run = func(cmd *cobra.Command, args []string) { + cmd.Run = func(_ *cobra.Command, _ []string) { internal.RunKubeStateMetricsWrapper(opts) } opts.AddFlags(cmd) diff --git a/pkg/app/server.go b/pkg/app/server.go index 27d00c0f92..9d25fd0e8b 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -30,6 +30,13 @@ import ( "strings" "time" + "gopkg.in/yaml.v3" + "k8s.io/client-go/kubernetes" + _ "k8s.io/client-go/plugin/pkg/client/auth" // Initialize common client auth plugins. + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" + + "github.com/KimMachineGun/automemlimit/memlimit" "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" @@ -38,10 +45,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" - "gopkg.in/yaml.v3" - _ "k8s.io/client-go/plugin/pkg/client/auth" // Initialize common client auth plugins. - "k8s.io/client-go/tools/clientcmd" - "k8s.io/klog/v2" "k8s.io/kube-state-metrics/v2/internal/discovery" "k8s.io/kube-state-metrics/v2/internal/store" @@ -59,6 +62,8 @@ import ( const ( metricsPath = "/metrics" healthzPath = "/healthz" + livezPath = "/livez" + readyzPath = "/readyz" ) // promLogger implements promhttp.Logger @@ -156,6 +161,20 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error { } } + if opts.AutoGoMemlimit { + if _, err := memlimit.SetGoMemLimitWithOpts( + memlimit.WithRatio(opts.AutoGoMemlimitRatio), + memlimit.WithProvider( + memlimit.ApplyFallback( + memlimit.FromCgroup, + memlimit.FromSystem, + ), + ), + ); err != nil { + return fmt.Errorf("failed to set GOMEMLIMIT automatically: %w", err) + } + } + kubeConfig, err := clientcmd.BuildConfigFromFlags(opts.Apiserver, opts.Kubeconfig) if err != nil { return fmt.Errorf("failed to build config from flags: %v", err) @@ -321,11 +340,14 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error { WebConfigFile: &tlsConfig, } - metricsMux := buildMetricsServer(m, durationVec) + metricsMux := buildMetricsServer(m, durationVec, kubeClient) metricsServerListenAddress := net.JoinHostPort(opts.Host, strconv.Itoa(opts.Port)) metricsServer := http.Server{ Handler: metricsMux, - ReadHeaderTimeout: 5 * time.Second, + ReadHeaderTimeout: opts.ServerReadHeaderTimeout, + ReadTimeout: opts.ServerReadTimeout, + WriteTimeout: opts.ServerWriteTimeout, + IdleTimeout: opts.ServerIdleTimeout, } metricsFlags := web.FlagConfig{ WebListenAddresses: &[]string{metricsServerListenAddress}, @@ -370,6 +392,18 @@ func buildTelemetryServer(registry prometheus.Gatherer) *http.ServeMux { // Add metricsPath mux.Handle(metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorLog: promLogger{}})) + // Add readyzPath + mux.Handle(readyzPath, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + count, err := util.GatherAndCount(registry) + if err != nil || count == 0 { + w.WriteHeader(http.StatusServiceUnavailable) + w.Write([]byte(http.StatusText(http.StatusServiceUnavailable))) + return + } + w.WriteHeader(http.StatusOK) + w.Write([]byte(http.StatusText(http.StatusOK))) + })) + // Add index landingConfig := web.LandingConfig{ Name: "kube-state-metrics", @@ -390,7 +424,20 @@ func buildTelemetryServer(registry prometheus.Gatherer) *http.ServeMux { return mux } -func buildMetricsServer(m *metricshandler.MetricsHandler, durationObserver prometheus.ObserverVec) *http.ServeMux { +func handleClusterDelegationForProber(client kubernetes.Interface, probeType string) http.HandlerFunc { + return func(w http.ResponseWriter, _ *http.Request) { + got := client.CoreV1().RESTClient().Get().AbsPath(probeType).Do(context.Background()) + if got.Error() != nil { + w.WriteHeader(http.StatusServiceUnavailable) + w.Write([]byte(http.StatusText(http.StatusServiceUnavailable))) + return + } + w.WriteHeader(http.StatusOK) + w.Write([]byte(http.StatusText(http.StatusOK))) + } +} + +func buildMetricsServer(m *metricshandler.MetricsHandler, durationObserver prometheus.ObserverVec, client kubernetes.Interface) *http.ServeMux { mux := http.NewServeMux() // TODO: This doesn't belong into serveMetrics @@ -400,10 +447,14 @@ func buildMetricsServer(m *metricshandler.MetricsHandler, durationObserver prome mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) mux.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) + // Add metricsPath mux.Handle(metricsPath, promhttp.InstrumentHandlerDuration(durationObserver, m)) + // Add livezPath + mux.Handle(livezPath, handleClusterDelegationForProber(client, livezPath)) + // Add healthzPath - mux.HandleFunc(healthzPath, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(healthzPath, func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(http.StatusText(http.StatusOK))) }) @@ -422,6 +473,10 @@ func buildMetricsServer(m *metricshandler.MetricsHandler, durationObserver prome Address: healthzPath, Text: "Healthz", }, + { + Address: livezPath, + Text: "Livez", + }, }, } landingPage, err := web.NewLandingPage(landingConfig) diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index 88bf39d49e..f7d33bac85 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -100,7 +100,7 @@ func BenchmarkKubeStateMetrics(b *testing.B) { // This test is not suitable to be compared in terms of time, as it includes // a one second wait. Use for memory allocation comparisons, profiling, ... handler := metricshandler.New(&options.Options{}, kubeClient, builder, false) - b.Run("GenerateMetrics", func(b *testing.B) { + b.Run("GenerateMetrics", func(_ *testing.B) { handler.ConfigureSharding(ctx, 0, 1) // Wait for caches to fill diff --git a/pkg/metrics_store/metrics_store_test.go b/pkg/metrics_store/metrics_store_test.go index b32e1bcb38..dbde02b98a 100644 --- a/pkg/metrics_store/metrics_store_test.go +++ b/pkg/metrics_store/metrics_store_test.go @@ -41,7 +41,7 @@ func (f *metricFamily) ByteSlice() []byte { } func TestObjectsSameNameDifferentNamespaces(t *testing.T) { - serviceIDS := []string{"a", "b"} + serviceIDs := []string{"a", "b"} genFunc := func(obj interface{}) []metric.FamilyInterface { o, err := meta.Accessor(obj) @@ -65,7 +65,7 @@ func TestObjectsSameNameDifferentNamespaces(t *testing.T) { ms := NewMetricsStore([]string{"Information about service."}, genFunc) - for _, id := range serviceIDS { + for _, id := range serviceIDs { s := v1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "service", @@ -88,7 +88,7 @@ func TestObjectsSameNameDifferentNamespaces(t *testing.T) { } m := w.String() - for _, id := range serviceIDS { + for _, id := range serviceIDs { if !strings.Contains(m, fmt.Sprintf("uid=\"%v\"", id)) { t.Fatalf("expected to find metric with uid %v", id) } diff --git a/pkg/metrics_store/metrics_writer_test.go b/pkg/metrics_store/metrics_writer_test.go index b7d2907b0f..d32cc45cf9 100644 --- a/pkg/metrics_store/metrics_writer_test.go +++ b/pkg/metrics_store/metrics_writer_test.go @@ -238,7 +238,7 @@ func TestWriteAllWithMultipleStores(t *testing.T) { // TestWriteAllWithEmptyStores checks that nothing is printed if no metrics exist for metric families. func TestWriteAllWithEmptyStores(t *testing.T) { - genFunc := func(obj interface{}) []metric.FamilyInterface { + genFunc := func(_ interface{}) []metric.FamilyInterface { mf1 := metric.Family{ Name: "kube_service_info_1", Metrics: []*metric.Metric{}, diff --git a/pkg/metricshandler/metrics_handler.go b/pkg/metricshandler/metrics_handler.go index 955a6a84bb..62543785b0 100644 --- a/pkg/metricshandler/metrics_handler.go +++ b/pkg/metricshandler/metrics_handler.go @@ -111,12 +111,12 @@ func (m *MetricsHandler) Run(ctx context.Context) error { } statefulSetName := ss.Name - labelSelectorOptions := func(o *metav1.ListOptions) { - o.LabelSelector = fields.SelectorFromSet(ss.Labels).String() + fieldSelectorOptions := func(o *metav1.ListOptions) { + o.FieldSelector = fields.OneTermEqualSelector("metadata.name", statefulSetName).String() } i := cache.NewSharedIndexInformer( - cache.NewFilteredListWatchFromClient(m.kubeClient.AppsV1().RESTClient(), "statefulsets", m.opts.Namespace, labelSelectorOptions), + cache.NewFilteredListWatchFromClient(m.kubeClient.AppsV1().RESTClient(), "statefulsets", m.opts.Namespace, fieldSelectorOptions), &appsv1.StatefulSet{}, 0, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) i.AddEventHandler(cache.ResourceEventHandlerFuncs{ diff --git a/pkg/options/options.go b/pkg/options/options.go index c89ef63f43..74debacab1 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -21,16 +21,29 @@ import ( "fmt" "os" "strings" + "time" "github.com/prometheus/common/version" "github.com/spf13/cobra" "k8s.io/klog/v2" ) +var ( + // Align with the default scrape interval from Prometheus: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config + defaultServerReadTimeout = 60 * time.Second + defaultServerWriteTimeout = 60 * time.Second + // ServerIdleTimeout is set to 5 minutes to match the default idle timeout of Prometheus scrape clients + // https://github.com/prometheus/common/blob/318309999517402ad522877ac7e55fa650a11114/config/http_config.go#L55 + defaultServerIdleTimeout = 5 * time.Minute + defaultServerReadHeaderTimeout = 5 * time.Second +) + // Options are the configurable parameters for kube-state-metrics. type Options struct { AnnotationsAllowList LabelsAllowList `yaml:"annotations_allow_list"` Apiserver string `yaml:"apiserver"` + AutoGoMemlimit bool `yaml:"auto-gomemlimit"` + AutoGoMemlimitRatio float64 `yaml:"auto-gomemlimit-ratio"` CustomResourceConfig string `yaml:"custom_resource_config"` CustomResourceConfigFile string `yaml:"custom_resource_config_file"` CustomResourcesOnly bool `yaml:"custom_resources_only"` @@ -55,6 +68,10 @@ type Options struct { TelemetryPort int `yaml:"telemetry_port"` TotalShards int `yaml:"total_shards"` UseAPIServerCache bool `yaml:"use_api_server_cache"` + ServerReadTimeout time.Duration `yaml:"server_read_timeout"` + ServerWriteTimeout time.Duration `yaml:"server_write_timeout"` + ServerIdleTimeout time.Duration `yaml:"server_idle_timeout"` + ServerReadHeaderTimeout time.Duration `yaml:"server_read_header_timeout"` Config string @@ -83,7 +100,7 @@ func NewOptions() *Options { func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd = cmd - completionCommand.SetHelpFunc(func(cmd *cobra.Command, args []string) { + completionCommand.SetHelpFunc(func(_ *cobra.Command, _ []string) { if shellPath, ok := os.LookupEnv("SHELL"); ok { shell := shellPath[strings.LastIndex(shellPath, "/")+1:] fmt.Println(FetchLoadInstructions(shell)) @@ -97,7 +114,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) { versionCommand := &cobra.Command{ Use: "version", Short: "Print version information.", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Printf("%s\n", version.Print("kube-state-metrics")) klog.FlushAndExit(klog.ExitFlushTimeout, 0) }, @@ -128,6 +145,8 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().IntVar(&o.TelemetryPort, "telemetry-port", 8081, `Port to expose kube-state-metrics self metrics on.`) o.cmd.Flags().IntVar(&o.TotalShards, "total-shards", 1, "The total number of shards. Sharding is disabled when total shards is set to 1.") o.cmd.Flags().StringVar(&o.Apiserver, "apiserver", "", `The URL of the apiserver to use as a master`) + o.cmd.Flags().BoolVar(&o.AutoGoMemlimit, "auto-gomemlimit", false, "Automatically set GOMEMLIMIT to match container or system memory limit. (experimental)") + o.cmd.Flags().Float64Var(&o.AutoGoMemlimitRatio, "auto-gomemlimit-ratio", float64(0.9), "The ratio of reserved GOMEMLIMIT memory to the detected maximum container or system memory. (experimental)") o.cmd.Flags().StringVar(&o.CustomResourceConfig, "custom-resource-state-config", "", "Inline Custom Resource State Metrics config YAML (experimental)") o.cmd.Flags().StringVar(&o.CustomResourceConfigFile, "custom-resource-state-config-file", "", "Path to a Custom Resource State Metrics config file (experimental)") o.cmd.Flags().StringVar(&o.Host, "host", "::", `Host to expose metrics on.`) @@ -146,6 +165,11 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().Var(&o.Namespaces, "namespaces", fmt.Sprintf("Comma-separated list of namespaces to be enabled. Defaults to %q", &DefaultNamespaces)) o.cmd.Flags().Var(&o.NamespacesDenylist, "namespaces-denylist", "Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, only namespaces that are excluded in namespaces-denylist will be used.") o.cmd.Flags().Var(&o.Resources, "resources", fmt.Sprintf("Comma-separated list of Resources to be enabled. Defaults to %q", &DefaultResources)) + + o.cmd.Flags().DurationVar(&o.ServerReadTimeout, "server-read-timeout", defaultServerReadTimeout, "The maximum duration for reading the entire request, including the body. Align with the scrape interval or timeout of scraping clients. ") + o.cmd.Flags().DurationVar(&o.ServerWriteTimeout, "server-write-timeout", defaultServerWriteTimeout, "The maximum duration before timing out writes of the response. Align with the scrape interval or timeout of scraping clients..") + o.cmd.Flags().DurationVar(&o.ServerIdleTimeout, "server-idle-timeout", defaultServerIdleTimeout, "The maximum amount of time to wait for the next request when keep-alives are enabled. Align with the idletimeout of your scrape clients.") + o.cmd.Flags().DurationVar(&o.ServerReadHeaderTimeout, "server-read-header-timeout", defaultServerReadHeaderTimeout, "The maximum duration for reading the header of requests.") } // Parse parses the flag definitions from the argument list. @@ -170,5 +194,10 @@ func (o *Options) Validate() error { return fmt.Errorf("resource %s can't be sharded by field selector spec.nodeName", x) } } + + if o.AutoGoMemlimitRatio <= 0.0 || o.AutoGoMemlimitRatio > 1.0 { + return fmt.Errorf("value for --auto-gomemlimit-ratio=%f must be greater than 0 and less than or equal to 1", o.AutoGoMemlimitRatio) + } + return nil } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 63e5aba650..14b108f37e 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -21,7 +21,6 @@ import ( "runtime" "strings" - "github.com/prometheus/common/version" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" @@ -32,6 +31,9 @@ import ( "k8s.io/klog/v2" testUnstructuredMock "k8s.io/sample-controller/pkg/apis/samplecontroller/v1alpha1" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/version" + "k8s.io/kube-state-metrics/v2/pkg/customresource" ) @@ -154,3 +156,19 @@ func GVRFromType(resourceName string, expectedType interface{}) *schema.GroupVer Resource: r, } } + +// GatherAndCount gathers all metrics from the provided Gatherer and counts +// them. It returns the number of metric children in all gathered metric +// families together. +func GatherAndCount(g prometheus.Gatherer) (int, error) { + got, err := g.Gather() + if err != nil { + return 0, fmt.Errorf("gathering metrics failed: %w", err) + } + + result := 0 + for _, mf := range got { + result += len(mf.GetMetric()) + } + return result, nil +} diff --git a/tests/e2e/discovery_test.go b/tests/e2e/discovery_test.go index 63f0878ff6..d34c932daf 100644 --- a/tests/e2e/discovery_test.go +++ b/tests/e2e/discovery_test.go @@ -97,7 +97,7 @@ func TestVariableVKsDiscoveryAndResolution(t *testing.T) { klog.InfoS("started KSM") // Wait for port 8080 to come up. - err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { return false, nil @@ -140,7 +140,7 @@ func TestVariableVKsDiscoveryAndResolution(t *testing.T) { // Wait for the metric to be available. ch := make(chan bool, 1) klog.InfoS("waiting for metrics to become available") - err = wait.PollUntilContextTimeout(context.TODO(), discovery.Interval, PopulateTimeout, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), discovery.Interval, PopulateTimeout, true, func(_ context.Context) (bool, error) { out, err := exec.Command("curl", "localhost:8080/metrics").Output() if err != nil { return false, err diff --git a/tests/e2e/hot-reload-kubeconfig_test.go b/tests/e2e/hot-reload-kubeconfig_test.go index 560801dd9b..050f2f6e94 100644 --- a/tests/e2e/hot-reload-kubeconfig_test.go +++ b/tests/e2e/hot-reload-kubeconfig_test.go @@ -74,7 +74,7 @@ func TestKubeConfigHotReload(t *testing.T) { go internal.RunKubeStateMetricsWrapper(opts) // Wait for port 8080 to come up. - err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { return false, nil @@ -108,7 +108,7 @@ func TestKubeConfigHotReload(t *testing.T) { // Wait for port 8080 to come up. ch := make(chan bool, 1) - err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { return false, nil diff --git a/tests/e2e/hot-reload_test.go b/tests/e2e/hot-reload_test.go index b1c88c8714..c416605e52 100644 --- a/tests/e2e/hot-reload_test.go +++ b/tests/e2e/hot-reload_test.go @@ -65,7 +65,7 @@ func TestConfigHotReload(t *testing.T) { go internal.RunKubeStateMetricsWrapper(opts) // Wait for port 8080 to come up. - err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { return false, nil @@ -89,7 +89,7 @@ func TestConfigHotReload(t *testing.T) { // Wait for port 8080 to come up. ch := make(chan bool, 1) - err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { conn, err := net.Dial("tcp", "localhost:8080") if err != nil { return false, nil diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 9860a14c6d..72d3f1db03 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -21,9 +21,9 @@ import ( "bytes" "flag" "fmt" + "io/fs" "log" "os" - "path" "path/filepath" "regexp" "sort" @@ -145,12 +145,6 @@ func TestDocumentation(t *testing.T) { func getLabelsDocumentation() (map[string][]string, error) { documentedMetrics := map[string][]string{} - docPath := "../../docs/" - docFiles, err := os.ReadDir(docPath) - if err != nil { - return nil, fmt.Errorf("failed to read documentation directory: %w", err) - } - // Match file names such as daemonset-metrics.md fileRe := regexp.MustCompile(`^([a-z]*)-metrics.md$`) // Match doc lines such as | kube_node_created | Gauge | `node`=<node-address>| STABLE | @@ -160,15 +154,16 @@ func getLabelsDocumentation() (map[string][]string, error) { // Match wildcard patterns for dynamic labels such as label_CRONJOB_LABEL patternRe := regexp.MustCompile(`_[A-Z_]+`) - for _, file := range docFiles { - if file.IsDir() || !fileRe.MatchString(file.Name()) { - continue + err := filepath.WalkDir("../../docs", func(p string, d fs.DirEntry, _ error) error { + + if d.IsDir() || !fileRe.MatchString(d.Name()) { + // Ignore the entry + return nil } - filePath := path.Join(docPath, file.Name()) - f, err := os.Open(filepath.Clean(filePath)) - if err != nil { - return nil, fmt.Errorf("cannot read file %s: %w", filePath, err) + f, e := os.Open(filepath.Clean(p)) + if e != nil { + return fmt.Errorf("cannot read file %s: %w", p, e) } scanner := bufio.NewScanner(f) for scanner.Scan() { @@ -183,14 +178,19 @@ func getLabelsDocumentation() (map[string][]string, error) { labelPatterns := make([]string, len(labels)) for i, l := range labels { if len(l) <= 1 { - return nil, fmt.Errorf("Label documentation %s did not match regex", labelsDoc) + return fmt.Errorf("label documentation %s did not match regex", labelsDoc) } labelPatterns[i] = patternRe.ReplaceAllString(l[1], "_.*") } documentedMetrics[metric] = labelPatterns } + return nil + }) + if err != nil { + log.Fatalf("cannot walk the documentation directory: %s", err) } + return documentedMetrics, nil } diff --git a/tools/go.mod b/tools/go.mod index 3f84208e77..ce3ed7dd37 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -6,15 +6,14 @@ require ( github.com/brancz/gojsontoyaml v0.1.0 github.com/campoy/embedmd v1.0.0 github.com/google/go-jsonnet v0.20.0 - github.com/hairyhenderson/gomplate/v3 v3.11.7 + github.com/hairyhenderson/gomplate/v3 v3.11.8 github.com/jsonnet-bundler/jsonnet-bundler v0.5.1 - golang.org/x/perf v0.0.0-20231127181059-b53752263861 + golang.org/x/perf v0.0.0-20240604174448-3b48cf0e0164 ) require ( cloud.google.com/go v0.110.7 // indirect - cloud.google.com/go/compute v1.23.0 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.1 // indirect cloud.google.com/go/storage v1.30.1 // indirect dario.cat/mergo v1.0.0 // indirect @@ -119,22 +118,22 @@ require ( github.com/ugorji/go/codec v1.2.7 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/zealic/xignore v0.3.3 // indirect - go.etcd.io/bbolt v1.3.6 // indirect + go.etcd.io/bbolt v1.3.10 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.9.0 // indirect go4.org/intern v0.0.0-20230205224052-192e9f60865c // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect gocloud.dev v0.25.1-0.20220408200107-09b10f7359f7 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.126.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -142,7 +141,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/tools/go.sum b/tools/go.sum index fabd55cb93..bb82af7f3b 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -43,10 +43,8 @@ cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTB cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= @@ -485,8 +483,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hairyhenderson/go-fsimpl v0.0.0-20220529183339-9deae3e35047 h1:nSSfN9G8O8XXDqB3aDEHJ8K+0llYYToNlTcWOe1Pti8= github.com/hairyhenderson/go-fsimpl v0.0.0-20220529183339-9deae3e35047/go.mod h1:30RY4Ey+bg+BGKBufZE2IEmxk7hok9U9mjdgZYomwN4= -github.com/hairyhenderson/gomplate/v3 v3.11.7 h1:fpOTFZsX4mCfp3E6jodUfurHjCcW2ixRrMtyGg78sgU= -github.com/hairyhenderson/gomplate/v3 v3.11.7/go.mod h1:5VhCNPRpC2ahGESvtIzfwz8teUyYmd2DqslTjrvjLrE= +github.com/hairyhenderson/gomplate/v3 v3.11.8 h1:T63wLRk+Y9C601ChYa/+FZ30XT/UEWydMDZhOOJM3K0= +github.com/hairyhenderson/gomplate/v3 v3.11.8/go.mod h1:xs1LnI1NftnB6o0Zvy1aLgDMSGUvGjz4uCQAZSIMP04= github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf h1:I1sbT4ZbIt9i+hB1zfKw2mE8C12TuGxPiW7YmtLbPa4= github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf/go.mod h1:jDHmWDKZY6MIIYltYYfW4Rs7hQ50oS4qf/6spSiZAxY= github.com/hairyhenderson/yaml v0.0.0-20220618171115-2d35fca545ce h1:cVkYhlWAxwuS2/Yp6qPtcl0fGpcWxuZNonywHZ6/I+s= @@ -860,8 +858,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t github.com/zealic/xignore v0.3.3 h1:EpLXUgZY/JEzFkTc+Y/VYypzXtNz+MSOMVCGW5Q4CKQ= github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3UiqEAU= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -925,8 +923,8 @@ golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -965,8 +963,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1026,8 +1024,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1048,10 +1046,10 @@ golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= -golang.org/x/perf v0.0.0-20231127181059-b53752263861 h1:oWUgm6RG0ZUKQeX7wxjnX+TFCrXDSheBtpiy5vpUdZg= -golang.org/x/perf v0.0.0-20231127181059-b53752263861/go.mod h1:sKqUfjZtdM78wIFCYFnmu2FhhanvRUbp67Zgmj3TZPM= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/perf v0.0.0-20240604174448-3b48cf0e0164 h1:EUu0oOwLbhVs3v7r1ulLp3a3czQ3XkvKcBGOMfft+nw= +golang.org/x/perf v0.0.0-20240604174448-3b48cf0e0164/go.mod h1:yzNzwBKxdK25sFy9NWFu/abeZOeugePuXQfvVIDA8os= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1065,8 +1063,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1113,7 +1111,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1163,8 +1160,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1172,8 +1169,8 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1187,8 +1184,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1263,8 +1260,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1464,8 +1461,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=