├── .circleci └── config.yml ├── .github └── workflows │ ├── blackbox-workflow.yml │ ├── codeql-analysis.yml │ ├── main.yaml │ ├── release.yaml │ └── security-workflow.yml ├── .gitignore ├── .lgtm.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── README.md ├── app.py ├── deploy ├── 00-permissions-metrics-server-exporter.yaml ├── 10-deployment-metrics-server-exporter.yaml ├── 20-service-metrics-server-exporter.yaml └── kustomization.yaml ├── helm ├── .helmignore ├── Chart.yaml ├── templates │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── permissions.yaml │ └── service.yaml └── values.yaml └── requirements.txt /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | defaults: &defaults 3 | machine: 4 | image: circleci/classic:latest 5 | environment: 6 | KUBE_VERSION: 1.14.0 7 | KUBEVAL_VERSION: 0.13.0 8 | 9 | jobs: 10 | run_tests: 11 | <<: *defaults 12 | steps: 13 | - checkout 14 | - run: 15 | name: Install kubeval 16 | command: curl -s -LO https://github.com/instrumenta/kubeval/releases/download/${KUBEVAL_VERSION}/kubeval-linux-amd64.tar.gz && tar xf kubeval-linux-amd64.tar.gz kubeval 17 | 18 | - run: 19 | name: Kubernetes yaml files validation (kubeval) 20 | command: ./kubeval --kubernetes-version ${KUBE_VERSION} -d deploy 21 | 22 | build_image: 23 | <<: *defaults 24 | steps: 25 | - checkout 26 | - run: docker build -t vivareal/metrics-server-exporter:build . 27 | - run: 28 | name: Docker save 29 | command: | 30 | mkdir -p docker-cache 31 | docker save -o docker-cache/metrics-server-exporter-build.tar vivareal/metrics-server-exporter:build 32 | - save_cache: 33 | key: metrics-server-exporter-{{ .Environment.CIRCLE_SHA1 }} 34 | paths: 35 | - docker-cache 36 | 37 | publish_master: 38 | <<: *defaults 39 | steps: 40 | - checkout 41 | - run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 42 | - restore_cache: 43 | keys: 44 | - metrics-server-exporter-{{ .Environment.CIRCLE_SHA1 }} 45 | - run: 46 | name: Load and tag image 47 | command: | 48 | docker load < docker-cache/metrics-server-exporter-build.tar 49 | docker tag vivareal/metrics-server-exporter:build vivareal/metrics-server-exporter:master 50 | - run: 51 | name: Publish Image 52 | command: docker push vivareal/metrics-server-exporter:master 53 | 54 | publish_tag: 55 | <<: *defaults 56 | steps: 57 | - checkout 58 | - run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 59 | - restore_cache: 60 | keys: 61 | - metrics-server-exporter-{{ .Environment.CIRCLE_SHA1 }} 62 | - run: 63 | name: Load Image 64 | command: docker load < docker-cache/metrics-server-exporter-build.tar 65 | - run: 66 | name: Tag and publish image 67 | command: | 68 | docker tag vivareal/metrics-server-exporter:build vivareal/metrics-server-exporter:${CIRCLE_TAG} 69 | docker push vivareal/metrics-server-exporter:${CIRCLE_TAG} 70 | 71 | workflows: 72 | version: 2 73 | ci: 74 | jobs: 75 | - run_tests 76 | - build_image: 77 | filters: 78 | tags: 79 | only: /^v[0-9]+(\.[0-9]+)*$/ 80 | - publish_master: 81 | context: docker-access 82 | requires: 83 | - build_image 84 | filters: 85 | branches: 86 | only: master 87 | - publish_tag: 88 | context: docker-access 89 | requires: 90 | - build_image 91 | filters: 92 | tags: 93 | only: /^v[0-9]+(\.[0-9]+)*$/ 94 | branches: 95 | ignore: /.*/ 96 | -------------------------------------------------------------------------------- /.github/workflows/blackbox-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Blackbox 2 | 3 | on: 4 | repository_dispatch: 5 | types: [event-trigger] 6 | workflow_dispatch: ~ 7 | 8 | # .github/workflows/blackbox-workflow.yml 9 | jobs: 10 | run-blackbox-action: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | ref: '${{ github.event.repository.default_branch }}' 16 | fetch-depth: 0 17 | - id: blackbox 18 | uses: olxbr/blackbox-action@v1 19 | with: 20 | config: ${{ secrets.BLACK_BOX_CONFIG }} 21 | env: 22 | DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} 23 | REPO_NAME: ${{ github.event.repository.name }} 24 | DOCKER_ECR_PASSWORD: ${{ secrets.DOCKER_ECR_PASSWORD }} 25 | DOCKER_REGISTRY: ${{ secrets.CONTAINER_REGISTRY_HOST }} 26 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CROSS_ACCESS_KEY_ID }} 27 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CROSS_SECRET_ACCESS_KEY }} 28 | LOGLEVEL: 'INFO' 29 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '41 10 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: Main 2 | on: 3 | pull_request: 4 | push: 5 | branches: [master] 6 | jobs: 7 | kubeval: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@master 11 | - name: validate 12 | uses: instrumenta/kubeval-action@master 13 | with: 14 | files: ./deploy 15 | strict: false 16 | version: "1.18.12" 17 | 18 | build: 19 | name: Build 20 | runs-on: ubuntu-20.04 21 | needs: unit-tests 22 | 23 | steps: 24 | - name: Checkout repo 25 | uses: actions/checkout@v2 26 | 27 | - name: Restore docker cache 28 | uses: actions/cache@v2 29 | with: 30 | path: ~/docker-cache 31 | key: metrics-server-exporter-docker-${{ github.sha }} 32 | restore-keys: | 33 | metrics-server-exporter-docker-${{ github.sha }} 34 | 35 | 36 | - name: Login to ECR 37 | run: | 38 | echo "${{ secrets.DOCKER_ECR_PASSWORD }}" | docker login --username AWS --password-stdin ${{ secrets.CONTAINER_REGISTRY_HOST }} 39 | 40 | - name: build final docker image 41 | run: | 42 | docker load < ~/docker-cache/metrics-server-exporter-test.tar 43 | docker build -t ${{ secrets.CONTAINER_REGISTRY_HOST }}//metrics-server-exporter:build . 44 | mkdir -p ~/docker-cache-final-image 45 | docker save -o ~/docker-cache-final-image/metrics-server-exporter.tar ${{ secrets.CONTAINER_REGISTRY_HOST }}//metrics-server-exporter 46 | 47 | - name: Save docker cache final image 48 | uses: actions/cache@v2 49 | with: 50 | path: ~/docker-cache-final-image 51 | key: metrics-server-exporter-docker-final-image-${{ github.sha }} 52 | 53 | publish: 54 | name: publish 55 | needs: build 56 | runs-on: ubuntu-20.04 57 | 58 | steps: 59 | - name: "Get release name" 60 | id: "release-name" 61 | run: "echo \"::set-output name=release::${GITHUB_REF##*/}\"" 62 | 63 | - name: Checkout repo 64 | uses: actions/checkout@v2 65 | 66 | - name: Restore docker cache 67 | uses: actions/cache@v2 68 | with: 69 | path: ~/docker-cache-final-image 70 | key: metrics-server-exporter-docker-final-image-${{ github.sha }} 71 | restore-keys: | 72 | metrics-server-exporter-docker-final-image-${{ github.sha }} 73 | 74 | - name: Load tar file 75 | run: docker load < ~/docker-cache-final-image/metrics-server-exporter.tar 76 | 77 | - name: Docker login 78 | uses: docker/login-action@v1 79 | with: 80 | username: ${{ secrets.DOCKERHUB_USERNAME }} 81 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 82 | 83 | - name: Push to ECR 84 | uses: olxbr/aws-ecr-push-action@v1 85 | id: ecr 86 | with: 87 | # The complete repository name from ECR {BU}/{TEAM}/{PROJECT} (ex. cross/devtools/devtools-scripts). 88 | ecr_repository: "/metrics-server-exporter" 89 | tags: "master" 90 | env: 91 | AWS_ACCOUNT_ID: ${{ secrets.AWS_CROSS_ACCOUNT_ID }} 92 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_CROSS_ACCESS_KEY_ID }} 93 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_CROSS_SECRET_ACCESS_KEY }} 94 | AWS_PRINCIPAL_RULES: ${{ secrets.AWS_PRINCIPAL_RULES }} 95 | 96 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: release 3 | jobs: 4 | 5 | publish: 6 | name: publish 7 | runs-on: ubuntu-20.04 8 | 9 | steps: 10 | - name: "Get release name" 11 | id: "release-name" 12 | run: "echo \"::set-output name=release::${GITHUB_REF##*/}\"" 13 | 14 | - name: Checkout repo 15 | uses: actions/checkout@v2 16 | 17 | - name: Restore docker cache 18 | uses: actions/cache@v2 19 | with: 20 | path: ~/docker-cache-final-image 21 | key: metrics-server-exporter-docker-final-image-${{ github.sha }} 22 | restore-keys: | 23 | metrics-server-exporter-docker-final-image-${{ github.sha }} 24 | 25 | - name: Load tar file 26 | run: docker load < ~/docker-cache-final-image/metrics-server-exporter.tar 27 | 28 | - name: Docker login 29 | uses: docker/login-action@v1 30 | with: 31 | username: ${{ secrets.DOCKERHUB_USERNAME }} 32 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 33 | 34 | - name: tag docker image 35 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') 36 | run: | 37 | docker tag ${{ secrets.CONTAINER_REGISTRY_HOST }}//metrics-server-exporter:build ${{ secrets.CONTAINER_REGISTRY_HOST }}//metrics-server-exporter:${{ steps.release-name.outputs.release }} 38 | docker push ${{ secrets.CONTAINER_REGISTRY_HOST }}//metrics-server-exporter:${{ steps.release-name.outputs.release }} 39 | -------------------------------------------------------------------------------- /.github/workflows/security-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Security Workflow 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | 7 | get-teams: 8 | name: "Get repository team names" 9 | runs-on: ubuntu-latest 10 | outputs: 11 | teams: ${{ steps.teams.outputs.teams }} 12 | 13 | if: | 14 | github.actor != 'dependabot[bot]' && 15 | ((github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) || 16 | github.event_name == 'pull_request' || 17 | github.event_name == 'workflow_dispatch') 18 | 19 | steps: 20 | - name: Export team names 21 | id: teams 22 | run: | 23 | TEAMS=$( \ 24 | curl -s -H "Authorization: token ${{ secrets.SECURITY_WORKFLOW_GH_PAT }}" \ 25 | -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/$GITHUB_REPOSITORY/teams | \ 26 | jq -c '. | [.[]? | .name ]' \ 27 | ) 28 | echo "::set-output name=teams::$TEAMS" 29 | 30 | static-analysis: 31 | name: "Static Analysis" 32 | runs-on: ubuntu-latest 33 | needs: get-teams 34 | 35 | if: | 36 | github.actor != 'dependabot[bot]' && 37 | ((github.event_name == 'push' && github.ref_name == github.event.repository.default_branch) || 38 | github.event_name == 'pull_request' || 39 | github.event_name == 'workflow_dispatch') 40 | 41 | steps: 42 | - name: Run checkout - push 43 | if: github.event_name == 'push' 44 | uses: actions/checkout@v2 45 | with: 46 | fetch-depth: 100 47 | 48 | - name: Run checkout - pull_request / workflow_dispatch 49 | if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' 50 | uses: actions/checkout@v2 51 | with: 52 | fetch-depth: 0 53 | 54 | - name: Run Gitleaks 55 | id: gitleaks 56 | uses: olxbr/gitleaks-action@main 57 | 58 | - name: Submit Gitleaks metrics 59 | run: | 60 | ENDPOINT=$(echo "${{ secrets.GH_METRICS_SERVER_ENDPOINT }}" | awk -F/ '{print $3}') 61 | DATA=$( \ 62 | jq -n \ 63 | --arg GITHUB_WORKFLOW "$GITHUB_WORKFLOW" \ 64 | --arg GITHUB_JOB "$GITHUB_JOB" \ 65 | --arg GITHUB_RUN_ID "$GITHUB_RUN_ID" \ 66 | --arg GITHUB_SHA "$GITHUB_SHA" \ 67 | --arg GITHUB_REPOSITORY "$GITHUB_REPOSITORY" \ 68 | --arg GITLEAKS_EXIT_CODE "${{ steps.gitleaks.outputs.exit_code }}" \ 69 | --argjson GITLEAKS_RESULT '${{ steps.gitleaks.outputs.result }}' \ 70 | --argjson TEAMS '${{ needs.get-teams.outputs.teams }}' \ 71 | '{ 72 | "workflow_job": { 73 | "name": $GITHUB_WORKFLOW, 74 | "id": $GITHUB_JOB, 75 | "run_id": $GITHUB_RUN_ID, 76 | "head_sha": $GITHUB_SHA 77 | }, 78 | "repository": { 79 | "full_name": $GITHUB_REPOSITORY 80 | }, 81 | "custom_metrics": { 82 | "outputs.exit_code": $GITLEAKS_EXIT_CODE, 83 | "outputs.result": $GITLEAKS_RESULT, 84 | "outputs.repository_teams": $TEAMS 85 | } 86 | }' \ 87 | ) 88 | curl -sv "https://${ENDPOINT}/gitleaks" -d "$DATA" -H "Content-Type: application/json" --connect-timeout 15 --max-time 30 89 | 90 | - name: Notify bad Gitleaks exit code 91 | if: steps.gitleaks.outputs.exit_code != 0 92 | run: | 93 | TEAMS=$(echo '${{ needs.get-teams.outputs.teams }}' | jq '.[]' | tr -d '\\"') 94 | MESSAGE=$(printf "Summary report for is ready for review.\nAssociated teams in this repository:\n\`\`\`$TEAMS\`\`\`") 95 | REPOSITORY_RUN="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" 96 | DATA=$( \ 97 | jq -n \ 98 | --arg CHANNEL "${{ secrets.SECURITY_WORKFLOW_SLACK_CHANNEL_ID }}" \ 99 | --arg REPOSITORY_RUN "$REPOSITORY_RUN" \ 100 | --arg MESSAGE "$MESSAGE" \ 101 | '{ 102 | "channel": $CHANNEL, 103 | "blocks": [ 104 | { 105 | "type": "header", 106 | "text": { 107 | "type": "plain_text", 108 | "text": "Gitleaks raised issues" 109 | } 110 | }, 111 | { 112 | "type": "section", 113 | "text": { 114 | "type": "mrkdwn", 115 | "text": $MESSAGE 116 | }, 117 | "accessory": { 118 | "type": "button", 119 | "text": { 120 | "type": "plain_text", 121 | "text": "See report" 122 | }, 123 | "url": $REPOSITORY_RUN 124 | } 125 | } 126 | ] 127 | }' \ 128 | ) 129 | curl -sv \ 130 | -d "$DATA" \ 131 | -H "Content-type: application/json" \ 132 | -H "Authorization: Bearer ${{ secrets.SEC_BOT_SLACK_TOKEN }}" \ 133 | -X POST https://slack.com/api/chat.postMessage 134 | 135 | - name: Evaluate Gitleaks exit code 136 | if: steps.gitleaks.outputs.exit_code != 0 137 | uses: actions/github-script@v5 138 | with: 139 | script: | 140 | core.setFailed("Gitleaks encountered leaks. Please fix it in order to keep a safe work.") 141 | 142 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | !.github/* 2 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | python: 3 | python_setup: 4 | version: 3 5 | requirements_files: 6 | - requirements.txt 7 | setup_py: false 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | This repository accepts contributions via Github pull requests. 4 | This document outlines some of the conventions on commit message formatting, 5 | contact points for developers and other resources to make getting your 6 | contribution accepted. 7 | 8 | # Before opening a issue 9 | 10 | Before opening a new issue, it's helpful to search the issues - it's likely that another user 11 | has already reported the issue you're facing, or it's a known issue that we're already aware of. 12 | 13 | When opening an issue, please provide as much information as possible. 14 | 15 | ## Contribution Flow 16 | 17 | This is a rough outline of what a contributor's workflow looks like: 18 | 19 | - Clone the repo. 20 | - Create a topic branch from where you want to base your work. This is usually master. 21 | - Make commits of logical units. 22 | - Make sure your commit messages are in the proper format, see below 23 | - Push your changes to a topic branch in your fork of the repository. 24 | - Submit a PR, make sure to provide as much information as possible. 25 | 26 | ### Commit Style Guideline 27 | 28 | We follow a rough convention for commit messages borrowed from CoreOS, who borrowed theirs 29 | from AngularJS. This is an example of a commit: 30 | 31 | feat(scripts/test-cluster): add a cluster test command 32 | 33 | this uses tmux to setup a test cluster that you can easily kill and 34 | start for debugging. 35 | 36 | To make it more formal, it looks something like this: 37 | 38 | 39 | {type}({scope}): {subject} 40 | 41 | {body} 42 | 43 | {footer} 44 | 45 | The {scope} can be anything specifying place of the commit change. 46 | 47 | The {subject} needs to use imperative, present tense: “change”, not “changed” nor 48 | “changes”. The first letter should not be capitalized, and there is no dot (.) at the end. 49 | 50 | Just like the {subject}, the message {body} needs to be in the present tense, and includes 51 | the motivation for the change, as well as a contrast with the previous behavior. The first 52 | letter in a paragraph must be capitalized. 53 | 54 | All breaking changes need to be mentioned in the {footer} with the description of the 55 | change, the justification behind the change and any migration notes required. 56 | 57 | Any line of the commit message cannot be longer than 72 characters, with the subject line 58 | limited to 50 characters. This allows the message to be easier to read on github as well 59 | as in various git tools. 60 | 61 | The allowed {types} are as follows: 62 | 63 | chore -> maintenance 64 | docs -> documentation 65 | feat -> feature 66 | fix -> bug fix 67 | ref -> refactoring code 68 | style -> formatting 69 | test -> adding missing tests 70 | 71 | 72 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6-alpine 2 | 3 | EXPOSE 8000 4 | 5 | WORKDIR /app 6 | 7 | COPY requirements.txt /app 8 | RUN pip install --requirement requirements.txt 9 | 10 | COPY . /app 11 | CMD ["python", "app.py"] 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | Copyright © 2019 Grupo ZAP 3 | 4 | * * * 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the “Software”), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # metrics-server-exporter [![CircleCI](https://circleci.com/gh/grupozap/metrics-server-exporter.svg?style=svg)](https://circleci.com/gh/grupozap/metrics-server-exporter) [![Total alerts](https://img.shields.io/lgtm/alerts/g/grupozap/metrics-server-exporter.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/grupozap/metrics-server-exporter/alerts/) [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/grupozap/metrics-server-exporter.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/grupozap/metrics-server-exporter/context:python) 3 | 4 | > **Deprecated project, replaced by using kube-state-metrics**. 5 | 6 | metrics-server-exporter provides cpu and memory metrics for nodes and pods, directly querying the metrics-server API `/apis/metrics.k8s.io/v1beta1/{pods, nodes}` 7 | 8 | 9 | ### Node metrics 10 | 11 | * kube_metrics_server_nodes_mem 12 | * Provides nodes memory information in kibibytes. 13 | * kube_metrics_server_nodes_cpu 14 | * Provides nodes CPU information in nanocores. 15 | 16 | ##### labels 17 | 18 | * instance 19 | 20 | ### Pod metrics 21 | 22 | * kube_metrics_server_pods_mem 23 | * Provides pods/container memory information. 24 | * kube_metrics_server_pods_cpu 25 | * Provides pods/container memory information. 26 | 27 | ##### labels 28 | 29 | * pod_name 30 | * pod_namespace 31 | * pod_container_name 32 | 33 | ### API metrics 34 | 35 | * kube_metrics_server_response_time 36 | * Provides API response time in seconds. 37 | 38 | ### Variables 39 | 40 | * K8S_ENDPOINT 41 | * Url of API of kubernetes (default kubernetes.default.svc) 42 | 43 | * K8S_TOKEN 44 | * The authorization token (default ServiceAccount token) 45 | 46 | * K8S_FILEPATH_TOKEN 47 | * Path of ServiceAccount token file (default /var/run/secrets/kubernetes.io/serviceaccount/token) 48 | 49 | * K8S_CA_CERT_PATH 50 | * Path of Kubernetes CA certificate (default /var/run/secrets/kubernetes.io/serviceaccount/ca.crt) 51 | 52 | * NAMES_BLACKLIST 53 | * A list of names from pods, containers or namespaces to exclude from metrics. 54 | * NAMESPACE_WHITELIST 55 | * A list of namespace to scrape from this way you can create namespaced rolebinding instead of cluster binding. ( quite useful for larger clusters ) ( default : '' (all namespaces)) 56 | * LABEL_SELECTOR 57 | * A list of Label Selectors. 58 | ### Options 59 | 60 | * --insecure-tls 61 | * Disables TLS verification of the Kubernetes API Server. (Not recommended in production) 62 | 63 | ### How to build 64 | 65 | $ docker build . -t ${{ secrets.CONTAINER_REGISTRY_HOST }}/metrics-server-exporter 66 | 67 | ### How to run 68 | 69 | You will need `K8S_TOKEN` and `K8S_ENDPOINT` to access the api-server. Use "--insecure-tls" or mount the CA certificate into the container. Kubernetes will provide the CA certificate in a Kubernetes installation. 70 | 71 | $ docker run -p 8000:8000 -e "K8S_ENDPOINT=${K8S_ENDPOINT}" -e "K8S_TOKEN=${K8S_TOKEN}" ${{ secrets.CONTAINER_REGISTRY_HOST }}/metrics-server-exporter --insecure-tls 72 | 73 | ### How to deploy 74 | 75 | Set you target k8s context and apply the deployment files 76 | 77 | $ kubectl apply -f deploy/ 78 | 79 | #### Blacklist 80 | 81 | If you want, you could blacklist some names of namespaces, pods or containers, you just need to apply this ConfigMap, replacing the example names 82 | 83 | ```yaml 84 | apiVersion: v1 85 | kind: ConfigMap 86 | metadata: 87 | name: metrics-server-exporter 88 | labels: 89 | k8s-app: metrics-server-exporter 90 | data: 91 | NAMES_BLACKLIST: kube-proxy,calico-node,kube2iam # example names 92 | ``` 93 | 94 | ### Minikube 95 | 96 | How to test in Minikube 97 | 98 | $ minikube delete; minikube start --vm-driver=kvm2 --cpus=2 --memory=4096 99 | * Deleting "minikube" from kvm2 ... 100 | * The "minikube" cluster has been deleted. 101 | * minikube v1.2.0 on linux (amd64) 102 | * Creating kvm2 VM (CPUs=2, Memory=4096MB, Disk=20000MB) ... 103 | * Configuring environment for Kubernetes v1.15.0 on Docker 18.09.6 104 | * Downloading kubelet v1.15.0 105 | * Downloading kubeadm v1.15.0 106 | * Pulling images ... 107 | * Launching Kubernetes ... 108 | * Verifying: apiserver proxy etcd scheduler controller dns 109 | * Done! kubectl is now configured to use "minikube" 110 | 111 | Enable metrics-server addon 112 | 113 | $ minikube addons enable metrics-server 114 | * metrics-server was successfully enabled 115 | 116 | Deploy the files in minikube 117 | 118 | $ kubectl apply -R -f deploy/ -n kube-system 119 | 120 | Then, test the connectivity 121 | 122 | $ kubectl port-forward -n kube-system svc/metrics-server-exporter 9104:9104 & 123 | $ curl http://localhost:9104/metrics 124 | 125 | ### Helm 126 | 127 | To install metrics-server-exporter, use 128 | 129 | $ helm install --name=metrics-server-exporter --namespace kube-system helm/ 130 | 131 | You could set the variables using the `--set` parameters 132 | 133 | $ helm install --name=metrics-server-exporter --set custom.k8s_endpoint=https://kubernetes.default.svc helm/ 134 | 135 | You could assign a specific nodePort. 136 | $ helm install --name=metrics-server-exporter --set service.type=NodePort --set service.nodePort=31001 helm/ 137 | 138 | ### Grafana Dashboard 139 | 140 | You can use the following dashboard to plot metrics from metrics-server-exporter to Grafana. 141 | 142 | ![image](https://user-images.githubusercontent.com/3788237/82919047-e6b1d880-9f4b-11ea-9133-584d9b6abf86.png) 143 | 144 | https://grafana.com/grafana/dashboards/12363 145 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import datetime 4 | import getopt 5 | import os 6 | import requests 7 | import string 8 | import sys 9 | import time 10 | 11 | from requests.adapters import HTTPAdapter 12 | from requests.packages.urllib3.util.retry import Retry 13 | 14 | from prometheus_client import Metric, start_http_server 15 | from prometheus_client.core import REGISTRY 16 | 17 | class MetricsServerExporter: 18 | 19 | def __init__(self): 20 | self.svc_token = os.environ.get('K8S_FILEPATH_TOKEN', '/var/run/secrets/kubernetes.io/serviceaccount/token') 21 | self.ca_cert = os.environ.get('K8S_CA_CERT_PATH', '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt') 22 | self.api_url = os.environ.get('K8S_ENDPOINT', 'https://kubernetes.default.svc') 23 | self.names_blacklist = os.environ.get('NAMES_BLACKLIST', '').split(',') 24 | self.namespaces = os.environ.get('NAMESPACE_WHITELIST','').split(',') 25 | self.labelSelector = os.environ.get('LABEL_SELECTOR','') 26 | 27 | self.api_nodes_url = "{}/apis/metrics.k8s.io/v1beta1/nodes".format(self.api_url) 28 | self.api_pods_url = "{}/apis/metrics.k8s.io/v1beta1/pods".format( self.api_url) 29 | 30 | self.insecure_tls = self.set_tls_mode() 31 | self.token = self.set_token() 32 | 33 | def set_tls_mode(self): 34 | return ('--insecure-tls','') in options 35 | 36 | def set_token(self): 37 | if os.environ.get('K8S_TOKEN') is not None: 38 | return os.environ.get('K8S_TOKEN') 39 | 40 | if os.path.exists(self.svc_token): 41 | with open(self.svc_token, 'r') as f: 42 | os.environ['K8S_TOKEN'] = f.readline() 43 | return os.environ.get('K8S_TOKEN') 44 | 45 | return None 46 | 47 | def set_namespaced_pod_url(self,namespace): 48 | return '{}/apis/metrics.k8s.io/v1beta1/namespaces/{}/pods?labelSelector={}'.format( self.api_url ,namespace,self.labelSelector ) 49 | 50 | def kube_metrics(self): 51 | headers = { "Authorization": "Bearer {}".format(self.token) } 52 | query = { 'labelSelector' : self.labelSelector } 53 | session = requests.Session() 54 | retry = Retry(total=3, connect=3, backoff_factor=0.1) 55 | adapter = HTTPAdapter(max_retries=retry) 56 | session.mount('http://', adapter) 57 | session.mount('https://', adapter) 58 | if self.insecure_tls: 59 | session.verify = False 60 | elif os.path.exists(self.ca_cert): 61 | session.verify = self.ca_cert 62 | if self.namespaces: 63 | pod_data = None 64 | for namespace in self.namespaces: 65 | if pod_data is None: 66 | pod_data = session.get(self.set_namespaced_pod_url(namespace), headers=headers, params=query).json() 67 | else: 68 | pod_data['items'] += session.get(self.set_namespaced_pod_url(namespace), headers=headers, params=query).json()['items'] 69 | payload = { 70 | 'nodes': session.get(self.api_nodes_url, headers=headers, params=query).json(), 71 | 'pods': pod_data 72 | } 73 | else: 74 | payload = { 75 | 'nodes': session.get(self.api_nodes_url, headers=headers, params=query).json(), 76 | 'pods': session.get(self.api_pods_url, headers=headers, params=query).json() 77 | } 78 | 79 | return payload 80 | 81 | def collect(self): 82 | start_time = datetime.datetime.now() 83 | ret = self.kube_metrics() 84 | end_time = datetime.datetime.now() 85 | total_time = (end_time - start_time).total_seconds() 86 | 87 | nodes = ret['nodes'] 88 | pods = ret['pods'] 89 | 90 | metrics_nodes_mem = Metric('kube_metrics_server_nodes_mem', 'Metrics Server Nodes Memory', 'gauge') 91 | metrics_nodes_cpu = Metric('kube_metrics_server_nodes_cpu', 'Metrics Server Nodes CPU', 'gauge') 92 | 93 | metrics_response_time = Metric('kube_metrics_server_response_time', 'Metrics Server API Response Time', 'gauge') 94 | metrics_response_time.add_sample('kube_metrics_server_response_time', value=total_time, labels={ 'api_url': '{}/metrics.k8s.io'.format(self.api_url) }) 95 | yield metrics_response_time 96 | 97 | for node in nodes.get('items', []): 98 | node_instance = node['metadata']['name'] 99 | node_cpu = node['usage']['cpu'] 100 | node_cpu = node_cpu.translate(str.maketrans('', '', string.ascii_letters)) 101 | node_mem = node['usage']['memory'] 102 | node_mem = node_mem.translate(str.maketrans('', '', string.ascii_letters)) 103 | 104 | metrics_nodes_mem.add_sample('kube_metrics_server_nodes_mem', value=int(node_mem), labels={ 'instance': node_instance }) 105 | metrics_nodes_cpu.add_sample('kube_metrics_server_nodes_cpu', value=int(node_cpu), labels={ 'instance': node_instance }) 106 | 107 | yield metrics_nodes_mem 108 | yield metrics_nodes_cpu 109 | 110 | metrics_pods_mem = Metric('kube_metrics_server_pods_mem', 'Metrics Server Pods Memory', 'gauge') 111 | metrics_pods_cpu = Metric('kube_metrics_server_pods_cpu', 'Metrics Server Pods CPU', 'gauge') 112 | 113 | for pod in pods.get('items', []): 114 | pod_name = pod['metadata']['name'] 115 | pod_namespace = pod['metadata']['namespace'] 116 | 117 | pod_container_mem = 0 118 | pod_container_cpu = 0 119 | pod_container_name = "" 120 | 121 | for container in pod['containers']: 122 | pod_container_name = container['name'] 123 | pod_container_cpu = container['usage']['cpu'] 124 | pod_container_cpu = pod_container_cpu.translate(str.maketrans('', '', string.ascii_letters)) 125 | pod_container_mem = container['usage']['memory'] 126 | pod_container_mem = pod_container_mem.translate(str.maketrans('', '', string.ascii_letters)) 127 | 128 | if not any(blacklisted in self.names_blacklist for blacklisted in [pod_container_name, pod_name, pod_namespace]): 129 | metrics_pods_mem.add_sample('kube_metrics_server_pods_mem', value=int(pod_container_mem), labels={ 'pod_name': pod_name, 'pod_namespace': pod_namespace, 'pod_container_name': pod_container_name }) 130 | metrics_pods_cpu.add_sample('kube_metrics_server_pods_cpu', value=int(pod_container_cpu), labels={ 'pod_name': pod_name, 'pod_namespace': pod_namespace, 'pod_container_name': pod_container_name }) 131 | 132 | yield metrics_pods_mem 133 | yield metrics_pods_cpu 134 | 135 | if __name__ == '__main__': 136 | options, remainder = getopt.gnu_getopt(sys.argv[1:], '', ['insecure-tls']) 137 | REGISTRY.register(MetricsServerExporter()) 138 | start_http_server(8000) 139 | while True: 140 | time.sleep(5) 141 | -------------------------------------------------------------------------------- /deploy/00-permissions-metrics-server-exporter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1beta1 3 | kind: ClusterRole 4 | metadata: 5 | name: metrics-server-exporter 6 | labels: 7 | k8s-app: metrics-server-exporter 8 | rules: 9 | - apiGroups: ["metrics.k8s.io"] 10 | resources: ["*"] 11 | verbs: ["*"] 12 | --- 13 | apiVersion: v1 14 | kind: ServiceAccount 15 | metadata: 16 | name: metrics-server-exporter 17 | labels: 18 | k8s-app: metrics-server-exporter 19 | --- 20 | apiVersion: rbac.authorization.k8s.io/v1beta1 21 | kind: ClusterRoleBinding 22 | metadata: 23 | name: metrics-server-exporter 24 | subjects: 25 | - kind: ServiceAccount 26 | namespace: kube-system 27 | name: metrics-server-exporter 28 | roleRef: 29 | kind: ClusterRole 30 | name: metrics-server-exporter 31 | apiGroup: rbac.authorization.k8s.io 32 | -------------------------------------------------------------------------------- /deploy/10-deployment-metrics-server-exporter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: metrics-server-exporter 5 | labels: 6 | k8s-app: metrics-server-exporter 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | k8s-app: metrics-server-exporter 12 | strategy: 13 | rollingUpdate: 14 | maxSurge: 1 15 | maxUnavailable: 0 16 | type: RollingUpdate 17 | template: 18 | metadata: 19 | labels: 20 | k8s-app: metrics-server-exporter 21 | spec: 22 | serviceAccountName: metrics-server-exporter 23 | containers: 24 | - name: metrics-server-exporter 25 | image: 073521391622.dkr.ecr.us-east-1.amazonaws.com/metrics-server-exporter:v0.0.7 26 | imagePullPolicy: IfNotPresent 27 | ports: 28 | - containerPort: 8000 29 | protocol: TCP 30 | livenessProbe: 31 | failureThreshold: 3 32 | httpGet: 33 | path: /metrics 34 | port: 8000 35 | scheme: HTTP 36 | initialDelaySeconds: 30 37 | periodSeconds: 10 38 | successThreshold: 1 39 | timeoutSeconds: 30 40 | readinessProbe: 41 | failureThreshold: 3 42 | httpGet: 43 | path: /metrics 44 | port: 8000 45 | scheme: HTTP 46 | initialDelaySeconds: 5 47 | periodSeconds: 10 48 | successThreshold: 1 49 | timeoutSeconds: 10 50 | resources: 51 | requests: 52 | memory: 150Mi 53 | cpu: 100m 54 | limits: 55 | memory: 150Mi 56 | cpu: 100m 57 | restartPolicy: Always 58 | -------------------------------------------------------------------------------- /deploy/20-service-metrics-server-exporter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | prometheus.io/path: /metrics 6 | prometheus.io/port: "8000" 7 | prometheus.io/scrape: "true" 8 | name: metrics-server-exporter 9 | labels: 10 | k8s-app: metrics-server-exporter 11 | spec: 12 | ports: 13 | - port: 9104 14 | protocol: TCP 15 | targetPort: 8000 16 | selector: 17 | k8s-app: metrics-server-exporter 18 | -------------------------------------------------------------------------------- /deploy/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - 00-permissions-metrics-server-exporter.yaml 5 | - 10-deployment-metrics-server-exporter.yaml 6 | - 20-service-metrics-server-exporter.yaml 7 | -------------------------------------------------------------------------------- /helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "0.0.6" 3 | description: A Helm chart for metrics-server-exporter 4 | name: metrics-server-exporter 5 | version: 0.1.0 6 | -------------------------------------------------------------------------------- /helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "metrics-server-exporter.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "metrics-server-exporter.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "metrics-server-exporter.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "metrics-server-exporter.labels" -}} 38 | app.kubernetes.io/name: {{ include "metrics-server-exporter.name" . }} 39 | helm.sh/chart: {{ include "metrics-server-exporter.chart" . }} 40 | app.kubernetes.io/instance: {{ .Release.Name }} 41 | {{- if .Chart.AppVersion }} 42 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 43 | {{- end }} 44 | app.kubernetes.io/managed-by: {{ .Release.Service }} 45 | {{- end -}} 46 | -------------------------------------------------------------------------------- /helm/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "metrics-server-exporter.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{ include "metrics-server-exporter.labels" . | indent 4 }} 8 | spec: 9 | replicas: {{ .Values.replicaCount }} 10 | selector: 11 | matchLabels: 12 | app.kubernetes.io/name: {{ include "metrics-server-exporter.name" . }} 13 | app.kubernetes.io/instance: {{ .Release.Name }} 14 | template: 15 | metadata: 16 | {{- if .Values.podAnnotations }} 17 | annotations: 18 | {{ toYaml .Values.podAnnotations | indent 8 }} 19 | {{- end }} 20 | labels: 21 | app.kubernetes.io/name: {{ include "metrics-server-exporter.name" . }} 22 | app.kubernetes.io/instance: {{ .Release.Name }} 23 | spec: 24 | serviceAccountName: {{ include "metrics-server-exporter.fullname" . }} 25 | {{- with .Values.imagePullSecrets }} 26 | imagePullSecrets: 27 | {{- toYaml . | nindent 8 }} 28 | {{- end }} 29 | containers: 30 | - name: {{ .Chart.Name }} 31 | {{- if or (.Values.custom) (.Values.env) }} 32 | env: 33 | {{- end }} 34 | {{- if .Values.custom }} 35 | {{- if .Values.custom.k8s_endpoint }} 36 | - name: K8S_ENDPOINT 37 | value: {{ .Values.custom.k8s_endpoint }} 38 | {{- end }} 39 | {{- if .Values.custom.names_blacklist }} 40 | - name: NAMES_BLACKLIST 41 | value: "{{ .Values.custom.names_blacklist }}" 42 | {{- end }} 43 | {{- if .Values.custom.k8s_token }} 44 | - name: K8S_TOKEN 45 | value: "{{ .Values.custom.k8s_token }}" 46 | {{- end }} 47 | {{- if .Values.custom.k8s_filepath_token }} 48 | - name: K8S_FILEPATH_TOKEN 49 | value: "{{ .Values.custom.k8s_filepath_token }}" 50 | {{- end }} 51 | {{- if .Values.custom.k8s_ca_cert_path }} 52 | - name: K8S_CA_CERT_PATH 53 | value: "{{ .Values.custom.k8s_ca_cert_path }}" 54 | {{- end }} 55 | {{- end }} 56 | {{- if .Values.env }} 57 | {{- with .Values.env }} 58 | {{- toYaml . | nindent 10 }} 59 | {{- end }} 60 | {{- end }} 61 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 62 | imagePullPolicy: {{ .Values.image.pullPolicy }} 63 | ports: 64 | - name: http 65 | containerPort: 8000 66 | protocol: TCP 67 | livenessProbe: 68 | httpGet: 69 | path: /metrics 70 | port: 8000 71 | scheme: HTTP 72 | readinessProbe: 73 | httpGet: 74 | path: /metrics 75 | port: 8000 76 | scheme: HTTP 77 | resources: 78 | {{- toYaml .Values.resources | nindent 12 }} 79 | {{- with .Values.nodeSelector }} 80 | nodeSelector: 81 | {{- toYaml . | nindent 8 }} 82 | {{- end }} 83 | {{- with .Values.affinity }} 84 | affinity: 85 | {{- toYaml . | nindent 8 }} 86 | {{- end }} 87 | {{- with .Values.tolerations }} 88 | tolerations: 89 | {{- toYaml . | nindent 8 }} 90 | {{- end }} 91 | -------------------------------------------------------------------------------- /helm/templates/permissions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "metrics-server-exporter.fullname" . }} 5 | labels: 6 | {{ include "metrics-server-exporter.labels" . | indent 4 }} 7 | rules: 8 | - apiGroups: ["metrics.k8s.io"] 9 | resources: ["*"] 10 | verbs: ["*"] 11 | --- 12 | apiVersion: v1 13 | kind: ServiceAccount 14 | metadata: 15 | name: {{ include "metrics-server-exporter.fullname" . }} 16 | namespace: {{ .Release.Namespace }} 17 | labels: 18 | {{ include "metrics-server-exporter.labels" . | indent 4 }} 19 | --- 20 | apiVersion: rbac.authorization.k8s.io/v1beta1 21 | kind: ClusterRoleBinding 22 | metadata: 23 | name: {{ include "metrics-server-exporter.fullname" . }} 24 | subjects: 25 | - kind: ServiceAccount 26 | namespace: {{ .Release.Namespace }} 27 | name: {{ include "metrics-server-exporter.fullname" . }} 28 | roleRef: 29 | kind: ClusterRole 30 | name: {{ include "metrics-server-exporter.fullname" . }} 31 | apiGroup: rbac.authorization.k8s.io 32 | -------------------------------------------------------------------------------- /helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "metrics-server-exporter.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{ include "metrics-server-exporter.labels" . | indent 4 }} 8 | {{- if .Values.serviceAnnotations }} 9 | annotations: 10 | {{ toYaml .Values.serviceAnnotations | indent 4 }} 11 | {{- end }} 12 | spec: 13 | type: {{ .Values.service.type }} 14 | ports: 15 | - port: {{ .Values.service.port }} 16 | targetPort: 8000 17 | protocol: TCP 18 | name: http 19 | {{- if .Values.service.nodePort }} 20 | nodePort: {{ .Values.service.nodePort }} 21 | {{- end }} 22 | selector: 23 | app.kubernetes.io/name: {{ include "metrics-server-exporter.name" . }} 24 | app.kubernetes.io/instance: {{ .Release.Name }} 25 | -------------------------------------------------------------------------------- /helm/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for metrics-server-exporter. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: vivareal/metrics-server-exporter 9 | tag: v0.0.6 10 | pullPolicy: IfNotPresent 11 | 12 | imagePullSecrets: [] 13 | nameOverride: "" 14 | fullnameOverride: "" 15 | 16 | service: 17 | type: ClusterIP 18 | port: 9104 19 | # nodePort: 30104 20 | 21 | # custom: 22 | # names_blacklist: "" 23 | # k8s_endpoint: "" 24 | # k8s_token: "" 25 | # k8s_filepath_token: "" 26 | # k8s_ca_cert_path: "" 27 | 28 | podAnnotations: 29 | # When installing Prometheus from official Helm charts, it has a job rule that will 30 | # discover the pods with the following annotations. 31 | prometheus.io/scrape: "true" 32 | prometheus.io/port: "8000" 33 | 34 | serviceAnnotations: {} 35 | # Alternatively official Prometheus chart can probe services. 36 | # prometheus.io/probe: "true" 37 | 38 | resources: {} 39 | # We usually recommend not to specify default resources and to leave this as a conscious 40 | # choice for the user. This also increases chances charts run on environments with little 41 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 42 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 43 | # limits: 44 | # cpu: 100m 45 | # memory: 128Mi 46 | # requests: 47 | # cpu: 100m 48 | # memory: 128Mi 49 | 50 | nodeSelector: {} 51 | 52 | tolerations: [] 53 | 54 | affinity: {} 55 | 56 | env: {} 57 | # Add ability to include more opinionated environment variables 58 | # - name: POD_IP 59 | # valueFrom: 60 | # fieldRef: 61 | # fieldPath: status.podIP 62 | # - name: SERVICE_8000_NAME 63 | # value: metrics-server-exporter 64 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | prometheus-client==0.3.1 2 | requests==2.20.0 3 | --------------------------------------------------------------------------------