├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── govulncheck.yml │ ├── openvex.yml │ ├── sbom.yaml │ └── semantic.yml ├── .gitignore ├── .golangci.yml ├── .markdownlint-cli2.jsonc ├── .openvex └── templates │ ├── README.md │ └── main.openvex.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── MAINTAINER.md ├── Makefile ├── OWNERS ├── README.md ├── README.md.tpl ├── RELEASE.md ├── SECURITY-INSIGHTS.yml ├── SECURITY.md ├── SECURITY_CONTACTS ├── cloudbuild.yaml ├── code-of-conduct.md ├── data.yaml ├── docs ├── README.md ├── dependencies-policy.md ├── design │ ├── metrics-best-practices.md │ └── metrics-store-performance-optimization.md ├── developer │ ├── cli-arguments.md │ └── guide.md └── metrics │ ├── auth │ ├── certificatesigningrequest-metrics.md │ ├── role-metrics.md │ ├── rolebinding-metrics.md │ └── serviceaccount-metrics.md │ ├── cluster │ ├── clusterrole-metrics.md │ ├── clusterrolebinding-metrics.md │ ├── lease-metrics.md │ ├── namespace-metrics.md │ └── node-metrics.md │ ├── extend │ ├── customresourcestate-metrics.md │ ├── mutatingwebhookconfiguration-metrics.md │ └── validatingwebhookconfiguration-metrics.md │ ├── policy │ ├── limitrange-metrics.md │ ├── networkpolicy-metrics.md │ ├── poddisruptionbudget-metrics.md │ └── resourcequota-metrics.md │ ├── service │ ├── endpoint-metrics.md │ ├── endpointslice-metrics.md │ ├── ingress-metrics.md │ ├── ingressclass-metrics.md │ └── service-metrics.md │ ├── storage │ ├── configmap-metrics.md │ ├── persistentvolume-metrics.md │ ├── persistentvolumeclaim-metrics.md │ ├── secret-metrics.md │ ├── storageclass-metrics.md │ └── volumeattachment-metrics.md │ └── workload │ ├── cronjob-metrics.md │ ├── daemonset-metrics.md │ ├── deployment-metrics.md │ ├── horizontalpodautoscaler-metrics.md │ ├── job-metrics.md │ ├── pod-metrics.md │ ├── replicaset-metrics.md │ ├── replicationcontroller-metrics.md │ └── statefulset-metrics.md ├── examples ├── autosharding │ ├── cluster-role-binding.yaml │ ├── cluster-role.yaml │ ├── kustomization.yaml │ ├── role-binding.yaml │ ├── role.yaml │ ├── service-account.yaml │ ├── service.yaml │ └── statefulset.yaml ├── daemonsetsharding │ ├── cluster-role-binding.yaml │ ├── cluster-role.yaml │ ├── daemonset-service.yaml │ ├── daemonset.yaml │ ├── deployment-service.yaml │ ├── deployment-unscheduled-pods-fetching-service.yaml │ ├── deployment-unscheduled-pods-fetching.yaml │ ├── deployment.yaml │ └── service-account.yaml ├── prometheus-alerting-rules │ └── alerts.yaml └── standard │ ├── cluster-role-binding.yaml │ ├── cluster-role.yaml │ ├── deployment.yaml │ ├── kustomization.yaml │ ├── service-account.yaml │ └── service.yaml ├── go.mod ├── go.sum ├── internal ├── discovery │ ├── discovery.go │ ├── discovery_test.go │ └── types.go ├── store │ ├── builder.go │ ├── builder_test.go │ ├── certificatesigningrequest.go │ ├── certificatesigningrequest_test.go │ ├── clusterrole.go │ ├── clusterrole_test.go │ ├── clusterrolebinding.go │ ├── clusterrolebinding_test.go │ ├── configmap.go │ ├── configmap_test.go │ ├── cronjob.go │ ├── cronjob_test.go │ ├── daemonset.go │ ├── daemonset_test.go │ ├── deployment.go │ ├── deployment_test.go │ ├── endpoint.go │ ├── endpoint_test.go │ ├── endpointslice.go │ ├── endpointslice_test.go │ ├── horizontalpodautoscaler.go │ ├── horizontalpodautoscaler_test.go │ ├── ingress.go │ ├── ingress_test.go │ ├── ingressclass.go │ ├── ingressclass_test.go │ ├── job.go │ ├── job_test.go │ ├── lease.go │ ├── lease_test.go │ ├── limitrange.go │ ├── limitrange_test.go │ ├── mutatingwebhookconfiguration.go │ ├── mutatingwebhookconfiguration_test.go │ ├── namespace.go │ ├── namespace_test.go │ ├── networkpolicy.go │ ├── networkpolicy_test.go │ ├── node.go │ ├── node_test.go │ ├── persistentvolume.go │ ├── persistentvolume_test.go │ ├── persistentvolumeclaim.go │ ├── persistentvolumeclaim_test.go │ ├── pod.go │ ├── pod_test.go │ ├── poddisruptionbudget.go │ ├── poddisruptionbudget_test.go │ ├── replicaset.go │ ├── replicaset_test.go │ ├── replicationcontroller.go │ ├── replicationcontroller_test.go │ ├── resourcequota.go │ ├── resourcequota_test.go │ ├── role.go │ ├── role_test.go │ ├── rolebinding.go │ ├── rolebinding_test.go │ ├── secret.go │ ├── secret_test.go │ ├── service.go │ ├── service_test.go │ ├── serviceaccount.go │ ├── serviceaccount_test.go │ ├── statefulset.go │ ├── statefulset_test.go │ ├── storageclass.go │ ├── storageclass_test.go │ ├── testutils.go │ ├── testutils_test.go │ ├── utils.go │ ├── utils_test.go │ ├── validatingwebhookconfiguration.go │ ├── validatingwebhookconfiguration_test.go │ ├── volumeattachment.go │ └── volumeattachment_test.go └── wrapper.go ├── jsonnet ├── kube-state-metrics-mixin │ ├── alerts.libsonnet │ ├── config.libsonnet │ └── mixin.libsonnet └── kube-state-metrics │ ├── jsonnetfile.json │ └── kube-state-metrics.libsonnet ├── kustomization.yaml ├── main.go ├── pkg ├── allow │ └── allow_labels.go ├── allowdenylist │ ├── allowdenylist.go │ └── allowdenylist_test.go ├── app │ ├── server.go │ └── server_test.go ├── builder │ ├── builder.go │ ├── builder_test.go │ └── types │ │ └── interfaces.go ├── constant │ └── resource_unit.go ├── customresource │ └── registry_factory.go ├── customresourcestate │ ├── config.go │ ├── config_metrics_types.go │ ├── config_test.go │ ├── custom_resource_metrics.go │ ├── custom_resource_metrics_test.go │ ├── doc.go │ ├── example_config.yaml │ ├── registry_factory.go │ └── registry_factory_test.go ├── metric │ ├── family.go │ ├── metric.go │ └── metric_test.go ├── metric_generator │ ├── filter.go │ └── generator.go ├── metrics_store │ ├── metrics_store.go │ ├── metrics_store_test.go │ ├── metrics_writer.go │ └── metrics_writer_test.go ├── metricshandler │ └── metrics_handler.go ├── optin │ ├── optin.go │ └── optin_test.go ├── options │ ├── autoload.go │ ├── options.go │ ├── options_test.go │ ├── resource.go │ ├── types.go │ └── types_test.go ├── sharding │ ├── listwatch.go │ ├── listwatch_test.go │ └── metrics.go ├── util │ ├── proc │ │ ├── reaper.go │ │ └── reaper_unsupported.go │ └── utils.go └── watch │ └── watch.go ├── scripts ├── autosharding.jsonnet ├── daemonsetsharding.jsonnet ├── generate-help-text.sh ├── jsonnetfile.json ├── jsonnetfile.lock.json ├── mixin.jsonnet └── standard.jsonnet └── tests ├── README.md ├── compare-sharding.sh ├── compare_benchmarks.sh ├── e2e.sh ├── e2e ├── README.md ├── discovery_test.go ├── framework │ └── framework.go ├── hot-reload-kubeconfig_test.go ├── hot-reload_test.go ├── main_test.go └── testdata │ └── pods.yaml ├── lib ├── doc.go └── lib_test.go ├── manifests ├── clusterole.yaml ├── clusterrolebinding.yaml ├── cronjob.yaml ├── csr.yaml ├── daemonset.yaml ├── endpointslice.yaml ├── hpa.yaml ├── ingress.yaml ├── ingressclass.yaml ├── job.yaml ├── limitrange.yaml ├── mutatingwebhookconfiguration.yaml ├── networkpolicy.yaml ├── persistentvolume.yaml ├── persistentvolumeclaim.yaml ├── poddisruptionbudget.yaml ├── replicationcontroller.yaml ├── resourcequota.yaml ├── role.yaml ├── rolebinding.yaml ├── serviceaccount.yaml ├── statefulset.yaml ├── storageclass.yaml ├── validatingwebhookconfiguration.yaml └── volumeattachment.yaml └── rules └── alerts-test.yaml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug encountered while running kube-state-metrics 4 | title: '' 5 | labels: kind/bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 14 | 15 | **What happened**: 16 | 17 | **What you expected to happen**: 18 | 19 | **How to reproduce it (as minimally and precisely as possible)**: 20 | 21 | ```bash 22 | # An example: https://github.com/kubernetes/kube-state-metrics/issues/2223#issuecomment-1792850276 23 | minikube start 24 | ... 25 | go run main.go --custom-resource-state-only --custom-resource-state-config-file ksm-2223/custom-resource-config-file.yaml --kubeconfig ~/.kube/config 26 | ``` 27 | 28 | **Anything else we need to know?**: 29 | 30 | **Environment**: 31 | 32 | * kube-state-metrics version: 33 | * Kubernetes version (use `kubectl version`): 34 | * Cloud provider or hardware configuration: 35 | * Other info: 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a new feature 4 | title: '' 5 | labels: kind/feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **What would you like to be added**: 13 | 14 | **Why is this needed**: 15 | 16 | **Describe the solution you'd like** 17 | 18 | **Additional context** 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | **What this PR does / why we need it**: 9 | 10 | **How does this change affect the cardinality of KSM**: *(increases, decreases or does not change cardinality)* 11 | 12 | **Which issue(s) this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close the issue(s) when PR gets merged)*: 13 | Fixes # 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | groups: 6 | k8s-dependencies: 7 | patterns: 8 | - "k8s.io*" 9 | schedule: 10 | interval: "weekly" 11 | - package-ecosystem: "github-actions" 12 | directory: "/" 13 | schedule: 14 | interval: "weekly" 15 | -------------------------------------------------------------------------------- /.github/workflows/govulncheck.yml: -------------------------------------------------------------------------------- 1 | name: govulncheck 2 | 3 | on: 4 | schedule: 5 | # Run every Monday 6 | - cron: '0 0 * * 1' 7 | 8 | env: 9 | GO_VERSION: "^1.24" 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | ci-security-checks: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 19 | name: Checkout code 20 | - name: Set up Go 1.x 21 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 22 | with: 23 | go-version: ${{ env.GO_VERSION }} 24 | - name: Install govulncheck binary 25 | run: | 26 | go install golang.org/x/vuln/cmd/govulncheck@latest 27 | - name: Run security checks 28 | run: | 29 | govulncheck ./... 30 | -------------------------------------------------------------------------------- /.github/workflows/openvex.yml: -------------------------------------------------------------------------------- 1 | name: openvex 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: 7 | - released 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | vexctl: 14 | runs-on: ubuntu-latest 15 | 16 | permissions: 17 | contents: write 18 | 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 22 | 23 | - name: Set environment variables 24 | run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV 25 | 26 | - uses: openvex/generate-vex@c59881b41451d7ccba5c3b74cd195382b8971fcd 27 | # Refer: https://github.com/openvex/vexctl#operational-model 28 | name: Run vexctl 29 | with: 30 | product: pkg:golang/k8s.io/kube-state-metrics/v2@${{ env.RELEASE_VERSION }} 31 | file: kube-state-metrics.openvex.json 32 | 33 | - name: Upload OpenVEX document to GitHub Release 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | run: | 37 | gh release upload ${{ env.RELEASE_VERSION }} kube-state-metrics.openvex.json 38 | -------------------------------------------------------------------------------- /.github/workflows/sbom.yaml: -------------------------------------------------------------------------------- 1 | name: Generate SBOM with Kubernetes BOM 2 | 3 | on: 4 | release: 5 | types: 6 | - released 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | sbom: 13 | runs-on: ubuntu-latest 14 | 15 | permissions: 16 | contents: write 17 | 18 | env: 19 | OUTPUT: sbom.spdx 20 | TAG: ${{ github.event.release.tag_name }} 21 | 22 | steps: 23 | - name: Fetch source code into GITHUB_WORKSPACE 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | 26 | - name: Install Kubernetes BOM 27 | uses: kubernetes-sigs/release-actions/setup-bom@a30d93cf2aa029e1e4c8a6c79f766aebf429fddb # v0.3.1 28 | 29 | - name: Generate SBOM 30 | run: | 31 | bom generate \ 32 | --dirs=. \ 33 | --image=registry.k8s.io/kube-state-metrics/kube-state-metrics:$TAG \ 34 | --namespace=https://github.com/kubernetes/kube-state-metrics/releases/download/$TAG/$OUTPUT \ 35 | --output=$OUTPUT 36 | 37 | - name: Upload SBOM to GitHub Release 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | run: | 41 | gh release upload $TAG $OUTPUT 42 | -------------------------------------------------------------------------------- /.github/workflows/semantic.yml: -------------------------------------------------------------------------------- 1 | name: "Lint pull request title" 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | main: 15 | permissions: 16 | pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs 17 | statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR 18 | name: Validate PR title for semantic commit message 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /kube-state-metrics 2 | documented_metrics 3 | code_metrics 4 | 5 | # E2e tests output 6 | /log 7 | *.bak 8 | 9 | # Created by https://www.gitignore.io/api/go 10 | 11 | ### Go ### 12 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 13 | *.o 14 | *.a 15 | *.so 16 | vendor 17 | 18 | # Folders 19 | _obj 20 | _test 21 | 22 | # Architecture specific extensions/prefixes 23 | *.[568vq] 24 | [568vq].out 25 | 26 | *.cgo1.go 27 | *.cgo2.c 28 | _cgo_defun.c 29 | _cgo_gotypes.go 30 | _cgo_export.* 31 | 32 | _testmain.go 33 | 34 | *.exe 35 | *.test 36 | *.prof 37 | 38 | *.iml 39 | .idea/ 40 | 41 | # Generated CLI help file 42 | help.txt 43 | 44 | # jsonnet dependency management 45 | /scripts/vendor 46 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: none 4 | enable: 5 | - gocritic 6 | - gocyclo 7 | - gosec 8 | - govet 9 | - ineffassign 10 | - misspell 11 | - promlinter 12 | - revive 13 | - staticcheck 14 | - unconvert 15 | - unused 16 | exclusions: 17 | generated: lax 18 | rules: 19 | - linters: 20 | - promlinter 21 | path: _test\.go 22 | - linters: 23 | - gosec 24 | text: 'G104:' 25 | - linters: 26 | - revive 27 | text: 'package-comments:' 28 | paths: 29 | - third_party$ 30 | - builtin$ 31 | - examples$ 32 | issues: 33 | max-issues-per-linter: 0 34 | max-same-issues: 0 35 | formatters: 36 | enable: 37 | - gofmt 38 | - goimports 39 | settings: 40 | goimports: 41 | local-prefixes: 42 | - k8s.io/kube-state-metrics 43 | - k8s.io/kube-state-metrics/v2 44 | exclusions: 45 | generated: lax 46 | paths: 47 | - third_party$ 48 | - builtin$ 49 | - examples$ 50 | -------------------------------------------------------------------------------- /.markdownlint-cli2.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "globs": [ 3 | "**/*.md" 4 | ], 5 | // ToDo: Following rules can't be fixed automatically. They should be enabled when fixed. 6 | "config": { 7 | "MD004": { 8 | "style": "asterisk" 9 | }, 10 | "MD013": false, // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md013---line-length 11 | "MD024": false, // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md024---multiple-headers-with-the-same-content 12 | "MD033": false, // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md033---inline-html 13 | "MD036": false, // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md036---emphasis-used-instead-of-a-header 14 | "MD040": false, // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md040---fenced-code-blocks-should-have-a-language-specified 15 | "MD041": false // https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md#md041---first-line-in-file-should-be-a-top-level-header 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.openvex/templates/README.md: -------------------------------------------------------------------------------- 1 | # OpenVEX Templates Directory 2 | 3 | This directory contains the OpenVEX data for this repository. 4 | The files stored in this directory are used as templates by 5 | `vexctl generate` when generating VEX data for a release or 6 | a specific artifact. 7 | 8 | To add new statements to publish data about a vulnerability, 9 | download [vexctl](https://github.com/openvex/vexctl) 10 | and append new statements using `vexctl add`. For example: 11 | 12 | ``` 13 | vexctl add --in-place main.openvex.json pkg:oci/test CVE-2014-1234567 fixed 14 | ``` 15 | 16 | That will add a new VEX statement expressing that the impact of 17 | CVE-2014-1234567 is under investigation in the test image. When 18 | cutting a new release, for `pkg:oci/test` the new file will be 19 | incorporated to the relase's VEX data. 20 | 21 | ## Read more about OpenVEX 22 | 23 | To know more about generating, publishing and using VEX data 24 | in your project, please check out the [vexctl repository and 25 | documentation](https://github.com/openvex/vexctl). 26 | 27 | OpenVEX also has an [examples repository](https://github.com/openvex/examples) 28 | with samples and docs. 29 | -------------------------------------------------------------------------------- /.openvex/templates/main.openvex.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://openvex.dev/ns/v0.2.0", 3 | "@id": "https://openvex.dev/docs/public/vex-2912204db7d51d98234a931d600f7cc2dd0bf24a5b5b326de138d64b30c22911", 4 | "author": "vexctl (automated template)", 5 | "timestamp": "2023-12-15T22:55:18.754525+05:30", 6 | "version": 1, 7 | "statements": [] 8 | } 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). Here is an excerpt: 4 | 5 | _As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ 6 | 7 | ## Getting Started 8 | 9 | We have full documentation on how to get started contributing here: 10 | 11 | ### Semantic Commit Messages 12 | 13 | We use [semantic commit messages](https://www.conventionalcommits.org/en/v1.0.0/) in this repository. 14 | 15 | They follow this format: `[optional scope]: ` 16 | 17 | Examples for commit messages following this are: 18 | 19 | `feat: allow provided config object to extend other configs` 20 | 21 | You can also include a scope within parenthesis: 22 | 23 | `fix(scope): Prevent wrong calculation of storage` 24 | 25 | Here's a list of types that we use: 26 | 27 | | Type | Explanation | 28 | |---|---| 29 | | feat | A new feature | 30 | | fix | A bug fix | 31 | | docs | Documentation only changes | 32 | | style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) | 33 | | refactor | A code change that neither fixes a bug nor adds a feature | 34 | | perf | A code change that improves performance | 35 | | test | Adding missing tests or correcting existing tests | 36 | | build |Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) | 37 | | ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) | 38 | | chore | Other changes that don't modify src or test files | 39 | | revert | Reverts a previous commit | 40 | 41 | ### Further Information 42 | 43 | * [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests 44 | * [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) 45 | * [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md) - Common resources for existing developers 46 | 47 | ## Mentorship 48 | 49 | * [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! 50 | 51 | ## Contact Information 52 | 53 | * [Join Slack](http://slack.k8s.io) to sign up and join the Kubernetes Slack. Please make sure to read our [Slack Guidelines](https://github.com/kubernetes/community/blob/master/communication/slack-guidelines.md) before participating. 54 | * The [kube-state-metrics slack channel](https://kubernetes.slack.com/messages/CJJ529RUY) provides an effective communication platform to reach out to members and other users of the project. It offers an alternative to submitting a GitHub issue for when you have questions and issues. 55 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG GOVERSION=1.24 2 | ARG GOARCH 3 | FROM golang:${GOVERSION} AS builder 4 | ARG GOARCH 5 | ENV GOARCH=${GOARCH} 6 | WORKDIR /go/src/k8s.io/kube-state-metrics/ 7 | COPY . /go/src/k8s.io/kube-state-metrics/ 8 | 9 | RUN make build-local 10 | 11 | FROM gcr.io/distroless/static-debian12:latest-${GOARCH} 12 | COPY --from=builder /go/src/k8s.io/kube-state-metrics/kube-state-metrics / 13 | 14 | USER nobody 15 | 16 | ENTRYPOINT ["/kube-state-metrics", "--port=8080", "--telemetry-port=8081"] 17 | 18 | EXPOSE 8080 8081 19 | -------------------------------------------------------------------------------- /MAINTAINER.md: -------------------------------------------------------------------------------- 1 | # Maintaining kube-state-metrics 2 | 3 | kube-state-metrics is welcoming contributions from the community. If you are interested in intensifying your contributions and becoming a maintainer, this doc describes the necessary steps. 4 | 5 | As part of the Kubernetes project, we use the community membership process as described [here](https://github.com/kubernetes/community/blob/master/community-membership.md). We do not adhere strictly to the numbers of contributions and reviews. Still as becoming a maintainer is a trust-based process and we desire positive outcomes for the project, we look for a long-term interest and engagement. 6 | 7 | ## Adding a new reviewer 8 | 9 | * Ensure the new reviewer is a member of the [kubernetes organization](https://github.com/kubernetes/org/blob/main/config/kubernetes/org.yaml). 10 | * Add the new reviewer to the [OWNERS](OWNERS) file to be able to review pull requests. 11 | * Add the new reviewer to the [kube-state-metrics-maintainers group](https://github.com/kubernetes/org/blob/main/config/kubernetes/sig-instrumentation/teams.yaml), to gain write access to the kube-state-metrics repository (e.g. for creating new releases). 12 | 13 | ## Adding a new approver 14 | 15 | * Ensure the new approver is already a reviewer in the [OWNERS](OWNERS) file. 16 | * Add the new approver to the [OWNERS](OWNERS) file to be able to approve pull requests. 17 | * Add the new approver to the [SECURITY_CONTACTS](SECURITY_CONTACTS) file to be able to get notified on security related incidents. 18 | * Add the new approver to the [kube-state-metrics-admin group](https://github.com/kubernetes/org/blob/main/config/kubernetes/sig-instrumentation/teams.yaml), to get admin access to the kube-state-metrics repository. 19 | * Add the new approver to the k8s.io [OWNERS](https://github.com/kubernetes/k8s.io/blob/main/k8s.gcr.io/images/k8s-staging-kube-state-metrics/OWNERS) file to be able to approve image promotion from the staging registry. 20 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | reviewers: 2 | - CatherineF-dev 3 | - dgrisonnet 4 | - logicalhan 5 | - mrueg 6 | - rexagod 7 | approvers: 8 | - CatherineF-dev 9 | - dgrisonnet 10 | - mrueg 11 | - rexagod 12 | emeritus_approvers: 13 | - LiliC 14 | - andyxning 15 | - brancz 16 | - tariq1890 17 | - zouyee 18 | - fpetkovski 19 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # How to cut a new release 2 | 3 | ## Branch management and versioning strategy 4 | 5 | We use [Semantic Versioning](http://semver.org/). 6 | 7 | We maintain a separate branch for each minor release, named `release-.`, e.g. `release-1.1`, `release-2.0`. 8 | 9 | The usual flow is to merge new features and changes into the main branch and to merge bug fixes into the latest release branch. Bug fixes are then merged into main from the latest release branch. The main branch should always contain all commits from the latest release branch. 10 | 11 | If a bug fix got accidentally merged into main, cherry-pick commits have to be created in the latest release branch, which then have to be merged back into main. Try to avoid that situation. 12 | 13 | Maintaining the release branches for older minor releases happens on a best effort basis. 14 | 15 | ## Prepare your release 16 | 17 | * Update the [data.yaml](data.yaml) 18 | * Update the compat list 19 | * Update the version key to refer to your new release 20 | * Run `make examples`, which will re-generate all example manifests to use the new version. 21 | * Make a PR to update: 22 | * Run `make generate`, which will update the compatibility matrix in README.md 23 | * Changelog entry 24 | * Only include user relevant changes 25 | * Entries in the [`CHANGELOG.md`](CHANGELOG.md) are meant to be in this order: 26 | 27 | ``` 28 | [CHANGE] 29 | [FEATURE] 30 | [ENHANCEMENT] 31 | [BUGFIX] 32 | ``` 33 | 34 | * All lines should be full sentences 35 | * kube-state-metrics image tag used in Kubernetes deployment yaml config. 36 | * Cut the new release branch, e.g. `release-1.2`, or merge/cherry-pick changes onto the minor release branch you intend to tag the release on 37 | * Cut the new release tag, e.g. `v1.2.0-rc.0` 38 | * Create a new **pre-release** on github 39 | * New images are automatically built and pushed to `gcr.io/k8s-staging-kube-state-metrics/kube-state-metrics` 40 | * Promote image by sending a PR to [kubernetes/k8s.io](https://github.com/kubernetes/k8s.io) repository. Follow the [example PR](https://github.com/kubernetes/k8s.io/pull/3798). Use [kpromo pr](https://github.com/kubernetes-sigs/promo-tools/blob/main/docs/promotion-pull-requests.md) to update the manifest files in this repository, e.g. `kpromo pr --fork=$YOURNAME -i --project=kube-state-metrics -t=v2.5.0` 41 | * Create a PR to merge the changes of this release back into the main branch. 42 | * Once the PR to promote the image is merged, mark the pre-release as a regular release. 43 | 44 | ## Stable release 45 | 46 | First a release candidate (e.g. `v1.2.0-rc.0`) should be cut. If after a period of 7 days no bugs or issues were reported after publishing the release candidate, a stable release (e.g. `v1.2.0`) can be cut. 47 | -------------------------------------------------------------------------------- /SECURITY-INSIGHTS.yml: -------------------------------------------------------------------------------- 1 | # Refer: https://github.com/ossf/security-insights-spec/blob/main/specification.md#specification 2 | header: 3 | schema-version: "1.0.0" 4 | expiration-date: "2024-12-15T19:10:00.000Z" 5 | project-url: https://github.com/kubernetes/kube-state-metrics 6 | changelog: https://github.com/kubernetes/kube-state-metrics/blob/main/CHANGELOG.md 7 | license: https://github.com/kubernetes/kube-state-metrics/blob/main/LICENSE 8 | project-lifecycle: 9 | status: active 10 | bug-fixes-only: false 11 | core-maintainers: 12 | - github:dgrisonnet 13 | - github:mrueg 14 | - github:rexagod 15 | release-process: https://github.com/kubernetes/kube-state-metrics/blob/main/RELEASE.md 16 | contribution-policy: 17 | accepts-pull-requests: true 18 | accepts-automated-pull-requests: true 19 | contributing-policy: https://github.com/kubernetes/kube-state-metrics/blob/main/CONTRIBUTING.md 20 | code-of-conduct: https://github.com/kubernetes/kube-state-metrics/blob/main/code-of-conduct.md 21 | distribution-points: 22 | - https://github.com/kubernetes/kube-state-metrics/releases 23 | - https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-kube-state-metrics/images.yaml 24 | security-contacts: 25 | - type: website 26 | value: https://github.com/kubernetes/kube-state-metrics/blob/main/SECURITY_CONTACTS 27 | vulnerability-reporting: 28 | accepts-vulnerability-reports: true 29 | security-policy: https://github.com/kubernetes/kube-state-metrics/blob/main/SECURITY.md 30 | dependencies: 31 | third-party-packages: true 32 | dependencies-lists: 33 | - https://github.com/kubernetes/kube-state-metrics/blob/main/go.mod 34 | - https://github.com/kubernetes/kube-state-metrics/blob/main/Dockerfile 35 | env-dependencies-policy: 36 | policy-url: https://github.com/kubernetes/kube-state-metrics/blob/main/docs/dependencies-policy.md 37 | documentation: 38 | - https://github.com/kubernetes/kube-state-metrics/tree/main/docs 39 | security-testing: 40 | - tool-type: dast 41 | tool-name: govulncheck 42 | tool-version: latest 43 | tool-url: https://go.googlesource.com/vuln 44 | tool-rulesets: 45 | - built-in 46 | integration: 47 | ci: true 48 | comment: | 49 | Detects vulnerabilities as a result of the affected call-paths being invoked directly in the repository, while reducing false positives by ignoring dormant call-paths for package dependencies. 50 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security Announcements 4 | 5 | Join the [kubernetes-security-announce] group for security and vulnerability announcements. 6 | 7 | You can also subscribe to an RSS feed of the above using [this link][kubernetes-security-announce-rss]. 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Instructions for reporting a vulnerability can be found on the 12 | [Kubernetes Security and Disclosure Information] page. 13 | 14 | ## Supported Versions 15 | 16 | Information about supported Kubernetes versions can be found on the 17 | [Kubernetes version and version skew support policy] page on the Kubernetes website. 18 | 19 | [kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce 20 | [kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50 21 | [Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions 22 | [Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability 23 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | dgrisonnet 14 | mrueg 15 | rexagod 16 | -------------------------------------------------------------------------------- /cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # See https://cloud.google.com/cloud-build/docs/build-config 2 | timeout: 2700s 3 | options: 4 | substitution_option: ALLOW_LOOSE 5 | steps: 6 | - name: 'gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v20241111-71c32dbdcc' 7 | entrypoint: make 8 | env: 9 | - TAG=$_PULL_BASE_REF 10 | - GIT_COMMIT=$_PULL_BASE_SHA 11 | args: 12 | - push 13 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /data.yaml: -------------------------------------------------------------------------------- 1 | # The purpose of this config is to keep all versions in a single file and make them machine accessible 2 | 3 | # Marks the latest release 4 | version: "2.15.0" 5 | 6 | # List at max 5 releases here + the main branch 7 | compat: 8 | - version: "v2.11.0" 9 | kubernetes: "1.28" 10 | - version: "v2.12.0" 11 | kubernetes: "1.29" 12 | - version: "v2.13.0" 13 | kubernetes: "1.30" 14 | - version: "v2.14.0" 15 | kubernetes: "1.31" 16 | - version: "v2.15.0" 17 | kubernetes: "1.32" 18 | - version: "main" 19 | kubernetes: "1.32" 20 | -------------------------------------------------------------------------------- /docs/dependencies-policy.md: -------------------------------------------------------------------------------- 1 | # Dependencies Policy 2 | 3 | ## Purpose 4 | 5 | This policy describes how kube-state-metrics maintainers consume third-party packages. 6 | 7 | ## Scope 8 | 9 | This policy applies to all kube-state-metrics maintainers and all third-party packages used in the kube-state-metrics project. 10 | 11 | ## Policy 12 | 13 | kube-state-metrics maintainers must follow these guidelines when consuming third-party packages: 14 | 15 | * Only use third-party packages that are necessary for the functionality of kube-state-metrics. 16 | * Use the latest version of all third-party packages whenever possible. 17 | * Avoid using third-party packages that are known to have security vulnerabilities. 18 | * Pin all third-party packages to specific versions in the kube-state-metrics codebase. 19 | * Use a dependency management tool, such as Go modules, to manage third-party dependencies. 20 | 21 | ## Procedure 22 | 23 | When adding a new third-party package to kube-state-metrics, maintainers must follow these steps: 24 | 25 | 1. Evaluate the need for the package. Is it necessary for the functionality of kube-state-metrics? 26 | 2. Research the package. Is it actively maintained? Does it have a good reputation? 27 | 3. Choose a version of the package. Use the latest version whenever possible. 28 | 4. Pin the package to the specific version in the kube-state-metrics codebase. 29 | 5. Update the kube-state-metrics documentation to reflect the new dependency. 30 | 31 | ## Enforcement 32 | 33 | This policy is enforced by the kube-state-metrics maintainers. 34 | 35 | Maintainers are expected to review each other's code changes to ensure that they comply with this policy. 36 | 37 | ## Exceptions 38 | 39 | Exceptions to this policy may be granted by the kube-state-metrics project owners on a case-by-case basis. 40 | 41 | ## Credits 42 | 43 | This policy was adapted from Kubescape's [Environment Dependencies Policy](https://github.com/kubescape/kubescape/blob/master/docs/environment-dependencies-policy.md). 44 | -------------------------------------------------------------------------------- /docs/developer/guide.md: -------------------------------------------------------------------------------- 1 | # Developer Guide 2 | 3 | This developer guide documentation is intended to assist all contributors in various code contributions. 4 | Any contribution to improving this documentation will be appreciated. 5 | 6 | ## Table of Contents 7 | 8 | * [Add New Kubernetes Resource Metric Collector](#add-new-kubernetes-resource-metric-collector) 9 | * [Add New Metrics](#add-new-metrics) 10 | 11 | ### Add New Kubernetes Resource Metric Collector 12 | 13 | The following steps are needed to introduce a new resource and its respective resource metrics. 14 | 15 | * Reference your new resource(s) to the [docs/README.md](./../README.md#exposed-metrics). 16 | * Reference your new resource(s) in the [docs/developer/cli-arguments.md](./cli-arguments.md#available-options) as part of the `--resources` flag. 17 | * 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. 18 | * 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`. 19 | * 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). 20 | * Reference and add build functions for the new resource(s) in [internal/store/builder.go](./../../internal/store/builder.go). 21 | * Reference the new resource in [pkg/options/resource.go](./../../pkg/options/resource.go). 22 | * Add a sample Kubernetes manifest to be used by tests in the [tests/manifests/](./../../tests/manifests) directory. 23 | * 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. 24 | 25 | ### Add New Metrics 26 | 27 | * Make metrics experimental first when introducing them, refer [#1910](https://github.com/kubernetes/kube-state-metrics/pull/1910) for more information. 28 | 29 | | Metric stability level | | 30 | |------------------------|--------------------| 31 | | EXPERIMENTAL | basemetrics.ALPHA | 32 | | STABLE | basemetrics.STABLE | 33 | -------------------------------------------------------------------------------- /docs/metrics/auth/certificatesigningrequest-metrics.md: -------------------------------------------------------------------------------- 1 | # CertificateSigningRequest Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_certificatesigningrequest_created | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | STABLE | 7 | | kube_certificatesigningrequest_condition | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name>
`condition`=<approved\|denied> | STABLE | 8 | | 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 | 9 | | kube_certificatesigningrequest_cert_length | Gauge | | `certificatesigningrequest`=<certificatesigningrequest-name>
`signer_name`=<certificatesigningrequest-signer-name> | STABLE | 10 | -------------------------------------------------------------------------------- /docs/metrics/auth/role-metrics.md: -------------------------------------------------------------------------------- 1 | # Role Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ----------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | 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 | 7 | | kube_role_info | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | 8 | | kube_role_created | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | 9 | | kube_role_metadata_resource_version | Gauge | | `role`=<role-name>
`namespace`=<role-namespace> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/auth/rolebinding-metrics.md: -------------------------------------------------------------------------------- 1 | # RoleBinding Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | 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 | 7 | | kube_rolebinding_info | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace>
`roleref_kind`=<role-kind>
`roleref_name`=<role-name> | EXPERIMENTAL | 8 | | kube_rolebinding_created | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | 9 | | kube_rolebinding_metadata_resource_version | Gauge | | `rolebinding`=<rolebinding-name>
`namespace`=<rolebinding-namespace> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/auth/serviceaccount-metrics.md: -------------------------------------------------------------------------------- 1 | # ServiceAccount Metrics 2 | 3 | | Metric name | Metric type | Description | Unit (where applicable) | Labels/tags | Status | 4 | | ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_serviceaccount_info | Gauge | Information about a service account | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`automount_token`=<serviceaccount-automount-token> | EXPERIMENTAL | 6 | | kube_serviceaccount_created | Gauge | Unix creation timestamp | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid> | EXPERIMENTAL | 7 | | kube_serviceaccount_deleted | Gauge | Unix deletion timestamp | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid> | EXPERIMENTAL | 8 | | kube_serviceaccount_secret | Gauge | Secret being referenced by a service account | | `namespace`=<serviceaccount-namespace>
`serviceaccount`=<serviceaccount-name>
`uid`=<serviceaccount-uid>
`name`=<secret-name> | EXPERIMENTAL | 9 | | 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 | 10 | | 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 | 11 | | 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 | 12 | -------------------------------------------------------------------------------- /docs/metrics/cluster/clusterrole-metrics.md: -------------------------------------------------------------------------------- 1 | # ClusterRole Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------ | 5 | | kube_clusterrole_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | 6 | | kube_clusterrole_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | 7 | | kube_clusterrole_info | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | 8 | | kube_clusterrole_created | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | 9 | | kube_clusterrole_metadata_resource_version | Gauge | | `clusterrole`=<clusterrole-name> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/cluster/clusterrolebinding-metrics.md: -------------------------------------------------------------------------------- 1 | # ClusterRoleBinding Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_clusterrolebinding_annotations | Gauge | Kubernetes annotations converted to Prometheus labels controlled via [--metric-annotations-allowlist](../../developer/cli-arguments.md) | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | 6 | | kube_clusterrolebinding_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](../../developer/cli-arguments.md) | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | 7 | | kube_clusterrolebinding_info | Gauge | | `clusterrolebinding`=<clusterrolebinding-name>
`roleref_kind`=<role-kind>
`roleref_name`=<role-name> | EXPERIMENTAL | 8 | | kube_clusterrolebinding_created | Gauge | | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | 9 | | kube_clusterrolebinding_metadata_resource_version | Gauge | | `clusterrolebinding`=<clusterrolebinding-name> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/cluster/lease-metrics.md: -------------------------------------------------------------------------------- 1 | # Lease Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | --------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | 5 | | kube_lease_owner | Gauge | | `lease`=<lease-name>
`owner_kind`=<onwer kind>
`owner_name`=<owner name>
`namespace` = <namespace>
`lease_holder`=<lease holder name> | EXPERIMENTAL | 6 | | kube_lease_renew_time | Gauge | | `lease`=<lease-name>
`namespace` = <namespace> | EXPERIMENTAL | 7 | -------------------------------------------------------------------------------- /docs/metrics/cluster/namespace-metrics.md: -------------------------------------------------------------------------------- 1 | # Namespace Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_namespace_created | Gauge | | `namespace`=<namespace-name> | STABLE | 7 | | 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 | 8 | | kube_namespace_status_condition | Gauge | | `namespace`=<namespace-name>
`condition`=<NamespaceDeletionDiscoveryFailure\|NamespaceDeletionContentFailure\|NamespaceDeletionGroupVersionParsingFailure>
`status`=<true\|false\|unknown> | EXPERIMENTAL | 9 | | kube_namespace_status_phase | Gauge | | `namespace`=<namespace-name>
`phase`=<Active\|Terminating> | STABLE | 10 | -------------------------------------------------------------------------------- /docs/metrics/extend/mutatingwebhookconfiguration-metrics.md: -------------------------------------------------------------------------------- 1 | # MutatingWebhookConfiguration Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | -------------------------------------------------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_mutatingwebhookconfiguration_info | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | 6 | | kube_mutatingwebhookconfiguration_created | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | 7 | | kube_mutatingwebhookconfiguration_metadata_resource_version | Gauge | | `mutatingwebhookconfiguration`=<mutatingwebhookconfiguration-name>
`namespace`=<mutatingwebhookconfiguration-namespace> | EXPERIMENTAL | 8 | | 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 | 9 | -------------------------------------------------------------------------------- /docs/metrics/extend/validatingwebhookconfiguration-metrics.md: -------------------------------------------------------------------------------- 1 | # ValidatingWebhookConfiguration Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ---------------------------------------------------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_validatingwebhookconfiguration_info | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | 6 | | kube_validatingwebhookconfiguration_created | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | 7 | | kube_validatingwebhookconfiguration_metadata_resource_version | Gauge | | `validatingwebhookconfiguration`=<validatingwebhookconfiguration-name>
`namespace`=<validatingwebhookconfiguration-namespace> | EXPERIMENTAL | 8 | | 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 | 9 | -------------------------------------------------------------------------------- /docs/metrics/policy/limitrange-metrics.md: -------------------------------------------------------------------------------- 1 | # LimitRange Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ----------------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | 5 | | kube_limitrange | Gauge | | `limitrange`=<limitrange-name>
`namespace`=<namespace>
`resource`=<ResourceName>
`type`=<Pod\|Container\|PersistentVolumeClaim>
`constraint`=<constraint> | STABLE | 6 | | kube_limitrange_created | Gauge | | `limitrange`=<limitrange-name>
`namespace`=<namespace> | STABLE | 7 | -------------------------------------------------------------------------------- /docs/metrics/policy/networkpolicy-metrics.md: -------------------------------------------------------------------------------- 1 | # Network Policy Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_networkpolicy_created | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | 7 | | 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 | 8 | | kube_networkpolicy_spec_egress_rules | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | 9 | | kube_networkpolicy_spec_ingress_rules | Gauge | | `namespace`=<namespace name> `networkpolicy`=<networkpolicy name> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/policy/resourcequota-metrics.md: -------------------------------------------------------------------------------- 1 | # ResourceQuota Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_resourcequota | Gauge | | `resourcequota`=<quota-name>
`namespace`=<namespace>
`resource`=<ResourceName>
`type`=<quota-type> | STABLE | 6 | | kube_resourcequota_created | Gauge | | `resourcequota`=<quota-name>
`namespace`=<namespace> | STABLE | 7 | | 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 | 8 | | 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 | 9 | -------------------------------------------------------------------------------- /docs/metrics/service/endpoint-metrics.md: -------------------------------------------------------------------------------- 1 | # Endpoint Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_endpoint_info | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | STABLE | 7 | | 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 | 8 | | kube_endpoint_created | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace> | STABLE | 9 | | 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 (Deprecated from 2.14.0) | 10 | | kube_endpoint_address | Gauge | | `endpoint`=<endpoint-name>
`namespace`=<endpoint-namespace>
`ip`=<endpoint-ip>
`port_name`=<endpoint-port-name>
`port_protocol`=<endpoint-port-protocol>
`port_number`=<endpoint-port-number>`ready`=<true if available, false if unavailalbe> | STABLE | 11 | -------------------------------------------------------------------------------- /docs/metrics/service/ingressclass-metrics.md: -------------------------------------------------------------------------------- 1 | # IngressClass Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------ | 5 | | 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 | 6 | | kube_ingressclass_info | Gauge | | `ingressclass`=<ingressclass-name>
`controller`=<ingress-controller-name>
| EXPERIMENTAL | 7 | | 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 | 8 | | kube_ingressclass_created | Gauge | | `ingressclass`=<ingressclass-name> | EXPERIMENTAL | 9 | -------------------------------------------------------------------------------- /docs/metrics/storage/configmap-metrics.md: -------------------------------------------------------------------------------- 1 | # ConfigMap Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ---------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | 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 | 7 | | kube_configmap_info | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | STABLE | 8 | | kube_configmap_created | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | STABLE | 9 | | kube_configmap_metadata_resource_version | Gauge | | `configmap`=<configmap-name>
`namespace`=<configmap-namespace> | EXPERIMENTAL | 10 | -------------------------------------------------------------------------------- /docs/metrics/storage/secret-metrics.md: -------------------------------------------------------------------------------- 1 | # Secret Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_secret_info | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | STABLE | 7 | | kube_secret_type | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace>
`type`=<secret-type> | STABLE | 8 | | 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 | 9 | | kube_secret_created | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | STABLE | 10 | | kube_secret_metadata_resource_version | Gauge | | `secret`=<secret-name>
`namespace`=<secret-namespace> | EXPERIMENTAL | 11 | | 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 | 12 | -------------------------------------------------------------------------------- /docs/metrics/storage/storageclass-metrics.md: -------------------------------------------------------------------------------- 1 | # StorageClass Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | 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 | 6 | | kube_storageclass_info | Gauge | | `storageclass`=<storageclass-name>
`provisioner`=<storageclass-provisioner>
`reclaim_policy`=<storageclass-reclaimPolicy>
`volume_binding_mode`=<storageclass-volumeBindingMode> | STABLE | 7 | | 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 | 8 | | kube_storageclass_created | Gauge | | `storageclass`=<storageclass-name> | STABLE | 9 | -------------------------------------------------------------------------------- /docs/metrics/storage/volumeattachment-metrics.md: -------------------------------------------------------------------------------- 1 | # VolumeAttachment Metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | -------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ | 5 | | kube_volumeattachment_info | Gauge | | `volumeattachment`=<volumeattachment-name>
`attacher`=<attacher-name>
`node`=<node-name> | EXPERIMENTAL | 6 | | kube_volumeattachment_created | Gauge | | `volumeattachment`=<volumeattachment-name> | EXPERIMENTAL | 7 | | 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 | 8 | | kube_volumeattachment_spec_source_persistentvolume | Gauge | | `volumeattachment`=<volumeattachment-name>
`volumename`=<persistentvolume-name> | EXPERIMENTAL | 9 | | kube_volumeattachment_status_attached | Gauge | | `volumeattachment`=<volumeattachment-name> | EXPERIMENTAL | 10 | | kube_volumeattachment_status_attachment_metadata | Gauge | | `volumeattachment`=<volumeattachment-name>
`metadata_METADATA_KEY`=<METADATA_VALUE> | EXPERIMENTAL | 11 | -------------------------------------------------------------------------------- /docs/metrics/workload/replicationcontroller-metrics.md: -------------------------------------------------------------------------------- 1 | # ReplicationController metrics 2 | 3 | | Metric name | Metric type | Description | Labels/tags | Status | 4 | | -------------------------------------------------------- | ----------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | 5 | | kube_replicationcontroller_status_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 6 | | kube_replicationcontroller_status_fully_labeled_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 7 | | kube_replicationcontroller_status_ready_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 8 | | kube_replicationcontroller_status_available_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 9 | | kube_replicationcontroller_status_observed_generation | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 10 | | kube_replicationcontroller_spec_replicas | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 11 | | kube_replicationcontroller_metadata_generation | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 12 | | kube_replicationcontroller_created | Gauge | | `replicationcontroller`=<replicationcontroller-name>
`namespace`=<replicationcontroller-namespace> | STABLE | 13 | | 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 | 14 | -------------------------------------------------------------------------------- /examples/autosharding/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: ClusterRole 12 | name: kube-state-metrics 13 | subjects: 14 | - kind: ServiceAccount 15 | name: kube-state-metrics 16 | namespace: kube-system 17 | -------------------------------------------------------------------------------- /examples/autosharding/cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | - secrets 15 | - nodes 16 | - pods 17 | - services 18 | - serviceaccounts 19 | - resourcequotas 20 | - replicationcontrollers 21 | - limitranges 22 | - persistentvolumeclaims 23 | - persistentvolumes 24 | - namespaces 25 | - endpoints 26 | verbs: 27 | - list 28 | - watch 29 | - apiGroups: 30 | - apps 31 | resources: 32 | - statefulsets 33 | - daemonsets 34 | - deployments 35 | - replicasets 36 | verbs: 37 | - list 38 | - watch 39 | - apiGroups: 40 | - batch 41 | resources: 42 | - cronjobs 43 | - jobs 44 | verbs: 45 | - list 46 | - watch 47 | - apiGroups: 48 | - autoscaling 49 | resources: 50 | - horizontalpodautoscalers 51 | verbs: 52 | - list 53 | - watch 54 | - apiGroups: 55 | - authentication.k8s.io 56 | resources: 57 | - tokenreviews 58 | verbs: 59 | - create 60 | - apiGroups: 61 | - authorization.k8s.io 62 | resources: 63 | - subjectaccessreviews 64 | verbs: 65 | - create 66 | - apiGroups: 67 | - policy 68 | resources: 69 | - poddisruptionbudgets 70 | verbs: 71 | - list 72 | - watch 73 | - apiGroups: 74 | - certificates.k8s.io 75 | resources: 76 | - certificatesigningrequests 77 | verbs: 78 | - list 79 | - watch 80 | - apiGroups: 81 | - discovery.k8s.io 82 | resources: 83 | - endpointslices 84 | verbs: 85 | - list 86 | - watch 87 | - apiGroups: 88 | - storage.k8s.io 89 | resources: 90 | - storageclasses 91 | - volumeattachments 92 | verbs: 93 | - list 94 | - watch 95 | - apiGroups: 96 | - admissionregistration.k8s.io 97 | resources: 98 | - mutatingwebhookconfigurations 99 | - validatingwebhookconfigurations 100 | verbs: 101 | - list 102 | - watch 103 | - apiGroups: 104 | - networking.k8s.io 105 | resources: 106 | - networkpolicies 107 | - ingressclasses 108 | - ingresses 109 | verbs: 110 | - list 111 | - watch 112 | - apiGroups: 113 | - coordination.k8s.io 114 | resources: 115 | - leases 116 | verbs: 117 | - list 118 | - watch 119 | - apiGroups: 120 | - rbac.authorization.k8s.io 121 | resources: 122 | - clusterrolebindings 123 | - clusterroles 124 | - rolebindings 125 | - roles 126 | verbs: 127 | - list 128 | - watch 129 | -------------------------------------------------------------------------------- /examples/autosharding/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: kube-system 5 | 6 | resources: 7 | - cluster-role-binding.yaml 8 | - cluster-role.yaml 9 | - role-binding.yaml 10 | - role.yaml 11 | - service-account.yaml 12 | - service.yaml 13 | - statefulset.yaml 14 | -------------------------------------------------------------------------------- /examples/autosharding/role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | roleRef: 11 | apiGroup: rbac.authorization.k8s.io 12 | kind: Role 13 | name: kube-state-metrics 14 | subjects: 15 | - kind: ServiceAccount 16 | name: kube-state-metrics 17 | -------------------------------------------------------------------------------- /examples/autosharding/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | rules: 11 | - apiGroups: 12 | - "" 13 | resources: 14 | - pods 15 | verbs: 16 | - get 17 | - apiGroups: 18 | - apps 19 | resourceNames: 20 | - kube-state-metrics 21 | resources: 22 | - statefulsets 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /examples/autosharding/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | automountServiceAccountToken: false 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/component: exporter 7 | app.kubernetes.io/name: kube-state-metrics 8 | app.kubernetes.io/version: 2.15.0 9 | name: kube-state-metrics 10 | namespace: kube-system 11 | -------------------------------------------------------------------------------- /examples/autosharding/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: http-metrics 14 | port: 8080 15 | targetPort: http-metrics 16 | - name: telemetry 17 | port: 8081 18 | targetPort: telemetry 19 | selector: 20 | app.kubernetes.io/name: kube-state-metrics 21 | -------------------------------------------------------------------------------- /examples/autosharding/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | replicas: 2 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: kube-state-metrics 15 | serviceName: kube-state-metrics 16 | template: 17 | metadata: 18 | labels: 19 | app.kubernetes.io/component: exporter 20 | app.kubernetes.io/name: kube-state-metrics 21 | app.kubernetes.io/version: 2.15.0 22 | spec: 23 | automountServiceAccountToken: true 24 | containers: 25 | - args: 26 | - --pod=$(POD_NAME) 27 | - --pod-namespace=$(POD_NAMESPACE) 28 | env: 29 | - name: POD_NAME 30 | valueFrom: 31 | fieldRef: 32 | fieldPath: metadata.name 33 | - name: POD_NAMESPACE 34 | valueFrom: 35 | fieldRef: 36 | fieldPath: metadata.namespace 37 | image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 38 | livenessProbe: 39 | httpGet: 40 | path: /livez 41 | port: http-metrics 42 | initialDelaySeconds: 5 43 | timeoutSeconds: 5 44 | name: kube-state-metrics 45 | ports: 46 | - containerPort: 8080 47 | name: http-metrics 48 | - containerPort: 8081 49 | name: telemetry 50 | readinessProbe: 51 | httpGet: 52 | path: /readyz 53 | port: telemetry 54 | initialDelaySeconds: 5 55 | timeoutSeconds: 5 56 | securityContext: 57 | allowPrivilegeEscalation: false 58 | capabilities: 59 | drop: 60 | - ALL 61 | readOnlyRootFilesystem: true 62 | runAsNonRoot: true 63 | runAsUser: 65534 64 | seccompProfile: 65 | type: RuntimeDefault 66 | nodeSelector: 67 | kubernetes.io/os: linux 68 | serviceAccountName: kube-state-metrics 69 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: ClusterRole 12 | name: kube-state-metrics 13 | subjects: 14 | - kind: ServiceAccount 15 | name: kube-state-metrics 16 | namespace: kube-system 17 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | - secrets 15 | - nodes 16 | - pods 17 | - services 18 | - serviceaccounts 19 | - resourcequotas 20 | - replicationcontrollers 21 | - limitranges 22 | - persistentvolumeclaims 23 | - persistentvolumes 24 | - namespaces 25 | - endpoints 26 | verbs: 27 | - list 28 | - watch 29 | - apiGroups: 30 | - apps 31 | resources: 32 | - statefulsets 33 | - daemonsets 34 | - deployments 35 | - replicasets 36 | verbs: 37 | - list 38 | - watch 39 | - apiGroups: 40 | - batch 41 | resources: 42 | - cronjobs 43 | - jobs 44 | verbs: 45 | - list 46 | - watch 47 | - apiGroups: 48 | - autoscaling 49 | resources: 50 | - horizontalpodautoscalers 51 | verbs: 52 | - list 53 | - watch 54 | - apiGroups: 55 | - authentication.k8s.io 56 | resources: 57 | - tokenreviews 58 | verbs: 59 | - create 60 | - apiGroups: 61 | - authorization.k8s.io 62 | resources: 63 | - subjectaccessreviews 64 | verbs: 65 | - create 66 | - apiGroups: 67 | - policy 68 | resources: 69 | - poddisruptionbudgets 70 | verbs: 71 | - list 72 | - watch 73 | - apiGroups: 74 | - certificates.k8s.io 75 | resources: 76 | - certificatesigningrequests 77 | verbs: 78 | - list 79 | - watch 80 | - apiGroups: 81 | - discovery.k8s.io 82 | resources: 83 | - endpointslices 84 | verbs: 85 | - list 86 | - watch 87 | - apiGroups: 88 | - storage.k8s.io 89 | resources: 90 | - storageclasses 91 | - volumeattachments 92 | verbs: 93 | - list 94 | - watch 95 | - apiGroups: 96 | - admissionregistration.k8s.io 97 | resources: 98 | - mutatingwebhookconfigurations 99 | - validatingwebhookconfigurations 100 | verbs: 101 | - list 102 | - watch 103 | - apiGroups: 104 | - networking.k8s.io 105 | resources: 106 | - networkpolicies 107 | - ingressclasses 108 | - ingresses 109 | verbs: 110 | - list 111 | - watch 112 | - apiGroups: 113 | - coordination.k8s.io 114 | resources: 115 | - leases 116 | verbs: 117 | - list 118 | - watch 119 | - apiGroups: 120 | - rbac.authorization.k8s.io 121 | resources: 122 | - clusterrolebindings 123 | - clusterroles 124 | - rolebindings 125 | - roles 126 | verbs: 127 | - list 128 | - watch 129 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/daemonset-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics-shard 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics-shard 9 | namespace: kube-system 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: http-metrics 14 | port: 8080 15 | targetPort: http-metrics 16 | - name: telemetry 17 | port: 8081 18 | targetPort: telemetry 19 | selector: 20 | app.kubernetes.io/name: kube-state-metrics-shard 21 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics-shard 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics-shard 9 | namespace: kube-system 10 | spec: 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/name: kube-state-metrics-shard 14 | template: 15 | metadata: 16 | labels: 17 | app.kubernetes.io/component: exporter 18 | app.kubernetes.io/name: kube-state-metrics-shard 19 | app.kubernetes.io/version: 2.15.0 20 | spec: 21 | automountServiceAccountToken: true 22 | containers: 23 | - args: 24 | - --resources=pods 25 | - --node=$(NODE_NAME) 26 | env: 27 | - name: NODE_NAME 28 | valueFrom: 29 | fieldRef: 30 | apiVersion: v1 31 | fieldPath: spec.nodeName 32 | image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 33 | livenessProbe: 34 | httpGet: 35 | path: /livez 36 | port: http-metrics 37 | initialDelaySeconds: 5 38 | timeoutSeconds: 5 39 | name: kube-state-metrics-shard 40 | ports: 41 | - containerPort: 8080 42 | name: http-metrics 43 | - containerPort: 8081 44 | name: telemetry 45 | readinessProbe: 46 | httpGet: 47 | path: /readyz 48 | port: telemetry 49 | initialDelaySeconds: 5 50 | timeoutSeconds: 5 51 | securityContext: 52 | allowPrivilegeEscalation: false 53 | capabilities: 54 | drop: 55 | - ALL 56 | readOnlyRootFilesystem: true 57 | runAsNonRoot: true 58 | runAsUser: 65534 59 | seccompProfile: 60 | type: RuntimeDefault 61 | nodeSelector: 62 | kubernetes.io/os: linux 63 | serviceAccountName: kube-state-metrics 64 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/deployment-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: http-metrics 14 | port: 8080 15 | targetPort: http-metrics 16 | - name: telemetry 17 | port: 8081 18 | targetPort: telemetry 19 | selector: 20 | app.kubernetes.io/name: kube-state-metrics 21 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/deployment-unscheduled-pods-fetching-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics-unscheduled-pods-fetching 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics-unscheduled-pods-fetching 9 | namespace: kube-system 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: http-metrics 14 | port: 8080 15 | targetPort: http-metrics 16 | - name: telemetry 17 | port: 8081 18 | targetPort: telemetry 19 | selector: 20 | app.kubernetes.io/name: kube-state-metrics-unscheduled-pods-fetching 21 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/deployment-unscheduled-pods-fetching.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics-unscheduled-pods-fetching 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics-unscheduled-pods-fetching 9 | namespace: kube-system 10 | spec: 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: kube-state-metrics-unscheduled-pods-fetching 15 | template: 16 | metadata: 17 | labels: 18 | app.kubernetes.io/component: exporter 19 | app.kubernetes.io/name: kube-state-metrics-unscheduled-pods-fetching 20 | app.kubernetes.io/version: 2.15.0 21 | spec: 22 | automountServiceAccountToken: true 23 | containers: 24 | - args: 25 | - --resources=pods 26 | - --track-unscheduled-pods 27 | image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 28 | livenessProbe: 29 | httpGet: 30 | path: /livez 31 | port: http-metrics 32 | initialDelaySeconds: 5 33 | timeoutSeconds: 5 34 | name: kube-state-metrics-unscheduled-pods-fetching 35 | ports: 36 | - containerPort: 8080 37 | name: http-metrics 38 | - containerPort: 8081 39 | name: telemetry 40 | readinessProbe: 41 | httpGet: 42 | path: /readyz 43 | port: telemetry 44 | initialDelaySeconds: 5 45 | timeoutSeconds: 5 46 | securityContext: 47 | allowPrivilegeEscalation: false 48 | capabilities: 49 | drop: 50 | - ALL 51 | readOnlyRootFilesystem: true 52 | runAsNonRoot: true 53 | runAsUser: 65534 54 | seccompProfile: 55 | type: RuntimeDefault 56 | nodeSelector: 57 | kubernetes.io/os: linux 58 | serviceAccountName: kube-state-metrics 59 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: kube-state-metrics 15 | template: 16 | metadata: 17 | labels: 18 | app.kubernetes.io/component: exporter 19 | app.kubernetes.io/name: kube-state-metrics 20 | app.kubernetes.io/version: 2.15.0 21 | spec: 22 | automountServiceAccountToken: true 23 | containers: 24 | - args: 25 | - --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 26 | image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 27 | livenessProbe: 28 | httpGet: 29 | path: /livez 30 | port: http-metrics 31 | initialDelaySeconds: 5 32 | timeoutSeconds: 5 33 | name: kube-state-metrics 34 | ports: 35 | - containerPort: 8080 36 | name: http-metrics 37 | - containerPort: 8081 38 | name: telemetry 39 | readinessProbe: 40 | httpGet: 41 | path: /readyz 42 | port: telemetry 43 | initialDelaySeconds: 5 44 | timeoutSeconds: 5 45 | securityContext: 46 | allowPrivilegeEscalation: false 47 | capabilities: 48 | drop: 49 | - ALL 50 | readOnlyRootFilesystem: true 51 | runAsNonRoot: true 52 | runAsUser: 65534 53 | seccompProfile: 54 | type: RuntimeDefault 55 | nodeSelector: 56 | kubernetes.io/os: linux 57 | serviceAccountName: kube-state-metrics 58 | -------------------------------------------------------------------------------- /examples/daemonsetsharding/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | automountServiceAccountToken: false 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/component: exporter 7 | app.kubernetes.io/name: kube-state-metrics 8 | app.kubernetes.io/version: 2.15.0 9 | name: kube-state-metrics 10 | namespace: kube-system 11 | -------------------------------------------------------------------------------- /examples/prometheus-alerting-rules/alerts.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - name: kube-state-metrics 3 | rules: 4 | - alert: KubeStateMetricsListErrors 5 | annotations: 6 | description: kube-state-metrics is experiencing errors at an elevated rate in list operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. 7 | summary: kube-state-metrics is experiencing errors in list operations. 8 | expr: | 9 | (sum(rate(kube_state_metrics_list_total{job="kube-state-metrics",result="error"}[5m])) by (cluster) 10 | / 11 | sum(rate(kube_state_metrics_list_total{job="kube-state-metrics"}[5m])) by (cluster)) 12 | > 0.01 13 | for: 15m 14 | labels: 15 | severity: critical 16 | - alert: KubeStateMetricsWatchErrors 17 | annotations: 18 | description: kube-state-metrics is experiencing errors at an elevated rate in watch operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. 19 | summary: kube-state-metrics is experiencing errors in watch operations. 20 | expr: | 21 | (sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics",result="error"}[5m])) by (cluster) 22 | / 23 | sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics"}[5m])) by (cluster)) 24 | > 0.01 25 | for: 15m 26 | labels: 27 | severity: critical 28 | - alert: KubeStateMetricsShardingMismatch 29 | annotations: 30 | description: kube-state-metrics pods are running with different --total-shards configuration, some Kubernetes objects may be exposed multiple times or not exposed at all. 31 | summary: kube-state-metrics sharding is misconfigured. 32 | expr: | 33 | stdvar (kube_state_metrics_total_shards{job="kube-state-metrics"}) by (cluster) != 0 34 | for: 15m 35 | labels: 36 | severity: critical 37 | - alert: KubeStateMetricsShardsMissing 38 | annotations: 39 | description: kube-state-metrics shards are missing, some Kubernetes objects are not being exposed. 40 | summary: kube-state-metrics shards are missing. 41 | expr: | 42 | 2^max(kube_state_metrics_total_shards{job="kube-state-metrics"}) by (cluster) - 1 43 | - 44 | sum( 2 ^ max by (cluster, shard_ordinal) (kube_state_metrics_shard_ordinal{job="kube-state-metrics"}) ) by (cluster) 45 | != 0 46 | for: 15m 47 | labels: 48 | severity: critical 49 | -------------------------------------------------------------------------------- /examples/standard/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | roleRef: 10 | apiGroup: rbac.authorization.k8s.io 11 | kind: ClusterRole 12 | name: kube-state-metrics 13 | subjects: 14 | - kind: ServiceAccount 15 | name: kube-state-metrics 16 | namespace: kube-system 17 | -------------------------------------------------------------------------------- /examples/standard/cluster-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | - secrets 15 | - nodes 16 | - pods 17 | - services 18 | - serviceaccounts 19 | - resourcequotas 20 | - replicationcontrollers 21 | - limitranges 22 | - persistentvolumeclaims 23 | - persistentvolumes 24 | - namespaces 25 | - endpoints 26 | verbs: 27 | - list 28 | - watch 29 | - apiGroups: 30 | - apps 31 | resources: 32 | - statefulsets 33 | - daemonsets 34 | - deployments 35 | - replicasets 36 | verbs: 37 | - list 38 | - watch 39 | - apiGroups: 40 | - batch 41 | resources: 42 | - cronjobs 43 | - jobs 44 | verbs: 45 | - list 46 | - watch 47 | - apiGroups: 48 | - autoscaling 49 | resources: 50 | - horizontalpodautoscalers 51 | verbs: 52 | - list 53 | - watch 54 | - apiGroups: 55 | - authentication.k8s.io 56 | resources: 57 | - tokenreviews 58 | verbs: 59 | - create 60 | - apiGroups: 61 | - authorization.k8s.io 62 | resources: 63 | - subjectaccessreviews 64 | verbs: 65 | - create 66 | - apiGroups: 67 | - policy 68 | resources: 69 | - poddisruptionbudgets 70 | verbs: 71 | - list 72 | - watch 73 | - apiGroups: 74 | - certificates.k8s.io 75 | resources: 76 | - certificatesigningrequests 77 | verbs: 78 | - list 79 | - watch 80 | - apiGroups: 81 | - discovery.k8s.io 82 | resources: 83 | - endpointslices 84 | verbs: 85 | - list 86 | - watch 87 | - apiGroups: 88 | - storage.k8s.io 89 | resources: 90 | - storageclasses 91 | - volumeattachments 92 | verbs: 93 | - list 94 | - watch 95 | - apiGroups: 96 | - admissionregistration.k8s.io 97 | resources: 98 | - mutatingwebhookconfigurations 99 | - validatingwebhookconfigurations 100 | verbs: 101 | - list 102 | - watch 103 | - apiGroups: 104 | - networking.k8s.io 105 | resources: 106 | - networkpolicies 107 | - ingressclasses 108 | - ingresses 109 | verbs: 110 | - list 111 | - watch 112 | - apiGroups: 113 | - coordination.k8s.io 114 | resources: 115 | - leases 116 | verbs: 117 | - list 118 | - watch 119 | - apiGroups: 120 | - rbac.authorization.k8s.io 121 | resources: 122 | - clusterrolebindings 123 | - clusterroles 124 | - rolebindings 125 | - roles 126 | verbs: 127 | - list 128 | - watch 129 | -------------------------------------------------------------------------------- /examples/standard/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: kube-state-metrics 15 | template: 16 | metadata: 17 | labels: 18 | app.kubernetes.io/component: exporter 19 | app.kubernetes.io/name: kube-state-metrics 20 | app.kubernetes.io/version: 2.15.0 21 | spec: 22 | automountServiceAccountToken: true 23 | containers: 24 | - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.0 25 | livenessProbe: 26 | httpGet: 27 | path: /livez 28 | port: http-metrics 29 | initialDelaySeconds: 5 30 | timeoutSeconds: 5 31 | name: kube-state-metrics 32 | ports: 33 | - containerPort: 8080 34 | name: http-metrics 35 | - containerPort: 8081 36 | name: telemetry 37 | readinessProbe: 38 | httpGet: 39 | path: /readyz 40 | port: telemetry 41 | initialDelaySeconds: 5 42 | timeoutSeconds: 5 43 | securityContext: 44 | allowPrivilegeEscalation: false 45 | capabilities: 46 | drop: 47 | - ALL 48 | readOnlyRootFilesystem: true 49 | runAsNonRoot: true 50 | runAsUser: 65534 51 | seccompProfile: 52 | type: RuntimeDefault 53 | nodeSelector: 54 | kubernetes.io/os: linux 55 | serviceAccountName: kube-state-metrics 56 | -------------------------------------------------------------------------------- /examples/standard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: kube-system 4 | 5 | resources: 6 | - cluster-role.yaml 7 | - cluster-role-binding.yaml 8 | - service-account.yaml 9 | - deployment.yaml 10 | - service.yaml 11 | -------------------------------------------------------------------------------- /examples/standard/service-account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | automountServiceAccountToken: false 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/component: exporter 7 | app.kubernetes.io/name: kube-state-metrics 8 | app.kubernetes.io/version: 2.15.0 9 | name: kube-state-metrics 10 | namespace: kube-system 11 | -------------------------------------------------------------------------------- /examples/standard/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/version: 2.15.0 8 | name: kube-state-metrics 9 | namespace: kube-system 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: http-metrics 14 | port: 8080 15 | targetPort: http-metrics 16 | - name: telemetry 17 | port: 8081 18 | targetPort: telemetry 19 | selector: 20 | app.kubernetes.io/name: kube-state-metrics 21 | -------------------------------------------------------------------------------- /internal/discovery/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors All rights reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package discovery 15 | 16 | import ( 17 | "fmt" 18 | "sync" 19 | 20 | "github.com/prometheus/client_golang/prometheus" 21 | "k8s.io/apimachinery/pkg/runtime/schema" 22 | ) 23 | 24 | type groupVersionKindPlural struct { 25 | schema.GroupVersionKind 26 | Plural string 27 | } 28 | 29 | func (g groupVersionKindPlural) String() string { 30 | return fmt.Sprintf("%s/%s, Kind=%s, Plural=%s", g.Group, g.Version, g.Kind, g.Plural) 31 | } 32 | 33 | type kindPlural struct { 34 | Kind string 35 | Plural string 36 | } 37 | 38 | // CRDiscoverer provides a cache of the collected GVKs, along with helper utilities. 39 | type CRDiscoverer struct { 40 | // CRDsAddEventsCounter tracks the number of times that the CRD informer triggered the "add" event. 41 | CRDsAddEventsCounter prometheus.Counter 42 | // CRDsDeleteEventsCounter tracks the number of times that the CRD informer triggered the "remove" event. 43 | CRDsDeleteEventsCounter prometheus.Counter 44 | // CRDsCacheCountGauge tracks the net amount of CRDs affecting the cache at this point. 45 | CRDsCacheCountGauge prometheus.Gauge 46 | // Map is a cache of the collected GVKs. 47 | Map map[string]map[string][]kindPlural 48 | // m is a mutex to protect the cache. 49 | m sync.RWMutex 50 | // ShouldUpdate is a flag that indicates whether the cache was updated. 51 | WasUpdated bool 52 | } 53 | 54 | // SafeRead executes the given function while holding a read lock. 55 | func (r *CRDiscoverer) SafeRead(f func()) { 56 | r.m.RLock() 57 | defer r.m.RUnlock() 58 | f() 59 | } 60 | 61 | // SafeWrite executes the given function while holding a write lock. 62 | func (r *CRDiscoverer) SafeWrite(f func()) { 63 | r.m.Lock() 64 | defer r.m.Unlock() 65 | f() 66 | } 67 | 68 | // AppendToMap appends the given GVKs to the cache. 69 | func (r *CRDiscoverer) AppendToMap(gvkps ...groupVersionKindPlural) { 70 | if r.Map == nil { 71 | r.Map = map[string]map[string][]kindPlural{} 72 | } 73 | for _, gvkp := range gvkps { 74 | if _, ok := r.Map[gvkp.Group]; !ok { 75 | r.Map[gvkp.Group] = map[string][]kindPlural{} 76 | } 77 | if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { 78 | r.Map[gvkp.Group][gvkp.Version] = []kindPlural{} 79 | } 80 | r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version], kindPlural{Kind: gvkp.Kind, Plural: gvkp.Plural}) 81 | } 82 | } 83 | 84 | // RemoveFromMap removes the given GVKs from the cache. 85 | func (r *CRDiscoverer) RemoveFromMap(gvkps ...groupVersionKindPlural) { 86 | for _, gvkp := range gvkps { 87 | if _, ok := r.Map[gvkp.Group]; !ok { 88 | continue 89 | } 90 | if _, ok := r.Map[gvkp.Group][gvkp.Version]; !ok { 91 | continue 92 | } 93 | for i, el := range r.Map[gvkp.Group][gvkp.Version] { 94 | if el.Kind == gvkp.Kind { 95 | if len(r.Map[gvkp.Group][gvkp.Version]) == 1 { 96 | delete(r.Map[gvkp.Group], gvkp.Version) 97 | if len(r.Map[gvkp.Group]) == 0 { 98 | delete(r.Map, gvkp.Group) 99 | } 100 | break 101 | } 102 | r.Map[gvkp.Group][gvkp.Version] = append(r.Map[gvkp.Group][gvkp.Version][:i], r.Map[gvkp.Group][gvkp.Version][i+1:]...) 103 | break 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /internal/store/ingressclass_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors All rights reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package store 15 | 16 | import ( 17 | "testing" 18 | 19 | networkingv1 "k8s.io/api/networking/v1" 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | 22 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 23 | ) 24 | 25 | func TestIngressClassStore(t *testing.T) { 26 | startTime := 1501569018 27 | metav1StartTime := metav1.Unix(int64(startTime), 0) 28 | 29 | cases := []generateMetricsTestCase{ 30 | { 31 | Obj: &networkingv1.IngressClass{ 32 | ObjectMeta: metav1.ObjectMeta{ 33 | Name: "test_ingressclass-info", 34 | }, 35 | Spec: networkingv1.IngressClassSpec{ 36 | Controller: "controller", 37 | }, 38 | }, 39 | Want: ` 40 | # HELP kube_ingressclass_info Information about ingressclass. 41 | # TYPE kube_ingressclass_info gauge 42 | kube_ingressclass_info{ingressclass="test_ingressclass-info",controller="controller"} 1 43 | `, 44 | MetricNames: []string{ 45 | "kube_ingressclass_info", 46 | }, 47 | }, 48 | { 49 | Obj: &networkingv1.IngressClass{ 50 | ObjectMeta: metav1.ObjectMeta{ 51 | Name: "test_kube_ingressclass-created", 52 | CreationTimestamp: metav1StartTime, 53 | }, 54 | Spec: networkingv1.IngressClassSpec{ 55 | Controller: "controller", 56 | }, 57 | }, 58 | Want: ` 59 | # HELP kube_ingressclass_created Unix creation timestamp 60 | # TYPE kube_ingressclass_created gauge 61 | kube_ingressclass_created{ingressclass="test_kube_ingressclass-created"} 1.501569018e+09 62 | `, 63 | MetricNames: []string{ 64 | "kube_ingressclass_created", 65 | }, 66 | }, 67 | { 68 | AllowAnnotationsList: []string{ 69 | "ingressclass.kubernetes.io/is-default-class", 70 | }, 71 | Obj: &networkingv1.IngressClass{ 72 | ObjectMeta: metav1.ObjectMeta{ 73 | Name: "test_ingressclass-labels", 74 | Annotations: map[string]string{ 75 | "ingressclass.kubernetes.io/is-default-class": "true", 76 | }, 77 | Labels: map[string]string{ 78 | "foo": "bar", 79 | }, 80 | }, 81 | Spec: networkingv1.IngressClassSpec{ 82 | Controller: "controller", 83 | }, 84 | }, 85 | Want: ` 86 | # HELP kube_ingressclass_annotations Kubernetes annotations converted to Prometheus labels. 87 | # HELP kube_ingressclass_labels Kubernetes labels converted to Prometheus labels. 88 | # TYPE kube_ingressclass_annotations gauge 89 | # TYPE kube_ingressclass_labels gauge 90 | kube_ingressclass_annotations{ingressclass="test_ingressclass-labels",annotation_ingressclass_kubernetes_io_is_default_class="true"} 1 91 | `, 92 | MetricNames: []string{ 93 | "kube_ingressclass_annotations", "kube_ingressclass_labels", 94 | }, 95 | }, 96 | } 97 | for i, c := range cases { 98 | c.Func = generator.ComposeMetricGenFuncs(ingressClassMetricFamilies(c.AllowAnnotationsList, nil)) 99 | c.Headers = generator.ExtractMetricFamilyHeaders(ingressClassMetricFamilies(c.AllowAnnotationsList, nil)) 100 | if err := c.run(); err != nil { 101 | t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /internal/store/lease_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | coordinationv1 "k8s.io/api/coordination/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | 26 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 27 | ) 28 | 29 | func TestLeaseStore(t *testing.T) { 30 | const metadata = ` 31 | # HELP kube_lease_owner Information about the Lease's owner. 32 | # TYPE kube_lease_owner gauge 33 | # HELP kube_lease_renew_time Kube lease renew time. 34 | # TYPE kube_lease_renew_time gauge 35 | ` 36 | leaseOwner := "kube-master" 37 | var ( 38 | cases = []generateMetricsTestCase{ 39 | { 40 | Obj: &coordinationv1.Lease{ 41 | ObjectMeta: metav1.ObjectMeta{ 42 | Generation: 2, 43 | Name: "kube-master", 44 | Namespace: "default", 45 | CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, 46 | OwnerReferences: []metav1.OwnerReference{ 47 | { 48 | Kind: "Node", 49 | Name: leaseOwner, 50 | }, 51 | }, 52 | }, 53 | Spec: coordinationv1.LeaseSpec{ 54 | RenewTime: &metav1.MicroTime{Time: time.Unix(1500000000, 0)}, 55 | HolderIdentity: &leaseOwner, 56 | }, 57 | }, 58 | Want: metadata + ` 59 | kube_lease_owner{lease="kube-master",owner_kind="Node",owner_name="kube-master",namespace="default",lease_holder="kube-master"} 1 60 | kube_lease_renew_time{lease="kube-master",namespace="default"} 1.5e+09 61 | `, 62 | MetricNames: []string{ 63 | "kube_lease_owner", 64 | "kube_lease_renew_time", 65 | }, 66 | }, 67 | { 68 | Obj: &coordinationv1.Lease{ 69 | ObjectMeta: metav1.ObjectMeta{ 70 | Generation: 2, 71 | Name: "kube-master", 72 | Namespace: "default", 73 | CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, 74 | OwnerReferences: []metav1.OwnerReference{ 75 | { 76 | Kind: "Node", 77 | Name: leaseOwner, 78 | }, 79 | }, 80 | }, 81 | Spec: coordinationv1.LeaseSpec{ 82 | RenewTime: &metav1.MicroTime{Time: time.Unix(1500000000, 0)}, 83 | }, 84 | }, 85 | Want: metadata + ` 86 | kube_lease_owner{lease="kube-master",owner_kind="Node",owner_name="kube-master",namespace="default",lease_holder=""} 1 87 | kube_lease_renew_time{lease="kube-master",namespace="default"} 1.5e+09 88 | `, 89 | MetricNames: []string{ 90 | "kube_lease_owner", 91 | "kube_lease_renew_time", 92 | }, 93 | }, 94 | } 95 | ) 96 | for i, c := range cases { 97 | c.Func = generator.ComposeMetricGenFuncs(leaseMetricFamilies) 98 | c.Headers = generator.ExtractMetricFamilyHeaders(leaseMetricFamilies) 99 | if err := c.run(); err != nil { 100 | t.Errorf("unexpected collecting result in %dth run:\n%v", i, err) 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /internal/store/limitrange_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | v1 "k8s.io/api/core/v1" 24 | "k8s.io/apimachinery/pkg/api/resource" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | 27 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 28 | ) 29 | 30 | func TestLimitRangeStore(t *testing.T) { 31 | testMemory := "2.1G" 32 | testMemoryQuantity := resource.MustParse(testMemory) 33 | // Fixed metadata on type and help text. We prepend this to every expected 34 | // output so we only have to modify a single place when doing adjustments. 35 | const metadata = ` 36 | # HELP kube_limitrange_created [STABLE] Unix creation timestamp 37 | # TYPE kube_limitrange_created gauge 38 | # HELP kube_limitrange [STABLE] Information about limit range. 39 | # TYPE kube_limitrange gauge 40 | ` 41 | cases := []generateMetricsTestCase{ 42 | { 43 | Obj: &v1.LimitRange{ 44 | ObjectMeta: metav1.ObjectMeta{ 45 | Name: "quotaTest", 46 | CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, 47 | Namespace: "testNS", 48 | }, 49 | Spec: v1.LimitRangeSpec{ 50 | Limits: []v1.LimitRangeItem{ 51 | { 52 | Type: v1.LimitTypePod, 53 | Max: map[v1.ResourceName]resource.Quantity{ 54 | v1.ResourceMemory: testMemoryQuantity, 55 | }, 56 | Min: map[v1.ResourceName]resource.Quantity{ 57 | v1.ResourceMemory: testMemoryQuantity, 58 | }, 59 | Default: map[v1.ResourceName]resource.Quantity{ 60 | v1.ResourceMemory: testMemoryQuantity, 61 | }, 62 | DefaultRequest: map[v1.ResourceName]resource.Quantity{ 63 | v1.ResourceMemory: testMemoryQuantity, 64 | }, 65 | MaxLimitRequestRatio: map[v1.ResourceName]resource.Quantity{ 66 | v1.ResourceMemory: testMemoryQuantity, 67 | }, 68 | }, 69 | }, 70 | }, 71 | }, 72 | Want: metadata + ` 73 | kube_limitrange_created{limitrange="quotaTest",namespace="testNS"} 1.5e+09 74 | kube_limitrange{constraint="default",limitrange="quotaTest",namespace="testNS",resource="memory",type="Pod"} 2.1e+09 75 | kube_limitrange{constraint="defaultRequest",limitrange="quotaTest",namespace="testNS",resource="memory",type="Pod"} 2.1e+09 76 | kube_limitrange{constraint="max",limitrange="quotaTest",namespace="testNS",resource="memory",type="Pod"} 2.1e+09 77 | kube_limitrange{constraint="maxLimitRequestRatio",limitrange="quotaTest",namespace="testNS",resource="memory",type="Pod"} 2.1e+09 78 | kube_limitrange{constraint="min",limitrange="quotaTest",namespace="testNS",resource="memory",type="Pod"} 2.1e+09 79 | 80 | `, 81 | }, 82 | } 83 | for i, c := range cases { 84 | c.Func = generator.ComposeMetricGenFuncs(limitRangeMetricFamilies) 85 | c.Headers = generator.ExtractMetricFamilyHeaders(limitRangeMetricFamilies) 86 | if err := c.run(); err != nil { 87 | t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /internal/store/networkpolicy_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | 22 | networkingv1 "k8s.io/api/networking/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | 25 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 26 | ) 27 | 28 | func TestNetworkPolicyStore(t *testing.T) { 29 | startTime := 1501569018 30 | metav1StartTime := metav1.Unix(int64(startTime), 0) 31 | 32 | cases := []generateMetricsTestCase{ 33 | { 34 | Obj: &networkingv1.NetworkPolicy{ 35 | ObjectMeta: metav1.ObjectMeta{ 36 | Name: "netpol1", 37 | Namespace: "ns1", 38 | CreationTimestamp: metav1StartTime, 39 | }, 40 | Spec: networkingv1.NetworkPolicySpec{ 41 | Ingress: []networkingv1.NetworkPolicyIngressRule{ 42 | {}, 43 | {}, 44 | }, 45 | Egress: []networkingv1.NetworkPolicyEgressRule{ 46 | {}, 47 | {}, 48 | {}, 49 | }, 50 | }, 51 | }, 52 | Want: ` 53 | kube_networkpolicy_created{namespace="ns1",networkpolicy="netpol1"} 1.501569018e+09 54 | kube_networkpolicy_spec_egress_rules{namespace="ns1",networkpolicy="netpol1"} 3 55 | kube_networkpolicy_spec_ingress_rules{namespace="ns1",networkpolicy="netpol1"} 2 56 | `, 57 | MetricNames: []string{ 58 | "kube_networkpolicy_created", 59 | "kube_networkpolicy_labels", 60 | "kube_networkpolicy_spec_egress_rules", 61 | "kube_networkpolicy_spec_ingress_rules", 62 | }, 63 | }, 64 | } 65 | for i, c := range cases { 66 | c.Func = generator.ComposeMetricGenFuncs(networkPolicyMetricFamilies(nil, nil)) 67 | if err := c.run(); err != nil { 68 | t.Errorf("unexpected collecting result in %dth run:\n%s", i, err) 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /internal/store/role_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | 22 | rbacv1 "k8s.io/api/rbac/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | 25 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 26 | ) 27 | 28 | func TestRoleStore(t *testing.T) { 29 | startTime := 1501569018 30 | metav1StartTime := metav1.Unix(int64(startTime), 0) 31 | 32 | cases := []generateMetricsTestCase{ 33 | { 34 | AllowAnnotationsList: []string{ 35 | "app.k8s.io/owner", 36 | }, 37 | AllowLabelsList: []string{ 38 | "app", 39 | }, 40 | Obj: &rbacv1.Role{ 41 | ObjectMeta: metav1.ObjectMeta{ 42 | Name: "role1", 43 | Namespace: "ns1", 44 | ResourceVersion: "BBBBB", 45 | Annotations: map[string]string{ 46 | "app": "mysql-server", 47 | "app.k8s.io/owner": "@foo", 48 | }, 49 | Labels: map[string]string{ 50 | "excluded": "me", 51 | "app": "mysql-server", 52 | }, 53 | }, 54 | }, 55 | Want: ` 56 | # HELP kube_role_annotations Kubernetes annotations converted to Prometheus labels. 57 | # HELP kube_role_labels Kubernetes labels converted to Prometheus labels. 58 | # HELP kube_role_info Information about role. 59 | # HELP kube_role_metadata_resource_version Resource version representing a specific version of the role. 60 | # TYPE kube_role_annotations gauge 61 | # TYPE kube_role_labels gauge 62 | # TYPE kube_role_info gauge 63 | # TYPE kube_role_metadata_resource_version gauge 64 | kube_role_annotations{annotation_app_k8s_io_owner="@foo",role="role1",namespace="ns1"} 1 65 | kube_role_labels{role="role1",label_app="mysql-server",namespace="ns1"} 1 66 | kube_role_info{role="role1",namespace="ns1"} 1 67 | `, 68 | MetricNames: []string{ 69 | "kube_role_annotations", 70 | "kube_role_labels", 71 | "kube_role_info", 72 | "kube_role_metadata_resource_version", 73 | }, 74 | }, 75 | { 76 | Obj: &rbacv1.Role{ 77 | ObjectMeta: metav1.ObjectMeta{ 78 | Name: "role2", 79 | Namespace: "ns2", 80 | CreationTimestamp: metav1StartTime, 81 | ResourceVersion: "10596", 82 | }, 83 | }, 84 | Want: ` 85 | # HELP kube_role_created Unix creation timestamp 86 | # HELP kube_role_info Information about role. 87 | # HELP kube_role_metadata_resource_version Resource version representing a specific version of the role. 88 | # TYPE kube_role_created gauge 89 | # TYPE kube_role_info gauge 90 | # TYPE kube_role_metadata_resource_version gauge 91 | kube_role_info{role="role2",namespace="ns2"} 1 92 | kube_role_created{role="role2",namespace="ns2"} 1.501569018e+09 93 | kube_role_metadata_resource_version{role="role2",namespace="ns2"} 10596 94 | `, 95 | MetricNames: []string{"kube_role_info", "kube_role_created", "kube_role_metadata_resource_version"}, 96 | }, 97 | } 98 | for i, c := range cases { 99 | c.Func = generator.ComposeMetricGenFuncs(roleMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) 100 | c.Headers = generator.ExtractMetricFamilyHeaders(roleMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) 101 | if err := c.run(); err != nil { 102 | t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /internal/store/serviceaccount_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | v1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "k8s.io/utils/ptr" 26 | 27 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 28 | ) 29 | 30 | func TestServiceAccountStore(t *testing.T) { 31 | cases := []generateMetricsTestCase{ 32 | { 33 | Obj: &v1.ServiceAccount{ 34 | ObjectMeta: metav1.ObjectMeta{ 35 | Name: "serviceAccountName", 36 | CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)}, 37 | DeletionTimestamp: &metav1.Time{Time: time.Unix(3000000000, 0)}, 38 | Namespace: "serviceAccountNS", 39 | UID: "serviceAccountUID", 40 | }, 41 | AutomountServiceAccountToken: ptr.To(true), 42 | Secrets: []v1.ObjectReference{ 43 | { 44 | APIVersion: "v1", 45 | Kind: "Secret", 46 | Name: "secretName", 47 | Namespace: "serviceAccountNS", 48 | }, 49 | }, 50 | ImagePullSecrets: []v1.LocalObjectReference{ 51 | { 52 | Name: "imagePullSecretName", 53 | }, 54 | }, 55 | }, 56 | Want: ` 57 | # HELP kube_serviceaccount_info Information about a service account 58 | # HELP kube_serviceaccount_created Unix creation timestamp 59 | # HELP kube_serviceaccount_deleted Unix deletion timestamp 60 | # HELP kube_serviceaccount_secret Secret being referenced by a service account 61 | # HELP kube_serviceaccount_image_pull_secret Secret being referenced by a service account for the purpose of pulling images 62 | # TYPE kube_serviceaccount_info gauge 63 | # TYPE kube_serviceaccount_created gauge 64 | # TYPE kube_serviceaccount_deleted gauge 65 | # TYPE kube_serviceaccount_secret gauge 66 | # TYPE kube_serviceaccount_image_pull_secret gauge 67 | kube_serviceaccount_info{namespace="serviceAccountNS",serviceaccount="serviceAccountName",uid="serviceAccountUID",automount_token="true"} 1 68 | kube_serviceaccount_created{namespace="serviceAccountNS",serviceaccount="serviceAccountName",uid="serviceAccountUID"} 1.5e+09 69 | kube_serviceaccount_deleted{namespace="serviceAccountNS",serviceaccount="serviceAccountName",uid="serviceAccountUID"} 3e+09 70 | kube_serviceaccount_secret{namespace="serviceAccountNS",serviceaccount="serviceAccountName",uid="serviceAccountUID",name="secretName"} 1 71 | kube_serviceaccount_image_pull_secret{namespace="serviceAccountNS",serviceaccount="serviceAccountName",uid="serviceAccountUID",name="imagePullSecretName"} 1`, 72 | MetricNames: []string{ 73 | "kube_serviceaccount_info", 74 | "kube_serviceaccount_created", 75 | "kube_serviceaccount_deleted", 76 | "kube_serviceaccount_secret", 77 | "kube_serviceaccount_image_pull_secret", 78 | }, 79 | }, 80 | } 81 | for i, c := range cases { 82 | c.Func = generator.ComposeMetricGenFuncs(serviceAccountMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) 83 | c.Headers = generator.ExtractMetricFamilyHeaders(serviceAccountMetricFamilies(c.AllowAnnotationsList, c.AllowLabelsList)) 84 | if err := c.run(); err != nil { 85 | t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /internal/store/testutils_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store 18 | 19 | import ( 20 | "testing" 21 | ) 22 | 23 | func TestSortLabels(t *testing.T) { 24 | in := `kube_pod_container_info{container_id="docker://cd456",image="k8s.gcr.io/hyperkube2",container="container2",image_id="docker://sha256:bbb",namespace="ns2",pod="pod2"} 1 25 | kube_pod_container_info{namespace="ns2",container="container3",container_id="docker://ef789",image="k8s.gcr.io/hyperkube3",image_id="docker://sha256:ccc",pod="pod2"} 1` 26 | 27 | want := `kube_pod_container_info{container="container2",container_id="docker://cd456",image="k8s.gcr.io/hyperkube2",image_id="docker://sha256:bbb",namespace="ns2",pod="pod2"} 1 28 | kube_pod_container_info{container="container3",container_id="docker://ef789",image="k8s.gcr.io/hyperkube3",image_id="docker://sha256:ccc",namespace="ns2",pod="pod2"} 1` 29 | 30 | out := sortLabels(in) 31 | 32 | if want != out { 33 | t.Fatalf("expected:\n%v\nbut got:\n%v", want, out) 34 | } 35 | } 36 | 37 | func TestRemoveUnusedWhitespace(t *testing.T) { 38 | in := " kube_cron_job_info \n kube_pod_container_info \n kube_config_map_info " 39 | 40 | want := "kube_cron_job_info\nkube_pod_container_info\nkube_config_map_info" 41 | 42 | out := removeUnusedWhitespace(in) 43 | 44 | if want != out { 45 | t.Fatalf("expected: %q\nbut got: %q", want, out) 46 | } 47 | } 48 | 49 | func TestSortByLine(t *testing.T) { 50 | in := "kube_cron_job_info \nkube_pod_container_info \nkube_config_map_info" 51 | 52 | want := "kube_config_map_info\nkube_cron_job_info \nkube_pod_container_info " 53 | 54 | out := sortByLine(in) 55 | 56 | if want != out { 57 | t.Fatalf("expected: %q\nbut got: %q", want, out) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /jsonnet/kube-state-metrics-mixin/alerts.libsonnet: -------------------------------------------------------------------------------- 1 | { 2 | prometheusAlerts+:: { 3 | groups+: [ 4 | { 5 | name: 'kube-state-metrics', 6 | rules: [ 7 | { 8 | alert: 'KubeStateMetricsListErrors', 9 | expr: ||| 10 | (sum(rate(kube_state_metrics_list_total{%(kubeStateMetricsSelector)s,result="error"}[5m])) by (%(clusterLabel)s) 11 | / 12 | sum(rate(kube_state_metrics_list_total{%(kubeStateMetricsSelector)s}[5m])) by (%(clusterLabel)s)) 13 | > 0.01 14 | ||| % $._config, 15 | 'for': '15m', 16 | labels: { 17 | severity: 'critical', 18 | }, 19 | annotations: { 20 | summary: 'kube-state-metrics is experiencing errors in list operations.', 21 | description: 'kube-state-metrics is experiencing errors at an elevated rate in list operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all.', 22 | }, 23 | }, 24 | { 25 | alert: 'KubeStateMetricsWatchErrors', 26 | expr: ||| 27 | (sum(rate(kube_state_metrics_watch_total{%(kubeStateMetricsSelector)s,result="error"}[5m])) by (%(clusterLabel)s) 28 | / 29 | sum(rate(kube_state_metrics_watch_total{%(kubeStateMetricsSelector)s}[5m])) by (%(clusterLabel)s)) 30 | > 0.01 31 | ||| % $._config, 32 | 'for': '15m', 33 | labels: { 34 | severity: 'critical', 35 | }, 36 | annotations: { 37 | summary: 'kube-state-metrics is experiencing errors in watch operations.', 38 | description: 'kube-state-metrics is experiencing errors at an elevated rate in watch operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all.', 39 | }, 40 | }, 41 | { 42 | alert: 'KubeStateMetricsShardingMismatch', 43 | // 44 | expr: ||| 45 | stdvar (kube_state_metrics_total_shards{%(kubeStateMetricsSelector)s}) by (%(clusterLabel)s) != 0 46 | ||| % $._config, 47 | 'for': '15m', 48 | labels: { 49 | severity: 'critical', 50 | }, 51 | annotations: { 52 | summary: 'kube-state-metrics sharding is misconfigured.', 53 | description: 'kube-state-metrics pods are running with different --total-shards configuration, some Kubernetes objects may be exposed multiple times or not exposed at all.', 54 | }, 55 | }, 56 | { 57 | alert: 'KubeStateMetricsShardsMissing', 58 | // Each shard ordinal is assigned a binary position (2^ordinal) and we compute a sum of those. 59 | // This sum is compared to the expected number (2^total_shards - 1). 60 | // Result of zero all shards are being scraped, anything else indicates an issue. 61 | // A handy side effect of this computation is the result indicates what ordinals are missing. 62 | // Eg. a result of "5" decimal, which translates to binary "101", means shards #0 and #2 are not available. 63 | expr: ||| 64 | 2^max(kube_state_metrics_total_shards{%(kubeStateMetricsSelector)s}) by (%(clusterLabel)s) - 1 65 | - 66 | sum( 2 ^ max by (%(clusterLabel)s, shard_ordinal) (kube_state_metrics_shard_ordinal{%(kubeStateMetricsSelector)s}) ) by (%(clusterLabel)s) 67 | != 0 68 | ||| % $._config, 69 | 'for': '15m', 70 | labels: { 71 | severity: 'critical', 72 | }, 73 | annotations: { 74 | summary: 'kube-state-metrics shards are missing.', 75 | description: 'kube-state-metrics shards are missing, some Kubernetes objects are not being exposed.', 76 | }, 77 | }, 78 | ], 79 | }, 80 | ], 81 | }, 82 | } 83 | -------------------------------------------------------------------------------- /jsonnet/kube-state-metrics-mixin/config.libsonnet: -------------------------------------------------------------------------------- 1 | { 2 | _config+:: { 3 | // Select the metrics coming from the kube state metrics. 4 | kubeStateMetricsSelector: 'job="kube-state-metrics"', 5 | clusterLabel: 'cluster', 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /jsonnet/kube-state-metrics-mixin/mixin.libsonnet: -------------------------------------------------------------------------------- 1 | (import 'config.libsonnet') + 2 | (import 'alerts.libsonnet') 3 | -------------------------------------------------------------------------------- /jsonnet/kube-state-metrics/jsonnetfile.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [] 3 | } 4 | -------------------------------------------------------------------------------- /kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: kube-system 2 | 3 | resources: 4 | - examples/standard/cluster-role-binding.yaml 5 | - examples/standard/cluster-role.yaml 6 | - examples/standard/deployment.yaml 7 | - examples/standard/service-account.yaml 8 | - examples/standard/service.yaml 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "github.com/spf13/cobra" 21 | "k8s.io/klog/v2" 22 | 23 | "k8s.io/kube-state-metrics/v2/internal" 24 | "k8s.io/kube-state-metrics/v2/pkg/options" 25 | ) 26 | 27 | func main() { 28 | opts := options.NewOptions() 29 | cmd := options.InitCommand 30 | cmd.Run = func(_ *cobra.Command, _ []string) { 31 | internal.RunKubeStateMetricsWrapper(opts) 32 | } 33 | opts.AddFlags(cmd) 34 | if err := opts.Parse(); err != nil { 35 | klog.FlushAndExit(klog.ExitFlushTimeout, 1) 36 | } 37 | if err := opts.Validate(); err != nil { 38 | klog.ErrorS(err, "Validating options error") 39 | klog.FlushAndExit(klog.ExitFlushTimeout, 1) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pkg/allow/allow_labels.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package allow 18 | 19 | import ( 20 | "regexp" 21 | ) 22 | 23 | var defaultMetricLabels = map[*regexp.Regexp][]string{ 24 | regexp.MustCompile(".*_labels$"): {}, 25 | regexp.MustCompile(".*_annotations$"): {}, 26 | } 27 | 28 | // Labels provide a way to allow only specified labels for metrics. 29 | // Falls back to default labels, if your metric doesn't have defaults 30 | // then all labels are allowed. 31 | type Labels map[string][]string 32 | 33 | // Allowed returns allowed metric keys and values for the metric. 34 | func (a Labels) Allowed(metric string, labels, values []string) ([]string, []string) { 35 | allowedLabels, ok := a[metric] 36 | if !ok { 37 | var defaultsPresent bool 38 | for metricReg, lbls := range defaultMetricLabels { 39 | if metricReg.MatchString(metric) { 40 | allowedLabels = append(allowedLabels, lbls...) 41 | defaultsPresent = true 42 | } 43 | } 44 | 45 | if !defaultsPresent { 46 | return labels, values 47 | } 48 | } 49 | 50 | var finalLabels, finalValues []string 51 | labelSet := labelSet(allowedLabels) 52 | for _, allowedLabel := range labelSet { 53 | for i, label := range labels { 54 | if label == allowedLabel { 55 | finalLabels = append(finalLabels, label) 56 | finalValues = append(finalValues, values[i]) 57 | } 58 | } 59 | } 60 | 61 | return finalLabels, finalValues 62 | } 63 | 64 | func labelSet(lists ...[]string) []string { 65 | m := make(map[string]interface{}) 66 | var set []string 67 | for _, list := range lists { 68 | for _, e := range list { 69 | if _, ok := m[e]; !ok { 70 | m[e] = struct{}{} 71 | set = append(set, e) 72 | } 73 | } 74 | } 75 | return set 76 | } 77 | -------------------------------------------------------------------------------- /pkg/builder/builder_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package builder_test 18 | 19 | import ( 20 | "reflect" 21 | "testing" 22 | 23 | clientset "k8s.io/client-go/kubernetes" 24 | "k8s.io/client-go/tools/cache" 25 | 26 | "k8s.io/kube-state-metrics/v2/pkg/builder" 27 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 28 | ) 29 | 30 | var ( 31 | fakeMetricLists = [][]string{ 32 | {"metric0.1", "metric0.2"}, 33 | {"metric1.1", "metric1.2"}, 34 | } 35 | ) 36 | 37 | // BuilderInterface and Builder are public, and designed to allow 38 | // injecting custom stores notably when ksm is used as a library. 39 | // This test case ensures we don't break compatibility for external consumers. 40 | func TestBuilderWithCustomStore(t *testing.T) { 41 | b := builder.NewBuilder() 42 | b.WithFamilyGeneratorFilter(generator.NewCompositeFamilyGeneratorFilter()) 43 | err := b.WithEnabledResources([]string{"pods"}) 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | 48 | b.WithGenerateStoresFunc(customStore) 49 | var fStores []*fakeStore 50 | for _, stores := range b.BuildStores() { 51 | for _, store := range stores { 52 | fStores = append(fStores, store.(*fakeStore)) 53 | } 54 | } 55 | 56 | for i, fStore := range fStores { 57 | metrics := fStore.List() 58 | for j, m := range metrics { 59 | if !reflect.DeepEqual(m, fakeMetricLists[i][j]) { 60 | t.Fatalf("Unexpected store values: want %v found %v", fakeMetricLists[i], metrics) 61 | } 62 | } 63 | } 64 | } 65 | 66 | func customStore(_ []generator.FamilyGenerator, 67 | _ interface{}, 68 | _ func(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher, 69 | _ bool, 70 | ) []cache.Store { 71 | stores := make([]cache.Store, 0, 2) 72 | stores = append(stores, newFakeStore(fakeMetricLists[0])) 73 | stores = append(stores, newFakeStore(fakeMetricLists[1])) 74 | return stores 75 | } 76 | 77 | func newFakeStore(metrics []string) *fakeStore { 78 | return &fakeStore{ 79 | metrics: metrics, 80 | } 81 | } 82 | 83 | type fakeStore struct { 84 | metrics []string 85 | } 86 | 87 | func (s *fakeStore) Add(_ interface{}) error { 88 | return nil 89 | } 90 | 91 | func (s *fakeStore) Update(_ interface{}) error { 92 | return nil 93 | } 94 | 95 | func (s *fakeStore) Delete(_ interface{}) error { 96 | return nil 97 | } 98 | 99 | func (s *fakeStore) List() []interface{} { 100 | metrics := make([]interface{}, len(s.metrics)) 101 | for i, m := range s.metrics { 102 | metrics[i] = m 103 | } 104 | 105 | return metrics 106 | } 107 | 108 | func (s *fakeStore) ListKeys() []string { 109 | return nil 110 | } 111 | 112 | func (s *fakeStore) Get(_ interface{}) (item interface{}, exists bool, err error) { 113 | return nil, false, nil 114 | } 115 | 116 | func (s *fakeStore) GetByKey(_ string) (item interface{}, exists bool, err error) { 117 | return nil, false, nil 118 | } 119 | 120 | func (s *fakeStore) Replace(_ []interface{}, _ string) error { 121 | return nil 122 | } 123 | 124 | func (s *fakeStore) Resync() error { 125 | return nil 126 | } 127 | -------------------------------------------------------------------------------- /pkg/builder/types/interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | import ( 20 | "context" 21 | 22 | metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store" 23 | 24 | "github.com/prometheus/client_golang/prometheus" 25 | clientset "k8s.io/client-go/kubernetes" 26 | "k8s.io/client-go/tools/cache" 27 | 28 | "k8s.io/kube-state-metrics/v2/pkg/customresource" 29 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 30 | "k8s.io/kube-state-metrics/v2/pkg/options" 31 | ) 32 | 33 | // BuilderInterface represent all methods that a Builder should implements 34 | type BuilderInterface interface { 35 | WithMetrics(r prometheus.Registerer) 36 | WithEnabledResources(c []string) error 37 | WithNamespaces(n options.NamespaceList) 38 | WithFieldSelectorFilter(fieldSelectors string) 39 | WithSharding(shard int32, totalShards int) 40 | WithContext(ctx context.Context) 41 | WithKubeClient(c clientset.Interface) 42 | WithCustomResourceClients(cs map[string]interface{}) 43 | WithUsingAPIServerCache(u bool) 44 | WithFamilyGeneratorFilter(l generator.FamilyGeneratorFilter) 45 | WithAllowAnnotations(a map[string][]string) error 46 | WithAllowLabels(l map[string][]string) error 47 | WithGenerateStoresFunc(f BuildStoresFunc) 48 | DefaultGenerateStoresFunc() BuildStoresFunc 49 | DefaultGenerateCustomResourceStoresFunc() BuildCustomResourceStoresFunc 50 | WithCustomResourceStoreFactories(fs ...customresource.RegistryFactory) 51 | Build() metricsstore.MetricsWriterList 52 | BuildStores() [][]cache.Store 53 | WithGenerateCustomResourceStoresFunc(f BuildCustomResourceStoresFunc) 54 | } 55 | 56 | // BuildStoresFunc function signature that is used to return a list of cache.Store 57 | type BuildStoresFunc func(metricFamilies []generator.FamilyGenerator, 58 | expectedType interface{}, 59 | listWatchFunc func(kubeClient clientset.Interface, ns string, fieldSelector string) cache.ListerWatcher, 60 | useAPIServerCache bool, 61 | ) []cache.Store 62 | 63 | // BuildCustomResourceStoresFunc function signature that is used to return a list of custom resource cache.Store 64 | type BuildCustomResourceStoresFunc func(resourceName string, 65 | metricFamilies []generator.FamilyGenerator, 66 | expectedType interface{}, 67 | listWatchFunc func(customResourceClient interface{}, ns string, fieldSelector string) cache.ListerWatcher, 68 | useAPIServerCache bool, 69 | ) []cache.Store 70 | 71 | // AllowDenyLister interface for AllowDeny lister that can allow or exclude metrics by there names 72 | type AllowDenyLister interface { 73 | IsIncluded(string) bool 74 | IsExcluded(string) bool 75 | } 76 | -------------------------------------------------------------------------------- /pkg/constant/resource_unit.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package constant 18 | 19 | // ResourceUnit represents the unit of measure for certain metrics. 20 | type ResourceUnit string 21 | 22 | const ( 23 | // UnitByte is the unit of measure in bytes. 24 | UnitByte ResourceUnit = "byte" 25 | // UnitCore is the unit of measure in CPU cores. 26 | UnitCore ResourceUnit = "core" 27 | // UnitInteger is the unit of measure in integers. 28 | UnitInteger ResourceUnit = "integer" 29 | ) 30 | -------------------------------------------------------------------------------- /pkg/customresourcestate/config_metrics_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package customresourcestate 18 | 19 | // MetricMeta are variables which may used for any metric type. 20 | type MetricMeta struct { 21 | // LabelsFromPath adds additional labels where the value of the label is taken from a field under Path. 22 | LabelsFromPath map[string][]string `yaml:"labelsFromPath" json:"labelsFromPath"` 23 | // Path is the path to to generate metric(s) for. 24 | Path []string `yaml:"path" json:"path"` 25 | } 26 | 27 | // MetricGauge targets a Path that may be a single value, array, or object. Arrays and objects will generate a metric per element. 28 | // Ref: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#gauge 29 | type MetricGauge struct { 30 | // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. 31 | LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` 32 | MetricMeta `yaml:",inline" json:",inline"` 33 | 34 | // ValueFrom is the path to a numeric field under Path that will be the metric value. 35 | ValueFrom []string `yaml:"valueFrom" json:"valueFrom"` 36 | // NilIsZero indicates that if a value is nil it will be treated as zero value. 37 | NilIsZero bool `yaml:"nilIsZero" json:"nilIsZero"` 38 | } 39 | 40 | // MetricInfo is a metric which is used to expose textual information. 41 | // Ref: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#info 42 | type MetricInfo struct { 43 | // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. 44 | LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` 45 | MetricMeta `yaml:",inline" json:",inline"` 46 | } 47 | 48 | // MetricStateSet is a metric which represent a series of related boolean values, also called a bitset. 49 | // Ref: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#stateset 50 | type MetricStateSet struct { 51 | MetricMeta `yaml:",inline" json:",inline"` 52 | 53 | // List is the list of values to expose a value for. 54 | List []string `yaml:"list" json:"list"` 55 | // LabelName is the key of the label which is used for each entry in List to expose the value. 56 | LabelName string `yaml:"labelName" json:"labelName"` 57 | // ValueFrom is the subpath to compare the list to. 58 | ValueFrom []string `yaml:"valueFrom" json:"valueFrom"` 59 | } 60 | -------------------------------------------------------------------------------- /pkg/customresourcestate/config_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package customresourcestate 18 | 19 | import ( 20 | _ "embed" 21 | "strings" 22 | "testing" 23 | 24 | "github.com/stretchr/testify/assert" 25 | "k8s.io/klog/v2" 26 | yaml "sigs.k8s.io/yaml/goyaml.v3" 27 | ) 28 | 29 | //go:embed example_config.yaml 30 | var testData string 31 | 32 | func Test_Metrics_deserialization(t *testing.T) { 33 | var m Metrics 34 | assert.NoError(t, yaml.NewDecoder(strings.NewReader(testData)).Decode(&m)) 35 | configOverrides(&m) 36 | assert.Equal(t, "active_count", m.Spec.Resources[0].Metrics[0].Name) 37 | 38 | t.Run("can create resource factory", func(t *testing.T) { 39 | rf, err := NewCustomResourceMetrics(m.Spec.Resources[0]) 40 | assert.NoError(t, err) 41 | 42 | t.Run("labels are merged", func(t *testing.T) { 43 | assert.Equal(t, map[string]string{ 44 | "name": mustCompilePath(t, "metadata", "name").String(), 45 | }, toPaths(rf.(*customResourceMetrics).Families[1].LabelFromPath)) 46 | }) 47 | 48 | t.Run("errorLogV", func(t *testing.T) { 49 | assert.Equal(t, klog.Level(5), rf.(*customResourceMetrics).Families[1].ErrorLogV) 50 | }) 51 | 52 | t.Run("resource name", func(t *testing.T) { 53 | assert.Equal(t, rf.(*customResourceMetrics).ResourceName, "foos") 54 | }) 55 | }) 56 | } 57 | 58 | func toPaths(m map[string]valuePath) map[string]string { 59 | out := make(map[string]string) 60 | for k, v := range m { 61 | out[k] = v.String() 62 | } 63 | return out 64 | } 65 | -------------------------------------------------------------------------------- /pkg/customresourcestate/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package customresourcestate contains JSON/YAML configuration structs and factories 18 | // for generating custom resource state metrics from a config file. 19 | package customresourcestate 20 | -------------------------------------------------------------------------------- /pkg/customresourcestate/example_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 The Kubernetes Authors All rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | kind: CustomResourceStateMetrics 16 | spec: 17 | resources: 18 | - 19 | groupVersionKind: 20 | group: myteam.io 21 | kind: "Foo" 22 | version: "v1" 23 | labelsFromPath: 24 | name: [ metadata, name ] 25 | metrics: 26 | - name: "active_count" 27 | help: "Number Foo Bars active" 28 | each: 29 | type: Gauge 30 | gauge: 31 | path: [status, active] 32 | labelFromKey: type 33 | labelsFromPath: 34 | bar: [bar] 35 | value: [count] 36 | commonLabels: 37 | custom_metric: "yes" 38 | 39 | labelsFromPath: 40 | "*": [metadata, labels] # copy all labels from CR labels 41 | foo: [metadata, labels, foo] # copy a single label (overrides *) 42 | 43 | - name: "other_count" 44 | each: 45 | type: Gauge 46 | gauge: 47 | path: [status, other] 48 | errorLogV: 5 49 | 50 | - name: "info" 51 | each: 52 | type: Info 53 | info: 54 | path: [spec, version] 55 | errorLogV: 5 56 | 57 | - name: "phase" 58 | each: 59 | type: StateSet 60 | stateSet: 61 | path: [status, phase] 62 | labelName: phase 63 | list: [Active, Running, Terminating] 64 | errorLogV: 5 65 | -------------------------------------------------------------------------------- /pkg/metric/family.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metric 18 | 19 | import ( 20 | "strings" 21 | ) 22 | 23 | // FamilyInterface interface for a family 24 | type FamilyInterface interface { 25 | Inspect(inspect func(Family)) 26 | ByteSlice() []byte 27 | } 28 | 29 | // Family represents a set of metrics with the same name and help text. 30 | type Family struct { 31 | Name string 32 | Type Type 33 | Metrics []*Metric 34 | } 35 | 36 | // Inspect use to inspect the inside of a Family 37 | func (f Family) Inspect(inspect func(Family)) { 38 | inspect(f) 39 | } 40 | 41 | // ByteSlice returns the given Family in its string representation. 42 | func (f Family) ByteSlice() []byte { 43 | b := strings.Builder{} 44 | for _, m := range f.Metrics { 45 | b.WriteString(f.Name) 46 | m.Write(&b) 47 | } 48 | 49 | return []byte(b.String()) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/metric/metric.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metric 18 | 19 | import ( 20 | "fmt" 21 | "math" 22 | "strconv" 23 | "strings" 24 | "sync" 25 | ) 26 | 27 | const ( 28 | initialNumBufSize = 24 29 | ) 30 | 31 | var ( 32 | numBufPool = sync.Pool{ 33 | New: func() interface{} { 34 | b := make([]byte, 0, initialNumBufSize) 35 | return &b 36 | }, 37 | } 38 | ) 39 | 40 | // Type represents the type of the metric. See https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#metric-types. 41 | type Type string 42 | 43 | // Supported metric types. 44 | var ( 45 | 46 | // Gauge defines an OpenMetrics gauge. 47 | Gauge Type = "gauge" 48 | 49 | // Info defines an OpenMetrics info. 50 | Info Type = "info" 51 | 52 | // StateSet defines an OpenMetrics stateset. 53 | StateSet Type = "stateset" 54 | 55 | // Counter defines an OpenMetrics counter. 56 | Counter Type = "counter" 57 | ) 58 | 59 | // Metric represents a single time series. 60 | type Metric struct { 61 | // The name of a metric is injected by its family to reduce duplication. 62 | LabelKeys []string 63 | LabelValues []string 64 | Value float64 65 | } 66 | 67 | func (m *Metric) Write(s *strings.Builder) { 68 | if len(m.LabelKeys) != len(m.LabelValues) { 69 | panic(fmt.Sprintf( 70 | "expected labelKeys %q to be of same length as labelValues %q", 71 | m.LabelKeys, m.LabelValues, 72 | )) 73 | } 74 | 75 | labelsToString(s, m.LabelKeys, m.LabelValues) 76 | s.WriteByte(' ') 77 | writeFloat(s, m.Value) 78 | s.WriteByte('\n') 79 | } 80 | 81 | func labelsToString(m *strings.Builder, keys, values []string) { 82 | if len(keys) > 0 { 83 | var separator byte = '{' 84 | 85 | for i := 0; i < len(keys); i++ { 86 | m.WriteByte(separator) 87 | m.WriteString(keys[i]) 88 | m.WriteString("=\"") 89 | escapeString(m, values[i]) 90 | m.WriteByte('"') 91 | separator = ',' 92 | } 93 | 94 | m.WriteByte('}') 95 | } 96 | } 97 | 98 | var ( 99 | escapeWithDoubleQuote = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`) 100 | ) 101 | 102 | // escapeString replaces '\' by '\\', new line character by '\n', and '"' by 103 | // '\"'. 104 | // Taken from github.com/prometheus/common/expfmt/text_create.go. 105 | func escapeString(m *strings.Builder, v string) { 106 | escapeWithDoubleQuote.WriteString(m, v) 107 | } 108 | 109 | // writeFloat is equivalent to fmt.Fprint with a float64 argument but hardcodes 110 | // a few common cases for increased efficiency. For non-hardcoded cases, it uses 111 | // strconv.AppendFloat to avoid allocations, similar to writeInt. 112 | // Taken from github.com/prometheus/common/expfmt/text_create.go. 113 | func writeFloat(w *strings.Builder, f float64) { 114 | switch { 115 | case f == 1: 116 | w.WriteByte('1') 117 | case f == 0: 118 | w.WriteByte('0') 119 | case f == -1: 120 | w.WriteString("-1") 121 | case math.IsNaN(f): 122 | w.WriteString("NaN") 123 | case math.IsInf(f, +1): 124 | w.WriteString("+Inf") 125 | case math.IsInf(f, -1): 126 | w.WriteString("-Inf") 127 | default: 128 | bp := numBufPool.Get().(*[]byte) 129 | *bp = strconv.AppendFloat((*bp)[:0], f, 'g', -1, 64) 130 | w.Write(*bp) 131 | numBufPool.Put(bp) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /pkg/metric/metric_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metric 18 | 19 | import ( 20 | "strings" 21 | "testing" 22 | ) 23 | 24 | func TestFamilyString(t *testing.T) { 25 | m := Metric{ 26 | LabelKeys: []string{"namespace"}, 27 | LabelValues: []string{"default"}, 28 | Value: 1, 29 | } 30 | 31 | f := Family{ 32 | Name: "kube_pod_info", 33 | Metrics: []*Metric{&m}, 34 | } 35 | 36 | expected := "kube_pod_info{namespace=\"default\"} 1" 37 | got := strings.TrimSpace(string(f.ByteSlice())) 38 | 39 | if got != expected { 40 | t.Fatalf("expected %v but got %v", expected, got) 41 | } 42 | } 43 | 44 | func BenchmarkMetricWrite(b *testing.B) { 45 | tests := []struct { 46 | testName string 47 | metric Metric 48 | expectedLength int 49 | }{ 50 | { 51 | testName: "value-1", 52 | metric: Metric{ 53 | LabelKeys: []string{"container", "container_id", "image", "image_id", "namespace", "pod"}, 54 | LabelValues: []string{"container2", "docker://cd456", "k8s.gcr.io/hyperkube2", "docker://sha256:bbb", "ns2", "pod2"}, 55 | Value: float64(1), 56 | }, 57 | expectedLength: 145, 58 | }, 59 | { 60 | testName: "value-35.7", 61 | metric: Metric{ 62 | LabelKeys: []string{"container", "container_id", "image", "image_id", "namespace", "pod"}, 63 | LabelValues: []string{"container2", "docker://cd456", "k8s.gcr.io/hyperkube2", "docker://sha256:bbb", "ns2", "pod2"}, 64 | Value: 35.7, 65 | }, 66 | expectedLength: 148, 67 | }, 68 | } 69 | 70 | for _, test := range tests { 71 | b.Run(test.testName, func(b *testing.B) { 72 | for i := 0; i < b.N; i++ { 73 | builder := strings.Builder{} 74 | 75 | test.metric.Write(&builder) 76 | 77 | s := builder.String() 78 | 79 | // Ensuring that the string is actually build, not optimized 80 | // away by compilation. 81 | got := len(s) 82 | if test.expectedLength != got { 83 | b.Fatalf("expected string of length %v but got %v", test.expectedLength, got) 84 | } 85 | } 86 | }) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /pkg/metric_generator/filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package generator 18 | 19 | // FamilyGeneratorFilter represents a filter which decides whether a metric 20 | // family is exposed by the store or not 21 | type FamilyGeneratorFilter interface { 22 | 23 | // Test returns true if it passes the criteria of the filter, otherwise it 24 | // will return false and the metric family is not exposed by the store 25 | Test(generator FamilyGenerator) bool 26 | } 27 | 28 | // CompositeFamilyGeneratorFilter is composite for combining multiple filters 29 | type CompositeFamilyGeneratorFilter struct { 30 | filters []FamilyGeneratorFilter 31 | } 32 | 33 | // Test tests the generator by passing it through the filters contained within the composite 34 | // and return false if the generator does not match all the filters 35 | func (composite CompositeFamilyGeneratorFilter) Test(generator FamilyGenerator) bool { 36 | for _, filter := range composite.filters { 37 | if !filter.Test(generator) { 38 | return false 39 | } 40 | } 41 | return true 42 | } 43 | 44 | // FilterFamilyGenerators filters a given slice of family generators based upon a given filter 45 | // and returns a slice containing the family generators which passed the filter criteria 46 | func FilterFamilyGenerators(filter FamilyGeneratorFilter, families []FamilyGenerator) []FamilyGenerator { 47 | var filtered []FamilyGenerator 48 | 49 | for _, family := range families { 50 | if filter.Test(family) { 51 | filtered = append(filtered, family) 52 | } 53 | } 54 | 55 | return filtered 56 | } 57 | 58 | // NewCompositeFamilyGeneratorFilter combines multiple family generators filters into one composite filter 59 | func NewCompositeFamilyGeneratorFilter(filters ...FamilyGeneratorFilter) CompositeFamilyGeneratorFilter { 60 | return CompositeFamilyGeneratorFilter{filters} 61 | } 62 | -------------------------------------------------------------------------------- /pkg/metrics_store/metrics_store_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metricsstore 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | "testing" 23 | 24 | v1 "k8s.io/api/core/v1" 25 | "k8s.io/apimachinery/pkg/api/meta" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | "k8s.io/apimachinery/pkg/types" 28 | 29 | "k8s.io/kube-state-metrics/v2/pkg/metric" 30 | ) 31 | 32 | func TestObjectsSameNameDifferentNamespaces(t *testing.T) { 33 | serviceIDs := []string{"a", "b"} 34 | 35 | genFunc := func(obj interface{}) []metric.FamilyInterface { 36 | o, err := meta.Accessor(obj) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | 41 | metricFamily := metric.Family{ 42 | Name: "kube_service_info", 43 | Metrics: []*metric.Metric{ 44 | { 45 | LabelKeys: []string{"uid"}, 46 | LabelValues: []string{string(o.GetUID())}, 47 | Value: float64(1), 48 | }, 49 | }, 50 | } 51 | 52 | return []metric.FamilyInterface{&metricFamily} 53 | } 54 | 55 | ms := NewMetricsStore([]string{"Information about service."}, genFunc) 56 | 57 | for _, id := range serviceIDs { 58 | s := v1.Service{ 59 | ObjectMeta: metav1.ObjectMeta{ 60 | Name: "service", 61 | Namespace: id, 62 | UID: types.UID(id), 63 | }, 64 | } 65 | 66 | err := ms.Add(&s) 67 | if err != nil { 68 | t.Fatal(err) 69 | } 70 | } 71 | 72 | w := strings.Builder{} 73 | mw := NewMetricsWriter(ms) 74 | err := mw.WriteAll(&w) 75 | if err != nil { 76 | t.Fatalf("failed to write metrics: %v", err) 77 | } 78 | m := w.String() 79 | 80 | for _, id := range serviceIDs { 81 | if !strings.Contains(m, fmt.Sprintf("uid=\"%v\"", id)) { 82 | t.Fatalf("expected to find metric with uid %v", id) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /pkg/optin/optin.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package optin 18 | 19 | import ( 20 | "regexp" 21 | "sort" 22 | "strings" 23 | 24 | generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator" 25 | ) 26 | 27 | // MetricFamilyFilter filters metric families which are defined as opt-in by their generator.FamilyGenerator 28 | type MetricFamilyFilter struct { 29 | metrics []*regexp.Regexp 30 | } 31 | 32 | // Test tests if a given generator is an opt-in metric family and was passed as an opt-in metric family at startup 33 | func (filter MetricFamilyFilter) Test(generator generator.FamilyGenerator) bool { 34 | if !generator.OptIn { 35 | return true 36 | } 37 | for _, metric := range filter.metrics { 38 | if metric.MatchString(generator.Name) { 39 | return true 40 | } 41 | } 42 | return false 43 | } 44 | 45 | // Status returns the metrics contained within the filter as a comma-separated string 46 | func (filter MetricFamilyFilter) Status() string { 47 | asStrings := make([]string, 0) 48 | for _, metric := range filter.metrics { 49 | asStrings = append(asStrings, metric.String()) 50 | } 51 | // sort the strings for the sake of ux such that the resulting status is consistent 52 | sort.Strings(asStrings) 53 | return strings.Join(asStrings, ", ") 54 | } 55 | 56 | // Count returns the amount of metrics contained within the filter 57 | func (filter MetricFamilyFilter) Count() int { 58 | return len(filter.metrics) 59 | } 60 | 61 | // NewMetricFamilyFilter creates new MetricFamilyFilter instances. 62 | func NewMetricFamilyFilter(metrics map[string]struct{}) (*MetricFamilyFilter, error) { 63 | regexes := make([]*regexp.Regexp, 0) 64 | for metric := range metrics { 65 | regex, err := regexp.Compile(metric) 66 | if err != nil { 67 | return nil, err 68 | } 69 | regexes = append(regexes, regex) 70 | } 71 | return &MetricFamilyFilter{regexes}, nil 72 | } 73 | -------------------------------------------------------------------------------- /pkg/options/options_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package options 18 | 19 | import ( 20 | "os" 21 | "testing" 22 | ) 23 | 24 | func TestOptionsParse(t *testing.T) { 25 | tests := []struct { 26 | Desc string 27 | Args []string 28 | ExpectsError bool 29 | }{ 30 | { 31 | Desc: "resources command line argument", 32 | Args: []string{"./kube-state-metrics", "--resources=configmaps,pods"}, 33 | ExpectsError: false, 34 | }, 35 | { 36 | Desc: "namespaces command line argument", 37 | Args: []string{"./kube-state-metrics", "--namespaces=default,kube-system"}, 38 | ExpectsError: false, 39 | }, 40 | { 41 | Desc: "foo command line argument", 42 | Args: []string{"./kube-state-metrics", "--foo=bar,baz"}, 43 | ExpectsError: true, 44 | }, 45 | } 46 | 47 | opts := NewOptions() 48 | opts.AddFlags(InitCommand) 49 | 50 | for _, test := range tests { 51 | t.Run(test.Desc, func(t *testing.T) { 52 | os.Args = test.Args 53 | 54 | err := opts.Parse() 55 | 56 | if !test.ExpectsError && err != nil { 57 | t.Errorf("Error for test with description: %s: %v", test.Desc, err.Error()) 58 | } 59 | 60 | if test.ExpectsError && err == nil { 61 | t.Errorf("Expected error for test with description: %s", test.Desc) 62 | } 63 | }) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /pkg/options/resource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package options 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | var ( 24 | // DefaultNamespaces is the default namespace selector for selecting and filtering across all namespaces. 25 | DefaultNamespaces = NamespaceList{metav1.NamespaceAll} 26 | 27 | // DefaultResources represents the default set of resources in kube-state-metrics. 28 | DefaultResources = ResourceSet{ 29 | "certificatesigningrequests": struct{}{}, 30 | "configmaps": struct{}{}, 31 | "cronjobs": struct{}{}, 32 | "daemonsets": struct{}{}, 33 | "deployments": struct{}{}, 34 | "endpoints": struct{}{}, 35 | "horizontalpodautoscalers": struct{}{}, 36 | "ingresses": struct{}{}, 37 | "jobs": struct{}{}, 38 | "leases": struct{}{}, 39 | "limitranges": struct{}{}, 40 | "mutatingwebhookconfigurations": struct{}{}, 41 | "namespaces": struct{}{}, 42 | "networkpolicies": struct{}{}, 43 | "nodes": struct{}{}, 44 | "persistentvolumes": struct{}{}, 45 | "persistentvolumeclaims": struct{}{}, 46 | "poddisruptionbudgets": struct{}{}, 47 | "pods": struct{}{}, 48 | "replicasets": struct{}{}, 49 | "replicationcontrollers": struct{}{}, 50 | "resourcequotas": struct{}{}, 51 | "secrets": struct{}{}, 52 | "services": struct{}{}, 53 | "statefulsets": struct{}{}, 54 | "storageclasses": struct{}{}, 55 | "validatingwebhookconfigurations": struct{}{}, 56 | "volumeattachments": struct{}{}, 57 | } 58 | ) 59 | -------------------------------------------------------------------------------- /pkg/sharding/listwatch.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package sharding 18 | 19 | import ( 20 | "hash/fnv" 21 | 22 | jump "github.com/dgryski/go-jump" 23 | "k8s.io/apimachinery/pkg/api/meta" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/apimachinery/pkg/watch" 27 | "k8s.io/client-go/tools/cache" 28 | ) 29 | 30 | type shardedListWatch struct { 31 | sharding *sharding 32 | lw cache.ListerWatcher 33 | } 34 | 35 | // NewShardedListWatch returns a new shardedListWatch via the cache.ListerWatcher interface. 36 | // In the case of no sharding needed, it returns the provided cache.ListerWatcher 37 | func NewShardedListWatch(shard int32, totalShards int, lw cache.ListerWatcher) cache.ListerWatcher { 38 | // This is an "optimization" as this configuration means no sharding is to 39 | // be performed. 40 | if shard == 0 && totalShards == 1 { 41 | return lw 42 | } 43 | 44 | return &shardedListWatch{sharding: &sharding{shard: shard, totalShards: totalShards}, lw: lw} 45 | } 46 | 47 | func (s *shardedListWatch) List(options metav1.ListOptions) (runtime.Object, error) { 48 | list, err := s.lw.List(options) 49 | if err != nil { 50 | return nil, err 51 | } 52 | items, err := meta.ExtractList(list) 53 | if err != nil { 54 | return nil, err 55 | } 56 | metaObj, err := meta.ListAccessor(list) 57 | if err != nil { 58 | return nil, err 59 | } 60 | res := &metav1.List{ 61 | Items: []runtime.RawExtension{}, 62 | } 63 | for _, item := range items { 64 | a, err := meta.Accessor(item) 65 | if err != nil { 66 | return nil, err 67 | } 68 | if s.sharding.keep(a) { 69 | res.Items = append(res.Items, runtime.RawExtension{Object: item}) 70 | } 71 | } 72 | res.ResourceVersion = metaObj.GetResourceVersion() 73 | 74 | return res, nil 75 | } 76 | 77 | func (s *shardedListWatch) Watch(options metav1.ListOptions) (watch.Interface, error) { 78 | w, err := s.lw.Watch(options) 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | return watch.Filter(w, func(in watch.Event) (out watch.Event, keep bool) { 84 | a, err := meta.Accessor(in.Object) 85 | if err != nil { 86 | // TODO(brancz): needs logging 87 | return in, true 88 | } 89 | 90 | return in, s.sharding.keep(a) 91 | }), nil 92 | } 93 | 94 | type sharding struct { 95 | shard int32 96 | totalShards int 97 | } 98 | 99 | func (s *sharding) keep(o metav1.Object) bool { 100 | h := fnv.New64a() 101 | h.Write([]byte(o.GetUID())) 102 | return jump.Hash(h.Sum64(), s.totalShards) == s.shard 103 | } 104 | -------------------------------------------------------------------------------- /pkg/sharding/listwatch_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package sharding 18 | 19 | import ( 20 | "testing" 21 | 22 | v1 "k8s.io/api/core/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | "k8s.io/apimachinery/pkg/types" 25 | ) 26 | 27 | func TestSharding(t *testing.T) { 28 | cm := &v1.ConfigMap{ 29 | ObjectMeta: metav1.ObjectMeta{ 30 | Name: "configmap1", 31 | Namespace: "ns1", 32 | UID: types.UID("test_uid"), 33 | }, 34 | } 35 | 36 | s1 := &sharding{ 37 | shard: 0, 38 | totalShards: 2, 39 | } 40 | s2 := &sharding{ 41 | shard: 1, 42 | totalShards: 2, 43 | } 44 | 45 | if !s1.keep(cm) && !s2.keep(cm) { 46 | t.Fatal("One shard must pick up the object.") 47 | } 48 | 49 | if !s1.keep(cm) { 50 | t.Fatal("Shard one should pick up the object.") 51 | } 52 | 53 | if s2.keep(cm) { 54 | t.Fatal("Shard two should not pick up the object.") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg/sharding/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package sharding 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | "github.com/prometheus/client_golang/prometheus/promauto" 22 | ) 23 | 24 | const ( 25 | // LabelOrdinal is name of Prometheus metric label to use in conjunction with kube_state_metrics_shard_ordinal. 26 | LabelOrdinal = "shard_ordinal" 27 | ) 28 | 29 | // Metrics stores the pointers of kube_state_metrics_shard_ordinal 30 | // and kube_state_metrics_total_shards metrics. 31 | type Metrics struct { 32 | Ordinal *prometheus.GaugeVec 33 | Total prometheus.Gauge 34 | } 35 | 36 | // NewShardingMetrics takes in a prometheus registry and initializes 37 | // and registers sharding configuration metrics. It returns those registered metrics. 38 | func NewShardingMetrics(r prometheus.Registerer) *Metrics { 39 | return &Metrics{ 40 | Ordinal: promauto.With(r).NewGaugeVec( 41 | prometheus.GaugeOpts{ 42 | Name: "kube_state_metrics_shard_ordinal", 43 | Help: "Current sharding ordinal/index of this instance", 44 | }, []string{LabelOrdinal}, 45 | ), 46 | Total: promauto.With(r).NewGauge( 47 | prometheus.GaugeOpts{ 48 | Name: "kube_state_metrics_total_shards", 49 | Help: "Number of total shards this instance is aware of", 50 | }, 51 | ), 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /pkg/util/proc/reaper.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | // +build linux 3 | 4 | /* 5 | Copyright 2019 The Kubernetes Authors All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package proc 21 | 22 | import ( 23 | "os" 24 | "os/signal" 25 | "syscall" 26 | 27 | "k8s.io/klog/v2" 28 | ) 29 | 30 | // StartReaper starts a goroutine to reap processes if called from a process 31 | // that has pid 1. 32 | func StartReaper() { 33 | if os.Getpid() == 1 { 34 | klog.V(4).InfoS("Launching reaper") 35 | go func() { 36 | sigs := make(chan os.Signal, 1) 37 | signal.Notify(sigs, syscall.SIGCHLD) 38 | for { 39 | // Wait for a child to terminate 40 | sig := <-sigs 41 | klog.V(4).InfoS("Signal received", "signal", sig) 42 | for { 43 | // Reap processes 44 | cpid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, nil) 45 | if cpid < 1 { 46 | break 47 | } 48 | 49 | klog.V(4).InfoS("Reaped process with pid", "cpid", cpid) 50 | } 51 | } 52 | }() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pkg/util/proc/reaper_unsupported.go: -------------------------------------------------------------------------------- 1 | //go:build !linux 2 | // +build !linux 3 | 4 | /* 5 | Copyright 2019 The Kubernetes Authors All rights reserved. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package proc 21 | 22 | // StartReaper has no effect on non-linux platforms. 23 | // Support for other unices will be added. 24 | func StartReaper() { 25 | } 26 | -------------------------------------------------------------------------------- /scripts/autosharding.jsonnet: -------------------------------------------------------------------------------- 1 | (import 'standard.jsonnet').autosharding 2 | -------------------------------------------------------------------------------- /scripts/daemonsetsharding.jsonnet: -------------------------------------------------------------------------------- 1 | (import 'standard.jsonnet').daemonsetsharding 2 | -------------------------------------------------------------------------------- /scripts/generate-help-text.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "$ kube-state-metrics -h" > help.txt 4 | ./kube-state-metrics -h >> help.txt 5 | exit 0 6 | -------------------------------------------------------------------------------- /scripts/jsonnetfile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": [ 4 | { 5 | "source": { 6 | "local": { 7 | "directory": "../jsonnet/kube-state-metrics" 8 | } 9 | }, 10 | "version": "" 11 | }, 12 | { 13 | "source": { 14 | "local": { 15 | "directory": "../jsonnet/kube-state-metrics-mixin" 16 | } 17 | }, 18 | "version": "" 19 | } 20 | ], 21 | "legacyImports": false 22 | } 23 | -------------------------------------------------------------------------------- /scripts/jsonnetfile.lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": [ 4 | { 5 | "source": { 6 | "local": { 7 | "directory": "../jsonnet/kube-state-metrics" 8 | } 9 | }, 10 | "version": "" 11 | }, 12 | { 13 | "source": { 14 | "local": { 15 | "directory": "../jsonnet/kube-state-metrics-mixin" 16 | } 17 | }, 18 | "version": "" 19 | } 20 | ], 21 | "legacyImports": false 22 | } 23 | -------------------------------------------------------------------------------- /scripts/mixin.jsonnet: -------------------------------------------------------------------------------- 1 | ((import 'kube-state-metrics-mixin/mixin.libsonnet') { 2 | _config+:: { 3 | // Selectors are inserted between {} in Prometheus queries. 4 | kubeStateMetricsSelector: 'job="kube-state-metrics"', 5 | }, 6 | }).prometheusAlerts 7 | -------------------------------------------------------------------------------- /scripts/standard.jsonnet: -------------------------------------------------------------------------------- 1 | local ksm = import 'kube-state-metrics/kube-state-metrics.libsonnet'; 2 | local version = std.extVar('version'); 3 | 4 | ksm { 5 | name:: 'kube-state-metrics', 6 | namespace:: 'kube-system', 7 | version:: version, 8 | image:: 'registry.k8s.io/kube-state-metrics/kube-state-metrics:v' + version, 9 | } 10 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # End2end testsuite 2 | 3 | This folder contains simple e2e tests. 4 | When launched, it spins up a kubernetes cluster using [kind](https://kind.sigs.k8s.io/), creates several kubernetes resources and launches a kube-state-metrics deployment. 5 | Then, it runs verification tests: check metrics' presence, lint metrics, check service health, etc. 6 | 7 | The test suite is run automatically using Github Actions. 8 | 9 | ## Running locally 10 | 11 | To run the e2e tests locally run the following command: 12 | 13 | ```bash 14 | ./tests/e2e.sh 15 | ``` 16 | -------------------------------------------------------------------------------- /tests/compare-sharding.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | trap 'kill 0' SIGTERM 4 | 5 | kubectl -n kube-system port-forward deployment/kube-state-metrics 8080:8080 & 6 | kubectl -n kube-system port-forward pod/kube-state-metrics-0 8082:8080 & 7 | kubectl -n kube-system port-forward pod/kube-state-metrics-1 8084:8080 & 8 | kubectl -n kube-system port-forward pod/kube-state-metrics-2 8086:8080 & 9 | 10 | sleep 3 11 | 12 | RESULT_UNSHARDED="$(mktemp)" 13 | RESULT_SHARDED_UNSORTED="$(mktemp)" 14 | RESULT_SHARDED="$(mktemp)" 15 | 16 | curl localhost:8080/metrics | grep -v "^#" | sort | tee "${RESULT_UNSHARDED}" 17 | curl localhost:8082/metrics | grep -v "^#" | tee "${RESULT_SHARDED_UNSORTED}" 18 | curl localhost:8084/metrics | grep -v "^#" | tee -a "${RESULT_SHARDED_UNSORTED}" 19 | curl localhost:8086/metrics | grep -v "^#" | tee -a "${RESULT_SHARDED_UNSORTED}" 20 | 21 | sort "${RESULT_SHARDED_UNSORTED}" | tee "${RESULT_SHARDED}" 22 | 23 | diff <(echo "${RESULT_UNSHARDED}") <(echo "${RESULT_SHARDED}") 24 | 25 | -------------------------------------------------------------------------------- /tests/compare_benchmarks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # exit immediately when a command fails 3 | set -e 4 | # only exit with zero if all commands of the pipeline exit successfully 5 | set -o pipefail 6 | # error on unset variables 7 | set -u 8 | 9 | [[ "$#" -le 2 ]] || echo "At least one argument required, $# provided." 10 | 11 | REF_CURRENT="$(git rev-parse --abbrev-ref HEAD)" 12 | REF_TO_COMPARE="${1}" 13 | 14 | COUNT=${2:-"1"} 15 | 16 | echo "Running benchmarks ${COUNT} time(s)" 17 | 18 | RESULT_CURRENT="$(mktemp)-${REF_CURRENT}" 19 | RESULT_TO_COMPARE="$(mktemp)-${REF_TO_COMPARE}" 20 | 21 | echo "" 22 | echo "### Testing ${REF_CURRENT}" 23 | 24 | go test -benchmem -run=NONE -bench=. -count="${COUNT}" ./... | tee "${RESULT_CURRENT}" 25 | 26 | echo "" 27 | echo "### Done testing ${REF_CURRENT}" 28 | 29 | echo "" 30 | echo "### Testing ${REF_TO_COMPARE}" 31 | 32 | git checkout "${REF_TO_COMPARE}" 33 | 34 | go test -benchmem -run=NONE -bench=. -count="${COUNT}" ./... | tee "${RESULT_TO_COMPARE}" 35 | 36 | echo "" 37 | echo "### Done testing ${REF_TO_COMPARE}" 38 | 39 | git checkout - 40 | 41 | echo "" 42 | echo "### Result" 43 | echo "old=${REF_TO_COMPARE} new=${REF_CURRENT}" 44 | 45 | if [[ -z "${BENCHSTAT_OUTPUT_FILE}" ]]; then 46 | go tool golang.org/x/perf/cmd/benchstat "${REF_TO_COMPARE}=${RESULT_TO_COMPARE}" "${REF_CURRENT}=${RESULT_CURRENT}" 47 | else 48 | go tool golang.org/x/perf/cmd/benchstat "${REF_TO_COMPARE}=${RESULT_TO_COMPARE}" "${REF_CURRENT}=${RESULT_CURRENT}" | tee -a "${BENCHSTAT_OUTPUT_FILE}" 49 | fi 50 | -------------------------------------------------------------------------------- /tests/e2e/README.md: -------------------------------------------------------------------------------- 1 | To run these tests, you need to provide two CLI flags: 2 | 3 | * `--ksm-http-metrics-url`: url to access the kube-state-metrics service 4 | * `--ksm-telemetry-url`: url to access the kube-state-metrics telemetry endpoint 5 | 6 | Example: 7 | 8 | ``` 9 | go test -v ./tests/e2e \ 10 | --ksm-http-metrics-url=http://localhost:8080/ \ 11 | --ksm-telemetry-url=http://localhost:8081/ 12 | ``` 13 | -------------------------------------------------------------------------------- /tests/e2e/hot-reload_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package e2e 18 | 19 | import ( 20 | "context" 21 | "net" 22 | "os" 23 | "testing" 24 | "time" 25 | 26 | "k8s.io/apimachinery/pkg/util/wait" 27 | 28 | "k8s.io/kube-state-metrics/v2/internal" 29 | "k8s.io/kube-state-metrics/v2/pkg/options" 30 | ) 31 | 32 | func TestConfigHotReload(t *testing.T) { 33 | 34 | // Initialise options. 35 | opts := options.NewOptions() 36 | cmd := options.InitCommand 37 | opts.AddFlags(cmd) 38 | 39 | // Create testdata. 40 | f, err := os.CreateTemp("", "config") 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | // Delete artefacts. 46 | defer func() { 47 | err := os.Remove(opts.Config) 48 | if err != nil { 49 | t.Fatalf("failed to remove config file: %v", err) 50 | } 51 | }() 52 | 53 | // Populate options. 54 | opts.Config = f.Name() 55 | 56 | // Assume $HOME is always defined. 57 | opts.Kubeconfig = os.Getenv("HOME") + "/.kube/config" 58 | 59 | // Run general validation on options. 60 | if err := opts.Parse(); err != nil { 61 | t.Fatalf("failed to parse options: %v", err) 62 | } 63 | 64 | // Make the process asynchronous. 65 | go internal.RunKubeStateMetricsWrapper(opts) 66 | 67 | // Wait for port 8080 to come up. 68 | err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { 69 | conn, err := net.Dial("tcp", "localhost:8080") 70 | if err != nil { 71 | return false, nil 72 | } 73 | err = conn.Close() 74 | if err != nil { 75 | return false, err 76 | } 77 | return true, nil 78 | }) 79 | if err != nil { 80 | t.Fatalf("failed to wait for port 8080 to come up for the first time: %v", err) 81 | } 82 | 83 | // Modify config to trigger hot reload. 84 | config := `foo: "bar"` 85 | err = os.WriteFile(opts.Config, []byte(config), 0600 /* rw------- */) 86 | if err != nil { 87 | t.Fatalf("failed to write config file: %v", err) 88 | } 89 | 90 | // Wait for port 8080 to come up. 91 | ch := make(chan bool, 1) 92 | err = wait.PollUntilContextTimeout(context.TODO(), 1*time.Second, 20*time.Second, true, func(_ context.Context) (bool, error) { 93 | conn, err := net.Dial("tcp", "localhost:8080") 94 | if err != nil { 95 | return false, nil 96 | } 97 | err = conn.Close() 98 | if err != nil { 99 | return false, err 100 | } 101 | // Indicate that the test has passed. 102 | ch <- true 103 | return true, nil 104 | }) 105 | if err != nil { 106 | t.Fatalf("failed to wait for port 8080 to come up after restarting the process: %v", err) 107 | } 108 | 109 | // Wait for process to exit. 110 | select { 111 | case <-ch: 112 | t.Log("test passed successfully") 113 | case <-time.After(20 * time.Second): 114 | t.Fatal("timed out waiting for test to pass, check the logs for more info") 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tests/e2e/testdata/pods.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: pendingpod2 6 | name: pendingpod2 7 | namespace: default 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: pendingpod2 13 | strategy: 14 | rollingUpdate: 15 | maxSurge: 25% 16 | maxUnavailable: 25% 17 | type: RollingUpdate 18 | template: 19 | metadata: 20 | labels: 21 | app: pendingpod2 22 | spec: 23 | nodeSelector: 24 | debug-node: "non" 25 | containers: 26 | - command: 27 | - /agnhost 28 | - netexec 29 | - --http-port=8080 30 | image: registry.k8s.io/e2e-test-images/agnhost@sha256:7e8bdd271312fd25fc5ff5a8f04727be84044eb3d7d8d03611972a6752e2e11e # 2.39 31 | imagePullPolicy: IfNotPresent 32 | name: agnhost 33 | terminationMessagePath: /dev/termination-log 34 | terminationMessagePolicy: File 35 | dnsPolicy: ClusterFirst 36 | restartPolicy: Always 37 | schedulerName: default-scheduler 38 | terminationGracePeriodSeconds: 30 39 | --- 40 | apiVersion: apps/v1 41 | kind: Deployment 42 | metadata: 43 | labels: 44 | app: runningpod1 45 | name: runningpod1 46 | namespace: default 47 | spec: 48 | replicas: 1 49 | selector: 50 | matchLabels: 51 | app: runningpod1 52 | strategy: 53 | rollingUpdate: 54 | maxSurge: 25% 55 | maxUnavailable: 25% 56 | type: RollingUpdate 57 | template: 58 | metadata: 59 | labels: 60 | app: runningpod1 61 | spec: 62 | containers: 63 | - command: 64 | - /agnhost 65 | - netexec 66 | - --http-port=8080 67 | image: registry.k8s.io/e2e-test-images/agnhost@sha256:7e8bdd271312fd25fc5ff5a8f04727be84044eb3d7d8d03611972a6752e2e11e # 2.39 68 | imagePullPolicy: IfNotPresent 69 | name: agnhost 70 | terminationMessagePath: /dev/termination-log 71 | terminationMessagePolicy: File 72 | dnsPolicy: ClusterFirst 73 | restartPolicy: Always 74 | schedulerName: default-scheduler 75 | terminationGracePeriodSeconds: 30 -------------------------------------------------------------------------------- /tests/lib/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package lib enables other projects to reuse the performance optimized metric 19 | exposition logic. While this package ensures this use-case is possible, it does 20 | not give any stability guarantees for the interface. 21 | */ 22 | package lib 23 | -------------------------------------------------------------------------------- /tests/lib/lib_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package lib 18 | 19 | import ( 20 | "context" 21 | "strings" 22 | "testing" 23 | "time" 24 | 25 | v1 "k8s.io/api/core/v1" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | "k8s.io/apimachinery/pkg/runtime" 28 | "k8s.io/apimachinery/pkg/watch" 29 | clientset "k8s.io/client-go/kubernetes" 30 | "k8s.io/client-go/kubernetes/fake" 31 | "k8s.io/client-go/tools/cache" 32 | 33 | "k8s.io/kube-state-metrics/v2/pkg/metric" 34 | metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store" 35 | ) 36 | 37 | func TestAsLibrary(t *testing.T) { 38 | kubeClient := fake.NewSimpleClientset() 39 | 40 | service := v1.Service{ 41 | ObjectMeta: metav1.ObjectMeta{ 42 | Name: "my-service", 43 | ResourceVersion: "123456", 44 | }, 45 | } 46 | 47 | _, err := kubeClient.CoreV1().Services(metav1.NamespaceDefault).Create(context.TODO(), &service, metav1.CreateOptions{}) 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | 52 | c := serviceCollector(kubeClient) 53 | 54 | // Wait for informers to sync 55 | time.Sleep(time.Second) 56 | 57 | w := strings.Builder{} 58 | mw := metricsstore.NewMetricsWriter(c) 59 | err = mw.WriteAll(&w) 60 | if err != nil { 61 | t.Fatalf("failed to write metrics: %v", err) 62 | } 63 | m := w.String() 64 | 65 | if !strings.Contains(m, service.Name) { 66 | t.Fatal("expected string to contain service name") 67 | } 68 | } 69 | 70 | func serviceCollector(kubeClient clientset.Interface) *metricsstore.MetricsStore { 71 | store := metricsstore.NewMetricsStore([]string{"test_metric describes a test metric"}, generateServiceMetrics) 72 | 73 | lw := cache.ListWatch{ 74 | ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { 75 | return kubeClient.CoreV1().Services(metav1.NamespaceDefault).List(context.TODO(), opts) 76 | }, 77 | WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { 78 | return kubeClient.CoreV1().Services(metav1.NamespaceDefault).Watch(context.TODO(), opts) 79 | }, 80 | } 81 | 82 | r := cache.NewReflectorWithOptions(&lw, &v1.Service{}, store, cache.ReflectorOptions{ResyncPeriod: 0}) 83 | 84 | go r.Run(context.TODO().Done()) 85 | 86 | return store 87 | } 88 | 89 | func generateServiceMetrics(obj interface{}) []metric.FamilyInterface { 90 | sPointer := obj.(*v1.Service) 91 | s := *sPointer 92 | 93 | m := metric.Metric{ 94 | LabelKeys: []string{"name"}, 95 | LabelValues: []string{s.Name}, 96 | Value: 1, 97 | } 98 | 99 | family := metric.Family{ 100 | Name: "test_metric", 101 | Metrics: []*metric.Metric{&m}, 102 | } 103 | 104 | return []metric.FamilyInterface{&family} 105 | } 106 | -------------------------------------------------------------------------------- /tests/manifests/clusterole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: clusterrole 5 | rules: 6 | - apiGroups: [""] 7 | resources: [""] 8 | verbs: ["get", "watch", "list"] -------------------------------------------------------------------------------- /tests/manifests/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: clusterrolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: test-service-account 8 | namespace: default 9 | roleRef: 10 | kind: ClusterRole 11 | name: clusterrole 12 | apiGroup: rbac.authorization.k8s.io 13 | -------------------------------------------------------------------------------- /tests/manifests/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | name: cronjob 5 | namespace: default 6 | spec: 7 | schedule: "@hourly" 8 | jobTemplate: 9 | spec: 10 | template: 11 | spec: 12 | containers: 13 | - name: cronjob 14 | image: nonexisting 15 | restartPolicy: OnFailure 16 | -------------------------------------------------------------------------------- /tests/manifests/csr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: certificates.k8s.io/v1 2 | kind: CertificateSigningRequest 3 | metadata: 4 | name: my-svc.my-namespace 5 | spec: 6 | groups: 7 | - system:masters 8 | - system:authenticated 9 | request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQllqQ0NBUWdDQVFBd01ERXVNQ3dHQTFVRUF4TWxiWGt0Y0c5a0xtMTVMVzVoYldWemNHRmpaUzV3YjJRdQpZMngxYzNSbGNpNXNiMk5oYkRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkpHai9CazNkTVNjCmNmQWdqbWk2d2wxdVYrQVNIR1g1ZHluWHFWdmJsaUd4clFBL2FFOWY0NDc5eFpVR0lDNjFPSmwrR0JJVGhBV0cKWlFiTEhDQ0xscXVnZGpCMEJna3Foa2lHOXcwQkNRNHhaekJsTUdNR0ExVWRFUVJjTUZxQ0pXMTVMWE4yWXk1dAplUzF1WVcxbGMzQmhZMlV1YzNaakxtTnNkWE4wWlhJdWJHOWpZV3lDSlcxNUxYQnZaQzV0ZVMxdVlXMWxjM0JoClkyVXVjRzlrTG1Oc2RYTjBaWEl1Ykc5allXeUhCS3lvQUJpSEJBb0FJZ0l3Q2dZSUtvWkl6ajBFQXdJRFNBQXcKUlFJZ1psb0J6Vkp4UkpjeUlweHZ1WGhTWFRhM3lPaXJDVVRCZytqQk5DUUcyT29DSVFDQVV6c2IzYWxuV1ljdAp5eGxEVEgxZkF6dms3R0ZINVVhd3RwaitWREFJNHc9PQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K 10 | signerName: kubernetes.io/kube-apiserver-client 11 | usages: 12 | - digital signature 13 | - key encipherment 14 | - server auth 15 | username: system:admin 16 | -------------------------------------------------------------------------------- /tests/manifests/daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset 5 | namespace: default 6 | spec: 7 | selector: 8 | matchLabels: 9 | name: daemonset 10 | template: 11 | metadata: 12 | labels: 13 | name: daemonset 14 | spec: 15 | containers: 16 | - name: daemonset 17 | image: nonexisting 18 | -------------------------------------------------------------------------------- /tests/manifests/endpointslice.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: discovery.k8s.io/v1 2 | kind: EndpointSlice 3 | metadata: 4 | name: example-endpointslice 5 | namespace: default 6 | addressType: IPv4 7 | endpoints: 8 | - addresses: 9 | - 10.0.0.2 10 | conditions: 11 | ready: true 12 | serving: true 13 | terminating: false 14 | -------------------------------------------------------------------------------- /tests/manifests/hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: hpa 5 | namespace: default 6 | spec: 7 | scaleTargetRef: 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | name: deployment 11 | minReplicas: 1 12 | maxReplicas: 10 13 | targetCPUUtilizationPercentage: 50 14 | -------------------------------------------------------------------------------- /tests/manifests/ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: example-ingress 5 | annotations: 6 | ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - http: 10 | paths: 11 | - path: /apple 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: apple-service 16 | port: 17 | number: 5678 18 | - path: /banana 19 | pathType: Prefix 20 | backend: 21 | service: 22 | name: banana-service 23 | port: 24 | number: 5678 25 | -------------------------------------------------------------------------------- /tests/manifests/ingressclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: IngressClass 3 | metadata: 4 | name: example-ingressclass 5 | annotations: 6 | ingressclass.kubernetes.io/is-default-class: "true" 7 | spec: 8 | controller: example-ingress/controller 9 | -------------------------------------------------------------------------------- /tests/manifests/job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: job 5 | namespace: default 6 | spec: 7 | template: 8 | metadata: 9 | name: job 10 | spec: 11 | containers: 12 | - name: job 13 | image: nonexisting 14 | restartPolicy: Never 15 | -------------------------------------------------------------------------------- /tests/manifests/limitrange.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: LimitRange 3 | metadata: 4 | name: limitrange 5 | spec: 6 | limits: 7 | - default: 8 | memory: 1000Mi 9 | defaultRequest: 10 | memory: 1Mi 11 | type: Container 12 | -------------------------------------------------------------------------------- /tests/manifests/mutatingwebhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admissionregistration.k8s.io/v1 2 | kind: MutatingWebhookConfiguration 3 | metadata: 4 | name: example-mutatingwebhookconfiguration 5 | webhooks: 6 | - name: "example.mutatingwebhookconfiguration.com" 7 | failurePolicy: Ignore 8 | clientConfig: 9 | service: 10 | name: apple-service 11 | namespace: apples 12 | path: /apple 13 | caBundle: "YXBwbGVz" 14 | admissionReviewVersions: ["v1", "v1beta1"] 15 | sideEffects: None 16 | timeoutSeconds: 5 17 | namespaceSelector: 18 | matchExpressions: 19 | - key: production 20 | operator: DoesNotExist 21 | rules: 22 | - apiGroups: 23 | - "" 24 | apiVersions: 25 | - v1 26 | operations: 27 | - CREATE 28 | - UPDATE 29 | resources: 30 | - pods 31 | -------------------------------------------------------------------------------- /tests/manifests/networkpolicy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: networking.k8s.io/v1 3 | kind: NetworkPolicy 4 | metadata: 5 | name: test-network-policy 6 | namespace: default 7 | spec: 8 | podSelector: 9 | matchLabels: 10 | foo: bar 11 | policyTypes: 12 | - Ingress 13 | - Egress 14 | ingress: 15 | - from: 16 | - ipBlock: 17 | cidr: 172.17.0.0/16 18 | except: 19 | - 172.17.1.0/24 20 | - namespaceSelector: 21 | matchLabels: 22 | project: myproject 23 | - podSelector: 24 | matchLabels: 25 | role: frontend 26 | ports: 27 | - protocol: TCP 28 | port: 6379 29 | egress: 30 | - to: 31 | - ipBlock: 32 | cidr: 10.0.0.0/24 33 | ports: 34 | - protocol: TCP 35 | port: 5978 36 | -------------------------------------------------------------------------------- /tests/manifests/persistentvolume.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: persistentvolume 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | capacity: 9 | storage: 5Gi 10 | hostPath: 11 | path: /data/pv0001/ 12 | -------------------------------------------------------------------------------- /tests/manifests/persistentvolumeclaim.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: persistentvolumeclaim 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | resources: 9 | requests: 10 | storage: 8Gi 11 | storageClassName: slow 12 | selector: 13 | matchLabels: 14 | release: "stable" 15 | matchExpressions: 16 | - {key: environment, operator: In, values: [dev]} 17 | -------------------------------------------------------------------------------- /tests/manifests/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | name: pdb 5 | spec: 6 | minAvailable: "50%" 7 | selector: 8 | matchLabels: 9 | name: pdb 10 | -------------------------------------------------------------------------------- /tests/manifests/replicationcontroller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: replicationcontroller 5 | spec: 6 | selector: 7 | app: replicationcontroller 8 | template: 9 | metadata: 10 | name: replicationcontroller 11 | labels: 12 | app: replicationcontroller 13 | spec: 14 | containers: 15 | - name: replicationcontroller 16 | image: nonexisting 17 | -------------------------------------------------------------------------------- /tests/manifests/resourcequota.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ResourceQuota 3 | metadata: 4 | name: resourcequota 5 | spec: 6 | hard: 7 | configmaps: "10" 8 | -------------------------------------------------------------------------------- /tests/manifests/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: role 5 | rules: 6 | - apiGroups: [""] 7 | resources: [""] 8 | verbs: ["get", "watch", "list"] -------------------------------------------------------------------------------- /tests/manifests/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: rolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: test-service-account 8 | roleRef: 9 | kind: Role 10 | name: role 11 | apiGroup: rbac.authorization.k8s.io 12 | -------------------------------------------------------------------------------- /tests/manifests/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: test-service-account 5 | -------------------------------------------------------------------------------- /tests/manifests/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: statefulset 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: statefulset 9 | serviceName: statefulset 10 | template: 11 | metadata: 12 | labels: 13 | app: statefulset 14 | spec: 15 | containers: 16 | - name: statefulset 17 | image: nonexisting 18 | -------------------------------------------------------------------------------- /tests/manifests/storageclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: storageclass 5 | provisioner: kubernetes.io/rbd 6 | reclaimPolicy: Delete 7 | volumeBindingMode: Immediate 8 | -------------------------------------------------------------------------------- /tests/manifests/validatingwebhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admissionregistration.k8s.io/v1 2 | kind: ValidatingWebhookConfiguration 3 | metadata: 4 | name: example-validatingwebhookconfiguration 5 | webhooks: 6 | - name: "example.validatingwebhookconfiguration.com" 7 | failurePolicy: Ignore 8 | clientConfig: 9 | service: 10 | name: apple-service 11 | namespace: apples 12 | path: /apple 13 | caBundle: "YXBwbGVz" 14 | admissionReviewVersions: ["v1", "v1beta1"] 15 | sideEffects: None 16 | timeoutSeconds: 5 17 | namespaceSelector: 18 | matchExpressions: 19 | - key: production 20 | operator: DoesNotExist 21 | rules: 22 | - apiGroups: 23 | - "" 24 | apiVersions: 25 | - v1 26 | operations: 27 | - CREATE 28 | - UPDATE 29 | resources: 30 | - pods 31 | -------------------------------------------------------------------------------- /tests/manifests/volumeattachment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: VolumeAttachment 3 | metadata: 4 | name: volumeattachment 5 | spec: 6 | attacher: attacher 7 | nodeName: kind 8 | source: 9 | persistentVolumeName: persistentvolume 10 | --------------------------------------------------------------------------------