├── .github ├── CODEOWNERS └── workflows │ ├── chart-lint-test.yml │ ├── fossa.yml │ ├── jsonnet-lint.yml │ └── release-charts.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── GOVERNANCE.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── RELEASE.md ├── SECURITY.md ├── SECURITY_CONTACTS.md ├── contribute ├── alerts.md ├── dashboards.md ├── design.md ├── images │ └── openebs-monitoring.png ├── release.md └── service-monitor.md ├── ct.yml ├── deploy └── charts │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── dashboards │ ├── lvmLocalPV │ │ └── lvmlocalpv-pool.json │ ├── mayastor │ │ ├── mayastor-diskpool.json │ │ ├── mayastor-volume-replica.json │ │ └── mayastor-volume.json │ ├── npd │ │ └── npd-node-volume-problem.json │ └── zfsLocalPV │ │ └── zfslocalpv.json │ ├── rules │ ├── lvmLocalPV │ │ └── lvmlocalpv-rules.json │ ├── npd │ │ └── npd-rules.json │ └── volume │ │ └── volume-rules.json │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── dashboards-json-configmap.yaml │ ├── podmonitors.yaml │ ├── prometheusRules.yaml │ └── servicemonitors.yaml │ └── values.yaml ├── docs ├── extends-stack-with-umbrella-chart.md ├── guide.md ├── metrics-csi.md ├── metrics-lvm.md ├── metrics-node-exporter.md ├── metrics-node-problem-detector.md └── openebs-mixin-user-guide.md ├── jsonnet ├── Makefile ├── buildscripts │ ├── go.mod │ ├── go.sum │ └── tools.go └── openebs-mixin │ ├── Makefile │ ├── README.md │ ├── build.sh │ ├── config.libsonnet │ ├── dashboards │ ├── dashboards.libsonnet │ ├── mayastor │ │ ├── mayastor-diskpool.json │ │ ├── mayastor-volume-replica.json │ │ └── mayastor-volume.json │ ├── npd │ │ └── npd-node-volume-problem.json │ └── openebs │ │ ├── lvmlocalpv-pool.json │ │ └── zfslocalpv.json │ ├── jsonnetfile.json │ ├── lib │ ├── dashboards.jsonnet │ └── rules.jsonnet │ ├── mixin.libsonnet │ └── rules │ ├── npd │ └── npd-rules.libsonnet │ ├── openebs │ └── lvmlocalpv-rules.libsonnet │ ├── prometheus-rules.libsonnet │ ├── rules.libsonnet │ └── volume │ └── volume-rules.libsonnet ├── nix ├── README.md ├── lib │ ├── rust.nix │ └── sourcer.nix ├── overlay.nix ├── sources.json └── sources.nix └── scripts ├── generate-readme.sh └── shell.nix /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Default code owners 2 | * @openebs/localpv-hostpath-approvers @openebs/localpv-zfs-approvers @openebs/localpv-lvm-approvers @openebs/mayastor-approvers 3 | 4 | # OEP owners 5 | /designs @openebs/org-maintainers 6 | 7 | # CODEOWNERS file owners 8 | /.github/CODEOWNERS @openebs/org-maintainers 9 | 10 | # Policy docs owners 11 | /CODE_OF_CONDUCT.md @openebs/org-maintainers 12 | /CONTRIBUTING.md @openebs/org-maintainers 13 | /GOVERNANCE.md @openebs/org-maintainers 14 | /LICENSE @openebs/org-maintainers 15 | /MAINTAINERS.md @openebs/org-maintainers 16 | /SECURITY.md @openebs/org-maintainers 17 | /SECURITY_CONTACTS.md @openebs/org-maintainers 18 | -------------------------------------------------------------------------------- /.github/workflows/chart-lint-test.yml: -------------------------------------------------------------------------------- 1 | name: Chart Lint and Test 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'deploy/charts/**' 7 | branches: 8 | - develop 9 | pull_request: 10 | paths: 11 | - 'deploy/charts/**' 12 | branches: 13 | - develop 14 | 15 | jobs: 16 | lint-test: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Set up Helm 25 | uses: azure/setup-helm@v4 26 | with: 27 | version: v3.14.3 28 | 29 | - uses: actions/setup-python@v5 30 | with: 31 | python-version: '3.10' 32 | check-latest: true 33 | 34 | - name: Set up chart-testing 35 | uses: helm/chart-testing-action@v2.6.1 36 | 37 | - name: Run chart-testing (list-changed) 38 | id: list-changed 39 | run: | 40 | changed=$(ct list-changed --config ct.yml) 41 | if [[ -n "$changed" ]]; then 42 | echo "changed=true" >> $GITHUB_OUTPUT 43 | fi 44 | 45 | - name: Run chart-testing (lint) 46 | run: ct lint --config ct.yml 47 | 48 | - name: Create kind cluster 49 | uses: helm/kind-action@v1.9.0 50 | if: steps.list-changed.outputs.changed == 'true' 51 | 52 | - name: Run chart-testing (install) 53 | run: ct install --config ct.yml 54 | -------------------------------------------------------------------------------- /.github/workflows/fossa.yml: -------------------------------------------------------------------------------- 1 | name: Fossa CLI 2 | on: 3 | push: 4 | branches: 5 | - 'develop' 6 | 7 | jobs: 8 | fossa-scan: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | submodules: recursive 14 | - uses: fossas/fossa-action@v1.4.0 15 | with: 16 | api-key: ${{ secrets.FOSSA_API_KEY }} 17 | -------------------------------------------------------------------------------- /.github/workflows/jsonnet-lint.yml: -------------------------------------------------------------------------------- 1 | name: Jsonnet lint 2 | 3 | on: 4 | push: 5 | paths: 6 | - "jsonnet/**" 7 | branches: 8 | - develop 9 | pull_request: 10 | paths: 11 | - "jsonnet/**" 12 | branches: 13 | - develop 14 | 15 | jobs: 16 | lint: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Jsonnet formatter and linter 25 | run: | 26 | cd jsonnet && make --always-make all 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/release-charts.yml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | push: 5 | paths: 6 | - "deploy/charts/**" 7 | branches: 8 | - develop 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Configure Git 20 | run: | 21 | git config user.name "$GITHUB_ACTOR" 22 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 23 | 24 | - name: Install Helm 25 | uses: azure/setup-helm@v4 26 | with: 27 | version: v3.14.3 28 | 29 | - name: Add dependency chart repos 30 | run: | 31 | helm repo add kube-prometheus-stack https://prometheus-community.github.io/helm-charts 32 | helm repo add node-problem-detector https://charts.deliveryhero.io/ 33 | helm repo add localpv-provisioner https://openebs.github.io/dynamic-localpv-provisioner 34 | 35 | - name: Run chart-releaser 36 | uses: helm/chart-releaser-action@v1.6.0 37 | env: 38 | CR_TOKEN: "${{ secrets.CR_TOKEN }}" 39 | with: 40 | charts_dir: deploy 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Chart dependencies 2 | /deploy/charts/charts 3 | /deploy/charts/Chart.lock 4 | 5 | # ide 6 | **/.idea 7 | 8 | jsonnet/vendor/ 9 | jsonnet/tmp/ 10 | jsonnet/buildscripts/vendor/ 11 | jsonnet/manifests 12 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 |
3 | 4 | ## Umbrella Project 5 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 6 |
7 | 8 | This project follows the [OpenEBS Code of Conduct](https://github.com/openebs/community/blob/HEAD/CODE_OF_CONDUCT.md) 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 |
3 | 4 | ## Umbrella Project 5 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 6 |
7 | 8 | This project follows the [OpenEBS Contributor Guidelines](https://github.com/openebs/community/blob/HEAD/CONTRIBUTING.md) 9 | 10 | # Contributing 11 | 12 | OpenEBS uses the standard GitHub pull requests process to review and accept contributions. There are several areas that could use your help. For starters, you could help in improving the sections in this document by either creating a new issue describing the improvement or submitting a pull request to this repository. The issues for the various OpenEBS components (including components in this repository) are maintained in [openebs/openebs](https://github.com/openebs/openebs/issues) repository. 13 | 14 | * If you have a trivial fix or improvement, go ahead and create a pull request, addressing (with `@...`) the maintainer of this repository (see [MAINTAINERS](MAINTAINERS)) in the description of the pull request. 15 | 16 | * If you would like to work on something more involved, please connect with the OpenEBS Contributors. See [OpenEBS Community](https://github.com/openebs/openebs/tree/master/community). 17 | 18 | ## Steps to Contribute 19 | 20 | OpenEBS is an Apache 2.0 Licensed project and all your commits should be signed with Developer Certificate of Origin. See [Sign your work](#sign-your-work). 21 | 22 | * Find an issue to work on or create a new issue. The issues are maintained at [openebs/openebs](https://github.com/openebs/openebs/issues). You can pick up from a list of [good-first-issues](https://github.com/openebs/openebs/labels/good%20first%20issue). 23 | * Claim your issue by commenting your intent to work on it to avoid duplication of efforts. 24 | * Fork the repository on GitHub. 25 | * Create a branch from where you want to base your work (usually master). 26 | * Make your changes. 27 | * Commit your changes by making sure the commit messages convey the need and notes about the commit. 28 | * Push your changes to the branch in your fork of the repository. 29 | * Submit a pull request to the original repository. See [Pull Request checklist](#pull-request-checklist). 30 | 31 | ## Pull Request Checklist 32 | 33 | * Rebase to the current master branch before submitting your pull request. 34 | * Commits should be as small as possible. Each commit should follow the checklist below: 35 | - For code changes, add tests relevant to the fixed bug or new feature. 36 | - Pass the compile and tests - includes spell checks, formatting, etc. 37 | - Commit header (first line) should convey what changed. 38 | - Commit body should include details such as why the changes are required and how the proposed changes. 39 | - DCO Signed. 40 | * If your PR is not getting reviewed or you need a specific person to review it, please reach out to the OpenEBS Contributors. See [OpenEBS Community](https://github.com/openebs/openebs/tree/master/community). 41 | 42 | ## Sign your work 43 | 44 | We use the Developer Certificate of Origin (DCO) as an additional safeguard for the OpenEBS project. This is a well established and widely used mechanism to assure that contributors have confirmed their right to license their contribution under the project's license. Please read [dcofile](https://github.com/openebs/openebs/blob/master/contribute/developer-certificate-of-origin). If you can certify it, then just add a line to every git commit message: 45 | 46 | ``` 47 | Signed-off-by: Random J Developer 48 | ``` 49 | 50 | Use your real name (sorry, no pseudonyms or anonymous contributions). The email id should match the email id provided in your GitHub profile. 51 | If you set your `user.name` and `user.email` in git config, you can sign your commit automatically with `git commit -s`. 52 | 53 | You can also use git [aliases](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases) like `git config --global alias.ci 'commit -s'`. Now you can commit with `git ci` and the commit will be signed. 54 | 55 | -------------------------------------------------------------------------------- /GOVERNANCE.md: -------------------------------------------------------------------------------- 1 | # Governance 2 |
3 | 4 | ## Umbrella Project 5 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 6 |
7 | 8 | This project follows the [OpenEBS Governance](https://github.com/openebs/community/blob/HEAD/GOVERNANCE.md) 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 |
4 | 5 | ## Umbrella Project 6 | 7 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 8 |
9 | 10 | Please refer to the [OpenEBS Maintainers](https://github.com/openebs/community/blob/HEAD/MAINTAINERS.md). 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenEBS Monitoring add-on 2 | 3 | [![Slack](https://img.shields.io/badge/chat-slack-ff1493.svg?style=flat-square)](https://kubernetes.slack.com/messages/openebs) 4 | [![Community Meetings](https://img.shields.io/badge/Community-Meetings-blue)](https://github.com/openebs/community/blob/HEAD/README.md#community) 5 | [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopenebs%2Fmonitoring.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopenebs%2Fmonitoring?ref=badge_shield&issueType=license) 6 | 7 | 8 | A set of Grafana dashboards and Prometheus alerts for OpenEBS that can be installed as a [helm chart](./deploy/charts/) or imported as [jsonnet mixin](./jsonnet/). 9 | 10 | ## Status 11 | 12 | **Beta**. This repository currently supports dashboards and alerts for `Mayastor`, `LocalPV LVM`, `LocalPV ZFS` OpenEBS storage engines. 13 | This project is under active development and seeking [contributions from the community](#contributing). 14 | 15 | 16 | ## Install 17 | 18 | ### Using helm 19 | 20 | Setup the monitoring helm repository. 21 | 22 | ```console 23 | helm repo add monitoring https://openebs.github.io/monitoring/ 24 | helm repo update 25 | ``` 26 | 27 | You can then run `helm search repo monitoring` to see the charts. 28 | 29 | Install the helm chart. 30 | ``` 31 | helm install monitoring monitoring/monitoring --namespace openebs --create-namespace 32 | ``` 33 | 34 | The detailed chart documentation is available in [charts directory](/deploy/charts/README.md). 35 | 36 | ### Using kubectl 37 | 38 | You can generate YAMLs and install using kubectl. See detailed steps at [./jsonnet](/jsonnet/README.md). 39 | 40 | ## Usage 41 | 42 | ### Accessing Grafana 43 | 44 | ```console 45 | # Look at the Grafana pod and check that the pod is in running state 46 | kubectl get pods -n [NAMESPACE] | grep -i grafana 47 | # Note the public IP of any one of the nodes 48 | kubectl get nodes -o wide 49 | # Note the Grafana Service IP 50 | kubectl get svc -n [NAMESPACE] | grep -i grafana 51 | # Open browser and visit http://: 52 | # (where is the public IP address of your node, and is Grafana Service Port) 53 | # Default Grafana login credentials- [username: admin, password: admin] 54 | ``` 55 | 56 | **NOTE:** If public IP is not available then you can access it via port-forwarding 57 | 58 | ```console 59 | # Perform port-forwarding 60 | # kubectl port-forward --namespace [NAMESPACE] pods/[grafana-pod-name] [grafrana-foward-port]:[grafana-cluster-port] 61 | # Open browser and visit http://127.0.0.1:[grafana-forward-port] 62 | # Default Grafana login credentials- [username: admin, password: admin] 63 | ``` 64 | 65 | 66 | ## Contributing 67 | 68 | OpenEBS welcomes your feedback and contributions in any form possible. 69 | 70 | - Want to raise an issue or help with fixes and features? 71 | - See [open issues](https://github.com/openebs/monitoring/issues) 72 | - See [Project Roadmap](https://github.com/orgs/openebs/projects/41) 73 | - See [contributing guide](./CONTRIBUTING.md) 74 | 75 | ## Community 76 | 77 | - [Join OpenEBS community on Kubernetes Slack](https://kubernetes.slack.com) 78 | - Already signed up? Head to our discussions at [#openebs](https://kubernetes.slack.com/messages/openebs/) 79 | - Want to join our contributor community meetings, [check this out](https://github.com/openebs/openebs/blob/HEAD/community/README.md). 80 | - Join our OpenEBS CNCF Mailing lists 81 | - For OpenEBS project updates, subscribe to [OpenEBS Announcements](https://lists.cncf.io/g/cncf-openebs-announcements) 82 | - For interacting with other OpenEBS users, subscribe to [OpenEBS Users](https://lists.cncf.io/g/cncf-openebs-users) 83 | 84 | ## Code of conduct 85 | 86 | Participation in the OpenEBS community is governed by the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/HEAD/code-of-conduct.md). 87 | 88 | 89 | ## License Compliance 90 | [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopenebs%2Fmonitoring.svg?type=large&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopenebs%2Fmonitoring?ref=badge_large&issueType=license) 91 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | This is a OpenEBS sub project and abides by the 2 | [OpenEBS Release Process](https://github.com/openebs/openebs/blob/master/RELEASE.md). 3 | 4 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 |
4 | 5 | ## Umbrella Project 6 | 7 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 8 |
9 | 10 | This project follows the [OpenEBS Security Policy](https://github.com/openebs/community/blob/HEAD/SECURITY.md). 11 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS.md: -------------------------------------------------------------------------------- 1 | # Security Contacts 2 | 3 |
4 | 5 | ## Umbrella Project 6 | 7 | OpenEBS is an "umbrella project". Every project, repository and file in the OpenEBS organization adopts and follows the policies found in the Community repo umbrella project files. 8 |
9 | 10 | Please refer to the [OpenEBS Security Contacts](https://github.com/openebs/community/blob/HEAD/SECURITY_CONTACTS.md). 11 | -------------------------------------------------------------------------------- /contribute/alerts.md: -------------------------------------------------------------------------------- 1 | ## How to add new alerts in openebs-mixin. 2 | To add new alert rules in openebs-mixin, you need to add alert rules in [rules](jsonnet/../../jsonnet/openebs-mixin/rules/) directory and import it through [rules.libsonnet](../jsonnet/openebs-mixin/dashboards/dashboards.libsonnet)and [prometheus-rules.libsonnet](../jsonnet/openebs-mixin/rules/prometheus-rules.libsonnet) to include it in prometheusRules object. 3 | 4 | ## Step by Step Process 5 | 1. Add alert rules in [rules](jsonnet/../../jsonnet/openebs-mixin/rules/) directory. 6 | - **new-alert-rules.libsonnet** 7 | ``` 8 | function(param) { 9 | //local rules = self, 10 | _config+:: param, 11 | prometheusRules+:: { 12 | npd: { 13 | groups+: [ 14 | { 15 | name: 'volume-node', 16 | rules: [ 17 | { 18 | alert-rule 1 19 | } 20 | . . . 21 | ] 22 | }] 23 | } 24 | } 25 | }; 26 | ``` 27 | 28 | 2. Add configuration in [config.libsonnet](../jsonnet/openebs-mixin/config.libsonnet) to allow users to configure alert rules. For example: 29 | ``` 30 | . . . 31 | // // AlertRules configuration. If set, then alert rules are included in the prometheusRules object. 32 | alertRules: { 33 | newAlertRules: true # to include alert rules in prometheusRules object 34 | }, 35 | . . . 36 | ``` 37 | 3. Import the alert rules in [rules.libsonnet](../jsonnet/openebs-mixin/dashboards/dashboards.libsonnet) and [prometheus-rules.libsonnet](../jsonnet/openebs-mixin/rules/prometheus-rules.libsonnet) and include it in `prometheusRules` object. 38 | Examples: 39 | - [**prometheus-rules.libsonnet**](../jsonnet/openebs-mixin/rules/prometheus-rules.libsonnet) 40 | ``` 41 | . . . 42 | local newAlertRules = (import './new-alert-rules.libsonnet'); 43 | 44 | prometheusRules+:: 45 | . . . 46 | + newAlertRules(prometheusRules._config).prometheusRules.newAlertRules, 47 | . . . 48 | ``` 49 | - [**rules.libsonnet**](../jsonnet/openebs-mixin/dashboards/dashboards.libsonnet) 50 | ``` 51 | . . . 52 | local newAlertRules = (import './new-alert-rules.libsonnet'); 53 | 54 | prometheusRules+:: 55 | . . . 56 | + newAlertRules(prometheusRules._config).prometheusRules.newAlertRules.groups, 57 | . . . 58 | ``` -------------------------------------------------------------------------------- /contribute/dashboards.md: -------------------------------------------------------------------------------- 1 | ## How to add new dashboards in openebs-mixin. 2 | To add new dashboard in openebs-mixin, you need to add dashboard json file in [dashboards](jsonnet/../../jsonnet/openebs-mixin/dashboards/) directory and import it through [dashboards.libsonnet](../jsonnet/openebs-mixin/dashboards/dashboards.libsonnet) to create grafanaDashboards object. 3 | 4 | ## Step by Step Process 5 | 1. Add dashboards json in [dashboards](jsonnet/../../jsonnet/openebs-mixin/dashboards/) directory. 6 | 2. Add configuration in [config.libsonnet](../jsonnet/openebs-mixin/config.libsonnet) to allow users to configure dashboard. For example: 7 | ``` 8 | . . . 9 | // dashboards configuration. If set, then dashboards are included in grafanaDashboards object. 10 | dashboards: { 11 | newDashboard: true # to import dashboard as grafanaDashboards object 12 | }, 13 | . . . 14 | ``` 15 | 3. Import the dashboard json in [dashboards.libsonnet](../jsonnet/openebs-mixin/dashboards/dashboards.libsonnet) to include it in `grafanaDashboards` object. 16 | ``` 17 | . . . 18 | grafanaDashboards+:: { 19 | . . . 20 | [if dashboard._config.dashboards.newDashboard then 'new-dashboard.json']: import './new-dashboard.json', 21 | }, 22 | . . . 23 | ``` -------------------------------------------------------------------------------- /contribute/design.md: -------------------------------------------------------------------------------- 1 | # openEBS Monitoring 2 | 3 | ![monitoring](images/monitoring.png) 4 | 5 | OpenEBS monitoring written in jsonnet has two components: 6 | 1. [**kube-prometheus stack**](https://github.com/prometheus-operator/kube-prometheus/tree/main/jsonnet/kube-prometheus) 7 | It is a monitoring stack which includes prometheus, grafana and alertmanager. 8 | 2. [**openebs-mixin**](https://github.com/openebs/monitoring/tree/develop/jsonnet/openebs-mixin) 9 | It is a mixin for openebs. It includes all the dashboards and alert rules for different cas types of openebs which are used to import grafanaDashboards and create prometheusRules objects. 10 | 11 | ## Directory structure 12 | 13 | - OpenEBS Monitoring 14 | 15 | ``` 16 | jsonnet 17 | ├── addons # monitoring addon 18 | │ ├── podMonitors.libsonnet # podMonitor to be created for different cas types 19 | │ ├── prometheusRules.libsonnet # create prometheusRule object which includes alert rules defined in openebs-mixin 20 | │ └── serviceMonitors.libsonnet # serviceMonitor to be created for different cas types 21 | | 22 | ├── config.libsonnet # configuration to be used for openebs monitoing 23 | | 24 | ├── jsonnetfile.json # direct dependencies 25 | ├── jsonnetfile.lock.json # all dependencies with exact version 26 | | 27 | ├── lib # contains code that is used in different places 28 | │ └── utils.libsonnet # code which is used to create monitoring addons 29 | | 30 | ├── main.jsonnet # entrypoint of code(openEBS Monitoring) 31 | ├── Makefile 32 | | 33 | └── openebs-mixin # contains grafanaDashboards and prometheusRules 34 | 35 | ``` 36 | 37 | - openebs-mixin 38 | 39 | 40 | ``` 41 | openebs-mixin # openebs-mixin for grafanaDashboards and prometheusRules. 42 | ├── build.sh 43 | ├── config.libsonnet # configuration that is used while writing dashboards and alert rules 44 | ├── dashboards 45 | │ ├── openebs/ 46 | │ ├── . . . 47 | │ ├── dashboards.libsonnet # to import all the dashboard json through grafanaDashboards object. 48 | | 49 | ├── jsonnetfile.json # direct dependencies 50 | | 51 | ├── lib 52 | │ ├── dashboards.jsonnet # to generate dashboards for helm charts 53 | │ └── rules.jsonnet # to generate alert rules for helm charts 54 | | 55 | ├── Makefile 56 | | 57 | ├── mixin.libsonnet # openebs-mixin that imports grafanaDashboards and prometheusRules 58 | | 59 | └── rules # contains alert rules for different cas types 60 | ├── openebs/ 61 | ├── . . . 62 | ├── rules.libsonnet # used in openebs monitoring 63 | └── prometheus-rules.libsonnet # to create prometheusRules object 64 | ``` -------------------------------------------------------------------------------- /contribute/images/openebs-monitoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openebs/monitoring/f0867a43571008ac2ecfbe5d2d95e24ea0ada9a2/contribute/images/openebs-monitoring.png -------------------------------------------------------------------------------- /contribute/release.md: -------------------------------------------------------------------------------- 1 | ## How to generate dashboards and alert rules for monitoring helm chart 2 | 3 | To generate dashboards and alert rules for monitoring helm chart and release a new version of helm chart. 4 | 5 | ## Step by Step Process 6 | 1. Add [dashboards](dashboards.md) and [alerts rules](alerts.md) in openebs-mixin by following the documented steps. 7 | 8 | 2. Update the dashboards and rules folder in [build.sh](../jsonnet/openebs-mixin/build.sh). The auto generated json files will be inside this folder. 9 | 10 | For example: If you add dashboards and alert rules for Mayastor in openebs-mixin, then add mayastor as a folder name in build.sh file. 11 | ``` 12 | generateDashboards(){ 13 | . . . 14 | dashboardsFolder=(npd lvmLocalPV zfsLocalPV mayastor) 15 | . . . 16 | } 17 | 18 | generateRules(){ 19 | . . . 20 | rulesFolder=(npd lvmLocalPV zfsLocalPV mayastor) 21 | . . . 22 | } 23 | ``` 24 | 3. Run `make generate` to generate the dashboards and alert rules for the monitoring helm chart. 25 | ``` 26 | $ cd jsonnet/openebs-mixin 27 | $ make generate 28 | ``` 29 | 30 | 4. Update [helm configurations](../deploy/charts/values.yaml). 31 | 32 | For example: Add mayastor configuration in values.yaml with the following fields. 33 | ``` 34 | . . . 35 | openebsMonitoringAddon: 36 | mayastor: 37 | enabled: true 38 | dashboards: 39 | enabled: true 40 | alertRules: 41 | enabled: true 42 | . . . 43 | ``` 44 | 45 | 5. Update chart version in [chart.yaml](../deploy/charts/Chart.yaml) 46 | ``` 47 | . . . 48 | version: 0.4.x 49 | . . . 50 | ``` 51 | 52 | --- 53 | **NOTE** 54 | 55 | - To upgrade the depdendencies like kube-prometheus, do `jb update`. 56 | ``` 57 | cd jsonnet 58 | jb update 59 | ``` 60 | 61 | - To upgrade the dependencies like kube-prometheus-stack in helm chart, update its version in [chart.yaml](../deploy/charts/Chart.yaml) 62 | ``` 63 | . . . 64 | dependencies: 65 | - name: kube-prometheus-stack 66 | version: "16.5.*" 67 | . . . 68 | ``` 69 | -------------------------------------------------------------------------------- /contribute/service-monitor.md: -------------------------------------------------------------------------------- 1 | ## How to add new serviceMonitor for a CAS type. 2 | To add serviceMonitor, you only need to add configuration in [config.libsonnet](jsonnet/../../jsonnet/config.libsonnet). 3 | 4 | Example: 5 | - To add serviceMonitor for mayastor: 6 | ``` 7 | . . . 8 | _config+:: { 9 | . . . 10 | // Configuration for different cas types. 11 | openebsMonitoringAddon: { 12 | mayastor: { 13 | serviceMonitor: serviceMonitor(, , ) { 14 | enabled: true, 15 | endpoints+: { 16 | . . . 17 | } 18 | } 19 | } 20 | } 21 | } 22 | . . . 23 | ``` -------------------------------------------------------------------------------- /ct.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/helm/chart-testing#configuration 2 | remote: origin 3 | target-branch: develop 4 | chart-dirs: 5 | - deploy 6 | chart-repos: 7 | - kube-prometheus-stack=https://prometheus-community.github.io/helm-charts 8 | - node-problem-detector=https://charts.deliveryhero.io/ 9 | - localpv-provisioner=https://openebs.github.io/dynamic-localpv-provisioner 10 | helm-extra-args: --timeout=500s 11 | validate-maintainers: false 12 | -------------------------------------------------------------------------------- /deploy/charts/.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 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deploy/charts/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: monitoring 3 | description: A Helm chart for monitoring OpenEBS 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | sources: 16 | - https://github.com/openebs/monitoring 17 | 18 | keywords: 19 | - openebs 20 | - monitoring 21 | 22 | # This is the chart version. This version number should be incremented each time you make changes 23 | # to the chart and its templates, including the app version. 24 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 25 | version: 4.0.1 26 | 27 | # This is the version number of the application being deployed. This version number should be 28 | # incremented each time you make changes to the application. Versions are not expected to 29 | # follow Semantic Versioning. They should reflect the version the application is using. 30 | appVersion: 4.0.1 31 | 32 | dependencies: 33 | - name: kube-prometheus-stack 34 | version: "61.0.*" 35 | repository: https://prometheus-community.github.io/helm-charts 36 | condition: kube-prometheus-stack.install 37 | - name: node-problem-detector 38 | version: "2.0.*" 39 | repository: https://charts.deliveryhero.io/ 40 | condition: node-problem-detector.install 41 | - name: localpv-provisioner 42 | version: 4.1.0 43 | repository: https://openebs.github.io/dynamic-localpv-provisioner 44 | condition: localpv-provisioner.enabled 45 | -------------------------------------------------------------------------------- /deploy/charts/README.md: -------------------------------------------------------------------------------- 1 | # monitoring 2 | 3 | ![Version: 4.0.1](https://img.shields.io/badge/Version-4.0.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.0.1](https://img.shields.io/badge/AppVersion-4.0.1-informational?style=flat-square) 4 | 5 | A Helm chart for monitoring OpenEBS 6 | 7 | ## Source Code 8 | 9 | * 10 | 11 | ## Requirements 12 | 13 | | Repository | Name | Version | 14 | |------------|------|---------| 15 | | https://charts.deliveryhero.io/ | node-problem-detector | 2.0.* | 16 | | https://openebs.github.io/dynamic-localpv-provisioner | localpv-provisioner | 4.1.0 | 17 | | https://prometheus-community.github.io/helm-charts | kube-prometheus-stack | 61.0.* | 18 | 19 | ## Values 20 | 21 | | Key | Type | Default | Description | 22 | |-----|------|---------|-------------| 23 | | fullnameOverride | string | `""` | | 24 | | kube-prometheus-stack.alertmanager.alertmanagerSpec.replicas | int | `1` | | 25 | | kube-prometheus-stack.alertmanager.alertmanagerSpec.storage | object | `{}` | | 26 | | kube-prometheus-stack.alertmanager.config.global.resolve_timeout | string | `"5m"` | | 27 | | kube-prometheus-stack.alertmanager.config.receivers[0].name | string | `"null"` | | 28 | | kube-prometheus-stack.alertmanager.config.route.group_by[0] | string | `"alertname"` | | 29 | | kube-prometheus-stack.alertmanager.config.route.group_by[1] | string | `"job"` | | 30 | | kube-prometheus-stack.alertmanager.config.route.group_by[2] | string | `"volName"` | | 31 | | kube-prometheus-stack.alertmanager.config.route.group_interval | string | `"5m"` | | 32 | | kube-prometheus-stack.alertmanager.config.route.group_wait | string | `"30s"` | | 33 | | kube-prometheus-stack.alertmanager.config.route.receiver | string | `"null"` | | 34 | | kube-prometheus-stack.alertmanager.config.route.repeat_interval | string | `"4h"` | | 35 | | kube-prometheus-stack.alertmanager.config.route.routes[0].matchers[0] | string | `"product=\"openebs\""` | | 36 | | kube-prometheus-stack.alertmanager.config.route.routes[0].receiver | string | `"null"` | | 37 | | kube-prometheus-stack.alertmanager.config.templates[0] | string | `"/etc/alertmanager/config/*.tmpl"` | | 38 | | kube-prometheus-stack.alertmanager.enabled | bool | `true` | | 39 | | kube-prometheus-stack.alertmanager.service.nodePort | int | `30903` | | 40 | | kube-prometheus-stack.alertmanager.service.type | string | `"NodePort"` | | 41 | | kube-prometheus-stack.global.rbac.pspEnabled | bool | `false` | | 42 | | kube-prometheus-stack.grafana."grafana.ini".panels.disable_sanitize_html | bool | `true` | | 43 | | kube-prometheus-stack.grafana.adminPassword | string | `"admin"` | | 44 | | kube-prometheus-stack.grafana.defaultDashboardsEnabled | bool | `true` | | 45 | | kube-prometheus-stack.grafana.enabled | bool | `true` | | 46 | | kube-prometheus-stack.grafana.persistence.accessModes[0] | string | `"ReadWriteOnce"` | | 47 | | kube-prometheus-stack.grafana.persistence.enabled | bool | `true` | | 48 | | kube-prometheus-stack.grafana.persistence.size | string | `"1Gi"` | | 49 | | kube-prometheus-stack.grafana.persistence.storageClassName | string | `"openebs-hostpath"` | | 50 | | kube-prometheus-stack.grafana.plugins[0] | string | `"grafana-polystat-panel"` | | 51 | | kube-prometheus-stack.grafana.plugins[1] | string | `"snuids-trafficlights-panel"` | | 52 | | kube-prometheus-stack.grafana.rbac.pspEnabled | bool | `false` | | 53 | | kube-prometheus-stack.grafana.service.nodePort | int | `32515` | | 54 | | kube-prometheus-stack.grafana.service.type | string | `"NodePort"` | | 55 | | kube-prometheus-stack.grafana.sidecar.dashboards.enabled | bool | `true` | | 56 | | kube-prometheus-stack.grafana.sidecar.dashboards.label | string | `"grafana_dashboard"` | | 57 | | kube-prometheus-stack.install | bool | `true` | | 58 | | kube-prometheus-stack.kube-state-metrics.podSecurityPolicy.enabled | bool | `false` | | 59 | | kube-prometheus-stack.prometheus-node-exporter.extraArgs[0] | string | `"--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+)($|/)"` | | 60 | | kube-prometheus-stack.prometheus-node-exporter.extraArgs[1] | string | `"--collector.filesystem.fs-types-exclude=^(tmpfs|autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$"` | | 61 | | kube-prometheus-stack.prometheus-node-exporter.extraArgs[2] | string | `"--collector.diskstats.device-exclude=^(ram|loop|fd|sr|(h|s|v|xv)d[a-z]+|nvme\\d+n\\d+p|nvme\\d+c\\d+n)\\d+$"` | | 62 | | kube-prometheus-stack.prometheus-node-exporter.rbac.pspEnabled | bool | `false` | | 63 | | kube-prometheus-stack.prometheus-node-exporter.securityContext.fsGroup | int | `65534` | | 64 | | kube-prometheus-stack.prometheus-node-exporter.securityContext.runAsGroup | int | `0` | | 65 | | kube-prometheus-stack.prometheus-node-exporter.securityContext.runAsNonRoot | bool | `false` | | 66 | | kube-prometheus-stack.prometheus-node-exporter.securityContext.runAsUser | int | `0` | | 67 | | kube-prometheus-stack.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues | bool | `false` | | 68 | | kube-prometheus-stack.prometheus.prometheusSpec.replicas | int | `1` | | 69 | | kube-prometheus-stack.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues | bool | `false` | | 70 | | kube-prometheus-stack.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues | bool | `false` | | 71 | | kube-prometheus-stack.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.metadata.name | string | `"openebs-prometheus-pv"` | | 72 | | kube-prometheus-stack.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.accessModes[0] | string | `"ReadWriteOnce"` | | 73 | | kube-prometheus-stack.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage | string | `"1Gi"` | | 74 | | kube-prometheus-stack.prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName | string | `"openebs-hostpath"` | | 75 | | kube-prometheus-stack.prometheus.service.nodePort | int | `32514` | | 76 | | kube-prometheus-stack.prometheus.service.type | string | `"NodePort"` | | 77 | | kube-prometheus-stack.prometheusOperator.enabled | bool | `true` | | 78 | | localpv-provisioner.analytics.enabled | bool | `true` | | 79 | | localpv-provisioner.enabled | bool | `true` | | 80 | | localpv-provisioner.hostpathClass.enabled | bool | `true` | Enable default hostpath localpv StorageClass. | 81 | | localpv-provisioner.hostpathClass.name | string | `"openebs-hostpath"` | | 82 | | nameOverride | string | `""` | | 83 | | namespaceOverride | string | `""` | | 84 | | node-problem-detector.extraVolumeMounts[0].mountPath | string | `"/dev/kmsg"` | | 85 | | node-problem-detector.extraVolumeMounts[0].name | string | `"kmsg"` | | 86 | | node-problem-detector.extraVolumeMounts[0].readOnly | bool | `true` | | 87 | | node-problem-detector.extraVolumes[0].hostPath.path | string | `"/dev/kmsg"` | | 88 | | node-problem-detector.extraVolumes[0].name | string | `"kmsg"` | | 89 | | node-problem-detector.install | bool | `false` | | 90 | | node-problem-detector.metrics.serviceMonitor.enabled | bool | `true` | | 91 | | openebsMonitoringAddon.lvmLocalPV.alertRules.enabled | bool | `true` | | 92 | | openebsMonitoringAddon.lvmLocalPV.dashboards.enabled | bool | `true` | | 93 | | openebsMonitoringAddon.lvmLocalPV.enabled | bool | `true` | | 94 | | openebsMonitoringAddon.lvmLocalPV.serviceMonitor.enabled | bool | `true` | | 95 | | openebsMonitoringAddon.lvmLocalPV.serviceMonitor.endpoints.path | string | `"/metrics"` | | 96 | | openebsMonitoringAddon.lvmLocalPV.serviceMonitor.endpoints.port | string | `"metrics"` | | 97 | | openebsMonitoringAddon.lvmLocalPV.serviceMonitor.namespaceSelector.any | bool | `true` | | 98 | | openebsMonitoringAddon.lvmLocalPV.serviceMonitor.selector.matchLabels.name | string | `"openebs-lvm-node"` | | 99 | | openebsMonitoringAddon.mayastor.dashboards.enabled | bool | `true` | | 100 | | openebsMonitoringAddon.mayastor.enabled | bool | `true` | | 101 | | openebsMonitoringAddon.mayastor.serviceMonitor.enabled | bool | `true` | | 102 | | openebsMonitoringAddon.mayastor.serviceMonitor.endpoints.path | string | `"/metrics"` | | 103 | | openebsMonitoringAddon.mayastor.serviceMonitor.endpoints.port | string | `"metrics"` | | 104 | | openebsMonitoringAddon.mayastor.serviceMonitor.namespaceSelector.any | bool | `true` | | 105 | | openebsMonitoringAddon.mayastor.serviceMonitor.selector.matchLabels.app | string | `"metrics-exporter-io-engine"` | | 106 | | openebsMonitoringAddon.npd.alertRules.enabled | bool | `false` | | 107 | | openebsMonitoringAddon.npd.dashboards.enabled | bool | `false` | | 108 | | openebsMonitoringAddon.npd.enabled | bool | `false` | | 109 | | openebsMonitoringAddon.volume.alertRules.enabled | bool | `true` | | 110 | | openebsMonitoringAddon.volume.enabled | bool | `true` | | 111 | | openebsMonitoringAddon.zfsLocalPV.dashboards.enabled | bool | `true` | | 112 | | openebsMonitoringAddon.zfsLocalPV.enabled | bool | `true` | | 113 | 114 | ---------------------------------------------- 115 | Autogenerated from chart metadata using [helm-docs vv1.11.0](https://github.com/norwoodj/helm-docs/releases/vv1.11.0) 116 | -------------------------------------------------------------------------------- /deploy/charts/dashboards/mayastor/mayastor-volume-replica.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": true, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "id": 43, 22 | "links": [ ], 23 | "panels": [ 24 | { 25 | "datasource": { 26 | "type": "prometheus", 27 | "uid": "$datasource" 28 | }, 29 | "fieldConfig": { 30 | "defaults": { 31 | "color": { 32 | "mode": "palette-classic" 33 | }, 34 | "custom": { 35 | "axisBorderShow": false, 36 | "axisCenteredZero": false, 37 | "axisColorMode": "text", 38 | "axisLabel": "", 39 | "axisPlacement": "auto", 40 | "barAlignment": 0, 41 | "drawStyle": "line", 42 | "fillOpacity": 10, 43 | "gradientMode": "none", 44 | "hideFrom": { 45 | "legend": false, 46 | "tooltip": false, 47 | "viz": false 48 | }, 49 | "insertNulls": false, 50 | "lineInterpolation": "linear", 51 | "lineStyle": { 52 | "fill": "solid" 53 | }, 54 | "lineWidth": 1, 55 | "pointSize": 5, 56 | "scaleDistribution": { 57 | "type": "linear" 58 | }, 59 | "showPoints": "never", 60 | "spanNulls": false, 61 | "stacking": { 62 | "group": "A", 63 | "mode": "none" 64 | }, 65 | "thresholdsStyle": { 66 | "mode": "off" 67 | } 68 | }, 69 | "mappings": [ ], 70 | "thresholds": { 71 | "mode": "absolute", 72 | "steps": [ 73 | { 74 | "color": "green", 75 | "value": null 76 | } 77 | ] 78 | }, 79 | "unit": "iops" 80 | }, 81 | "overrides": [ ] 82 | }, 83 | "gridPos": { 84 | "h": 8, 85 | "w": 12, 86 | "x": 0, 87 | "y": 0 88 | }, 89 | "id": 1, 90 | "options": { 91 | "legend": { 92 | "calcs": [ ], 93 | "displayMode": "list", 94 | "placement": "bottom", 95 | "showLegend": true 96 | }, 97 | "tooltip": { 98 | "mode": "multi", 99 | "sort": "none" 100 | } 101 | }, 102 | "pluginVersion": "10.4.0", 103 | "targets": [ 104 | { 105 | "datasource": { 106 | "uid": "$datasource" 107 | }, 108 | "editorMode": "code", 109 | "exemplar": false, 110 | "expr": "irate(replica_num_read_ops{name=~\"$replica_name\"}[1m])", 111 | "interval": "", 112 | "legendFormat": "read", 113 | "range": true, 114 | "refId": "A" 115 | }, 116 | { 117 | "datasource": { 118 | "type": "prometheus", 119 | "uid": "$datasource" 120 | }, 121 | "editorMode": "code", 122 | "expr": "irate(replica_num_write_ops{name=~\"$replica_name\"}[1m])", 123 | "format": "time_series", 124 | "hide": false, 125 | "instant": false, 126 | "interval": "", 127 | "legendFormat": "write", 128 | "range": true, 129 | "refId": "B" 130 | } 131 | ], 132 | "title": "IOPS", 133 | "type": "timeseries" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "prometheus", 138 | "uid": "$datasource" 139 | }, 140 | "fieldConfig": { 141 | "defaults": { 142 | "color": { 143 | "mode": "palette-classic" 144 | }, 145 | "custom": { 146 | "axisBorderShow": false, 147 | "axisCenteredZero": false, 148 | "axisColorMode": "text", 149 | "axisLabel": "", 150 | "axisPlacement": "auto", 151 | "barAlignment": 0, 152 | "drawStyle": "line", 153 | "fillOpacity": 10, 154 | "gradientMode": "none", 155 | "hideFrom": { 156 | "legend": false, 157 | "tooltip": false, 158 | "viz": false 159 | }, 160 | "insertNulls": false, 161 | "lineInterpolation": "linear", 162 | "lineStyle": { 163 | "fill": "solid" 164 | }, 165 | "lineWidth": 1, 166 | "pointSize": 5, 167 | "scaleDistribution": { 168 | "type": "linear" 169 | }, 170 | "showPoints": "never", 171 | "spanNulls": false, 172 | "stacking": { 173 | "group": "A", 174 | "mode": "none" 175 | }, 176 | "thresholdsStyle": { 177 | "mode": "off" 178 | } 179 | }, 180 | "mappings": [ ], 181 | "thresholds": { 182 | "mode": "absolute", 183 | "steps": [ 184 | { 185 | "color": "green", 186 | "value": null 187 | } 188 | ] 189 | }, 190 | "unit": "binBps" 191 | }, 192 | "overrides": [ ] 193 | }, 194 | "gridPos": { 195 | "h": 8, 196 | "w": 12, 197 | "x": 12, 198 | "y": 0 199 | }, 200 | "id": 2, 201 | "options": { 202 | "legend": { 203 | "calcs": [ ], 204 | "displayMode": "list", 205 | "placement": "bottom", 206 | "showLegend": true 207 | }, 208 | "tooltip": { 209 | "mode": "multi", 210 | "sort": "none" 211 | } 212 | }, 213 | "pluginVersion": "10.4.0", 214 | "targets": [ 215 | { 216 | "datasource": { 217 | "uid": "$datasource" 218 | }, 219 | "editorMode": "code", 220 | "exemplar": true, 221 | "expr": "irate(replica_bytes_read{name=~\"$replica_name\"}[1m])", 222 | "interval": "", 223 | "legendFormat": "read", 224 | "range": true, 225 | "refId": "A" 226 | }, 227 | { 228 | "datasource": { 229 | "type": "prometheus", 230 | "uid": "$datasource" 231 | }, 232 | "editorMode": "code", 233 | "expr": "irate(replica_bytes_written{name=~\"$replica_name\"}[1m])", 234 | "hide": false, 235 | "instant": false, 236 | "legendFormat": "write", 237 | "range": true, 238 | "refId": "B" 239 | } 240 | ], 241 | "title": "Throughput", 242 | "type": "timeseries" 243 | }, 244 | { 245 | "datasource": { 246 | "type": "prometheus", 247 | "uid": "$datasource" 248 | }, 249 | "fieldConfig": { 250 | "defaults": { 251 | "color": { 252 | "mode": "palette-classic" 253 | }, 254 | "custom": { 255 | "axisBorderShow": false, 256 | "axisCenteredZero": false, 257 | "axisColorMode": "text", 258 | "axisLabel": "", 259 | "axisPlacement": "auto", 260 | "barAlignment": 0, 261 | "drawStyle": "line", 262 | "fillOpacity": 10, 263 | "gradientMode": "none", 264 | "hideFrom": { 265 | "legend": false, 266 | "tooltip": false, 267 | "viz": false 268 | }, 269 | "insertNulls": false, 270 | "lineInterpolation": "linear", 271 | "lineStyle": { 272 | "fill": "solid" 273 | }, 274 | "lineWidth": 1, 275 | "pointSize": 5, 276 | "scaleDistribution": { 277 | "type": "linear" 278 | }, 279 | "showPoints": "never", 280 | "spanNulls": false, 281 | "stacking": { 282 | "group": "A", 283 | "mode": "none" 284 | }, 285 | "thresholdsStyle": { 286 | "mode": "off" 287 | } 288 | }, 289 | "mappings": [ ], 290 | "thresholds": { 291 | "mode": "absolute", 292 | "steps": [ 293 | { 294 | "color": "green", 295 | "value": null 296 | } 297 | ] 298 | }, 299 | "unit": "s" 300 | }, 301 | "overrides": [ ] 302 | }, 303 | "gridPos": { 304 | "h": 8, 305 | "w": 12, 306 | "x": 6, 307 | "y": 8 308 | }, 309 | "id": 3, 310 | "options": { 311 | "legend": { 312 | "calcs": [ ], 313 | "displayMode": "list", 314 | "placement": "bottom", 315 | "showLegend": true 316 | }, 317 | "tooltip": { 318 | "mode": "multi", 319 | "sort": "none" 320 | } 321 | }, 322 | "pluginVersion": "10.4.0", 323 | "targets": [ 324 | { 325 | "datasource": { 326 | "uid": "$datasource" 327 | }, 328 | "editorMode": "code", 329 | "exemplar": true, 330 | "expr": "((irate(replica_read_latency_us{name=~\"$replica_name\"}[1m]))/(irate(replica_num_read_ops{name=~\"$replica_name\"}[1m])))/1000000", 331 | "interval": "", 332 | "legendFormat": "read", 333 | "range": true, 334 | "refId": "A" 335 | }, 336 | { 337 | "datasource": { 338 | "type": "prometheus", 339 | "uid": "$datasource" 340 | }, 341 | "editorMode": "code", 342 | "expr": "((irate(replica_write_latency_us{name=~\"$replica_name\"}[1m]))/(irate(replica_num_write_ops{name=~\"$replica_name\"}[1m])))/1000000", 343 | "hide": false, 344 | "instant": false, 345 | "legendFormat": "write", 346 | "range": true, 347 | "refId": "B" 348 | } 349 | ], 350 | "title": "Latency", 351 | "type": "timeseries" 352 | } 353 | ], 354 | "refresh": "5s", 355 | "schemaVersion": 39, 356 | "tags": [ 357 | "OpenEBS", 358 | "Mayastor" 359 | ], 360 | "templating": { 361 | "list": [ 362 | { 363 | "current": { 364 | "selected": false, 365 | "text": "Prometheus", 366 | "value": "prometheus" 367 | }, 368 | "hide": 0, 369 | "includeAll": false, 370 | "multi": false, 371 | "name": "datasource", 372 | "options": [ ], 373 | "query": "prometheus", 374 | "refresh": 1, 375 | "regex": "", 376 | "skipUrlSync": false, 377 | "type": "datasource" 378 | }, 379 | { 380 | "current": { 381 | "selected": true, 382 | "text": [ 383 | "All" 384 | ], 385 | "value": [ 386 | "$__all" 387 | ] 388 | }, 389 | "datasource": { 390 | "type": "prometheus", 391 | "uid": "${datasource}" 392 | }, 393 | "definition": "label_values(replica_num_read_ops,name)", 394 | "hide": 0, 395 | "includeAll": true, 396 | "multi": true, 397 | "name": "replica_name", 398 | "options": [ ], 399 | "query": { 400 | "qryType": 1, 401 | "query": "label_values(replica_num_read_ops,name)", 402 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 403 | }, 404 | "refresh": 2, 405 | "regex": "", 406 | "skipUrlSync": false, 407 | "sort": 0, 408 | "type": "query" 409 | } 410 | ] 411 | }, 412 | "time": { 413 | "from": "now-1h", 414 | "to": "now" 415 | }, 416 | "timepicker": { }, 417 | "timezone": "browser", 418 | "title": "OpenEBS / Replicated PV / Mayastor / Volume Replica", 419 | "uid": "fdl05xto1hn28e", 420 | "version": 6, 421 | "weekStart": "" 422 | } 423 | -------------------------------------------------------------------------------- /deploy/charts/dashboards/mayastor/mayastor-volume.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": true, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "id": 42, 22 | "links": [ ], 23 | "panels": [ 24 | { 25 | "datasource": { 26 | "type": "prometheus", 27 | "uid": "$datasource" 28 | }, 29 | "fieldConfig": { 30 | "defaults": { 31 | "color": { 32 | "mode": "palette-classic" 33 | }, 34 | "custom": { 35 | "axisBorderShow": false, 36 | "axisCenteredZero": false, 37 | "axisColorMode": "text", 38 | "axisLabel": "", 39 | "axisPlacement": "auto", 40 | "barAlignment": 0, 41 | "drawStyle": "line", 42 | "fillOpacity": 10, 43 | "gradientMode": "none", 44 | "hideFrom": { 45 | "legend": false, 46 | "tooltip": false, 47 | "viz": false 48 | }, 49 | "insertNulls": false, 50 | "lineInterpolation": "linear", 51 | "lineStyle": { 52 | "fill": "solid" 53 | }, 54 | "lineWidth": 1, 55 | "pointSize": 5, 56 | "scaleDistribution": { 57 | "type": "linear" 58 | }, 59 | "showPoints": "never", 60 | "spanNulls": false, 61 | "stacking": { 62 | "group": "A", 63 | "mode": "none" 64 | }, 65 | "thresholdsStyle": { 66 | "mode": "off" 67 | } 68 | }, 69 | "mappings": [ ], 70 | "thresholds": { 71 | "mode": "absolute", 72 | "steps": [ 73 | { 74 | "color": "green", 75 | "value": null 76 | } 77 | ] 78 | }, 79 | "unit": "iops" 80 | }, 81 | "overrides": [ ] 82 | }, 83 | "gridPos": { 84 | "h": 8, 85 | "w": 12, 86 | "x": 0, 87 | "y": 0 88 | }, 89 | "id": 1, 90 | "options": { 91 | "legend": { 92 | "calcs": [ ], 93 | "displayMode": "list", 94 | "placement": "bottom", 95 | "showLegend": true 96 | }, 97 | "tooltip": { 98 | "mode": "multi", 99 | "sort": "none" 100 | } 101 | }, 102 | "pluginVersion": "10.4.0", 103 | "targets": [ 104 | { 105 | "datasource": { 106 | "uid": "$datasource" 107 | }, 108 | "editorMode": "code", 109 | "exemplar": false, 110 | "expr": "irate(volume_num_read_ops{pv_name=~\"$pv_name\"}[1m])", 111 | "interval": "", 112 | "legendFormat": "read", 113 | "range": true, 114 | "refId": "A" 115 | }, 116 | { 117 | "datasource": { 118 | "type": "prometheus", 119 | "uid": "$datasource" 120 | }, 121 | "editorMode": "code", 122 | "expr": "irate(volume_num_write_ops{pv_name=~\"$pv_name\"}[1m])", 123 | "format": "time_series", 124 | "hide": false, 125 | "instant": false, 126 | "interval": "", 127 | "legendFormat": "write", 128 | "range": true, 129 | "refId": "B" 130 | } 131 | ], 132 | "title": "IOPS", 133 | "type": "timeseries" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "prometheus", 138 | "uid": "$datasource" 139 | }, 140 | "fieldConfig": { 141 | "defaults": { 142 | "color": { 143 | "mode": "palette-classic" 144 | }, 145 | "custom": { 146 | "axisBorderShow": false, 147 | "axisCenteredZero": false, 148 | "axisColorMode": "text", 149 | "axisLabel": "", 150 | "axisPlacement": "auto", 151 | "barAlignment": 0, 152 | "drawStyle": "line", 153 | "fillOpacity": 10, 154 | "gradientMode": "none", 155 | "hideFrom": { 156 | "legend": false, 157 | "tooltip": false, 158 | "viz": false 159 | }, 160 | "insertNulls": false, 161 | "lineInterpolation": "linear", 162 | "lineStyle": { 163 | "fill": "solid" 164 | }, 165 | "lineWidth": 1, 166 | "pointSize": 5, 167 | "scaleDistribution": { 168 | "type": "linear" 169 | }, 170 | "showPoints": "never", 171 | "spanNulls": false, 172 | "stacking": { 173 | "group": "A", 174 | "mode": "none" 175 | }, 176 | "thresholdsStyle": { 177 | "mode": "off" 178 | } 179 | }, 180 | "mappings": [ ], 181 | "thresholds": { 182 | "mode": "absolute", 183 | "steps": [ 184 | { 185 | "color": "green", 186 | "value": null 187 | } 188 | ] 189 | }, 190 | "unit": "binBps" 191 | }, 192 | "overrides": [ ] 193 | }, 194 | "gridPos": { 195 | "h": 8, 196 | "w": 12, 197 | "x": 12, 198 | "y": 0 199 | }, 200 | "id": 2, 201 | "options": { 202 | "legend": { 203 | "calcs": [ ], 204 | "displayMode": "list", 205 | "placement": "bottom", 206 | "showLegend": true 207 | }, 208 | "tooltip": { 209 | "mode": "multi", 210 | "sort": "none" 211 | } 212 | }, 213 | "pluginVersion": "10.4.0", 214 | "targets": [ 215 | { 216 | "datasource": { 217 | "uid": "$datasource" 218 | }, 219 | "editorMode": "code", 220 | "exemplar": true, 221 | "expr": "irate(volume_bytes_read{pv_name=~\"$pv_name\"}[1m])", 222 | "interval": "", 223 | "legendFormat": "read", 224 | "range": true, 225 | "refId": "A" 226 | }, 227 | { 228 | "datasource": { 229 | "type": "prometheus", 230 | "uid": "$datasource" 231 | }, 232 | "editorMode": "code", 233 | "expr": "irate(volume_bytes_written{pv_name=~\"$pv_name\"}[1m])", 234 | "hide": false, 235 | "instant": false, 236 | "legendFormat": "write", 237 | "range": true, 238 | "refId": "B" 239 | } 240 | ], 241 | "title": "Throughput", 242 | "type": "timeseries" 243 | }, 244 | { 245 | "datasource": { 246 | "type": "prometheus", 247 | "uid": "$datasource" 248 | }, 249 | "fieldConfig": { 250 | "defaults": { 251 | "color": { 252 | "mode": "palette-classic" 253 | }, 254 | "custom": { 255 | "axisBorderShow": false, 256 | "axisCenteredZero": false, 257 | "axisColorMode": "text", 258 | "axisLabel": "", 259 | "axisPlacement": "auto", 260 | "barAlignment": 0, 261 | "drawStyle": "line", 262 | "fillOpacity": 10, 263 | "gradientMode": "none", 264 | "hideFrom": { 265 | "legend": false, 266 | "tooltip": false, 267 | "viz": false 268 | }, 269 | "insertNulls": false, 270 | "lineInterpolation": "linear", 271 | "lineStyle": { 272 | "fill": "solid" 273 | }, 274 | "lineWidth": 1, 275 | "pointSize": 5, 276 | "scaleDistribution": { 277 | "type": "linear" 278 | }, 279 | "showPoints": "never", 280 | "spanNulls": false, 281 | "stacking": { 282 | "group": "A", 283 | "mode": "none" 284 | }, 285 | "thresholdsStyle": { 286 | "mode": "off" 287 | } 288 | }, 289 | "mappings": [ ], 290 | "thresholds": { 291 | "mode": "absolute", 292 | "steps": [ 293 | { 294 | "color": "green", 295 | "value": null 296 | } 297 | ] 298 | }, 299 | "unit": "s" 300 | }, 301 | "overrides": [ ] 302 | }, 303 | "gridPos": { 304 | "h": 8, 305 | "w": 12, 306 | "x": 6, 307 | "y": 8 308 | }, 309 | "id": 3, 310 | "options": { 311 | "legend": { 312 | "calcs": [ ], 313 | "displayMode": "list", 314 | "placement": "bottom", 315 | "showLegend": true 316 | }, 317 | "tooltip": { 318 | "mode": "multi", 319 | "sort": "none" 320 | } 321 | }, 322 | "pluginVersion": "10.4.0", 323 | "targets": [ 324 | { 325 | "datasource": { 326 | "uid": "$datasource" 327 | }, 328 | "editorMode": "code", 329 | "exemplar": true, 330 | "expr": "((irate(volume_read_latency_us{pv_name=~\"$pv_name\"}[1m]))/(irate(volume_num_read_ops{pv_name=~\"$pv_name\"}[1m])))/1000000", 331 | "interval": "", 332 | "legendFormat": "read", 333 | "range": true, 334 | "refId": "A" 335 | }, 336 | { 337 | "datasource": { 338 | "type": "prometheus", 339 | "uid": "$datasource" 340 | }, 341 | "editorMode": "code", 342 | "expr": "((irate(volume_write_latency_us{pv_name=~\"$pv_name\"}[1m]))/(irate(volume_num_write_ops{pv_name=~\"$pv_name\"}[1m])))/1000000", 343 | "hide": false, 344 | "instant": false, 345 | "legendFormat": "write", 346 | "range": true, 347 | "refId": "B" 348 | } 349 | ], 350 | "title": "Latency", 351 | "type": "timeseries" 352 | } 353 | ], 354 | "refresh": "5s", 355 | "schemaVersion": 39, 356 | "tags": [ 357 | "OpenEBS", 358 | "Mayastor" 359 | ], 360 | "templating": { 361 | "list": [ 362 | { 363 | "current": { 364 | "selected": false, 365 | "text": "Prometheus", 366 | "value": "prometheus" 367 | }, 368 | "hide": 0, 369 | "includeAll": false, 370 | "multi": false, 371 | "name": "datasource", 372 | "options": [ ], 373 | "query": "prometheus", 374 | "refresh": 1, 375 | "regex": "", 376 | "skipUrlSync": false, 377 | "type": "datasource" 378 | }, 379 | { 380 | "current": { 381 | "selected": true, 382 | "text": [ 383 | "pvc-d070ac1c-6bb7-4ece-9893-5471c0c636a8" 384 | ], 385 | "value": [ 386 | "pvc-d070ac1c-6bb7-4ece-9893-5471c0c636a8" 387 | ] 388 | }, 389 | "datasource": { 390 | "type": "prometheus", 391 | "uid": "${datasource}" 392 | }, 393 | "definition": "label_values(volume_num_read_ops,pv_name)", 394 | "hide": 0, 395 | "includeAll": true, 396 | "multi": true, 397 | "name": "pv_name", 398 | "options": [ ], 399 | "query": { 400 | "qryType": 1, 401 | "query": "label_values(volume_num_read_ops,pv_name)", 402 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 403 | }, 404 | "refresh": 2, 405 | "regex": "", 406 | "skipUrlSync": false, 407 | "sort": 0, 408 | "type": "query" 409 | } 410 | ] 411 | }, 412 | "time": { 413 | "from": "now-1h", 414 | "to": "now" 415 | }, 416 | "timepicker": { }, 417 | "timezone": "browser", 418 | "title": "OpenEBS / Replicated PV / Mayastor / Volume", 419 | "uid": "fdl05gxyisqo0d", 420 | "version": 6, 421 | "weekStart": "" 422 | } 423 | -------------------------------------------------------------------------------- /deploy/charts/rules/lvmLocalPV/lvmlocalpv-rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "lvm-pool", 5 | "rules": [ 6 | { 7 | "alert": "LVMVolumeGroupMissingPhysicalVolume", 8 | "annotations": { 9 | "componentType": "volume group", 10 | "description": "LVM volume group '{{ $labels.name }}' on node '{{ $labels.instance }}' is missing {{ $value }} underlying physical volume(s).", 11 | "summary": "LVM volume group '{{ $labels.name }}' is missing the underlying physical volume.", 12 | "vgName": "{{ $labels.name }}" 13 | }, 14 | "expr": "lvm_vg_missing_pv_count > 0", 15 | "for": "5m", 16 | "labels": { 17 | "engine": "localpv-lvm", 18 | "product": "openebs", 19 | "severity": "critical" 20 | } 21 | }, 22 | { 23 | "alert": "LVMVolumeGroupCapacityLow", 24 | "annotations": { 25 | "componentType": "volume group", 26 | "description": "LVM volume group '{{ $labels.name }}' on node '{{ $labels.instance }}' has {{ with printf \"lvm_vg_free_size_bytes{instance='%s',name='%s'}\" $labels.instance $labels.name | query }} {{ . | first | value }} {{ end }}bytes of space remaining", 27 | "summary": "LVM volume group '{{ $labels.name }}' is running low on capacity. Already {{ $value }}% of total capacity is consumed.", 28 | "vgName": "{{ $labels.name }}" 29 | }, 30 | "expr": "((lvm_vg_total_size_bytes - lvm_vg_free_size_bytes)/lvm_vg_total_size_bytes)*100 > 90", 31 | "for": "5m", 32 | "labels": { 33 | "engine": "localpv-lvm", 34 | "product": "openebs", 35 | "severity": "critical" 36 | } 37 | }, 38 | { 39 | "alert": "LVMThinPoolCapacityLow", 40 | "annotations": { 41 | "componentType": "logical volume", 42 | "description": "LVM thin pool '{{ $labels.name }}' on node '{{ $labels.instance }}' has {{ with printf \"lvm_lv_total_size_bytes{instance='%s',name='%s',segtype='%s'}-((lvm_lv_used_percent{instance='%s',name='%s',segtype='%s'}*lvm_lv_total_size_bytes{instance='%s',name='%s',segtype='%s'})/100)\" $labels.instance $labels.name $labels.segtype $labels.instance $labels.name $labels.segtype $labels.instance $labels.name $labels.segtype | query }} {{ . | first | value }} {{ end }}bytes of space remaining", 43 | "lvName": "{{ $labels.name }}", 44 | "summary": "LVM thin pool '{{ $labels.name }}' is running low on capacity. Already {{ $value }}% of total capacity is consumed." 45 | }, 46 | "expr": "lvm_lv_used_percent{segtype=\"thin-pool\"} > 90", 47 | "for": "5m", 48 | "labels": { 49 | "engine": "localpv-lvm", 50 | "product": "openebs", 51 | "severity": "critical" 52 | } 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /deploy/charts/rules/npd/npd-rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "volume-node", 5 | "rules": [ 6 | { 7 | "alert": "VolumeNodeFileSystemIsReadOnly", 8 | "annotations": { 9 | "description": "Persistent Volume's filesystem on node '{{ $labels.node }}' for persistent volume claim '{{ $labels.persistentvolumeclaim }}' has become read-only", 10 | "summary": "Volume mount failed for persistent volume claim '{{ $labels.persistentvolumeclaim }}' on node '{{ $labels.node }}' due to read-only file-system" 11 | }, 12 | "expr": "kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason=\"FilesystemIsReadOnly\"} > 0", 13 | "for": "5m", 14 | "labels": { 15 | "severity": "critical" 16 | } 17 | }, 18 | { 19 | "alert": "VolumeNodeExt4Error", 20 | "annotations": { 21 | "description": "Persistent Volume's on node '{{ $labels.node }}' persistent volume claim '{{ $labels.persistentvolumeclaim }}' encountering ext4 filesystem error", 22 | "summary": "Node '{{ $labels.node }}' has encountered errors on ext4 file-system on volume having claim '{{ $labels.persistentvolumeclaim }}'" 23 | }, 24 | "expr": "kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason=\"Ext4Error\"} > 0", 25 | "for": "5m", 26 | "labels": { 27 | "severity": "critical" 28 | } 29 | }, 30 | { 31 | "alert": "VolumeNodeIOError", 32 | "annotations": { 33 | "description": "Persistent Volume on node '{{ $labels.node }}' for persistent volume claim '{{ $labels.persistentvolumeclaim }}' encountering errors w.r.t buffer I/O ", 34 | "summary": "IO errors encountered on volume having persistent volume claim '{{ $labels.persistentvolumeclaim }}' on node '{{ $labels.node }}'" 35 | }, 36 | "expr": "kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason=\"IOError\"} > 0", 37 | "for": "5m", 38 | "labels": { 39 | "severity": "critical" 40 | } 41 | }, 42 | { 43 | "alert": "VolumeNodeExt4Warning", 44 | "annotations": { 45 | "description": "Persistent Volume on node '{{ $labels.node }}' receiving ext4 filesystem warning for persistent volume claim '{{ $labels.persistentvolumeclaim }}'", 46 | "summary": "Node '{{ $labels.node }}' has encountered warning on ext4 file-system on volume having claim '{{ $labels.persistentvolumeclaim }}'" 47 | }, 48 | "expr": "kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason=\"Ext4Warning\"} > 0", 49 | "for": "5m", 50 | "labels": { 51 | "severity": "critical" 52 | } 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /deploy/charts/rules/volume/volume-rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "persistent-volume-claim", 5 | "rules": [ 6 | { 7 | "alert": "StalePersistentVolumeClaim", 8 | "annotations": { 9 | "description": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has no consumer", 10 | "summary": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' in namespace '{{ $labels.namespace }}' is not consumed by any pod in any namespace" 11 | }, 12 | "expr": "kube_persistentvolumeclaim_info unless (kube_persistentvolumeclaim_info * on(persistentvolumeclaim) group_left (max by (persistentvolumeclaim) (kube_pod_spec_volumes_persistentvolumeclaims_info)))) == 1", 13 | "for": "5m", 14 | "labels": { 15 | "severity": "info" 16 | } 17 | }, 18 | { 19 | "alert": "PendingPersistentVolumeClaim", 20 | "annotations": { 21 | "description": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has been in pending state for more than 5 minutes", 22 | "summary": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' pending in namespace '{{ $labels.namespace }}'" 23 | }, 24 | "expr": "kube_persistentvolumeclaim_status_phase{phase=\"Pending\"} == 1", 25 | "for": "5m", 26 | "labels": { 27 | "severity": "warning" 28 | } 29 | }, 30 | { 31 | "alert": "LostPersistentVolumeClaim", 32 | "annotations": { 33 | "description": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has been in lost state for more than 5 minutes", 34 | "summary": "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' in namespace '{{ $labels.namespace }}' lost it's corresponding persistent volume" 35 | }, 36 | "expr": "kube_persistentvolumeclaim_status_phase{phase=\"Lost\"} == 1", 37 | "for": "5m", 38 | "labels": { 39 | "severity": "warning" 40 | } 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /deploy/charts/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | OpenEBS monitoring has been installed. 2 | Check its status by running: 3 | $ kubectl get pods -n {{ .Release.Namespace }} -o wide 4 | 5 | Use `kubectl get svc -n {{ .Release.Namespace }}` to list all the 6 | services in the `{{ .Release.Namespace }}` namespace. 7 | 8 | To access the dashboards, form the Grafana URL and open it in the browser 9 | {{- if (index $.Values "kube-prometheus-stack" "install") }} 10 | {{- if (index $.Values "kube-prometheus-stack" "grafana" "ingress" "enabled") }} 11 | {{- range $host := (index $.Values "kube-prometheus-stack" "grafana" "ingress" "hosts") }} 12 | http{{ if (index $.Values "kube-prometheus-stack" "grafana" "ingress" "tls") }}s{{ end }}://{{ $host }}{{ regexReplaceAll "\\(.*\\)" (index $.Values "kube-prometheus-stack" "grafana" "ingress" "path") "" }} 13 | {{- end }} 14 | {{- else if contains "NodePort" (index $.Values "kube-prometheus-stack" "grafana" "service" "type") }} 15 | export NODE_PORT={{ index $.Values "kube-prometheus-stack" "grafana" "service" "nodePort" }} 16 | export NODE_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "call-nested" (list . "kube-prometheus-stack.grafana" "grafana.name") }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].spec.nodeName}") 17 | export NODE_IP=$(kubectl get node $NODE_NAME -o jsonpath='{$.status.addresses[?(@.type=="ExternalIP")].address}') 18 | echo http://$NODE_IP:$NODE_PORT 19 | NOTE: The above IP should be a public IP 20 | echo 21 | Or you could use a port-forward to forward to 8080 22 | export SVC_NAME=$(kubectl -n {{ .Release.Namespace }} get svc -l "app.kubernetes.io/name={{ include "call-nested" (list . "kube-prometheus-stack.grafana" "grafana.name") }},app.kubernetes.io/instance={{ .Release.Name }}" -o name) 23 | kubectl --namespace {{ .Release.Namespace }} port-forward $SVC_NAME 8080:80 24 | echo "Visit http://127.0.0.1:8080" 25 | 26 | {{- else if contains "ClusterIP" (index $.Values "kube-prometheus-stack" "grafana" "service" "type") }} 27 | export PORT= {{ index $.Values "kube-prometheus-stack" "grafana" "service" "port" }} 28 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "call-nested" (list . "kube-prometheus-stack.grafana" "grafana.name") }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 29 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 32515:$PORT 30 | echo "Visit http://127.0.0.1:32515" 31 | {{- end }} 32 | {{- end }} 33 | 34 | For more information, visit our Slack at https://openebs.io/community 35 | -------------------------------------------------------------------------------- /deploy/charts/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "monitoring.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 50 | 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 "monitoring.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 26 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Allow the release namespace to be overridden for multi-namespace deployments in combined charts 29 | */}} 30 | {{- define "monitoring.namespace" -}} 31 | {{- if .Values.namespaceOverride -}} 32 | {{- .Values.namespaceOverride -}} 33 | {{- else -}} 34 | {{- .Release.Namespace -}} 35 | {{- end -}} 36 | {{- end -}} 37 | 38 | 39 | {{/* 40 | Create chart name and version as used by the chart label. 41 | */}} 42 | {{- define "monitoring.chart" -}} 43 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 44 | {{- end }} 45 | 46 | {{/* 47 | Common labels 48 | */}} 49 | {{- define "monitoring.labels" -}} 50 | helm.sh/chart: {{ include "monitoring.chart" . }} 51 | {{ include "monitoring.selectorLabels" . }} 52 | {{- if .Chart.AppVersion }} 53 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 54 | {{- end }} 55 | app.kubernetes.io/managed-by: {{ .Release.Service }} 56 | {{- end }} 57 | 58 | {{/* 59 | Selector labels 60 | */}} 61 | {{- define "monitoring.selectorLabels" -}} 62 | app.kubernetes.io/name: {{ include "monitoring.name" . }} 63 | app.kubernetes.io/instance: {{ .Release.Name }} 64 | release: {{ $.Release.Name | quote }} 65 | {{- end }} 66 | 67 | {{/* 68 | Template to support multiple levels of sub-charts 69 | 70 | Call a template from the context of a subchart. 71 | 72 | Usage: 73 | {{ include "call-nested" (list . "" "") }} 74 | */}} 75 | {{- define "call-nested" }} 76 | {{- $dot := index . 0 }} 77 | {{- $subchart := index . 1 | splitList "." }} 78 | {{- $template := index . 2 }} 79 | {{- $values := $dot.Values }} 80 | {{- range $subchart }} 81 | {{- $values = index $values . }} 82 | {{- end }} 83 | {{- if $values.enabled }} 84 | {{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }} 85 | {{- end }} 86 | {{- end }} 87 | 88 | -------------------------------------------------------------------------------- /deploy/charts/templates/dashboards-json-configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $grafanaSidecarDashboardsLabel := index .Values "kube-prometheus-stack" "grafana" "sidecar" "dashboards" "label" }} 2 | {{- $dashboards := dict -}} 3 | {{- range $monitoringAddon,$fields := .Values.openebsMonitoringAddon }} 4 | {{- if (and (hasKey $fields "enabled") ($fields.enabled)) }} 5 | {{- if (hasKey $fields "dashboards") }} 6 | {{- if ($fields.dashboards.enabled) }} 7 | {{ $_ := set $dashboards $monitoringAddon $fields.dashboards.enabled }} 8 | {{- end }} 9 | {{- end }} 10 | {{- end }} 11 | {{- end }} 12 | {{- $files := .Files.Glob "dashboards/**.json" }} 13 | {{- if $files }} 14 | {{- range $fileName, $fileContents := $files }} 15 | {{- $dirName := split "/" $fileName }} 16 | {{- if and (hasKey $dashboards $dirName._1 ) $dashboards }} 17 | {{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $fileName "${2}" }} 18 | apiVersion: v1 19 | kind: ConfigMap 20 | metadata: 21 | name: {{ lower (printf "%s-%s" (include "monitoring.fullname" $) $dashboardName) | trunc 63 | trimSuffix "-" }} 22 | namespace: {{ template "monitoring.namespace" $ }} 23 | labels: 24 | {{ $grafanaSidecarDashboardsLabel }}: "1" 25 | app: {{ template "monitoring.name" $ }}-grafana 26 | {{ include "monitoring.labels" $ | indent 4 }} 27 | data: 28 | {{ $dashboardName }}.json: {{ $.Files.Get $fileName | toPrettyJson }} 29 | --- 30 | {{- end }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /deploy/charts/templates/podmonitors.yaml: -------------------------------------------------------------------------------- 1 | {{ if (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} 2 | {{- range $monitoringAddon, $fields := .Values.openebsMonitoringAddon }} 3 | {{- if (and (hasKey $fields "enabled") ($fields.enabled)) }} 4 | {{- if (hasKey $fields "podMonitor") }} 5 | {{- if ($fields.podMonitor.enabled) }} 6 | apiVersion: monitoring.coreos.com/v1 7 | kind: PodMonitor 8 | metadata: 9 | name: {{ lower (printf "%s-%s" (include "monitoring.fullname" $) $monitoringAddon) | trunc 63 | trimSuffix "-" }} 10 | namespace: {{ template "monitoring.namespace" $ }} 11 | labels: 12 | app: {{ template "monitoring.name" $ }}-{{ $monitoringAddon }} 13 | {{ include "monitoring.labels" $ | indent 4 }} 14 | spec: 15 | selector: 16 | {{ toYaml $fields.podMonitor.selector | indent 4 }} 17 | namespaceSelector: 18 | {{ toYaml $fields.podMonitor.namespaceSelector | indent 4 }} 19 | podMetricsEndpoints: 20 | - targetPort: {{ $fields.podMonitor.podMetricsEndpoints.targetPort }} 21 | path: {{ $fields.podMonitor.podMetricsEndpoints.path }} 22 | {{- if $fields.podMonitor.podMetricsEndpoints.relabelings }} 23 | relabelings: 24 | {{ toYaml $fields.podMonitor.podMetricsEndpoints.relabelings | indent 8 }} 25 | {{- end }} 26 | --- 27 | {{- end }} 28 | {{- end }} 29 | {{- end }} 30 | {{- end }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /deploy/charts/templates/prometheusRules.yaml: -------------------------------------------------------------------------------- 1 | {{ if (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} 2 | {{- $alertRules := dict -}} 3 | {{- range $monitoringAddon,$fields := .Values.openebsMonitoringAddon }} 4 | {{- if (and (hasKey $fields "enabled") ($fields.enabled)) }} 5 | {{- if (hasKey $fields "alertRules") }} 6 | {{- if ($fields.alertRules.enabled) }} 7 | {{ $_ := set $alertRules $monitoringAddon $fields.alertRules.enabled }} 8 | {{- end }} 9 | {{- end }} 10 | {{- end }} 11 | {{- end }} 12 | {{- $files := .Files.Glob "rules/**.json" }} 13 | {{- if $files }} 14 | {{- range $fileName, $fileContents := $files }} 15 | {{- $dirName := split "/" $fileName }} 16 | {{- if and (hasKey $alertRules $dirName._1 ) $alertRules }} 17 | {{- $ruleName := regexReplaceAll "(^.*/)(.*)\\.json$" $fileName "${2}" }} 18 | apiVersion: monitoring.coreos.com/v1 19 | kind: PrometheusRule 20 | metadata: 21 | name: {{ lower (printf "%s-%s" (include "monitoring.name" $) $ruleName) | trunc 63 | trimSuffix "-" }} 22 | namespace: {{ template "monitoring.namespace" $ }} 23 | labels: 24 | app: {{ template "monitoring.name" $ }} 25 | {{ include "monitoring.labels" $ | indent 4 }} 26 | spec: 27 | {{ $.Files.Get $fileName | indent 2 }} 28 | --- 29 | {{- end }} 30 | {{- end }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /deploy/charts/templates/servicemonitors.yaml: -------------------------------------------------------------------------------- 1 | {{ if (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} 2 | {{- range $monitoringAddon, $fields := .Values.openebsMonitoringAddon }} 3 | {{- if (and (hasKey $fields "enabled") ($fields.enabled)) }} 4 | {{- if (hasKey $fields "serviceMonitor") }} 5 | {{- if ($fields.serviceMonitor.enabled) }} 6 | apiVersion: monitoring.coreos.com/v1 7 | kind: ServiceMonitor 8 | metadata: 9 | name: {{ lower (printf "%s-%s" (include "monitoring.fullname" $) $monitoringAddon) | trunc 63 | trimSuffix "-" }} 10 | namespace: {{ template "monitoring.namespace" $ }} 11 | labels: 12 | app: {{ template "monitoring.name" $ }}-{{ $monitoringAddon }} 13 | {{ include "monitoring.labels" $ | indent 4 }} 14 | spec: 15 | selector: 16 | {{ toYaml $fields.serviceMonitor.selector | indent 4 }} 17 | namespaceSelector: 18 | {{ toYaml $fields.serviceMonitor.namespaceSelector | indent 4 }} 19 | endpoints: 20 | - port: {{ $fields.serviceMonitor.endpoints.port }} 21 | path: {{ $fields.serviceMonitor.endpoints.path }} 22 | {{- if $fields.serviceMonitor.endpoints.relabelings }} 23 | relabelings: 24 | {{ toYaml $fields.serviceMonitor.endpoints.relabelings | indent 8 }} 25 | {{- end }} 26 | --- 27 | {{- end }} 28 | {{- end }} 29 | {{- end }} 30 | {{- end }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /deploy/charts/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for monitoring. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | ## Provide a name in place of monitoring for `app:` labels 6 | ## 7 | nameOverride: "" 8 | 9 | ## Override the deployment namespace 10 | ## 11 | namespaceOverride: "" 12 | 13 | ## Provide a name to substitute for the full names of resources 14 | ## 15 | fullnameOverride: "" 16 | 17 | ## Configuration for kube-prometheus-stack subchart 18 | kube-prometheus-stack: 19 | install: true 20 | 21 | global: 22 | rbac: 23 | pspEnabled: false 24 | 25 | kube-state-metrics: 26 | podSecurityPolicy: 27 | enabled: false 28 | 29 | prometheus-node-exporter: 30 | rbac: 31 | pspEnabled: false 32 | 33 | ## privilege and access control settings for node-exporter 34 | securityContext: 35 | fsGroup: 65534 36 | runAsGroup: 0 37 | runAsNonRoot: false 38 | runAsUser: 0 39 | 40 | ## Additional container arguments 41 | extraArgs: 42 | - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+)($|/) 43 | - --collector.filesystem.fs-types-exclude=^(tmpfs|autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ 44 | - --collector.diskstats.device-exclude=^(ram|loop|fd|sr|(h|s|v|xv)d[a-z]+|nvme\d+n\d+p|nvme\d+c\d+n)\d+$ 45 | 46 | prometheus: 47 | service: 48 | type: NodePort 49 | nodePort: 32514 50 | 51 | prometheusSpec: 52 | ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the 53 | ## prometheus resource to be created with selectors based on values in the helm deployment, 54 | ## which will also match the servicemonitors created 55 | ## 56 | serviceMonitorSelectorNilUsesHelmValues: false 57 | 58 | ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the 59 | ## prometheus resource to be created with selectors based on values in the helm deployment, 60 | ## which will also match the podmonitors created 61 | ## 62 | podMonitorSelectorNilUsesHelmValues: false 63 | 64 | ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the 65 | ## prometheus resource to be created with selectors based on values in the helm deployment, 66 | ## which will also match the PrometheusRule resources created 67 | ## 68 | ruleSelectorNilUsesHelmValues: false 69 | 70 | ## Number of replicas of each shard to deploy for a Prometheus deployment. 71 | ## Number of replicas multiplied by shards is the total number of Pods created. 72 | ## 73 | replicas: 1 74 | 75 | ## Prometheus StorageSpec for persistent data 76 | ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md 77 | ## 78 | storageSpec: 79 | volumeClaimTemplate: 80 | metadata: 81 | name: openebs-prometheus-pv 82 | spec: 83 | # This storageClass is backed by openebs localpv-provisioner. 84 | storageClassName: openebs-hostpath 85 | accessModes: ["ReadWriteOnce"] 86 | resources: 87 | requests: 88 | storage: 1Gi 89 | 90 | alertmanager: 91 | ## Deploy alertmanager 92 | ## 93 | enabled: true 94 | 95 | config: 96 | global: 97 | resolve_timeout: 5m 98 | route: 99 | group_by: ["alertname", "job", "volName"] 100 | group_wait: 30s 101 | group_interval: 5m 102 | repeat_interval: 4h 103 | receiver: "null" 104 | ## This route specifically groups openebs alerts. 105 | routes: 106 | - matchers: 107 | - product="openebs" 108 | receiver: "null" 109 | ## Add receivers as required. Ref: https://prometheus.io/docs/alerting/latest/configuration/#receiver-integration-settings 110 | receivers: 111 | - name: "null" 112 | templates: 113 | - /etc/alertmanager/config/*.tmpl 114 | 115 | service: 116 | type: NodePort 117 | nodePort: 30903 118 | 119 | alertmanagerSpec: 120 | ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the 121 | ## running cluster equal to the expected size. 122 | replicas: 1 123 | 124 | ## Storage is the definition of how storage will be used by the Alertmanager instances. 125 | ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md 126 | ## 127 | storage: 128 | {} 129 | # volumeClaimTemplate: 130 | # metadata: 131 | # name: alert-pv 132 | # spec: 133 | # # This storageClass is backed by openebs localpv-provisioner. 134 | # storageClassName: openebs-hostpath 135 | # accessModes: ["ReadWriteOnce"] 136 | # resources: 137 | # requests: 138 | # storage: 1Gi 139 | # selector: {} 140 | 141 | prometheusOperator: 142 | enabled: true 143 | 144 | ## Prometheus-Operator v0.39.0 and later support TLS natively. 145 | ## 146 | # tls: 147 | # enabled: false 148 | 149 | grafana: 150 | enabled: true 151 | 152 | rbac: 153 | pspEnabled: false 154 | 155 | ## In order to render HTML and Javascript in a text panel without being sanitized 156 | ## enable the `disable_sanitize_html` settings in Grafana ini file 157 | grafana.ini: 158 | panels: 159 | disable_sanitize_html: true 160 | 161 | service: 162 | type: NodePort 163 | nodePort: 32515 164 | 165 | ## Deploy default dashboards. 166 | ## 167 | defaultDashboardsEnabled: true 168 | adminPassword: admin 169 | 170 | sidecar: 171 | dashboards: 172 | enabled: true 173 | # ConfigMaps with label below will be added to Grafana as dashboards. 174 | label: grafana_dashboard 175 | 176 | ## Pass the plugins you want installed as a list. 177 | ## 178 | plugins: 179 | - grafana-polystat-panel 180 | - snuids-trafficlights-panel 181 | 182 | ## Add persistent storage for Grafana 183 | persistence: 184 | enabled: true 185 | # This storageClass is backed by openebs localpv-provisioner. 186 | storageClassName: openebs-hostpath 187 | accessModes: 188 | - ReadWriteOnce 189 | size: 1Gi 190 | 191 | localpv-provisioner: 192 | enabled: true 193 | hostpathClass: 194 | name: openebs-hostpath 195 | # -- Enable default hostpath localpv StorageClass. 196 | enabled: true 197 | analytics: 198 | enabled: true 199 | 200 | ## Configuration for node-problem-detector subchart 201 | node-problem-detector: 202 | install: false 203 | 204 | ## Volume for storing logs 205 | extraVolumes: 206 | - name: kmsg 207 | hostPath: 208 | path: /dev/kmsg 209 | 210 | extraVolumeMounts: 211 | - name: kmsg 212 | mountPath: /dev/kmsg 213 | readOnly: true 214 | 215 | ## Enabling service monitors of npd 216 | metrics: 217 | serviceMonitor: 218 | enabled: true 219 | 220 | ## Configuration for installing monitoring addons 221 | openebsMonitoringAddon: 222 | lvmLocalPV: 223 | enabled: true 224 | dashboards: 225 | enabled: true 226 | alertRules: 227 | enabled: true 228 | serviceMonitor: 229 | enabled: true 230 | 231 | ## Endpoints of the selected service to be monitored 232 | endpoints: 233 | ## Name of the endpoint's service port 234 | ## Mutually exclusive with targetPort 235 | # port: "" 236 | port: metrics 237 | 238 | ## HTTP path to scrape for metrics 239 | # path: /metrics 240 | path: /metrics 241 | 242 | ## Label selector for services to which this ServiceMonitor applies 243 | # selector: {} 244 | # matchLabels: {} 245 | 246 | ## Example 247 | 248 | # selector: 249 | # matchLabels: 250 | # name: openebs-lvm-node 251 | 252 | selector: 253 | matchLabels: 254 | name: openebs-lvm-node 255 | 256 | ## Namespaces from which services are selected 257 | # namespaceSelector: [] 258 | ## Match any namespace 259 | # any: true 260 | 261 | ## Example 262 | 263 | # namespaceSelector: 264 | # any: true 265 | 266 | ## Explicit list of namespace names to select 267 | # matchNames: [] 268 | 269 | ## Example 270 | 271 | # namespaceSelector: 272 | # matchNames: 273 | # - openebs 274 | # - default 275 | 276 | namespaceSelector: 277 | any: true 278 | 279 | npd: 280 | enabled: false 281 | dashboards: 282 | enabled: false 283 | alertRules: 284 | enabled: false 285 | 286 | volume: 287 | enabled: true 288 | alertRules: 289 | enabled: true 290 | 291 | zfsLocalPV: 292 | enabled: true 293 | dashboards: 294 | enabled: true 295 | 296 | mayastor: 297 | enabled: true 298 | dashboards: 299 | enabled: true 300 | serviceMonitor: 301 | enabled: true 302 | 303 | ## Endpoints of the selected service to be monitored 304 | endpoints: 305 | ## Name of the endpoint's service port 306 | ## Mutually exclusive with targetPort 307 | # port: "" 308 | port: metrics 309 | 310 | ## HTTP path to scrape for metrics 311 | # path: /metrics 312 | path: /metrics 313 | 314 | selector: 315 | matchLabels: 316 | app: metrics-exporter-io-engine 317 | 318 | namespaceSelector: 319 | any: true 320 | -------------------------------------------------------------------------------- /docs/extends-stack-with-umbrella-chart.md: -------------------------------------------------------------------------------- 1 | # Extending the monitoring stack 2 | 3 | ### Prerequisite 4 | 5 | - Helm 3+ installed 6 | - OpenEBS installed 7 | 8 | # What is a umbrella chart and why use it ? 9 | 10 | An umbrella chart is a way of encapsulate multiple complex charts with one chart. 11 | 12 | >Many of the charts in the CNCF Artifact Hub are "building blocks" for creating more advanced applications. But charts may be used to create instances of large-scale applications. In such cases, a single umbrella chart may have multiple subcharts, each of which functions as a piece of the whole. 13 | 14 | >The current best practice for composing a complex application from discrete parts is to create a top-level umbrella chart that exposes the global configurations, and then use the charts/ subdirectory to embed each of the components. 15 | Source: https://helm.sh/docs/howto/charts_tips_and_tricks/#complex-charts-with-many-dependencies 16 | 17 | Using an umbrella chart will allow you customize OpenEBS monitoring stack settings without modifying that chart content. It's also easier to update a dependency. 18 | 19 | To create your our umbrella chart, you will have a create a folder structure like this. 20 | 21 | ``` 22 | 📦umbrella 23 | ┣ 📜Chart.yaml 24 | ┗ 📜values.yaml 25 | ``` 26 | 27 | | File | Description | 28 | | ------ | ------ | 29 | | Chart.yaml | Contains your chart identification with a dependency to OpenEBS monitoring stack | 30 | | values.yaml | Contains all your settings values | 31 | 32 | # Umbrella chart with ingress and storage enabled 33 | 34 | Here a example that will enable ingress and storage for OpenEBS monitoring stack. 35 | 36 | In the file **Chart.yaml**, you will enter your umbrella chart information with a dependency to OpenEBS monitoring stack. The property name : `condition` is optional. That property will allow you to install that dependency or not depending of the value in `values.yaml`. 37 | 38 | #### Chart.yaml 39 | ````yaml 40 | apiVersion: v2 41 | name: monitoring-stack 42 | description: Umbrella Chart for OpenEBS monitoring stack 43 | icon: https://avatars.githubusercontent.com/u/20769039?s=200&v=4 44 | type: application 45 | version: 0.1.1 46 | appVersion: 1.0.0 47 | dependencies: 48 | - name: monitoring 49 | version: 0.4.8 50 | repository: "https://openebs.github.io/monitoring/" 51 | condition: monitoring.install 52 | ```` 53 | 54 | In the file **values.yaml**, you will define your configuration for the monitoring stack. 55 | 56 | If you defined a **dependency condition** in **Chart.yaml**, you will have to define the value in that condition. In this example, the condition name is `monitoring.install`. 57 | 58 | if you provide only the condition value, you will deploy OpenEBS monitoring stack with the default values provided in there chart. 59 | 60 | #### value.yaml (with default values) 61 | ````yaml 62 | monitoring: 63 | install: true 64 | ```` 65 | 66 | #### value.yaml (with ingress and storage) 67 | 68 | To use storage for the monitoring stack, you will have to create the storage class before using it. In the following example, I use a storage class named: `sc-metrics` which already exists in my cluster. 69 | 70 | Similarly you can also customize other parameters. For instance, if domain name has to be used to access the user interfaces, the `ingress` section needs to be updated. In the following example I use the value: `dev.dynamic.cluster109.local`. 71 | 72 | The applications will be accessible from : 73 | - http://dev.dynamic.cluster109.local/prometheus 74 | - http://dev.dynamic.cluster109.local/grafana 75 | - http://dev.dynamic.cluster109.local/alertmanager 76 | 77 | Here the content of **values.yaml** with those settings. 78 | 79 | ````yaml 80 | monitoring: 81 | install: true 82 | 83 | ## Configuration for kube-prometheus-stack subchart 84 | kube-prometheus-stack: 85 | # PROMETHEUS SECTION 86 | prometheus: 87 | ingress: 88 | enabled: true 89 | annotations: 90 | nginx.ingress.kubernetes.io/ssl-redirect: "false" 91 | paths: 92 | - /prometheus(/|$)(.*) 93 | hosts: 94 | - dev.dynamic.cluster109.local 95 | 96 | prometheusSpec: 97 | ## Prefix used to register routes, overriding externalUrl route. 98 | ## Useful for proxies that rewrite URLs. 99 | ## 100 | routePrefix: /prometheus 101 | 102 | ## Prometheus StorageSpec for persistent data 103 | ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md 104 | ## 105 | storageSpec: 106 | volumeClaimTemplate: 107 | metadata: 108 | name: prom 109 | spec: 110 | storageClassName: sc-metrics 111 | accessModes: [ "ReadWriteOnce" ] 112 | resources: 113 | requests: 114 | storage: 8Gi 115 | 116 | # ALERTMANAGER SECTION 117 | alertmanager: 118 | ingress: 119 | enabled: true 120 | 121 | annotations: 122 | nginx.ingress.kubernetes.io/ssl-redirect: "false" 123 | nginx.ingress.kubernetes.io/rewrite-target: /$2 124 | paths: 125 | - /alertmanager(/|$)(.*) 126 | hosts: 127 | - dev.dynamic.cluster109.local 128 | 129 | alertmanagerSpec: 130 | ## Storage is the definition of how storage will be used by the Alertmanager instances. 131 | ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md 132 | ## 133 | storage: 134 | volumeClaimTemplate: 135 | metadata: 136 | name: alert 137 | spec: 138 | storageClassName: sc-metrics 139 | accessModes: [ "ReadWriteOnce" ] 140 | resources: 141 | requests: 142 | storage: 8Gi 143 | 144 | # GRAFANA SECTION 145 | grafana: 146 | ## In order to render HTML and Javascript in a text panel without being sanitized 147 | ## enable the `disable_sanitize_html` settings in Grafana ini file 148 | grafana.ini: 149 | ## If you have Ingress, you need to change the root_url to match ingress path 150 | server: 151 | root_url: http://localhost:3000/grafana 152 | 153 | ## Enable persistence using Persistent Volume Claims 154 | ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ 155 | ## 156 | persistence: 157 | type: pvc 158 | enabled: true 159 | storageClassName: sc-metrics 160 | accessModes: 161 | - ReadWriteOnce 162 | size: 10Gi 163 | 164 | ingress: 165 | ## If true, Grafana Ingress will be created 166 | ## 167 | enabled: true 168 | 169 | annotations: 170 | nginx.ingress.kubernetes.io/ssl-redirect: "false" 171 | nginx.ingress.kubernetes.io/rewrite-target: /$2 172 | path: /grafana(/|$)(.*) 173 | hosts: 174 | - dev.dynamic.cluster109.local 175 | 176 | # NDP SECTION 177 | ## Configuration for node-problem-detector subchart 178 | node-problem-detector: 179 | install: true 180 | ```` 181 | 182 | # Add your Grafana Dashboards and Prometheus rules 183 | 184 | OpenEBS monitoring stack come with Grafana dashboards and Prometheus rules, but it's possible to add your own by extending the monitoring stack. 185 | 186 | In the monitoring stack, there is a folder named `dashboards` that contains Grafana dashboards and the folder `rules` contains Prometheus rules. To extends the stack, we will have the folder structure based on the structure within the monitoring stack. 187 | 188 | Our umbrella chart folder structure will look like that : 189 | 190 | | Folder/File | Description | 191 | | ------ | ------ | 192 | | charts | Contains your chart dependencies (auto-generated with helm) | 193 | | dashboards | Contains all your Grafana dashboards (json format) | 194 | | rules | Contains all your Prometheus rules (json or yaml format) | 195 | | templates | helm templates to include your dashboards and rules into OpenEBS monitoring stack| 196 | | Chart.yaml | Contains your chart identification with a dependency to OpenEBS monitoring stack | 197 | | values.yaml | Contains all your settings values | 198 | 199 | Here a example of umbrella chart using external Grafana dashboards and Prometheus rules. You can separate your files with sub folders to simplify and regroup them. The helm templates will check within the sub folders for files to import. 200 | 201 | ```` 202 | 📦umbrella 203 | ┣ 📂charts 204 | ┃ ┗ 📜monitoring-0.4.9.tgz 205 | ┣ 📂dashboards 206 | ┃ ┣ 📂custom 207 | ┃ ┃ ┣ 📜k8s-persistence-volumes.json 208 | ┃ ┃ ┗ 📜node-exporter-full.json 209 | ┃ ┗ 📂kafka 210 | ┃ ┃ ┣ 📜confluent-open-source-grafana-dashboard.json 211 | ┣ 📂rules 212 | ┃ ┗ 📂custom 213 | ┃ ┃ ┗ 📜instance-down.json 214 | ┣ 📂templates 215 | ┃ ┣ 📜dashboards-json-configmap.yaml 216 | ┃ ┣ 📜prometheusRules.yaml 217 | ┃ ┗ 📜_helpers.tpl 218 | ┣ 📜Chart.lock 219 | ┣ 📜Chart.yaml 220 | ┗ 📜values.yaml 221 | ```` 222 | 223 | ### Helm templates to import your files into OpenEBS monitoring stack 224 | 225 | Here the content of the files into templates folder. Those files are based on those within the monitoring stack. You can customize it to fit your needs or use it as is. 226 | 227 | | File | Description | 228 | | ------ | ------ | 229 | | _helpers.tpl | Helm template helper | 230 | | dashboard-json-configmap.yaml | Contains the logic to add Grafana dashboards to OpenEBS monitoring stack | 231 | | prometheusRules.yaml | Contains the logic to add Prometheus rules to OpenEBS monitoring stack | 232 | 233 | #### _helpers.tpl 234 | ````yaml 235 | {{/* vim: set filetype=mustache: */}} 236 | {{/* 237 | Expand the name of the chart. 238 | */}} 239 | {{- define "monitoring.name" -}} 240 | {{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" }} 241 | {{- end }} 242 | 243 | {{/* 244 | Create a default fully qualified app name. 245 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 246 | If release name contains chart name it will be used as a full name. 247 | */}} 248 | {{- define "monitoring.fullname" -}} 249 | {{- if .Values.fullnameOverride }} 250 | {{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" }} 251 | {{- else }} 252 | {{- $name := default .Chart.Name .Values.nameOverride }} 253 | {{- if contains $name .Release.Name }} 254 | {{- .Release.Name | trunc 26 | trimSuffix "-" }} 255 | {{- else }} 256 | {{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" }} 257 | {{- end }} 258 | {{- end }} 259 | {{- end }} 260 | 261 | {{/* 262 | Allow the release namespace to be overridden for multi-namespace deployments in combined charts 263 | */}} 264 | {{- define "monitoring.namespace" -}} 265 | {{- if .Values.namespaceOverride -}} 266 | {{- .Values.namespaceOverride -}} 267 | {{- else -}} 268 | {{- .Release.Namespace -}} 269 | {{- end -}} 270 | {{- end -}} 271 | 272 | 273 | {{/* 274 | Create chart name and version as used by the chart label. 275 | */}} 276 | {{- define "monitoring.chart" -}} 277 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 278 | {{- end }} 279 | 280 | {{/* 281 | Common labels 282 | */}} 283 | {{- define "monitoring.labels" -}} 284 | helm.sh/chart: {{ include "monitoring.chart" . }} 285 | {{ include "monitoring.selectorLabels" . }} 286 | {{- if .Chart.AppVersion }} 287 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 288 | {{- end }} 289 | app.kubernetes.io/managed-by: {{ .Release.Service }} 290 | {{- end }} 291 | 292 | {{/* 293 | Selector labels 294 | */}} 295 | {{- define "monitoring.selectorLabels" -}} 296 | app.kubernetes.io/name: {{ include "monitoring.name" . }} 297 | app.kubernetes.io/instance: {{ .Release.Name }} 298 | release: {{ $.Release.Name | quote }} 299 | {{- end }} 300 | 301 | {{/* 302 | Template to support multiple levels of sub-charts 303 | 304 | Call a template from the context of a subchart. 305 | 306 | Usage: 307 | {{ include "call-nested" (list . "" "") }} 308 | */}} 309 | {{- define "call-nested" }} 310 | {{- $dot := index . 0 }} 311 | {{- $subchart := index . 1 | splitList "." }} 312 | {{- $template := index . 2 }} 313 | {{- $values := $dot.Values }} 314 | {{- range $subchart }} 315 | {{- $values = index $values . }} 316 | {{- end }} 317 | {{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }} 318 | {{- end }} 319 | ```` 320 | 321 | #### dashboard-json-configmap.yaml 322 | ````yaml 323 | {{- $grafanaSidecarDashboardsLabel := index .Values "monitoring" "kube-prometheus-stack" "grafana" "sidecar" "dashboards" "label" }} 324 | {{- $files := .Files.Glob "dashboards/**.json" }} 325 | {{- if $files }} 326 | {{- range $fileName, $fileContents := $files }} 327 | {{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $fileName "${2}" }} 328 | apiVersion: v1 329 | kind: ConfigMap 330 | metadata: 331 | name: {{ lower (printf "%s-%s" (include "monitoring.fullname" $) $dashboardName) | trunc 63 | trimSuffix "-" }} 332 | namespace: {{ template "monitoring.namespace" $ }} 333 | labels: 334 | {{ $grafanaSidecarDashboardsLabel }}: "1" 335 | app: {{ template "monitoring.name" $ }}-grafana 336 | {{ include "monitoring.labels" $ | indent 4 }} 337 | data: 338 | {{ $dashboardName }}.json: {{ $.Files.Get $fileName | toPrettyJson }} 339 | --- 340 | {{- end }} 341 | {{- end }} 342 | ```` 343 | 344 | #### prometheusRules.yaml 345 | ````yaml 346 | {{- $files := .Files.Glob "rules/**.json" }} 347 | {{- if $files }} 348 | {{- range $fileName, $fileContents := $files }} 349 | {{- $ruleName := regexReplaceAll "(^.*/)(.*)\\.json$" $fileName "${2}" }} 350 | apiVersion: monitoring.coreos.com/v1 351 | kind: PrometheusRule 352 | metadata: 353 | name: {{ lower (printf "%s-%s" (include "monitoring.name" $) $ruleName) | trunc 63 | trimSuffix "-" }} 354 | namespace: {{ template "monitoring.namespace" $ }} 355 | labels: 356 | app: {{ template "monitoring.name" $ }} 357 | {{ include "monitoring.labels" $ | indent 4 }} 358 | spec: 359 | {{ $.Files.Get $fileName | indent 2 }} 360 | --- 361 | {{- end }} 362 | {{- end }} 363 | ```` 364 | 365 | Here a example of a custom Prometheus rules that you can add to the monitoring stack. 366 | 367 | #### instance-down.json 368 | ````json 369 | { 370 | "groups": [ 371 | { 372 | "name": "Instances", 373 | "rules": [ 374 | { 375 | "alert": "InstanceDown", 376 | "expr": "up == 0", 377 | "for": "10s", 378 | "labels": { 379 | "severity": "page" 380 | }, 381 | "annotations": { 382 | "description": "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minute.", 383 | "summary": "Instance {{ $labels.instance }} down" 384 | } 385 | } 386 | ] 387 | } 388 | ] 389 | } 390 | ```` 391 | 392 | # How to deploy the umbrella chart 393 | 394 | ### Download the dependencies 395 | The first step will be to download the dependencies by running this command in a terminal in the umbrella folder. 396 | 397 | ````console 398 | helm dep build 399 | ```` 400 | 401 | If you had already ran that command and you changed the dependencies in Chart.yaml, you will have to download the new dependencies by running this command. 402 | 403 | ````console 404 | helm dep up 405 | ```` 406 | 407 | You will obtain that folder structure 408 | 409 | ``` 410 | 📦umbrella 411 | ┣ 📂charts 412 | ┃ ┗ 📜monitoring-0.4.8.tgz 413 | ┣ 📂templates 414 | ┣ 📜Chart.lock 415 | ┣ 📜Chart.yaml 416 | ┗ 📜values.yaml 417 | ``` 418 | 419 | ### Install the chart 420 | 421 | #### From the umbrella folder 422 | 423 | In a terminal in the umbrella folder run this command : 424 | 425 | ```console 426 | helm install [RELEASE_NAME] . -n [NAMESPACE] --create-namespace 427 | ``` 428 | 429 | ex : 430 | ````console 431 | helm install monitoring . -n monitoring --create-namespace 432 | ```` 433 | 434 | #### From a helm chart repository 435 | 436 | In a terminal in the umbrella folder run this command : 437 | 438 | ```console 439 | helm install [RELEASE_NAME] [REPOSITORY]/[CHART_NAME] -n [NAMESPACE] --create-namespace 440 | ``` 441 | 442 | ex : 443 | ````console 444 | helm install monitoring chartmuseum/monitoring-stack -n monitoring --create-namespace 445 | ```` 446 | -------------------------------------------------------------------------------- /docs/guide.md: -------------------------------------------------------------------------------- 1 | # Install openebs-addon-only 2 | 3 | ### Prerequisite 4 | 5 | - Already installed prometheus-operator stack 6 | - OpenEBS installed 7 | 8 | --- 9 | **NOTE** 10 | 11 | - To allow Prometheus to discover all `PodMonitors/ServiceMonitors`, without applying label filtering, you have to set `prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues` and `prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues` to `false` 12 | 13 | - Install grafana plugin 14 | 15 | - There are two plugins that we are using for OpenEBS dashboards. 16 | 17 | - [grafana-polystat-panel]([https://link](https://grafana.com/grafana/plugins/grafana-polystat-panel/)) 18 | 19 | - [snuids-trafficlights-panel]([https://link](https://grafana.com/grafana/plugins/snuids-trafficlights-panel/)) 20 | 21 | - To install these plugin, exec into the `grafana` container and run 22 | ``` 23 | grafana-cli plugins install grafana-polystat-panel 24 | grafana-cli plugins install snuids-trafficlights-panel 25 | ``` 26 | - Update Grafana configuration 27 | 28 | - Append the below configuration in the configmap in which Grafana initialisation is done or cm in which `grafana.ini` file is declared. 29 | ```console 30 | grafana.ini: 31 | -------------- 32 | ... 33 | [panels] 34 | disable_sanitize_html = true 35 | ... 36 | ``` 37 | 38 | --- 39 | 40 | ## Step by Step Process 41 | 42 | 1. **Update values.yaml** 43 | 44 | - Disable dependent chart(kube-prometheus-stack) by updating `kube-prometheus-stack.install` to `false` 45 | - If you have updated the label for Grafana sidecar container(`grafana-sc-dashboard`), then update `kube-prometheus-stack.grafana.sidecar.dashboards.label: ` 46 | - Update `namespaceOverride` with the namespace name in which Prometheus stack is installed 47 | - After updating these specific values in values.yaml, these fields should look like this(example) : 48 | ```console 49 | ... 50 | namespaceOverride: "prometheus-operator" 51 | kube-prometheus-stack: 52 | install: false 53 | grafana: 54 | ## Sidecar container to load dashboard cm 55 | sidecar: 56 | dashboards: 57 | enabled: true 58 | # ConfigMaps with label below will be added to Grafana as dashboards. 59 | label: grafana_dashboard 60 | 61 | 62 | ... 63 | ``` 64 | 65 | 66 | 2. **Install `monitoring` chart** 67 | 68 | ```console 69 | # Helm 70 | helm install -f values.yaml [RELEASE_NAME] monitoring/monitoring 71 | ``` 72 | 73 | #### Helm Chart install with one line 74 | 75 | ```console 76 | #Helm 77 | helm install [RELEASE_NAME] monitoring/monitoring -n [PROMETHEUS-STACK-NAMESPACE] --set kube-prometheus-stack.install=false,kube-prometheus-stack.grafana.sidecar.dashboards.label=[UPDATED_LABEL] 78 | ``` 79 | 80 | #### Verification 81 | 82 | - Verify `PodMonitors/ServiceMonitors` are installed 83 | 84 | ```console 85 | kubectl get servicemonitors -n prometheus-operator -l release="monitoring" 86 | NAME AGE 87 | monitoring-openebs-mayastor 33m 88 | ``` 89 | 90 | - Verify `dashboards configmaps` are installed 91 | 92 | ```console 93 | kubectl get cm -n prometheus-operator -l release="monitoring" 94 | NAME DATA AGE 95 | monitoring-openebs-diskpool 1 37m 96 | ``` 97 | 98 | - To see the dashboards, form the Grafana URL and open it in the browser -------------------------------------------------------------------------------- /docs/metrics-csi.md: -------------------------------------------------------------------------------- 1 | # CSI metrics exposed 2 | 3 | Here is the list of csi volume metrics exposed by k8s:- 4 | 5 | ``` 6 | kubelet_volume_stats_available_bytes 7 | kubelet_volume_stats_capacity_bytes 8 | kubelet_volume_stats_inodes 9 | kubelet_volume_stats_inodes_free 10 | kubelet_volume_stats_inodes_used 11 | kubelet_volume_stats_used_bytes 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/metrics-lvm.md: -------------------------------------------------------------------------------- 1 | # Monitoring OpenEBS lvm-localpv volumes 2 | 3 | ## Metrics supported by lvm-localpv volumes as of the current release are: 4 | 5 | ### Logical volumes metrics: 6 | 7 | ``` 8 | lvm_lv_health_status # LV health status: [-1: undefined], [0: ""], [1: partial], [2: refresh needed], [3: mismatches exist] 9 | lvm_lv_mda_total_size_bytes # LVM LV metadata size in bytes 10 | lvm_lv_mda_used_percent # LVM LV metadata used size in percentage(1-100) 11 | lvm_lv_permission # LV permissions: [-1: undefined], [0: unknown], [1: writeable], [2: read-only], [3: read-only-override] 12 | lvm_lv_raid_sync_action # For LV RAID, the current synchronization action being performed: [-1: undefined], [0: idle], [1: frozen], [2: resync], [3: recover], [4: check], [5: repair] 13 | lvm_lv_snap_percent # LVM LV snap used size in percentage(1-100) 14 | lvm_lv_total_size_bytes # LVM LV total size in bytes 15 | lvm_lv_used_percent # LVM LV used size in percentage(1-100) 16 | lvm_lv_when_full # For thin pools, behavior when full: [-1: undefined], [0: error], [1: queue] 17 | ``` 18 | 19 | ### Physical volume metrics: 20 | 21 | ``` 22 | lvm_pv_device_size_bytes # LVM PV underlying device size in bytes 23 | lvm_pv_free_size_bytes # LVM PV free size in bytes 24 | lvm_pv_mda_free_size_bytes # LVM PV device free metadata area space in bytes 25 | lvm_pv_mda_total_size_bytes # LVM PV device smallest metadata area size in bytes 26 | lvm_pv_total_size_bytes # LVM PV total size in bytes 27 | lvm_pv_used_size_bytes # LVM PV used size in bytes 28 | ``` 29 | 30 | ### Volume group metrics: 31 | 32 | ``` 33 | lvm_vg_allocation_policy # VG allocation policy: [-1: undefined], [0: normal], [1: contiguous], [2: cling], [3: anywhere], [4: inherited] 34 | lvm_vg_free_size_bytes # LVM VG free size in bytes 35 | lvm_vg_lv_count # Number of LVs in VG 36 | lvm_vg_max_lv_count # Maximum number of LVs allowed in VG or 0 if unlimited 37 | lvm_vg_max_pv_count # Maximum number of PVs allowed in VG or 0 if unlimited 38 | lvm_vg_mda_count # Number of metadata areas on this VG 39 | lvm_vg_mda_free_size_bytes # Free metadata area space for this VG in bytes 40 | lvm_vg_mda_total_size_bytes # Size of smallest metadata area for this VG in bytes 41 | lvm_vg_mda_used_count # Number of metadata areas in use on this VG 42 | lvm_vg_missing_pv_count # Number of PVs in VG which are missing 43 | lvm_vg_permission # VG permissions: [-1: undefined], [0: writeable], [1: read-only] 44 | lvm_vg_pv_count # Number of PVs in VG 45 | lvm_vg_snap_count # Number of snapshots in VG 46 | lvm_vg_total_size_bytes # LVM VG total size in bytes 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/metrics-node-problem-detector.md: -------------------------------------------------------------------------------- 1 | # node-problem-detector metrics 2 | 3 | Here is a list of metrics exported by node-problem-detector metrics when kernel-monitor and docker-monitor is only enabled. Other rules can also be monitored by adding them to the `log_monitors` field in the values.yaml used by [node-problem-detector](https://git.app.uib.no/caleno/helm-charts/-/blob/master/stable/node-problem-detector/values.yaml). Accordingly the metrics will also appear. 4 | 5 | ## Metrics by enabling kernel-monitor 6 | 7 | ``` 8 | problem_counter{reason="OOMKilling"} # system logs with pattern- "Killed process \\d+ (.+) total-vm:\\d+kB, anon-rss:\\d+kB, file-rss:\\d+kB._" 9 | problem_counter{reason="TaskHung"} # system logs with pattern- "task [\\S ]+:\\w+ blocked for more than \\w+ seconds\\." 10 | problem_counter{reason="UnregisterNetDevice"} # system logs with pattern- "unregister_netdevice: waiting for \\w+ to become free. Usage count = \\d+" 11 | problem_counter{reason="KernelOops"} # system logs with pattern- "BUG: unable to handle kernel NULL pointer dereference at ._" 12 | problem_counter{reason="KernelOops"} # system logs with pattern- "divide error: 0000 \\[#\\d+\\] SMP" 13 | problem_counter{reason="Ext4Error"} # system logs with pattern- "EXT4-fs error ._" 14 | problem_counter{reason="Ext4Warning"} # system logs with pattern- "EXT4-fs warning ._" 15 | problem_counter{reason="IOError"} # system logs with pattern- "Buffer I/O error ._" 16 | problem_counter{reason="MemoryReadError"} # system logs with pattern- "CE memory read error ._" 17 | problem_counter{reason="AUFSUmountHung"} # system logs with pattern- "task umount\\.aufs:\\w+ blocked for more than \\w+ seconds\\." 18 | problem_counter{reason="DockerHung"} # system logs with pattern- "task docker:\\w+ blocked for more than \\w+ seconds\\." 19 | problem_counter{reason="FilesystemIsReadOnly"} # system logs with pattern- "Remounting filesystem read-only" 20 | ``` 21 | 22 | ## Metrics by enabling docker-monitor 23 | 24 | ``` 25 | problem_counter{reason="CorruptDockerImage"} # system logs with pattern- "Error trying v2 registry: failed to register layer: rename /var/lib/docker/image/(.+) /var/lib/docker/image/(.+): directory not empty._" 26 | problem_counter{reason="CorruptDockerOverlay2"} # system logs with pattern- "returned error: readlink /var/lib/docker/overlay2._: invalid argument.\*" 27 | problem_counter{reason="DockerContainerStartupFailure"} # system logs with pattern- "OCI runtime start failed: container process is already dead: unknown" 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/openebs-mixin-user-guide.md: -------------------------------------------------------------------------------- 1 | # Install openebs-mixin 2 | 3 | --- 4 | ### Different scenarios to use openebs-mixin 5 | 6 | 1. Install openebs-mixin with monitoring written in jsonnet. 7 | 2. Install openebs-mixin in existing prometheus stack. 8 | 9 | --- 10 | ## Install openebs-mixin with monitoring written in jsonnet. 11 | To install kube-prometheus stack with openebs-addons(serviceMonitors, grafana dashboards and alert rules). 12 | 13 | ### Prerequisite 14 | 15 | - OpenEBS installed 16 | 17 | #### Step by Step Process 18 | 19 | 1. **Configuration** 20 | The available fields and their default values are present in [config.libsonnet](../jsonnet/config.libsonnet). To update the configuration of mixin, you need to override the configuration through config.libsonnet. 21 | ``` 22 | . . . 23 | // import openebs-mixin and override configurations 24 | openebsMixin: (import './openebs-mixin/mixin.libsonnet') { 25 | _config+:: { 26 | dashboards+: { 27 | lvmLocalPV: $._config.openebsMonitoringAddon.lvmLocalPV.dashboards, 28 | }, 29 | alertRules+: { 30 | lvmLocalPV: $._config.openebsMonitoringAddon.lvmLocalPV.alertRules, 31 | }, 32 | }, 33 | }, 34 | . . . 35 | 36 | ``` 37 | 38 | 2. **Install kube-prometheus stack with monitoring addons** 39 | To generate manifest to install monitoring in kubernetes cluster, you need to run [main.jsonnet](../jsonnet/main.jsonnet). To generate manifests, please follow the steps listed over [here](../jsonnet/README.md). 40 | ``` 41 | . . . 42 | local config = import './config.libsonnet'; 43 | local openebsMixin = config.openebsMixin; 44 | 45 | local kp = 46 | config.kp { 47 | values+:: { 48 | grafana+: { 49 | dashboards+: openebsMixin.grafanaDashboards, 50 | }, 51 | }; 52 | 53 | // kube-prometheus stack 54 | { 'setup/0namespace-namespace': kp.kubePrometheus.namespace } + 55 | { 56 | ['setup/prometheus-operator-' + name]: kp.prometheusOperator[name] 57 | for name in std.filter((function(name) name != 'serviceMonitor' && name != 'prometheusRule'), std.objectFields(kp.prometheusOperator)) 58 | } + 59 | // serviceMonitor and prometheusRule are separated so that they can be created after the CRDs are ready 60 | { 'prometheus-operator-serviceMonitor': kp.prometheusOperator.serviceMonitor } + 61 | { 'prometheus-operator-prometheusRule': kp.prometheusOperator.prometheusRule } + 62 | { 'kube-prometheus-prometheusRule': kp.kubePrometheus.prometheusRule } + 63 | { ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } + 64 | { ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) } + 65 | { ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } + 66 | { ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } + 67 | { ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } + 68 | 69 | 70 | // servicemonitor, podmonitor and prometheusrules for different casTypes of openebs 71 | { ['openebs-addons/openebs-servicemonitor-' + casType]: serviceMonitor.serviceMonitors[casType] for casType in std.objectFields(serviceMonitor.serviceMonitors) } + 72 | { ['openebs-addons/openebs-podmonitor-' + casType]: podMonitors.podMonitors[casType] for casType in std.objectFields(podMonitors.podMonitors) } + 73 | // to enable alert rules 74 | { ['openebs-addons/openebs-rule-' + name]: rules.prometheusRules[name] for name in std.objectFields(rules.prometheusRules) } 75 | 76 | ``` 77 | --- 78 | 79 | ## Install openebs-mixin in existing prometheus stack. 80 | Setup Grafana dashboards and alert rules for OpenEBS monitoring. 81 | ### Prerequisite 82 | 83 | - OpenEBS installed 84 | - Prometheus stack installed 85 | - ServiceMonitors and PodMonitors are already installed for different cas types. 86 | 87 | #### Step by Step Process 88 | 89 | 1. **Override openebs-mixin configuration** 90 | The available fields and their default values are present in [config.libsonnet](../jsonnet/openebs-mixin/config.libsonnet). To update the configuration of mixin, you need to override the configuration. 91 | ``` 92 | . . . 93 | // import openebs-mixin and override configurations 94 | local openebsMixin=(import 'kube-prometheus/lib/mixin.libsonnet')({ 95 | name: 'openebsMixin', 96 | mixin: (import './openebs-mixin/mixin.libsonnet'){ 97 | _config+:: { 98 | dashboards+: { 99 | mayastor: true, 100 | lvmLocalPV: false, 101 | . . . 102 | }, 103 | alertRules+: { 104 | mayastor: true, 105 | lvmLocalPV: true, 106 | . . . 107 | }, 108 | } 109 | }, 110 | }); 111 | . . . 112 | ``` 113 | 2. **Install openebs-mixin** 114 | To create a openebs-mixin object that has Prometheus rules and Grafana dashboards: 115 | ``` 116 | local openebsMixin=(import 'kube-prometheus/lib/mixin.libsonnet')({ 117 | name: 'openebsMixin', 118 | mixin: (import './openebs-mixin/mixin.libsonnet'), 119 | }); 120 | ``` 121 | The openebsMixin object will have two objects - `prometheusRules` and `grafanaDashboards`. The `grafanaDashboards` object will be needed to be added to the dashboards field as in the example below: 122 | ``` 123 | . . . 124 | values+:: { 125 | grafana+: { 126 | // To install openebs dashboards 127 | dashboards+: openebsMixin.grafanaDashboards, 128 | }, 129 | } 130 | . . . 131 | ``` 132 | The `prometheusRules` object should be defined as its own jsonnet object. 133 | ``` 134 | . . . 135 | // To generate prometheusRule object 136 | { 'openebs-addons/openebs-mixin-prometheus-rules': openebsMixin.prometheusRules } 137 | . . . 138 | ``` -------------------------------------------------------------------------------- /jsonnet/Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/usr/bin/env bash -o pipefail 2 | 3 | BIN_DIR?=$(shell pwd)/tmp/bin 4 | 5 | JB_BIN=$(BIN_DIR)/jb 6 | JSONNET_BIN=$(BIN_DIR)/jsonnet 7 | JSONNETLINT_BIN=$(BIN_DIR)/jsonnet-lint 8 | JSONNETFMT_BIN=$(BIN_DIR)/jsonnetfmt 9 | TOOLING=$(JB_BIN) $(JSONNET_BIN) $(JSONNETLINT_BIN) $(JSONNETFMT_BIN) 10 | 11 | JSONNETFMT_ARGS=-n 2 --max-blank-lines 2 --string-style s --comment-style s 12 | 13 | all: lint fmt 14 | 15 | .PHONY: clean 16 | clean: 17 | # Remove all files and directories ignored by git. 18 | git clean -Xfd . 19 | 20 | .PHONY: fmt 21 | fmt: $(JSONNETFMT_BIN) 22 | find . -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ 23 | xargs -n 1 -- $(JSONNETFMT_BIN) $(JSONNETFMT_ARGS) -i 24 | 25 | .PHONY: lint 26 | lint: $(JSONNETLINT_BIN) 27 | find . -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ 28 | xargs -n 1 -- $(JSONNETLINT_BIN) 29 | 30 | 31 | $(BIN_DIR): 32 | mkdir -p $(BIN_DIR) 33 | 34 | $(TOOLING): $(BIN_DIR) 35 | @echo Installing tools from buildscripts/tools.go 36 | @cd buildscripts && cat tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go build -modfile=go.mod -o $(BIN_DIR) % 37 | -------------------------------------------------------------------------------- /jsonnet/buildscripts/go.mod: -------------------------------------------------------------------------------- 1 | module _ // go.mod created for tooling dependencies 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/google/go-jsonnet v0.20.0 7 | github.com/jsonnet-bundler/jsonnet-bundler v0.4.0 8 | ) 9 | 10 | require ( 11 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect 12 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect 13 | github.com/fatih/color v1.12.0 // indirect 14 | github.com/mattn/go-colorable v0.1.8 // indirect 15 | github.com/mattn/go-isatty v0.0.12 // indirect 16 | github.com/pkg/errors v0.8.0 // indirect 17 | golang.org/x/sys v0.1.0 // indirect 18 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect 19 | gopkg.in/yaml.v2 v2.4.0 // indirect 20 | sigs.k8s.io/yaml v1.2.0 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /jsonnet/buildscripts/go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= 2 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 3 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= 4 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 5 | github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 10 | github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= 11 | github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= 12 | github.com/google/go-jsonnet v0.20.0 h1:WG4TTSARuV7bSm4PMB4ohjxe33IHT5WVTrJSU33uT4g= 13 | github.com/google/go-jsonnet v0.20.0/go.mod h1:VbgWF9JX7ztlv770x/TolZNGGFfiHEVx9G6ca2eUmeA= 14 | github.com/jsonnet-bundler/jsonnet-bundler v0.4.0 h1:4BKZ6LDqPc2wJDmaKnmYD/vDjUptJtnUpai802MibFc= 15 | github.com/jsonnet-bundler/jsonnet-bundler v0.4.0/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= 16 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 17 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 18 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 19 | github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 20 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 21 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 22 | github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 23 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 24 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 25 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 26 | github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= 27 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 28 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 29 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 30 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 31 | golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 32 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= 35 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 37 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 38 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 39 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 40 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 41 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 42 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 43 | sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= 44 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 45 | -------------------------------------------------------------------------------- /jsonnet/buildscripts/tools.go: -------------------------------------------------------------------------------- 1 | //+build tools 2 | 3 | // Package tools tracks dependencies for tools that used in the build process. 4 | // See https://github.com/golang/go/wiki/Modules 5 | package tools 6 | 7 | import ( 8 | _ "github.com/google/go-jsonnet/cmd/jsonnet" 9 | _ "github.com/google/go-jsonnet/cmd/jsonnet-lint" 10 | _ "github.com/google/go-jsonnet/cmd/jsonnetfmt" 11 | _ "github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb" 12 | ) 13 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/Makefile: -------------------------------------------------------------------------------- 1 | JSONNET_ARGS := -n 2 --max-blank-lines 2 --string-style s --comment-style s 2 | ifneq (,$(shell which jsonnetfmt)) 3 | JSONNET_FMT_CMD := jsonnetfmt 4 | else 5 | JSONNET_FMT_CMD := jsonnet 6 | JSONNET_FMT_ARGS := fmt $(JSONNET_ARGS) 7 | endif 8 | JSONNET_FMT := $(JSONNET_FMT_CMD) $(JSONNET_FMT_ARGS) 9 | 10 | dashboardsDirPath=../../deploy/charts/dashboards 11 | rulessDirPath=../../deploy/charts/rules 12 | 13 | all: fmt generate lint 14 | 15 | fmt: 16 | find . -name 'vendor' -prune -o -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ 17 | xargs -n 1 -- $(JSONNET_FMT) -i 18 | 19 | generate: build.sh 20 | bash build.sh $< 21 | 22 | lint: 23 | find . -name 'vendor' -prune -o -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ 24 | while read f; do \ 25 | $(JSONNET_FMT) "$$f" | diff -u "$$f" -; \ 26 | done 27 | 28 | clean: 29 | rm -rf $(dashboardsDirPath) $(rulessDirPath) 30 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/README.md: -------------------------------------------------------------------------------- 1 | # openebs mixin 2 | 3 | A set of Grafana dashboards and Prometheus alerts for openebs. 4 | 5 | ## Generate dashboards and rules 6 | 7 | You can manually generate the alerts, dashboards and rules files. 8 | 9 | #### Steps: 10 | 11 | 1. Install `jsonnet` and `jb` 12 | ``` 13 | $ go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb 14 | $ sudo apt-get install jsonnet 15 | ``` 16 | 17 | 2. Then, grab the mixin and its dependencies: 18 | 19 | ``` 20 | $ git clone https://github.com/openebs/monitoring 21 | $ cd monitoring/jsonnet/openebs-mixin 22 | $ jb install 23 | ``` 24 | 25 | 3. Update the dashboards and rules directory path in `build.sh` 26 | ``` 27 | dashboardsDirPath = '' 28 | rulesDirPath = '' 29 | ``` 30 | 31 | 4. Finally, build the mixin: 32 | 33 | ``` 34 | $ make generate 35 | ``` 36 | 37 | The files in `rulesDirPath` contain Prometheus-based alert rules for OpenEBS. These files will be aggregated to form a prometheusRule yaml that need to be imported into your Prometheus instance. 38 | Similarly, the files in `dashboardsDirPath` are dashboard json files that need to be imported into your Grafana instance. 39 | 40 | ## Configuration 41 | 42 | The available fields and their default values are present in `config.libsonnet`. 43 | 44 | ``` 45 | { 46 | // openebs-mixin configurations 47 | _config+:: { 48 | // Configuration to set which cas types is installed. Based on this, dashboards and alert rules configuration will be set. 49 | casTypes: { 50 | mayastor: true, 51 | lvmLocalPV: true, 52 | zfsLocalPV: true, 53 | }, 54 | // dashboards configuration. If set, then dashboards json will be generated. 55 | dashboards: { 56 | mayastor: $._config.casTypes.mayastor 57 | lvmLocalPV: $._config.casTypes.lvmLocalPV, 58 | zfsLocalPV: $._config.casTypes.zfsLocalPV, 59 | npd: true, 60 | }, 61 | // AlertRules configuration. If set, then rules json will be generated. 62 | alertRules: { 63 | lvmLocalPV: $._config.casTypes.lvmLocalPV, 64 | volume: $._config.casTypes.lvmLocalPV, 65 | npd: true, 66 | }, 67 | }, 68 | } 69 | ``` 70 | --- 71 | 72 | ## How to use openebs-mixin? 73 | Please visit the [user guide](../../docs/openebs-mixin-user-guide.md) for detailed instructions. -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | set -e 5 | set -x 6 | # only exit with zero if all commands of the pipeline exit successfully 7 | set -o pipefail 8 | 9 | dashboardsDirPath=../../deploy/charts/dashboards 10 | rulesDirPath=../../deploy/charts/rules 11 | 12 | generateDashboards(){ 13 | rm -rf $dashboardsDirPath 14 | mkdir -p $dashboardsDirPath 15 | jsonnet -J vendor -m $dashboardsDirPath lib/dashboards.jsonnet 16 | dashboardsFolder=(npd lvmLocalPV zfsLocalPV mayastor) 17 | for i in ${dashboardsFolder[@]} 18 | do 19 | x=`echo $i | awk '{print tolower($0)}'` 20 | mkdir -p $dashboardsDirPath/$i 21 | find ./$dashboardsDirPath -type f -name "*$x*" |xargs -I{} sh -c "mv {} $dashboardsDirPath/$i/" 22 | done 23 | } 24 | 25 | generateRules(){ 26 | rm -rf $rulesDirPath 27 | mkdir -p $rulesDirPath 28 | jsonnet -J vendor -m $rulesDirPath lib/rules.jsonnet 29 | rulesFolder=(volume npd lvmLocalPV) 30 | for i in ${rulesFolder[@]} 31 | do 32 | x=`echo $i | awk '{print tolower($0)}'` 33 | mkdir -p $rulesDirPath/$i 34 | find ./$rulesDirPath -type f -name "*$x*" |xargs -I{} sh -c "mv {} $rulesDirPath/$i/" 35 | done 36 | } 37 | 38 | generateDashboards; 39 | generateRules; 40 | 41 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/config.libsonnet: -------------------------------------------------------------------------------- 1 | { 2 | // openebs-mixin configurations 3 | _config+:: { 4 | // Configuration to set which cas types is installed. Based on this, dashboards and alert rules configuration will be set. 5 | casTypes: { 6 | lvmLocalPV: true, 7 | zfsLocalPV: true, 8 | mayastor: true, 9 | }, 10 | 11 | // dashboards configuration. If set, then dashboards json will be generated. 12 | dashboards: { 13 | lvmLocalPV: $._config.casTypes.lvmLocalPV, 14 | zfsLocalPV: $._config.casTypes.zfsLocalPV, 15 | npd: true, 16 | mayastor: $._config.casTypes.mayastor, 17 | }, 18 | // AlertRules configuration. If set, then rules json will be generated. 19 | alertRules: { 20 | lvmLocalPV: $._config.casTypes.lvmLocalPV, 21 | volume: $._config.casTypes.lvmLocalPV, 22 | npd: true, 23 | }, 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/dashboards/dashboards.libsonnet: -------------------------------------------------------------------------------- 1 | // Populate grafanaDashboards object 2 | function(param) { 3 | local dashboard = self, 4 | _config+:: param, 5 | grafanaDashboards+:: { 6 | [if dashboard._config.dashboards.lvmLocalPV then 'lvmlocalpv-pool.json']: import './openebs/lvmlocalpv-pool.json', 7 | [if dashboard._config.dashboards.zfsLocalPV then 'zfslocalpv.json']: import './openebs/zfslocalpv.json', 8 | [if dashboard._config.dashboards.mayastor then 'mayastor-diskpool.json']: import './mayastor/mayastor-diskpool.json', 9 | [if dashboard._config.dashboards.mayastor then 'mayastor-volume.json']: import './mayastor/mayastor-volume.json', 10 | [if dashboard._config.dashboards.mayastor then 'mayastor-volume-replica.json']: import './mayastor/mayastor-volume-replica.json', 11 | [if dashboard._config.dashboards.npd then 'npd-node-volume-problem.json']: import './npd/npd-node-volume-problem.json', 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/dashboards/mayastor/mayastor-volume-replica.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": true, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "id": 43, 22 | "links": [], 23 | "panels": [ 24 | { 25 | "datasource": { 26 | "type": "prometheus", 27 | "uid": "$datasource" 28 | }, 29 | "fieldConfig": { 30 | "defaults": { 31 | "color": { 32 | "mode": "palette-classic" 33 | }, 34 | "custom": { 35 | "axisBorderShow": false, 36 | "axisCenteredZero": false, 37 | "axisColorMode": "text", 38 | "axisLabel": "", 39 | "axisPlacement": "auto", 40 | "barAlignment": 0, 41 | "drawStyle": "line", 42 | "fillOpacity": 10, 43 | "gradientMode": "none", 44 | "hideFrom": { 45 | "legend": false, 46 | "tooltip": false, 47 | "viz": false 48 | }, 49 | "insertNulls": false, 50 | "lineInterpolation": "linear", 51 | "lineStyle": { 52 | "fill": "solid" 53 | }, 54 | "lineWidth": 1, 55 | "pointSize": 5, 56 | "scaleDistribution": { 57 | "type": "linear" 58 | }, 59 | "showPoints": "never", 60 | "spanNulls": false, 61 | "stacking": { 62 | "group": "A", 63 | "mode": "none" 64 | }, 65 | "thresholdsStyle": { 66 | "mode": "off" 67 | } 68 | }, 69 | "mappings": [], 70 | "thresholds": { 71 | "mode": "absolute", 72 | "steps": [ 73 | { 74 | "color": "green", 75 | "value": null 76 | } 77 | ] 78 | }, 79 | "unit": "iops" 80 | }, 81 | "overrides": [] 82 | }, 83 | "gridPos": { 84 | "h": 8, 85 | "w": 12, 86 | "x": 0, 87 | "y": 0 88 | }, 89 | "id": 1, 90 | "options": { 91 | "legend": { 92 | "calcs": [], 93 | "displayMode": "list", 94 | "placement": "bottom", 95 | "showLegend": true 96 | }, 97 | "tooltip": { 98 | "mode": "multi", 99 | "sort": "none" 100 | } 101 | }, 102 | "pluginVersion": "10.4.0", 103 | "targets": [ 104 | { 105 | "datasource": { 106 | "uid": "$datasource" 107 | }, 108 | "editorMode": "code", 109 | "exemplar": false, 110 | "expr": "irate(replica_num_read_ops{name=~\"$replica_name\"}[1m])", 111 | "interval": "", 112 | "legendFormat": "read", 113 | "range": true, 114 | "refId": "A" 115 | }, 116 | { 117 | "datasource": { 118 | "type": "prometheus", 119 | "uid": "$datasource" 120 | }, 121 | "editorMode": "code", 122 | "expr": "irate(replica_num_write_ops{name=~\"$replica_name\"}[1m])", 123 | "format": "time_series", 124 | "hide": false, 125 | "instant": false, 126 | "interval": "", 127 | "legendFormat": "write", 128 | "range": true, 129 | "refId": "B" 130 | } 131 | ], 132 | "title": "IOPS", 133 | "type": "timeseries" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "prometheus", 138 | "uid": "$datasource" 139 | }, 140 | "fieldConfig": { 141 | "defaults": { 142 | "color": { 143 | "mode": "palette-classic" 144 | }, 145 | "custom": { 146 | "axisBorderShow": false, 147 | "axisCenteredZero": false, 148 | "axisColorMode": "text", 149 | "axisLabel": "", 150 | "axisPlacement": "auto", 151 | "barAlignment": 0, 152 | "drawStyle": "line", 153 | "fillOpacity": 10, 154 | "gradientMode": "none", 155 | "hideFrom": { 156 | "legend": false, 157 | "tooltip": false, 158 | "viz": false 159 | }, 160 | "insertNulls": false, 161 | "lineInterpolation": "linear", 162 | "lineStyle": { 163 | "fill": "solid" 164 | }, 165 | "lineWidth": 1, 166 | "pointSize": 5, 167 | "scaleDistribution": { 168 | "type": "linear" 169 | }, 170 | "showPoints": "never", 171 | "spanNulls": false, 172 | "stacking": { 173 | "group": "A", 174 | "mode": "none" 175 | }, 176 | "thresholdsStyle": { 177 | "mode": "off" 178 | } 179 | }, 180 | "mappings": [], 181 | "thresholds": { 182 | "mode": "absolute", 183 | "steps": [ 184 | { 185 | "color": "green", 186 | "value": null 187 | } 188 | ] 189 | }, 190 | "unit": "binBps" 191 | }, 192 | "overrides": [] 193 | }, 194 | "gridPos": { 195 | "h": 8, 196 | "w": 12, 197 | "x": 12, 198 | "y": 0 199 | }, 200 | "id": 2, 201 | "options": { 202 | "legend": { 203 | "calcs": [], 204 | "displayMode": "list", 205 | "placement": "bottom", 206 | "showLegend": true 207 | }, 208 | "tooltip": { 209 | "mode": "multi", 210 | "sort": "none" 211 | } 212 | }, 213 | "pluginVersion": "10.4.0", 214 | "targets": [ 215 | { 216 | "datasource": { 217 | "uid": "$datasource" 218 | }, 219 | "editorMode": "code", 220 | "exemplar": true, 221 | "expr": "irate(replica_bytes_read{name=~\"$replica_name\"}[1m])", 222 | "interval": "", 223 | "legendFormat": "read", 224 | "range": true, 225 | "refId": "A" 226 | }, 227 | { 228 | "datasource": { 229 | "type": "prometheus", 230 | "uid": "$datasource" 231 | }, 232 | "editorMode": "code", 233 | "expr": "irate(replica_bytes_written{name=~\"$replica_name\"}[1m])", 234 | "hide": false, 235 | "instant": false, 236 | "legendFormat": "write", 237 | "range": true, 238 | "refId": "B" 239 | } 240 | ], 241 | "title": "Throughput", 242 | "type": "timeseries" 243 | }, 244 | { 245 | "datasource": { 246 | "type": "prometheus", 247 | "uid": "$datasource" 248 | }, 249 | "fieldConfig": { 250 | "defaults": { 251 | "color": { 252 | "mode": "palette-classic" 253 | }, 254 | "custom": { 255 | "axisBorderShow": false, 256 | "axisCenteredZero": false, 257 | "axisColorMode": "text", 258 | "axisLabel": "", 259 | "axisPlacement": "auto", 260 | "barAlignment": 0, 261 | "drawStyle": "line", 262 | "fillOpacity": 10, 263 | "gradientMode": "none", 264 | "hideFrom": { 265 | "legend": false, 266 | "tooltip": false, 267 | "viz": false 268 | }, 269 | "insertNulls": false, 270 | "lineInterpolation": "linear", 271 | "lineStyle": { 272 | "fill": "solid" 273 | }, 274 | "lineWidth": 1, 275 | "pointSize": 5, 276 | "scaleDistribution": { 277 | "type": "linear" 278 | }, 279 | "showPoints": "never", 280 | "spanNulls": false, 281 | "stacking": { 282 | "group": "A", 283 | "mode": "none" 284 | }, 285 | "thresholdsStyle": { 286 | "mode": "off" 287 | } 288 | }, 289 | "mappings": [], 290 | "thresholds": { 291 | "mode": "absolute", 292 | "steps": [ 293 | { 294 | "color": "green", 295 | "value": null 296 | } 297 | ] 298 | }, 299 | "unit": "s" 300 | }, 301 | "overrides": [] 302 | }, 303 | "gridPos": { 304 | "h": 8, 305 | "w": 12, 306 | "x": 6, 307 | "y": 8 308 | }, 309 | "id": 3, 310 | "options": { 311 | "legend": { 312 | "calcs": [], 313 | "displayMode": "list", 314 | "placement": "bottom", 315 | "showLegend": true 316 | }, 317 | "tooltip": { 318 | "mode": "multi", 319 | "sort": "none" 320 | } 321 | }, 322 | "pluginVersion": "10.4.0", 323 | "targets": [ 324 | { 325 | "datasource": { 326 | "uid": "$datasource" 327 | }, 328 | "editorMode": "code", 329 | "exemplar": true, 330 | "expr": "((irate(replica_read_latency_us{name=~\"$replica_name\"}[1m]))/(irate(replica_num_read_ops{name=~\"$replica_name\"}[1m])))/1000000", 331 | "interval": "", 332 | "legendFormat": "read", 333 | "range": true, 334 | "refId": "A" 335 | }, 336 | { 337 | "datasource": { 338 | "type": "prometheus", 339 | "uid": "$datasource" 340 | }, 341 | "editorMode": "code", 342 | "expr": "((irate(replica_write_latency_us{name=~\"$replica_name\"}[1m]))/(irate(replica_num_write_ops{name=~\"$replica_name\"}[1m])))/1000000", 343 | "hide": false, 344 | "instant": false, 345 | "legendFormat": "write", 346 | "range": true, 347 | "refId": "B" 348 | } 349 | ], 350 | "title": "Latency", 351 | "type": "timeseries" 352 | } 353 | ], 354 | "refresh": "5s", 355 | "schemaVersion": 39, 356 | "tags": [ 357 | "OpenEBS", 358 | "Mayastor" 359 | ], 360 | "templating": { 361 | "list": [ 362 | { 363 | "current": { 364 | "selected": false, 365 | "text": "Prometheus", 366 | "value": "prometheus" 367 | }, 368 | "hide": 0, 369 | "includeAll": false, 370 | "multi": false, 371 | "name": "datasource", 372 | "options": [], 373 | "query": "prometheus", 374 | "refresh": 1, 375 | "regex": "", 376 | "skipUrlSync": false, 377 | "type": "datasource" 378 | }, 379 | { 380 | "current": { 381 | "selected": true, 382 | "text": [ 383 | "All" 384 | ], 385 | "value": [ 386 | "$__all" 387 | ] 388 | }, 389 | "datasource": { 390 | "type": "prometheus", 391 | "uid": "${datasource}" 392 | }, 393 | "definition": "label_values(replica_num_read_ops,name)", 394 | "hide": 0, 395 | "includeAll": true, 396 | "multi": true, 397 | "name": "replica_name", 398 | "options": [], 399 | "query": { 400 | "qryType": 1, 401 | "query": "label_values(replica_num_read_ops,name)", 402 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 403 | }, 404 | "refresh": 2, 405 | "regex": "", 406 | "skipUrlSync": false, 407 | "sort": 0, 408 | "type": "query" 409 | } 410 | ] 411 | }, 412 | "time": { 413 | "from": "now-1h", 414 | "to": "now" 415 | }, 416 | "timepicker": {}, 417 | "timezone": "browser", 418 | "title": "OpenEBS / Replicated PV / Mayastor / Volume Replica", 419 | "uid": "fdl05xto1hn28e", 420 | "version": 6, 421 | "weekStart": "" 422 | } -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/dashboards/mayastor/mayastor-volume.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "type": "dashboard" 15 | } 16 | ] 17 | }, 18 | "editable": true, 19 | "fiscalYearStartMonth": 0, 20 | "graphTooltip": 0, 21 | "id": 42, 22 | "links": [], 23 | "panels": [ 24 | { 25 | "datasource": { 26 | "type": "prometheus", 27 | "uid": "$datasource" 28 | }, 29 | "fieldConfig": { 30 | "defaults": { 31 | "color": { 32 | "mode": "palette-classic" 33 | }, 34 | "custom": { 35 | "axisBorderShow": false, 36 | "axisCenteredZero": false, 37 | "axisColorMode": "text", 38 | "axisLabel": "", 39 | "axisPlacement": "auto", 40 | "barAlignment": 0, 41 | "drawStyle": "line", 42 | "fillOpacity": 10, 43 | "gradientMode": "none", 44 | "hideFrom": { 45 | "legend": false, 46 | "tooltip": false, 47 | "viz": false 48 | }, 49 | "insertNulls": false, 50 | "lineInterpolation": "linear", 51 | "lineStyle": { 52 | "fill": "solid" 53 | }, 54 | "lineWidth": 1, 55 | "pointSize": 5, 56 | "scaleDistribution": { 57 | "type": "linear" 58 | }, 59 | "showPoints": "never", 60 | "spanNulls": false, 61 | "stacking": { 62 | "group": "A", 63 | "mode": "none" 64 | }, 65 | "thresholdsStyle": { 66 | "mode": "off" 67 | } 68 | }, 69 | "mappings": [], 70 | "thresholds": { 71 | "mode": "absolute", 72 | "steps": [ 73 | { 74 | "color": "green", 75 | "value": null 76 | } 77 | ] 78 | }, 79 | "unit": "iops" 80 | }, 81 | "overrides": [] 82 | }, 83 | "gridPos": { 84 | "h": 8, 85 | "w": 12, 86 | "x": 0, 87 | "y": 0 88 | }, 89 | "id": 1, 90 | "options": { 91 | "legend": { 92 | "calcs": [], 93 | "displayMode": "list", 94 | "placement": "bottom", 95 | "showLegend": true 96 | }, 97 | "tooltip": { 98 | "mode": "multi", 99 | "sort": "none" 100 | } 101 | }, 102 | "pluginVersion": "10.4.0", 103 | "targets": [ 104 | { 105 | "datasource": { 106 | "uid": "$datasource" 107 | }, 108 | "editorMode": "code", 109 | "exemplar": false, 110 | "expr": "irate(volume_num_read_ops{pv_name=~\"$pv_name\"}[1m])", 111 | "interval": "", 112 | "legendFormat": "read", 113 | "range": true, 114 | "refId": "A" 115 | }, 116 | { 117 | "datasource": { 118 | "type": "prometheus", 119 | "uid": "$datasource" 120 | }, 121 | "editorMode": "code", 122 | "expr": "irate(volume_num_write_ops{pv_name=~\"$pv_name\"}[1m])", 123 | "format": "time_series", 124 | "hide": false, 125 | "instant": false, 126 | "interval": "", 127 | "legendFormat": "write", 128 | "range": true, 129 | "refId": "B" 130 | } 131 | ], 132 | "title": "IOPS", 133 | "type": "timeseries" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "prometheus", 138 | "uid": "$datasource" 139 | }, 140 | "fieldConfig": { 141 | "defaults": { 142 | "color": { 143 | "mode": "palette-classic" 144 | }, 145 | "custom": { 146 | "axisBorderShow": false, 147 | "axisCenteredZero": false, 148 | "axisColorMode": "text", 149 | "axisLabel": "", 150 | "axisPlacement": "auto", 151 | "barAlignment": 0, 152 | "drawStyle": "line", 153 | "fillOpacity": 10, 154 | "gradientMode": "none", 155 | "hideFrom": { 156 | "legend": false, 157 | "tooltip": false, 158 | "viz": false 159 | }, 160 | "insertNulls": false, 161 | "lineInterpolation": "linear", 162 | "lineStyle": { 163 | "fill": "solid" 164 | }, 165 | "lineWidth": 1, 166 | "pointSize": 5, 167 | "scaleDistribution": { 168 | "type": "linear" 169 | }, 170 | "showPoints": "never", 171 | "spanNulls": false, 172 | "stacking": { 173 | "group": "A", 174 | "mode": "none" 175 | }, 176 | "thresholdsStyle": { 177 | "mode": "off" 178 | } 179 | }, 180 | "mappings": [], 181 | "thresholds": { 182 | "mode": "absolute", 183 | "steps": [ 184 | { 185 | "color": "green", 186 | "value": null 187 | } 188 | ] 189 | }, 190 | "unit": "binBps" 191 | }, 192 | "overrides": [] 193 | }, 194 | "gridPos": { 195 | "h": 8, 196 | "w": 12, 197 | "x": 12, 198 | "y": 0 199 | }, 200 | "id": 2, 201 | "options": { 202 | "legend": { 203 | "calcs": [], 204 | "displayMode": "list", 205 | "placement": "bottom", 206 | "showLegend": true 207 | }, 208 | "tooltip": { 209 | "mode": "multi", 210 | "sort": "none" 211 | } 212 | }, 213 | "pluginVersion": "10.4.0", 214 | "targets": [ 215 | { 216 | "datasource": { 217 | "uid": "$datasource" 218 | }, 219 | "editorMode": "code", 220 | "exemplar": true, 221 | "expr": "irate(volume_bytes_read{pv_name=~\"$pv_name\"}[1m])", 222 | "interval": "", 223 | "legendFormat": "read", 224 | "range": true, 225 | "refId": "A" 226 | }, 227 | { 228 | "datasource": { 229 | "type": "prometheus", 230 | "uid": "$datasource" 231 | }, 232 | "editorMode": "code", 233 | "expr": "irate(volume_bytes_written{pv_name=~\"$pv_name\"}[1m])", 234 | "hide": false, 235 | "instant": false, 236 | "legendFormat": "write", 237 | "range": true, 238 | "refId": "B" 239 | } 240 | ], 241 | "title": "Throughput", 242 | "type": "timeseries" 243 | }, 244 | { 245 | "datasource": { 246 | "type": "prometheus", 247 | "uid": "$datasource" 248 | }, 249 | "fieldConfig": { 250 | "defaults": { 251 | "color": { 252 | "mode": "palette-classic" 253 | }, 254 | "custom": { 255 | "axisBorderShow": false, 256 | "axisCenteredZero": false, 257 | "axisColorMode": "text", 258 | "axisLabel": "", 259 | "axisPlacement": "auto", 260 | "barAlignment": 0, 261 | "drawStyle": "line", 262 | "fillOpacity": 10, 263 | "gradientMode": "none", 264 | "hideFrom": { 265 | "legend": false, 266 | "tooltip": false, 267 | "viz": false 268 | }, 269 | "insertNulls": false, 270 | "lineInterpolation": "linear", 271 | "lineStyle": { 272 | "fill": "solid" 273 | }, 274 | "lineWidth": 1, 275 | "pointSize": 5, 276 | "scaleDistribution": { 277 | "type": "linear" 278 | }, 279 | "showPoints": "never", 280 | "spanNulls": false, 281 | "stacking": { 282 | "group": "A", 283 | "mode": "none" 284 | }, 285 | "thresholdsStyle": { 286 | "mode": "off" 287 | } 288 | }, 289 | "mappings": [], 290 | "thresholds": { 291 | "mode": "absolute", 292 | "steps": [ 293 | { 294 | "color": "green", 295 | "value": null 296 | } 297 | ] 298 | }, 299 | "unit": "s" 300 | }, 301 | "overrides": [] 302 | }, 303 | "gridPos": { 304 | "h": 8, 305 | "w": 12, 306 | "x": 6, 307 | "y": 8 308 | }, 309 | "id": 3, 310 | "options": { 311 | "legend": { 312 | "calcs": [], 313 | "displayMode": "list", 314 | "placement": "bottom", 315 | "showLegend": true 316 | }, 317 | "tooltip": { 318 | "mode": "multi", 319 | "sort": "none" 320 | } 321 | }, 322 | "pluginVersion": "10.4.0", 323 | "targets": [ 324 | { 325 | "datasource": { 326 | "uid": "$datasource" 327 | }, 328 | "editorMode": "code", 329 | "exemplar": true, 330 | "expr": "((irate(volume_read_latency_us{pv_name=~\"$pv_name\"}[1m]))/(irate(volume_num_read_ops{pv_name=~\"$pv_name\"}[1m])))/1000000", 331 | "interval": "", 332 | "legendFormat": "read", 333 | "range": true, 334 | "refId": "A" 335 | }, 336 | { 337 | "datasource": { 338 | "type": "prometheus", 339 | "uid": "$datasource" 340 | }, 341 | "editorMode": "code", 342 | "expr": "((irate(volume_write_latency_us{pv_name=~\"$pv_name\"}[1m]))/(irate(volume_num_write_ops{pv_name=~\"$pv_name\"}[1m])))/1000000", 343 | "hide": false, 344 | "instant": false, 345 | "legendFormat": "write", 346 | "range": true, 347 | "refId": "B" 348 | } 349 | ], 350 | "title": "Latency", 351 | "type": "timeseries" 352 | } 353 | ], 354 | "refresh": "5s", 355 | "schemaVersion": 39, 356 | "tags": [ 357 | "OpenEBS", 358 | "Mayastor" 359 | ], 360 | "templating": { 361 | "list": [ 362 | { 363 | "current": { 364 | "selected": false, 365 | "text": "Prometheus", 366 | "value": "prometheus" 367 | }, 368 | "hide": 0, 369 | "includeAll": false, 370 | "multi": false, 371 | "name": "datasource", 372 | "options": [], 373 | "query": "prometheus", 374 | "refresh": 1, 375 | "regex": "", 376 | "skipUrlSync": false, 377 | "type": "datasource" 378 | }, 379 | { 380 | "current": { 381 | "selected": true, 382 | "text": [ 383 | "pvc-d070ac1c-6bb7-4ece-9893-5471c0c636a8" 384 | ], 385 | "value": [ 386 | "pvc-d070ac1c-6bb7-4ece-9893-5471c0c636a8" 387 | ] 388 | }, 389 | "datasource": { 390 | "type": "prometheus", 391 | "uid": "${datasource}" 392 | }, 393 | "definition": "label_values(volume_num_read_ops,pv_name)", 394 | "hide": 0, 395 | "includeAll": true, 396 | "multi": true, 397 | "name": "pv_name", 398 | "options": [], 399 | "query": { 400 | "qryType": 1, 401 | "query": "label_values(volume_num_read_ops,pv_name)", 402 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 403 | }, 404 | "refresh": 2, 405 | "regex": "", 406 | "skipUrlSync": false, 407 | "sort": 0, 408 | "type": "query" 409 | } 410 | ] 411 | }, 412 | "time": { 413 | "from": "now-1h", 414 | "to": "now" 415 | }, 416 | "timepicker": {}, 417 | "timezone": "browser", 418 | "title": "OpenEBS / Replicated PV / Mayastor / Volume", 419 | "uid": "fdl05gxyisqo0d", 420 | "version": 6, 421 | "weekStart": "" 422 | } -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/dashboards/npd/npd-node-volume-problem.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "editable": true, 16 | "gnetId": null, 17 | "graphTooltip": 0, 18 | "id": 44, 19 | "links": [], 20 | "panels": [ 21 | { 22 | "datasource": "null", 23 | "fieldConfig": { 24 | "defaults": {}, 25 | "overrides": [] 26 | }, 27 | "gridPos": { 28 | "h": 7, 29 | "w": 24, 30 | "x": 0, 31 | "y": 0 32 | }, 33 | "id": 10, 34 | "options": { 35 | "content": "# *Node Problem Detector*\n---\n\nThe dashboard is used to detect problems with the nodes on which volumes are mounted on by watching the system logs. \nSince npd takes different approach in detecting node problems (parsing system log or dmesg files), it may be hard to find the disk device causing the actual problem. So, this dashboard currently associates the node problem(if any) with all the pvc provisioned on that bad node. \n```\nIf there are no probelm with the node on which the volume is mounted then the problem counter(or metric value) for each of the panels below will be '0'. But if any problem occurs then the counter value( or metric value) is increased by 1 everytime that error occurs in the system logs. Each panel below resembles one specific type of error. \n```\n ", 36 | "mode": "markdown" 37 | }, 38 | "pluginVersion": "7.5.5", 39 | "timeFrom": null, 40 | "timeShift": null, 41 | "title": "About the Dashboard", 42 | "type": "text" 43 | }, 44 | { 45 | "alert": { 46 | "alertRuleTags": {}, 47 | "conditions": [ 48 | { 49 | "evaluator": { 50 | "params": [0], 51 | "type": "gt" 52 | }, 53 | "operator": { 54 | "type": "and" 55 | }, 56 | "query": { 57 | "params": ["A", "5m", "now"] 58 | }, 59 | "reducer": { 60 | "params": [], 61 | "type": "avg" 62 | }, 63 | "type": "query" 64 | } 65 | ], 66 | "executionErrorState": "alerting", 67 | "for": "5m", 68 | "frequency": "1m", 69 | "handler": 1, 70 | "name": "FilesystemIsReadOnly", 71 | "noDataState": "no_data", 72 | "notifications": [] 73 | }, 74 | "aliasColors": {}, 75 | "bars": false, 76 | "dashLength": 10, 77 | "dashes": false, 78 | "datasource": null, 79 | "fieldConfig": { 80 | "defaults": {}, 81 | "overrides": [] 82 | }, 83 | "fill": 0, 84 | "fillGradient": 0, 85 | "gridPos": { 86 | "h": 9, 87 | "w": 12, 88 | "x": 0, 89 | "y": 7 90 | }, 91 | "hiddenSeries": false, 92 | "id": 2, 93 | "legend": { 94 | "alignAsTable": true, 95 | "avg": false, 96 | "current": true, 97 | "max": false, 98 | "min": false, 99 | "show": true, 100 | "total": false, 101 | "values": true 102 | }, 103 | "lines": true, 104 | "linewidth": 1, 105 | "nullPointMode": "null", 106 | "options": { 107 | "alertThreshold": true 108 | }, 109 | "percentage": false, 110 | "pluginVersion": "7.5.5", 111 | "pointradius": 2, 112 | "points": false, 113 | "renderer": "flot", 114 | "seriesOverrides": [], 115 | "spaceLength": 10, 116 | "stack": false, 117 | "steppedLine": false, 118 | "targets": [ 119 | { 120 | "exemplar": true, 121 | "expr": "(kubelet_volume_stats_inodes * 0) + on(node) group_left(reason) problem_counter{reason=\"FilesystemIsReadOnly\"}", 122 | "format": "time_series", 123 | "interval": "", 124 | "legendFormat": "Node: {{ node}}, PVC: {{ persistentvolumeclaim }} ", 125 | "refId": "A" 126 | } 127 | ], 128 | "thresholds": [ 129 | { 130 | "colorMode": "critical", 131 | "fill": true, 132 | "line": true, 133 | "op": "gt", 134 | "value": 0, 135 | "visible": true 136 | } 137 | ], 138 | "timeFrom": null, 139 | "timeRegions": [], 140 | "timeShift": null, 141 | "title": "FilesystemIsReadOnly", 142 | "tooltip": { 143 | "shared": true, 144 | "sort": 0, 145 | "value_type": "individual" 146 | }, 147 | "type": "graph", 148 | "xaxis": { 149 | "buckets": null, 150 | "mode": "time", 151 | "name": null, 152 | "show": true, 153 | "values": [] 154 | }, 155 | "yaxes": [ 156 | { 157 | "$$hashKey": "object:965", 158 | "format": "short", 159 | "label": null, 160 | "logBase": 1, 161 | "max": null, 162 | "min": null, 163 | "show": true 164 | }, 165 | { 166 | "$$hashKey": "object:966", 167 | "format": "short", 168 | "label": null, 169 | "logBase": 1, 170 | "max": null, 171 | "min": null, 172 | "show": false 173 | } 174 | ], 175 | "yaxis": { 176 | "align": false, 177 | "alignLevel": null 178 | } 179 | }, 180 | { 181 | "alert": { 182 | "alertRuleTags": {}, 183 | "conditions": [ 184 | { 185 | "evaluator": { 186 | "params": [0], 187 | "type": "gt" 188 | }, 189 | "operator": { 190 | "type": "and" 191 | }, 192 | "query": { 193 | "params": ["A", "5m", "now"] 194 | }, 195 | "reducer": { 196 | "params": [], 197 | "type": "avg" 198 | }, 199 | "type": "query" 200 | } 201 | ], 202 | "executionErrorState": "alerting", 203 | "for": "5m", 204 | "frequency": "1m", 205 | "handler": 1, 206 | "name": "Ext4Error", 207 | "noDataState": "no_data", 208 | "notifications": [] 209 | }, 210 | "aliasColors": {}, 211 | "bars": false, 212 | "dashLength": 10, 213 | "dashes": false, 214 | "datasource": null, 215 | "fieldConfig": { 216 | "defaults": {}, 217 | "overrides": [] 218 | }, 219 | "fill": 1, 220 | "fillGradient": 0, 221 | "gridPos": { 222 | "h": 9, 223 | "w": 12, 224 | "x": 12, 225 | "y": 7 226 | }, 227 | "hiddenSeries": false, 228 | "id": 4, 229 | "legend": { 230 | "alignAsTable": true, 231 | "avg": false, 232 | "current": true, 233 | "max": false, 234 | "min": false, 235 | "show": true, 236 | "total": false, 237 | "values": true 238 | }, 239 | "lines": true, 240 | "linewidth": 1, 241 | "nullPointMode": "null", 242 | "options": { 243 | "alertThreshold": true 244 | }, 245 | "percentage": false, 246 | "pluginVersion": "7.5.5", 247 | "pointradius": 2, 248 | "points": false, 249 | "renderer": "flot", 250 | "seriesOverrides": [], 251 | "spaceLength": 10, 252 | "stack": false, 253 | "steppedLine": false, 254 | "targets": [ 255 | { 256 | "exemplar": true, 257 | "expr": "(kubelet_volume_stats_inodes * 0) + on(node) group_left(reason) problem_counter{reason=\"Ext4Error\"}", 258 | "interval": "", 259 | "legendFormat": "Node: {{ node}}, PVC: {{ persistentvolumeclaim }}", 260 | "refId": "A" 261 | } 262 | ], 263 | "thresholds": [ 264 | { 265 | "colorMode": "critical", 266 | "fill": true, 267 | "line": true, 268 | "op": "gt", 269 | "value": 0, 270 | "visible": true 271 | } 272 | ], 273 | "timeFrom": null, 274 | "timeRegions": [], 275 | "timeShift": null, 276 | "title": "Ext4Error", 277 | "tooltip": { 278 | "shared": true, 279 | "sort": 0, 280 | "value_type": "individual" 281 | }, 282 | "type": "graph", 283 | "xaxis": { 284 | "buckets": null, 285 | "mode": "time", 286 | "name": null, 287 | "show": true, 288 | "values": [] 289 | }, 290 | "yaxes": [ 291 | { 292 | "$$hashKey": "object:1379", 293 | "format": "short", 294 | "label": null, 295 | "logBase": 1, 296 | "max": null, 297 | "min": null, 298 | "show": true 299 | }, 300 | { 301 | "$$hashKey": "object:1380", 302 | "format": "short", 303 | "label": null, 304 | "logBase": 1, 305 | "max": null, 306 | "min": null, 307 | "show": false 308 | } 309 | ], 310 | "yaxis": { 311 | "align": false, 312 | "alignLevel": null 313 | } 314 | }, 315 | { 316 | "alert": { 317 | "alertRuleTags": {}, 318 | "conditions": [ 319 | { 320 | "evaluator": { 321 | "params": [0], 322 | "type": "gt" 323 | }, 324 | "operator": { 325 | "type": "and" 326 | }, 327 | "query": { 328 | "params": ["A", "5m", "now"] 329 | }, 330 | "reducer": { 331 | "params": [], 332 | "type": "avg" 333 | }, 334 | "type": "query" 335 | } 336 | ], 337 | "executionErrorState": "alerting", 338 | "for": "5m", 339 | "frequency": "1m", 340 | "handler": 1, 341 | "name": "IOError", 342 | "noDataState": "no_data", 343 | "notifications": [] 344 | }, 345 | "aliasColors": {}, 346 | "bars": false, 347 | "dashLength": 10, 348 | "dashes": false, 349 | "datasource": null, 350 | "fieldConfig": { 351 | "defaults": {}, 352 | "overrides": [] 353 | }, 354 | "fill": 1, 355 | "fillGradient": 0, 356 | "gridPos": { 357 | "h": 8, 358 | "w": 12, 359 | "x": 0, 360 | "y": 16 361 | }, 362 | "hiddenSeries": false, 363 | "id": 6, 364 | "legend": { 365 | "alignAsTable": true, 366 | "avg": false, 367 | "current": true, 368 | "max": false, 369 | "min": false, 370 | "show": true, 371 | "total": false, 372 | "values": true 373 | }, 374 | "lines": true, 375 | "linewidth": 1, 376 | "nullPointMode": "null", 377 | "options": { 378 | "alertThreshold": true 379 | }, 380 | "percentage": false, 381 | "pluginVersion": "7.5.5", 382 | "pointradius": 2, 383 | "points": false, 384 | "renderer": "flot", 385 | "seriesOverrides": [], 386 | "spaceLength": 10, 387 | "stack": false, 388 | "steppedLine": false, 389 | "targets": [ 390 | { 391 | "exemplar": true, 392 | "expr": "(kubelet_volume_stats_inodes * 0) + on(node) group_left(reason) problem_counter{reason=\"IOError\"} ", 393 | "interval": "", 394 | "legendFormat": "Node: {{ node}}, PVC: {{ persistentvolumeclaim }}", 395 | "refId": "A" 396 | } 397 | ], 398 | "thresholds": [ 399 | { 400 | "colorMode": "critical", 401 | "fill": true, 402 | "line": true, 403 | "op": "gt", 404 | "value": 0, 405 | "visible": true 406 | } 407 | ], 408 | "timeFrom": null, 409 | "timeRegions": [], 410 | "timeShift": null, 411 | "title": "IOError", 412 | "tooltip": { 413 | "shared": true, 414 | "sort": 0, 415 | "value_type": "individual" 416 | }, 417 | "type": "graph", 418 | "xaxis": { 419 | "buckets": null, 420 | "mode": "time", 421 | "name": null, 422 | "show": true, 423 | "values": [] 424 | }, 425 | "yaxes": [ 426 | { 427 | "$$hashKey": "object:1470", 428 | "format": "short", 429 | "label": null, 430 | "logBase": 1, 431 | "max": null, 432 | "min": null, 433 | "show": true 434 | }, 435 | { 436 | "$$hashKey": "object:1471", 437 | "format": "short", 438 | "label": null, 439 | "logBase": 1, 440 | "max": null, 441 | "min": null, 442 | "show": false 443 | } 444 | ], 445 | "yaxis": { 446 | "align": false, 447 | "alignLevel": null 448 | } 449 | }, 450 | { 451 | "alert": { 452 | "alertRuleTags": {}, 453 | "conditions": [ 454 | { 455 | "evaluator": { 456 | "params": [0], 457 | "type": "gt" 458 | }, 459 | "operator": { 460 | "type": "and" 461 | }, 462 | "query": { 463 | "params": ["A", "5m", "now"] 464 | }, 465 | "reducer": { 466 | "params": [], 467 | "type": "avg" 468 | }, 469 | "type": "query" 470 | } 471 | ], 472 | "executionErrorState": "alerting", 473 | "for": "5m", 474 | "frequency": "1m", 475 | "handler": 1, 476 | "name": "Ext4Warning", 477 | "noDataState": "no_data", 478 | "notifications": [] 479 | }, 480 | "aliasColors": {}, 481 | "bars": false, 482 | "dashLength": 10, 483 | "dashes": false, 484 | "datasource": null, 485 | "fieldConfig": { 486 | "defaults": {}, 487 | "overrides": [] 488 | }, 489 | "fill": 1, 490 | "fillGradient": 0, 491 | "gridPos": { 492 | "h": 8, 493 | "w": 12, 494 | "x": 12, 495 | "y": 16 496 | }, 497 | "hiddenSeries": false, 498 | "id": 8, 499 | "legend": { 500 | "alignAsTable": true, 501 | "avg": false, 502 | "current": true, 503 | "max": false, 504 | "min": false, 505 | "show": true, 506 | "total": false, 507 | "values": true 508 | }, 509 | "lines": true, 510 | "linewidth": 1, 511 | "nullPointMode": "null", 512 | "options": { 513 | "alertThreshold": true 514 | }, 515 | "percentage": false, 516 | "pluginVersion": "7.5.5", 517 | "pointradius": 2, 518 | "points": false, 519 | "renderer": "flot", 520 | "seriesOverrides": [], 521 | "spaceLength": 10, 522 | "stack": false, 523 | "steppedLine": false, 524 | "targets": [ 525 | { 526 | "exemplar": true, 527 | "expr": "(kubelet_volume_stats_inodes * 0) + on(node) group_left(reason) problem_counter{reason=\"Ext4Warning\"} ", 528 | "interval": "", 529 | "legendFormat": "Node: {{ node}}, PVC: {{ persistentvolumeclaim }} ", 530 | "refId": "A" 531 | } 532 | ], 533 | "thresholds": [ 534 | { 535 | "colorMode": "critical", 536 | "fill": true, 537 | "line": true, 538 | "op": "gt", 539 | "value": 0, 540 | "visible": true 541 | } 542 | ], 543 | "timeFrom": null, 544 | "timeRegions": [], 545 | "timeShift": null, 546 | "title": "Ext4Warning", 547 | "tooltip": { 548 | "shared": true, 549 | "sort": 0, 550 | "value_type": "individual" 551 | }, 552 | "type": "graph", 553 | "xaxis": { 554 | "buckets": null, 555 | "mode": "time", 556 | "name": null, 557 | "show": true, 558 | "values": [] 559 | }, 560 | "yaxes": [ 561 | { 562 | "$$hashKey": "object:1561", 563 | "format": "short", 564 | "label": null, 565 | "logBase": 1, 566 | "max": null, 567 | "min": null, 568 | "show": true 569 | }, 570 | { 571 | "$$hashKey": "object:1562", 572 | "format": "short", 573 | "label": null, 574 | "logBase": 1, 575 | "max": null, 576 | "min": null, 577 | "show": false 578 | } 579 | ], 580 | "yaxis": { 581 | "align": false, 582 | "alignLevel": null 583 | } 584 | } 585 | ], 586 | "refresh": false, 587 | "schemaVersion": 27, 588 | "style": "dark", 589 | "tags": ["npd"], 590 | "templating": { 591 | "list": [] 592 | }, 593 | "time": { 594 | "from": "now-6h", 595 | "to": "now" 596 | }, 597 | "timepicker": {}, 598 | "timezone": "", 599 | "title": "OpenEBS / Node Volume Problem", 600 | "uid": "4dCJNj6Mz", 601 | "version": 5 602 | } 603 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/jsonnetfile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "dependencies": [], 4 | "legacyImports": true 5 | } 6 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/lib/dashboards.jsonnet: -------------------------------------------------------------------------------- 1 | local mixin = (import '../mixin.libsonnet').grafanaDashboards; 2 | 3 | { 4 | // To generate dashboards json 5 | [name]: mixin[name] 6 | for name in std.objectFields(mixin) 7 | } 8 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/lib/rules.jsonnet: -------------------------------------------------------------------------------- 1 | local rules = (import '../mixin.libsonnet'); 2 | local config = import '../config.libsonnet'; 3 | 4 | { 5 | // To generate rules json 6 | [if config._config.alertRules[name] then std.asciiLower(name) + '-rules.json']: rules.rules[name] 7 | for name in std.objectFields(config._config.alertRules) 8 | } 9 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/mixin.libsonnet: -------------------------------------------------------------------------------- 1 | local dashboards = (import 'dashboards/dashboards.libsonnet'); 2 | local rules = (import 'rules/rules.libsonnet'); 3 | local prometheusRules = (import 'rules/prometheus-rules.libsonnet'); 4 | 5 | (import 'config.libsonnet') + 6 | { 7 | grafanaDashboards: dashboards($._config).grafanaDashboards, 8 | rules: rules($._config).prometheusRules, 9 | prometheusRules: prometheusRules($._config).prometheusRules, 10 | } 11 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/rules/npd/npd-rules.libsonnet: -------------------------------------------------------------------------------- 1 | // npd alert rules 2 | function(param) { 3 | //local rules = self, 4 | _config+:: param, 5 | prometheusRules+:: { 6 | npd: { 7 | groups+: [ 8 | { 9 | name: 'volume-node', 10 | rules: [ 11 | { 12 | alert: 'VolumeNodeFileSystemIsReadOnly', 13 | annotations: { 14 | summary: "Volume mount failed for persistent volume claim '{{ $labels.persistentvolumeclaim }}' on node '{{ $labels.node }}' due to read-only file-system", 15 | description: "Persistent Volume's filesystem on node '{{ $labels.node }}' for persistent volume claim '{{ $labels.persistentvolumeclaim }}' has become read-only", 16 | }, 17 | expr: 'kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason="FilesystemIsReadOnly"} > 0', 18 | 'for': '5m', 19 | labels: { 20 | severity: 'critical', 21 | }, 22 | }, 23 | { 24 | alert: 'VolumeNodeExt4Error', 25 | annotations: { 26 | summary: "Node '{{ $labels.node }}' has encountered errors on ext4 file-system on volume having claim '{{ $labels.persistentvolumeclaim }}'", 27 | description: "Persistent Volume's on node '{{ $labels.node }}' persistent volume claim '{{ $labels.persistentvolumeclaim }}' encountering ext4 filesystem error", 28 | }, 29 | expr: 'kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason="Ext4Error"} > 0', 30 | 'for': '5m', 31 | labels: { 32 | severity: 'critical', 33 | }, 34 | }, 35 | { 36 | alert: 'VolumeNodeIOError', 37 | annotations: { 38 | summary: "IO errors encountered on volume having persistent volume claim '{{ $labels.persistentvolumeclaim }}' on node '{{ $labels.node }}'", 39 | description: "Persistent Volume on node '{{ $labels.node }}' for persistent volume claim '{{ $labels.persistentvolumeclaim }}' encountering errors w.r.t buffer I/O ", 40 | }, 41 | expr: 'kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason="IOError"} > 0', 42 | 'for': '5m', 43 | labels: { 44 | severity: 'critical', 45 | }, 46 | }, 47 | { 48 | alert: 'VolumeNodeExt4Warning', 49 | annotations: { 50 | summary: "Node '{{ $labels.node }}' has encountered warning on ext4 file-system on volume having claim '{{ $labels.persistentvolumeclaim }}'", 51 | description: "Persistent Volume on node '{{ $labels.node }}' receiving ext4 filesystem warning for persistent volume claim '{{ $labels.persistentvolumeclaim }}'", 52 | }, 53 | expr: 'kubelet_volume_stats_inodes * on(node) group_left(reason) problem_counter{reason="Ext4Warning"} > 0', 54 | 'for': '5m', 55 | labels: { 56 | severity: 'critical', 57 | }, 58 | }, 59 | ], 60 | }, 61 | ], 62 | }, 63 | }, 64 | } 65 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/rules/openebs/lvmlocalpv-rules.libsonnet: -------------------------------------------------------------------------------- 1 | function(param) { 2 | //local rules = self, 3 | _config+:: param, 4 | prometheusRules+:: { 5 | lvmLocalPV: { 6 | groups+: [ 7 | { 8 | name: 'lvm-pool', 9 | rules: [ 10 | { 11 | alert: 'LVMVolumeGroupMissingPhysicalVolume', 12 | annotations: { 13 | componentType: 'volume group', 14 | vgName: '{{ $labels.name }}', 15 | summary: "LVM volume group '{{ $labels.name }}' is missing the underlying physical volume.", 16 | description: "LVM volume group '{{ $labels.name }}' on node '{{ $labels.instance }}' is missing {{ $value }} underlying physical volume(s).", 17 | }, 18 | expr: 'lvm_vg_missing_pv_count > 0', 19 | 'for': '5m', 20 | labels: { 21 | severity: 'critical', 22 | product: 'openebs', 23 | engine: 'localpv-lvm', 24 | }, 25 | }, 26 | { 27 | alert: 'LVMVolumeGroupCapacityLow', 28 | annotations: { 29 | componentType: 'volume group', 30 | vgName: '{{ $labels.name }}', 31 | summary: "LVM volume group '{{ $labels.name }}' is running low on capacity. Already {{ $value }}% of total capacity is consumed.", 32 | description: "LVM volume group '{{ $labels.name }}' on node '{{ $labels.instance }}' has {{ with printf \"lvm_vg_free_size_bytes{instance='%s',name='%s'}\" $labels.instance $labels.name | query }} {{ . | first | value }} {{ end }}bytes of space remaining", 33 | }, 34 | expr: '((lvm_vg_total_size_bytes - lvm_vg_free_size_bytes)/lvm_vg_total_size_bytes)*100 > 90', 35 | 'for': '5m', 36 | labels: { 37 | severity: 'critical', 38 | product: 'openebs', 39 | engine: 'localpv-lvm', 40 | }, 41 | }, 42 | { 43 | alert: 'LVMThinPoolCapacityLow', 44 | annotations: { 45 | componentType: 'logical volume', 46 | lvName: '{{ $labels.name }}', 47 | summary: "LVM thin pool '{{ $labels.name }}' is running low on capacity. Already {{ $value }}% of total capacity is consumed.", 48 | description: "LVM thin pool '{{ $labels.name }}' on node '{{ $labels.instance }}' has {{ with printf \"lvm_lv_total_size_bytes{instance='%s',name='%s',segtype='%s'}-((lvm_lv_used_percent{instance='%s',name='%s',segtype='%s'}*lvm_lv_total_size_bytes{instance='%s',name='%s',segtype='%s'})/100)\" $labels.instance $labels.name $labels.segtype $labels.instance $labels.name $labels.segtype $labels.instance $labels.name $labels.segtype | query }} {{ . | first | value }} {{ end }}bytes of space remaining", 49 | }, 50 | expr: 'lvm_lv_used_percent{segtype="thin-pool"} > 90', 51 | 'for': '5m', 52 | labels: { 53 | severity: 'critical', 54 | product: 'openebs', 55 | engine: 'localpv-lvm', 56 | }, 57 | }, 58 | ], 59 | }, 60 | ], 61 | }, 62 | }, 63 | } 64 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/rules/prometheus-rules.libsonnet: -------------------------------------------------------------------------------- 1 | local lvmLocalPV = (import './openebs/lvmlocalpv-rules.libsonnet'); 2 | local volume = (import './volume/volume-rules.libsonnet'); 3 | local npd = (import './npd/npd-rules.libsonnet'); 4 | 5 | // Populate prometheusRules object from volume, and npd rules. 6 | // prometheusRules:{ 7 | // groups:[ 8 | // {npd alert-1}, 9 | // {npd alert-2} 10 | // . 11 | // . 12 | // {npd alert-n}, 13 | // ... 14 | // ] 15 | // }, 16 | 17 | function(param) { 18 | local prometheusRules = self, 19 | _config+:: param, 20 | prometheusRules+:: 21 | lvmLocalPV(prometheusRules._config).prometheusRules.lvmLocalPV + volume(prometheusRules._config).prometheusRules.volume 22 | + npd(prometheusRules._config).prometheusRules.npd, 23 | } 24 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/rules/rules.libsonnet: -------------------------------------------------------------------------------- 1 | local lvmLocalPV = (import './openebs/lvmlocalpv-rules.libsonnet'); 2 | local volume = (import './volume/volume-rules.libsonnet'); 3 | local npd = (import './npd/npd-rules.libsonnet'); 4 | 5 | // Alert rules for different CAS types and others(as defined in config.libsonnet under alertRules) are stored separately in prometheusRules object. 6 | // prometheusRules : { 7 | // mayastor: { 8 | // ... 9 | // }, 10 | // ... 11 | // } 12 | 13 | function(param) { 14 | local prometheusRules = self, 15 | _config+:: param, 16 | prometheusRules+:: 17 | lvmLocalPV(prometheusRules._config).prometheusRules + volume(prometheusRules._config).prometheusRules 18 | + npd(prometheusRules._config).prometheusRules, 19 | } 20 | -------------------------------------------------------------------------------- /jsonnet/openebs-mixin/rules/volume/volume-rules.libsonnet: -------------------------------------------------------------------------------- 1 | // alert rules for volume-pvc 2 | function(param) { 3 | //local rules = self, 4 | _config+:: param, 5 | prometheusRules+:: { 6 | volume: { 7 | groups+: [ 8 | { 9 | name: 'persistent-volume-claim', 10 | rules: [ 11 | { 12 | alert: 'StalePersistentVolumeClaim', 13 | annotations: { 14 | summary: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' in namespace '{{ $labels.namespace }}' is not consumed by any pod in any namespace", 15 | description: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has no consumer", 16 | }, 17 | expr: 'kube_persistentvolumeclaim_info unless (kube_persistentvolumeclaim_info * on(persistentvolumeclaim) group_left kube_pod_spec_volumes_persistentvolumeclaims_info) == 1', 18 | 'for': '5m', 19 | labels: { 20 | severity: 'info', 21 | }, 22 | }, 23 | { 24 | alert: 'PendingPersistentVolumeClaim', 25 | annotations: { 26 | summary: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' pending in namespace '{{ $labels.namespace }}'", 27 | description: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has been in pending state for more than 5 minutes", 28 | }, 29 | expr: 'kube_persistentvolumeclaim_status_phase{phase="Pending"} == 1', 30 | 'for': '5m', 31 | labels: { 32 | severity: 'warning', 33 | }, 34 | }, 35 | { 36 | alert: 'LostPersistentVolumeClaim', 37 | annotations: { 38 | summary: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' in namespace '{{ $labels.namespace }}' lost it's corresponding persistent volume", 39 | description: "Persistent Volume Claim '{{ $labels.persistentvolumeclaim }}' has been in lost state for more than 5 minutes", 40 | }, 41 | expr: 'kube_persistentvolumeclaim_status_phase{phase="Lost"} == 1', 42 | 'for': '5m', 43 | labels: { 44 | severity: 'warning', 45 | }, 46 | }, 47 | ], 48 | }, 49 | ], 50 | }, 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /nix/README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | These are a collection of packages we need, or packages where we 4 | want to control the exact version(s) of. 5 | 6 | The packages are imported through the `nix-shell` automatically. 7 | 8 | ## nix-shell 9 | 10 | Build environment including all test and debug dependencies. 11 | It can be run with two arguments: 12 | 13 | * `--arg norust true`: to use your own rust toolchain. 14 | * `--arg devrustup true`: to use rustup. 15 | -------------------------------------------------------------------------------- /nix/lib/rust.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ../sources.nix }: 2 | let 3 | pkgs = 4 | import sources.nixpkgs { overlays = [ (import sources.rust-overlay) ]; }; 5 | makeRustTarget = platform: pkgs.rust.toRustTargetSpec platform; 6 | static_target = makeRustTarget pkgs.pkgsStatic.stdenv.hostPlatform; 7 | in 8 | rec { 9 | inherit makeRustTarget; 10 | rust_default = { override ? { } }: rec { 11 | nightly_pkg = pkgs.rust-bin.nightly."2023-10-05"; 12 | stable_pkg = pkgs.rust-bin.stable."1.72.1"; 13 | 14 | nightly = nightly_pkg.default.override (override); 15 | stable = stable_pkg.default.override (override); 16 | 17 | nightly_src = nightly_pkg.rust-src; 18 | release_src = stable_pkg.rust-src; 19 | }; 20 | default = rust_default { }; 21 | default_src = rust_default { 22 | override = { extensions = [ "rust-src" ]; }; 23 | }; 24 | static = { target ? makeRustTarget pkgs.pkgsStatic.stdenv.hostPlatform }: rust_default { 25 | override = { targets = [ "${target}" ]; }; 26 | }; 27 | hostStatic = rust_default { override = { targets = [ "${makeRustTarget pkgs.pkgsStatic.stdenv.hostPlatform}" ]; }; }; 28 | windows_cross = rust_default { 29 | override = { targets = [ "${pkgs.rust.toRustTargetSpec pkgs.pkgsCross.mingwW64.hostPlatform}" ]; }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /nix/lib/sourcer.nix: -------------------------------------------------------------------------------- 1 | { lib, stdenv, git, sourcer, tag ? "" }: 2 | let 3 | whitelistSource = src: allowedPrefixes: 4 | builtins.path { 5 | filter = (path: type: 6 | (lib.any 7 | (allowedPrefix: 8 | (lib.hasPrefix (toString (src + "/${allowedPrefix}")) path) || 9 | (type == "directory" && lib.hasPrefix path (toString (src + "/${allowedPrefix}"))) 10 | ) 11 | allowedPrefixes) 12 | ## Remove unwanted files, example: 13 | # && path != (toString (src + "/utils/dependencies/scripts/release.sh")) 14 | ); 15 | path = src; 16 | name = "puls8"; 17 | }; 18 | in 19 | { 20 | inherit whitelistSource; 21 | 22 | git-src = whitelistSource ../../. [ ".git" ]; 23 | repo-org = whitelistSource ../../mayastor-extensions/dependencies/control-plane/utils/dependencies/scripts [ "git-org-name.sh" ]; 24 | } 25 | -------------------------------------------------------------------------------- /nix/overlay.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | self: super: { 3 | sourcer = super.callPackage ./lib/sourcer.nix { }; 4 | } 5 | -------------------------------------------------------------------------------- /nix/sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "naersk": { 3 | "branch": "master", 4 | "description": "Build rust crates in Nix. No configuration, no code generation, no IFD. Sandbox friendly. [maintainer: @nmattia]", 5 | "homepage": "", 6 | "owner": "nix-community", 7 | "repo": "naersk", 8 | "rev": "d9a33d69a9c421d64c8d925428864e93be895dcc", 9 | "sha256": "1lhz5haibfnbxwir61mhymxfqfgs2q1nb4rk88va8bpv6j2zlpbv", 10 | "type": "tarball", 11 | "url": "https://github.com/nix-community/naersk/archive/d9a33d69a9c421d64c8d925428864e93be895dcc.tar.gz", 12 | "url_template": "https://github.com///archive/.tar.gz" 13 | }, 14 | "niv": { 15 | "branch": "master", 16 | "description": "Easy dependency management for Nix projects", 17 | "homepage": "https://github.com/nmattia/niv", 18 | "owner": "nmattia", 19 | "repo": "niv", 20 | "rev": "914aba08a26cb10538b84d00d6cfb01c9776d80c", 21 | "sha256": "0gx316gc7prjay5b0cr13x4zc2pdbiwxkfkpjvrlb2rml80lm4pm", 22 | "type": "tarball", 23 | "url": "https://github.com/nmattia/niv/archive/914aba08a26cb10538b84d00d6cfb01c9776d80c.tar.gz", 24 | "url_template": "https://github.com///archive/.tar.gz" 25 | }, 26 | "nixpkgs": { 27 | "branch": "release-22.11", 28 | "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", 29 | "homepage": "https://github.com/NixOS/nixpkgs", 30 | "owner": "NixOS", 31 | "repo": "nixpkgs", 32 | "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", 33 | "sha256": "1xi53rlslcprybsvrmipm69ypd3g3hr7wkxvzc73ag8296yclyll", 34 | "type": "tarball", 35 | "url": "https://github.com/NixOS/nixpkgs/archive/ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b.tar.gz", 36 | "url_template": "https://github.com///archive/.tar.gz" 37 | }, 38 | "rust-overlay": { 39 | "branch": "master", 40 | "description": "Pure and reproducible nix overlay for binary distributed rust toolchains", 41 | "homepage": "", 42 | "owner": "oxalica", 43 | "repo": "rust-overlay", 44 | "rev": "c0df7f2a856b5ff27a3ce314f6d7aacf5fda546f", 45 | "sha256": "0hm2yznc083bys92h6zrx5lsar5nqphx1h27p7pxz4x7hmilxpsy", 46 | "type": "tarball", 47 | "url": "https://github.com/oxalica/rust-overlay/archive/c0df7f2a856b5ff27a3ce314f6d7aacf5fda546f.tar.gz", 48 | "url_template": "https://github.com///archive/.tar.gz" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nix/sources.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by Niv. 2 | let 3 | # 4 | # The fetchers. fetch_ fetches specs of type . 5 | # 6 | 7 | fetch_file = pkgs: spec: 8 | if spec.builtin or true then 9 | builtins_fetchurl { inherit (spec) url sha256; } 10 | else 11 | pkgs.fetchurl { inherit (spec) url sha256; }; 12 | 13 | fetch_tarball = pkgs: spec: 14 | if spec.builtin or true then 15 | builtins_fetchTarball { inherit (spec) url sha256; } 16 | else 17 | pkgs.fetchzip { inherit (spec) url sha256; }; 18 | 19 | fetch_git = spec: 20 | builtins.fetchGit { 21 | url = spec.repo; 22 | inherit (spec) rev ref; 23 | }; 24 | 25 | fetch_builtin-tarball = spec: 26 | builtins.trace '' 27 | WARNING: 28 | The niv type "builtin-tarball" will soon be deprecated. You should 29 | instead use `builtin = true`. 30 | 31 | $ niv modify -a type=tarball -a builtin=true 32 | '' 33 | builtins_fetchTarball 34 | { inherit (spec) url sha256; }; 35 | 36 | fetch_builtin-url = spec: 37 | builtins.trace '' 38 | WARNING: 39 | The niv type "builtin-url" will soon be deprecated. You should 40 | instead use `builtin = true`. 41 | 42 | $ niv modify -a type=file -a builtin=true 43 | '' 44 | (builtins_fetchurl { inherit (spec) url sha256; }); 45 | 46 | # 47 | # Various helpers 48 | # 49 | 50 | # The set of packages used when specs are fetched using non-builtins. 51 | mkPkgs = sources: 52 | let 53 | sourcesNixpkgs = 54 | import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) 55 | { }; 56 | hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; 57 | hasThisAsNixpkgsPath = == ./.; 58 | in 59 | if builtins.hasAttr "nixpkgs" sources then 60 | sourcesNixpkgs 61 | else if hasNixpkgsPath && !hasThisAsNixpkgsPath then 62 | import { } 63 | else 64 | abort '' 65 | Please specify either (through -I or NIX_PATH=nixpkgs=...) or 66 | add a package called "nixpkgs" to your sources.json. 67 | ''; 68 | 69 | # The actual fetching function. 70 | fetch = pkgs: name: spec: 71 | 72 | if !builtins.hasAttr "type" spec then 73 | abort "ERROR: niv spec ${name} does not have a 'type' attribute" 74 | else if spec.type == "file" then 75 | fetch_file pkgs spec 76 | else if spec.type == "tarball" then 77 | fetch_tarball pkgs spec 78 | else if spec.type == "git" then 79 | fetch_git spec 80 | else if spec.type == "builtin-tarball" then 81 | fetch_builtin-tarball spec 82 | else if spec.type == "builtin-url" then 83 | fetch_builtin-url spec 84 | else 85 | abort 86 | "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; 87 | 88 | # Ports of functions for older nix versions 89 | 90 | # a Nix version of mapAttrs if the built-in doesn't exist 91 | mapAttrs = builtins.mapAttrs or (f: set: 92 | with builtins; 93 | listToAttrs (map 94 | (attr: { 95 | name = attr; 96 | value = f attr set.${attr}; 97 | }) 98 | (attrNames set))); 99 | 100 | # fetchTarball version that is compatible between all the versions of Nix 101 | builtins_fetchTarball = { url, sha256 }@attrs: 102 | let inherit (builtins) lessThan nixVersion fetchTarball; 103 | in 104 | if lessThan nixVersion "1.12" then 105 | fetchTarball { inherit url; } 106 | else 107 | fetchTarball attrs; 108 | 109 | # fetchurl version that is compatible between all the versions of Nix 110 | builtins_fetchurl = { url, sha256 }@attrs: 111 | let inherit (builtins) lessThan nixVersion fetchurl; 112 | in 113 | if lessThan nixVersion "1.12" then 114 | fetchurl { inherit url; } 115 | else 116 | fetchurl attrs; 117 | 118 | # Create the final "sources" from the config 119 | mkSources = config: 120 | mapAttrs 121 | (name: spec: 122 | if builtins.hasAttr "outPath" spec then 123 | abort 124 | "The values in sources.json should not have an 'outPath' attribute" 125 | else 126 | spec // { outPath = fetch config.pkgs name spec; }) 127 | config.sources; 128 | 129 | # The "config" used by the fetchers 130 | mkConfig = 131 | { sourcesFile ? ./sources.json 132 | , sources ? builtins.fromJSON (builtins.readFile sourcesFile) 133 | , pkgs ? mkPkgs sources 134 | }: rec { 135 | # The sources, i.e. the attribute set of spec name to spec 136 | inherit sources; 137 | 138 | # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers 139 | inherit pkgs; 140 | }; 141 | in 142 | mkSources (mkConfig { }) // { 143 | __functor = _: settings: mkSources (mkConfig settings); 144 | } 145 | -------------------------------------------------------------------------------- /scripts/generate-readme.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPTDIR=$(dirname "$0") 4 | ROOTDIR="$(realpath $SCRIPTDIR/..)" 5 | CHART_DIR="$ROOTDIR/deploy/charts" 6 | README="README.md" 7 | SKIP_GIT=${SKIP_GIT:-} 8 | 9 | set -euo pipefail 10 | 11 | helm-docs -c "$ROOTDIR" -g "$CHART_DIR" -o $README 12 | 13 | 14 | if [ -z "$SKIP_GIT" ]; then 15 | git diff --exit-code "$CHART_DIR/$README" 16 | fi 17 | -------------------------------------------------------------------------------- /scripts/shell.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | let 3 | sources = import ../nix/sources.nix; 4 | pkgs = import sources.nixpkgs { 5 | overlays = [ (_: _: { inherit sources; }) (import ../nix/overlay.nix { }) ]; 6 | }; 7 | in 8 | with pkgs; 9 | let 10 | in 11 | mkShell { 12 | name = "helm-scripts-shell"; 13 | buildInputs = [ 14 | coreutils 15 | git 16 | helm-docs 17 | kubernetes-helm-wrapped 18 | semver-tool 19 | yq-go 20 | ]; 21 | } 22 | --------------------------------------------------------------------------------