From de720f0a2beed7f7d9c2737ea58b410d042a90f9 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:48:12 -0700 Subject: [PATCH 01/21] Reverting back to 7d5978acd6761778766317169a4f58fa7f23fe7f --- .github/workflows/e2e-ci.yaml | 5 - .../prometheus-federator-0.2.3.tgz | Bin 20565 -> 0 bytes .../prometheus-federator-0.3.0.tgz | Bin 20567 -> 0 bytes .../rancher-project-monitoring-0.3.0.tgz | Bin 124755 -> 0 bytes charts/prometheus-federator/0.2.3/Chart.yaml | 20 - charts/prometheus-federator/0.2.3/README.md | 120 - .../prometheus-federator/0.2.3/app-README.md | 27 - .../charts/helmProjectOperator/Chart.yaml | 15 - .../charts/helmProjectOperator/README.md | 77 - .../charts/helmProjectOperator/app-readme.md | 20 - .../charts/helmProjectOperator/questions.yaml | 43 - .../helmProjectOperator/templates/NOTES.txt | 2 - .../templates/_helpers.tpl | 66 - .../templates/cleanup.yaml | 82 - .../templates/clusterrole.yaml | 57 - .../templates/configmap.yaml | 14 - .../templates/deployment.yaml | 124 - .../helmProjectOperator/templates/psp.yaml | 68 - .../helmProjectOperator/templates/rbac.yaml | 32 - .../system-namespaces-configmap.yaml | 62 - .../templates/validate-psp-install.yaml | 7 - .../charts/helmProjectOperator/values.yaml | 226 -- .../prometheus-federator/0.2.3/questions.yaml | 43 - .../0.2.3/templates/NOTES.txt | 3 - .../0.2.3/templates/_helpers.tpl | 66 - charts/prometheus-federator/0.2.3/values.yaml | 94 - charts/prometheus-federator/0.3.0/Chart.yaml | 20 - charts/prometheus-federator/0.3.0/README.md | 120 - .../prometheus-federator/0.3.0/app-README.md | 27 - .../charts/helmProjectOperator/Chart.yaml | 15 - .../charts/helmProjectOperator/README.md | 77 - .../charts/helmProjectOperator/app-readme.md | 20 - .../charts/helmProjectOperator/questions.yaml | 43 - .../helmProjectOperator/templates/NOTES.txt | 2 - .../templates/_helpers.tpl | 66 - .../templates/cleanup.yaml | 82 - .../templates/clusterrole.yaml | 57 - .../templates/configmap.yaml | 14 - .../templates/deployment.yaml | 124 - .../helmProjectOperator/templates/psp.yaml | 68 - .../helmProjectOperator/templates/rbac.yaml | 32 - .../system-namespaces-configmap.yaml | 62 - .../templates/validate-psp-install.yaml | 7 - .../charts/helmProjectOperator/values.yaml | 226 -- .../prometheus-federator/0.3.0/questions.yaml | 43 - .../0.3.0/templates/NOTES.txt | 3 - .../0.3.0/templates/_helpers.tpl | 66 - charts/prometheus-federator/0.3.0/values.yaml | 94 - .../0.2.2/questions.yaml | 4 +- .../0.2.2/templates/_helpers.tpl | 19 - .../0.2.2/templates/dashboard-roles.yaml | 18 - .../prometheus-remote-write.yaml | 8 +- .../rancher-monitoring/hardened.yaml | 8 +- .../0.2.2/values.yaml | 14 - .../0.3.0/Chart.yaml | 33 - .../0.3.0/README.md | 29 - .../0.3.0/app-README.md | 10 - .../0.3.0/charts/grafana/.helmignore | 23 - .../0.3.0/charts/grafana/Chart.yaml | 29 - .../0.3.0/charts/grafana/README.md | 571 ---- .../grafana/dashboards/custom-dashboard.json | 1 - .../0.3.0/charts/grafana/templates/NOTES.txt | 54 - .../charts/grafana/templates/_helpers.tpl | 214 -- .../0.3.0/charts/grafana/templates/_pod.tpl | 885 ------ .../charts/grafana/templates/clusterrole.yaml | 25 - .../grafana/templates/clusterrolebinding.yaml | 24 - .../configmap-dashboard-provider.yaml | 29 - .../charts/grafana/templates/configmap.yaml | 117 - .../templates/dashboards-json-configmap.yaml | 35 - .../charts/grafana/templates/deployment.yaml | 50 - .../grafana/templates/headless-service.yaml | 22 - .../0.3.0/charts/grafana/templates/hpa.yaml | 21 - .../templates/image-renderer-deployment.yaml | 123 - .../image-renderer-network-policy.yaml | 73 - .../templates/image-renderer-service.yaml | 33 - .../charts/grafana/templates/ingress.yaml | 78 - .../grafana/templates/networkpolicy.yaml | 52 - .../grafana/templates/nginx-config.yaml | 93 - .../templates/poddisruptionbudget.yaml | 22 - .../grafana/templates/podsecuritypolicy.yaml | 45 - .../0.3.0/charts/grafana/templates/pvc.yaml | 35 - .../0.3.0/charts/grafana/templates/role.yaml | 32 - .../charts/grafana/templates/rolebinding.yaml | 25 - .../charts/grafana/templates/secret-env.yaml | 14 - .../charts/grafana/templates/secret.yaml | 26 - .../charts/grafana/templates/service.yaml | 55 - .../grafana/templates/serviceaccount.yaml | 14 - .../grafana/templates/servicemonitor.yaml | 58 - .../charts/grafana/templates/statefulset.yaml | 56 - .../templates/tests/test-configmap.yaml | 17 - .../tests/test-podsecuritypolicy.yaml | 29 - .../grafana/templates/tests/test-role.yaml | 14 - .../templates/tests/test-rolebinding.yaml | 17 - .../templates/tests/test-serviceaccount.yaml | 9 - .../charts/grafana/templates/tests/test.yaml | 51 - .../0.3.0/charts/grafana/values.yaml | 1062 ------- .../federate/federate-scrape-config.yaml | 13 - .../rancher/pods/rancher-pod-containers.json | 636 ---- .../0.3.0/files/rancher/pods/rancher-pod.json | 636 ---- .../workloads/rancher-workload-pods.json | 652 ---- .../rancher/workloads/rancher-workload.json | 652 ---- .../0.3.0/questions.yaml | 128 - .../0.3.0/templates/NOTES.txt | 4 - .../0.3.0/templates/_helpers.tpl | 252 -- .../templates/alertmanager/alertmanager.yaml | 165 - .../templates/alertmanager/extrasecret.yaml | 20 - .../0.3.0/templates/alertmanager/ingress.yaml | 77 - .../alertmanager/podDisruptionBudget.yaml | 21 - .../templates/alertmanager/psp-role.yaml | 21 - .../alertmanager/psp-rolebinding.yaml | 18 - .../0.3.0/templates/alertmanager/psp.yaml | 45 - .../0.3.0/templates/alertmanager/secret.yaml | 33 - .../0.3.0/templates/alertmanager/service.yaml | 53 - .../alertmanager/serviceaccount.yaml | 20 - .../alertmanager/servicemonitor.yaml | 55 - .../0.3.0/templates/dashboard-roles.yaml | 179 -- .../templates/dashboard-values-configmap.yaml | 57 - .../dashboards/rancher/pods-dashboards.yaml | 17 - .../rancher/workload-dashboards.yaml | 17 - .../grafana/configmap-dashboards.yaml | 24 - .../grafana/configmaps-datasources.yaml | 46 - .../alertmanager-overview.yaml | 616 ---- .../dashboards-1.14/cluster-total.yaml | 1646 ---------- .../dashboards-1.14/grafana-overview.yaml | 635 ---- .../k8s-resources-namespace.yaml | 2770 ----------------- .../dashboards-1.14/k8s-resources-node.yaml | 963 ------ .../dashboards-1.14/k8s-resources-pod.yaml | 2442 --------------- .../k8s-resources-project.yaml | 2480 --------------- .../k8s-resources-workload.yaml | 1997 ------------ .../k8s-resources-workloads-namespace.yaml | 2162 ------------- .../dashboards-1.14/namespace-by-pod.yaml | 1438 --------- .../namespace-by-workload.yaml | 1710 ---------- .../persistentvolumesusage.yaml | 561 ---- .../grafana/dashboards-1.14/pod-total.yaml | 1202 ------- .../prometheus-remote-write.yaml | 1674 ---------- .../grafana/dashboards-1.14/prometheus.yaml | 1235 -------- .../dashboards-1.14/workload-total.yaml | 1412 --------- .../0.3.0/templates/prometheus/_rules.tpl | 8 - .../templates/prometheus/clusterrole.yaml | 25 - .../prometheus/clusterrolebinding.yaml | 18 - .../templates/prometheus/extrasecret.yaml | 20 - .../0.3.0/templates/prometheus/federate.yaml | 10 - .../0.3.0/templates/prometheus/ingress.yaml | 77 - .../templates/prometheus/nginx-config.yaml | 68 - .../prometheus/podDisruptionBudget.yaml | 21 - .../templates/prometheus/prometheus.yaml | 319 -- .../templates/prometheus/psp-clusterrole.yaml | 20 - .../prometheus/psp-clusterrolebinding.yaml | 18 - .../0.3.0/templates/prometheus/psp.yaml | 52 - .../rules-1.14/alertmanager.rules.yaml | 217 -- .../prometheus/rules-1.14/general.rules.yaml | 98 - .../rules-1.14/kubernetes-apps.yaml | 375 --- .../rules-1.14/kubernetes-storage.yaml | 160 - .../prometheus/rules-1.14/prometheus.yaml | 448 --- .../0.3.0/templates/prometheus/service.yaml | 56 - .../templates/prometheus/serviceaccount.yaml | 20 - .../templates/prometheus/servicemonitor.yaml | 52 - .../rancher-monitoring/hardened.yaml | 129 - .../0.3.0/templates/validate-install-crd.yaml | 21 - .../0.3.0/templates/validate-psp-install.yaml | 7 - .../0.3.0/values.yaml | 1551 --------- index.yaml | 89 +- .../prometheus-federator/charts/Chart.yaml | 6 +- .../prometheus-federator/charts/values.yaml | 2 +- .../dependencies/grafana/dependency.yaml | 4 +- .../generated-changes/exclude/README.md | 2 +- .../generated-changes/exclude/app-README.md | 6 +- .../exporters/core-dns/servicemonitor.yaml | 14 +- .../kube-api-server/servicemonitor.yaml | 14 +- .../servicemonitor.yaml | 22 +- .../exporters/kube-dns/servicemonitor.yaml | 24 +- .../exporters/kube-etcd/servicemonitor.yaml | 11 +- .../exporters/kube-proxy/servicemonitor.yaml | 24 +- .../kube-scheduler/servicemonitor.yaml | 26 +- .../exporters/kubelet/servicemonitor.yaml | 26 +- .../prometheus-operator/deployment.yaml | 8 +- .../prometheus-operator/servicemonitor.yaml | 22 +- .../servicemonitorThanosSidecar.yaml | 16 +- .../ingress-nginx/servicemonitor.yaml | 22 +- .../exporters/rancher/servicemonitor.yaml | 17 +- .../thanos-ruler/servicemonitor.yaml | 19 +- .../generated-changes/overlay/questions.yaml | 4 +- .../overlay/templates/dashboard-roles.yaml | 18 - .../generated-changes/patch/Chart.yaml.patch | 7 +- .../charts/grafana/templates/_pod.tpl.patch | 5 +- .../grafana/templates/nginx-config.yaml.patch | 11 +- .../patch/templates/_helpers.tpl.patch | 24 - .../grafana/configmaps-datasources.yaml.patch | 8 +- .../k8s-resources-node.yaml.patch | 28 +- ...s-resources-workloads-namespace.yaml.patch | 17 +- .../prometheus-remote-write.yaml.patch | 23 - .../prometheus/prometheus.yaml.patch | 19 +- .../patch/templates/prometheus/psp.yaml.patch | 7 +- .../rancher-monitoring/hardened.yaml.patch | 19 +- .../generated-changes/patch/values.yaml.patch | 233 +- .../rancher-project-monitoring/package.yaml | 6 +- 196 files changed, 338 insertions(+), 39856 deletions(-) delete mode 100644 assets/prometheus-federator/prometheus-federator-0.2.3.tgz delete mode 100644 assets/prometheus-federator/prometheus-federator-0.3.0.tgz delete mode 100644 assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz delete mode 100644 charts/prometheus-federator/0.2.3/Chart.yaml delete mode 100644 charts/prometheus-federator/0.2.3/README.md delete mode 100644 charts/prometheus-federator/0.2.3/app-README.md delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/Chart.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/README.md delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/app-readme.md delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/questions.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/NOTES.txt delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/_helpers.tpl delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/cleanup.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/clusterrole.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/configmap.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/deployment.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/psp.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/rbac.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/validate-psp-install.yaml delete mode 100644 charts/prometheus-federator/0.2.3/charts/helmProjectOperator/values.yaml delete mode 100644 charts/prometheus-federator/0.2.3/questions.yaml delete mode 100644 charts/prometheus-federator/0.2.3/templates/NOTES.txt delete mode 100644 charts/prometheus-federator/0.2.3/templates/_helpers.tpl delete mode 100644 charts/prometheus-federator/0.2.3/values.yaml delete mode 100644 charts/prometheus-federator/0.3.0/Chart.yaml delete mode 100644 charts/prometheus-federator/0.3.0/README.md delete mode 100644 charts/prometheus-federator/0.3.0/app-README.md delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml delete mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml delete mode 100644 charts/prometheus-federator/0.3.0/questions.yaml delete mode 100644 charts/prometheus-federator/0.3.0/templates/NOTES.txt delete mode 100644 charts/prometheus-federator/0.3.0/templates/_helpers.tpl delete mode 100644 charts/prometheus-federator/0.3.0/values.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/Chart.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/README.md delete mode 100644 charts/rancher-project-monitoring/0.3.0/app-README.md delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json delete mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json delete mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json delete mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json delete mode 100644 charts/rancher-project-monitoring/0.3.0/questions.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml delete mode 100644 charts/rancher-project-monitoring/0.3.0/values.yaml delete mode 100644 packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch diff --git a/.github/workflows/e2e-ci.yaml b/.github/workflows/e2e-ci.yaml index 919d8d0b..62879638 100644 --- a/.github/workflows/e2e-ci.yaml +++ b/.github/workflows/e2e-ci.yaml @@ -54,11 +54,6 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: actions/setup-go@v4 - with: - go-version: '>=1.17.0' - - uses: azure/setup-kubectl@v3 - - uses: azure/setup-helm@v3 - name: Install mikefarah/yq run: | diff --git a/assets/prometheus-federator/prometheus-federator-0.2.3.tgz b/assets/prometheus-federator/prometheus-federator-0.2.3.tgz deleted file mode 100644 index 57e55b8e5c89d7778ef31c7f316f9efce30bed33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20565 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 diff --git a/assets/prometheus-federator/prometheus-federator-0.3.0.tgz b/assets/prometheus-federator/prometheus-federator-0.3.0.tgz deleted file mode 100644 index fbce34417a7b2581b883db7358b0c7eac49b0432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20567 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 diff --git a/assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz b/assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz deleted file mode 100644 index aa68796406afc2a26fac85b9f40f504c6b7eecab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124755 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�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 diff --git a/charts/prometheus-federator/0.2.3/Chart.yaml b/charts/prometheus-federator/0.2.3/Chart.yaml deleted file mode 100644 index 9a0b04b7..00000000 --- a/charts/prometheus-federator/0.2.3/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Prometheus Federator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-monitoring-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' - catalog.cattle.io/release-name: prometheus-federator -apiVersion: v2 -appVersion: 0.2.2 -dependencies: -- condition: helmProjectOperator.enabled - name: helmProjectOperator - repository: file://./charts/helmProjectOperator -description: Prometheus Federator -icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg -name: prometheus-federator -version: 0.2.3 diff --git a/charts/prometheus-federator/0.2.3/README.md b/charts/prometheus-federator/0.2.3/README.md deleted file mode 100644 index 7da4edfc..00000000 --- a/charts/prometheus-federator/0.2.3/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Prometheus Federator - -This chart is deploys a Helm Project Operator (based on the [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator)), an operator that manages deploying Helm charts each containing a Project Monitoring Stack, where each stack contains: -- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) -- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) -- Default ServiceMonitors that watch the deployed resources - -> **Important Note: Prometheus Federator is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs.** - -By default, the chart is configured and intended to be deployed alongside [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that each Project Monitoring Stack is configured to federate namespace-scoped metrics from by default. - -## Pre-Installation: Using Prometheus Federator with Rancher and rancher-monitoring - -If you are running your cluster on [Rancher](https://rancher.com/) and already have [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) deployed onto your cluster, Prometheus Federator's default configuration should already be configured to work with your existing Cluster Monitoring Stack; however, here are some notes on how we recommend you configure rancher-monitoring to optimize the security and usability of Prometheus Federator in your cluster: - -### Ensure the cattle-monitoring-system namespace is placed into the System Project (or a similarly locked down Project that has access to other Projects in the cluster) - -Prometheus Operator's security model expects that the namespace it is deployed into (`cattle-monitoring-system`) has limited access for anyone except Cluster Admins to avoid privilege escalation via execing into Pods (such as the Jobs executing Helm operations). In addition, deploying Prometheus Federator and all Project Prometheus stacks into the System Project ensures that the each Project Prometheus is able to reach out to scrape workloads across all Projects (even if Network Policies are defined via Project Network Isolation) but has limited access for Project Owners, Project Members, and other users to be able to access data they shouldn't have access to (i.e. being allowed to exec into pods, set up the ability to scrape namespaces outside of a given Project, etc.). - -### Configure rancher-monitoring to only watch for resources created by the Helm chart itself - -Since each Project Monitoring Stack will watch the other namespaces and collect additional custom workload metrics or dashboards already, it's recommended to configure the following settings on all selectors to ensure that the Cluster Prometheus Stack only monitors resources created by the Helm Chart itself: - -``` -matchLabels: - release: "rancher-monitoring" -``` - -The following selector fields are recommended to have this value: -- `.Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector` -- `.Values.prometheus.prometheusSpec.serviceMonitorSelector` -- `.Values.prometheus.prometheusSpec.podMonitorSelector` -- `.Values.prometheus.prometheusSpec.ruleSelector` -- `.Values.prometheus.prometheusSpec.probeSelector` - -Once this setting is turned on, you can always create ServiceMonitors or PodMonitors that are picked up by the Cluster Prometheus by adding the label `release: "rancher-monitoring"` to them (in which case they will be ignored by Project Monitoring Stacks automatically by default, even if the namespace in which those ServiceMonitors or PodMonitors reside in are not system namespaces). - -> Note: If you don't want to allow users to be able to create ServiceMonitors and PodMonitors that aggregate into the Cluster Prometheus in Project namespaces, you can additionally set the namespaceSelectors on the chart to only target system namespaces (which must contain `cattle-monitoring-system` and `cattle-dashboards`, where resources are deployed into by default by rancher-monitoring; you will also need to monitor the `default` namespace to get apiserver metrics or create a custom ServiceMonitor to scrape apiserver metrics from the Service residing in the default namespace) to limit your Cluster Prometheus from picking up other Prometheus Operator CRs; in that case, it would be recommended to turn `.Values.prometheus.prometheusSpec.ignoreNamespaceSelectors=true` to allow you to define ServiceMonitors that can monitor non-system namespaces from within a system namespace. - -In addition, if you modified the default `.Values.grafana.sidecar.*.searchNamespace` values on the Grafana Helm subchart for Monitoring V2, it is also recommended to remove the overrides or ensure that your defaults are scoped to only system namespaces for the following values: -- `.Values.grafana.sidecar.dashboards.searchNamespace` (default `cattle-dashboards`) -- `.Values.grafana.sidecar.datasources.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) -- `.Values.grafana.sidecar.plugins.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) -- `.Values.grafana.sidecar.notifiers.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) - -### Increase the CPU / memory limits of the Cluster Prometheus - -Depending on a cluster's setup, it's generally recommended to give a large amount of dedicated memory to the Cluster Prometheus to avoid restarts due to out-of-memory errors (OOMKilled), usually caused by churn created in the cluster that causes a large number of high cardinality metrics to be generated and ingested by Prometheus within one block of time; this is one of the reasons why the default Rancher Monitoring stack expects around 4GB of RAM to be able to operate in a normal-sized cluster. However, when introducing Project Monitoring Stacks that are all sending `/federate` requests to the same Cluster Prometheus and are reliant on the Cluster Prometheus being "up" to federate that system data on their namespaces, it's even more important that the Cluster Prometheus has an ample amount of CPU / memory assigned to it to prevent an outage that can cause data gaps across all Project Prometheis in the cluster. - -> Note: There are no specific recommendations on how much memory the Cluster Prometheus should be configured with since it depends entirely on the user's setup (namely the likelihood of encountering a high churn rate and the scale of metrics that could be generated at that time); it generally varies per setup. - -## How does the operator work? - -1. On deploying this chart, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `monitoring.cattle.io/v1alpha1` (also known as "Project Monitors" in the Rancher UI) in a **Project Registration Namespace (`cattle-project-`)**. -2. On seeing each ProjectHelmChartCR, the operator will automatically deploy a Project Prometheus stack on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--monitoring`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. -3. RBAC will automatically be assigned in the Project Release Namespace to allow users to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack deployed; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). - -### What is a Project? - -In Prometheus Federator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. - -### Configuring the Helm release created by a ProjectHelmChart - -The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: -- View to the chart's definition located at [`rancher/prometheus-federator` under `charts/rancher-project-monitoring`](https://github.com/rancher/prometheus-federator/blob/main/charts/rancher-project-monitoring) (where the chart version will be tied to the version of this operator) -- Look for the ConfigMap named `monitoring.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `prometheus-federator` binary). - -### Namespaces - -As a Project Operator based on [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator), Prometheus Federator has three different classifications of namespaces that the operator looks out for: -1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-monitoring-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** -2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. -> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project -> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace -3. **Project Release Namespace (`cattle-project--monitoring`)**: this is the set of namespaces that the operator deploys Project Monitoring Stacks within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Project Monitoring Stack based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Prometheus Federator.** -> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace -> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) -> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace - -### Helm Resources (HelmChart, HelmRelease) - -On deploying a ProjectHelmChart, the Prometheus Federator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: -- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). -> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** -- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). -> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified - -Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. - -### RBAC - -As described in the section on namespaces above, Prometheus Federator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: -- ClusterRoleBindings -- RoleBindings in the Project Release Namespace - -On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). - -> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. - -If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: -- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` -- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` - -By default, the `rancher-project-monitoring` (the underlying chart deployed by Prometheus Federator) creates three default Roles per Project Release Namespace that provide `admin`, `edit`, and `view` users to permissions to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack to provide least privilege; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. - -### Advanced Helm Project Operator Configuration - -|Value|Configuration| -|---|---------------------------| -|`helmProjectOperator.valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | -|`helmProjectOperator.projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | -|`helmProjectOperator.otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `cattle-monitoring-system`, `cattle-dashboards`, and `kube-system` are explicitly marked as system namespaces as well, regardless of label or annotation. | -|`helmProjectOperator.releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces -|`helmProjectOperator.releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | -|`helmProjectOperator.hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | -|`helmProjectOperator.hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | -|`helmProjectOperator.helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2/K3s clusters before v1.23.14 / v1.24.8 / v1.25.4 since RKE2/K3s clusters already run Helm Controller at a cluster-wide level to manage internal Kubernetes components | -|`helmProjectOperator.helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.2.3/app-README.md b/charts/prometheus-federator/0.2.3/app-README.md deleted file mode 100644 index 99fa7ca1..00000000 --- a/charts/prometheus-federator/0.2.3/app-README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Prometheus Federator - -This chart deploys an operator that manages Project Monitoring Stacks composed of the following set of resources that are scoped to project namespaces: -- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) -- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) -- Default ServiceMonitors that watch the deployed Prometheus, Grafana, and Alertmanager - -Since this Project Monitoring Stack deploys Prometheus Operator CRs, an existing Prometheus Operator instance must already be deployed in the cluster for Prometheus Federator to successfully be able to deploy Project Monitoring Stacks. It is recommended to use [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) for this. For more information on how the chart works or advanced configurations, please read the `README.md`. - -## Upgrading to Kubernetes v1.25+ - -Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. - -As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. -​ -> **Note:** -> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. - ​ -> **Note:** -> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** -> -> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. -Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. -​ -As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/Chart.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/Chart.yaml deleted file mode 100644 index 421aabb1..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/Chart.yaml +++ /dev/null @@ -1,15 +0,0 @@ -annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Helm Project Operator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-helm-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.0-0' - catalog.cattle.io/release-name: helm-project-operator -apiVersion: v2 -appVersion: 0.1.0 -description: Helm Project Operator -name: helmProjectOperator -version: 0.1.1 diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/README.md b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/README.md deleted file mode 100644 index fc1d39e8..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Helm Project Operator - -## How does the operator work? - -1. On deploying a Helm Project Operator, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `dummy.cattle.io/v1alpha1` in a **Project Registration Namespace (`cattle-project-`)**. -2. On seeing each ProjectHelmChartCR, the operator will automatically deploy the embedded Helm chart on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--dummy`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. -3. RBAC will automatically be assigned in the Project Release Namespace to allow users to based on Role created in the Project Release Namespace with a given set of labels; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). - -### What is a Project? - -In Helm Project Operator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. - -### What is a ProjectHelmChart? - -A ProjectHelmChart is an instance of a (project-scoped) Helm chart deployed on behalf of a user who has permissions to create ProjectHelmChart resources in a Project Registration namespace. - -Generally, the best way to think about the ProjectHelmChart model is by comparing it to two other models: -1. Managed Kubernetes providers (EKS, GKE, AKS, etc.): in this model, a user has the ability to say "I want a Kubernetes cluster" but the underlying cloud provider is responsible for provisioning the infrastructure and offering **limited view and access** of the underlying resources created on their behalf; similarly, Helm Project Operator allows a Project Owner to say "I want this Helm chart deployed", but the underlying Operator is responsible for "provisioning" (deploying) the Helm chart and offering **limited view and access** of the underlying Kubernetes resources created on their behalf (based on configuring "least-privilege" Kubernetes RBAC for the Project Owners / Members in the newly created Project Release Namespace). -2. Dynamically-provisioned Persistent Volumes: in this model, a single resource (PersistentVolume) exists that allows you to specify a Storage Class that actually implements provisioning the underlying storage via a Storage Class Provisioner (e.g. Longhorn). Similarly, the ProjectHelmChart exists that allows you to specify a `spec.helmApiVersion` ("storage class") that actually implements deploying the underlying Helm chart via a Helm Project Operator (e.g. [`rancher/prometheus-federator`](https://github.com/rancher/prometheus-federator)). - -### Configuring the Helm release created by a ProjectHelmChart - -The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: -- View to the chart's definition located at [`rancher/helm-project-operator` under `charts/example-chart`](https://github.com/rancher/helm-project-operator/blob/main/charts/example-chart) (where the chart version will be tied to the version of this operator) -- Look for the ConfigMap named `dummy.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `helm-project-operator` binary). - -### Namespaces - -All Helm Project Operators have three different classifications of namespaces that the operator looks out for: -1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-helm-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** -2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. -> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project -> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace -3. **Project Release Namespace (`cattle-project--dummy`)**: this is the set of namespaces that the operator deploys Helm charts within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Helm charts based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Helm Project Operator.** -> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace -> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) -> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace - -### Helm Resources (HelmChart, HelmRelease) - -On deploying a ProjectHelmChart, the Helm Project Operator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: -- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). -> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** -- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). -> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified - -Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. - -### RBAC - -As described in the section on namespaces above, Helm Project Operator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: -- ClusterRoleBindings -- RoleBindings in the Project Release Namespace - -On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). - -> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. - -If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: -- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` -- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` - -By default, the `example-chart` (the underlying chart deployed by Helm Project Operator) does not create any default roles; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. - -### Advanced Helm Project Operator Configuration - -|Value|Configuration| -|---|---------------------------| -|`valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | -|`projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | -|`otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `kube-system` is explicitly marked as a system namespace as well, regardless of label or annotation. | -|`releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces -|`releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | -|`hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | -|`hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | -|`helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2 clusters since RKE2 clusters already run Helm Controller to manage internal Kubernetes components | -|`helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/app-readme.md b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/app-readme.md deleted file mode 100644 index fd551467..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/app-readme.md +++ /dev/null @@ -1,20 +0,0 @@ -# Helm Project Operator - -This chart installs the example [Helm Project Operator](https://github.com/rancher/helm-project-operator) onto your cluster. - -## Upgrading to Kubernetes v1.25+ - -Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. - -As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. -​ -> **Note:** -> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. - ​ -> **Note:** -> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** -> -> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. -Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. -​ -As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/questions.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/questions.yaml deleted file mode 100644 index 054361a7..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/questions.yaml +++ /dev/null @@ -1,43 +0,0 @@ -questions: -- variable: global.cattle.psp.enabled - default: "false" - description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." - label: "Enable PodSecurityPolicies" - type: boolean - group: "Security Settings" -- variable: helmController.enabled - label: Enable Embedded Helm Controller - description: 'Note: If you are running this chart in an RKE2 cluster, this should be disabled.' - type: boolean - group: Helm Controller -- variable: helmLocker.enabled - label: Enable Embedded Helm Locker - type: boolean - group: Helm Locker -- variable: projectReleaseNamespaces.labelValue - label: Project Release Namespace Project ID - description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) - type: string - required: false - group: Namespaces -- variable: releaseRoleBindings.clusterRoleRefs.admin - label: Admin ClusterRole - description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: admin - required: false - group: RBAC -- variable: releaseRoleBindings.clusterRoleRefs.edit - label: Edit ClusterRole - description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: edit - required: false - group: RBAC -- variable: releaseRoleBindings.clusterRoleRefs.view - label: View ClusterRole - description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: view - required: false - group: RBAC diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/NOTES.txt b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/NOTES.txt deleted file mode 100644 index 32baeebc..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "helm-project-operator.namespace" . }} get pods -l "release={{ $.Release.Name }}" diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/_helpers.tpl b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/_helpers.tpl deleted file mode 100644 index 97dd6b36..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -# Helm Project Operator - -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "helm-project-operator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "helm-project-operator.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "helm-project-operator.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "helm-project-operator.labels" -}} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" -app.kubernetes.io/part-of: {{ template "helm-project-operator.name" . }} -chart: {{ template "helm-project-operator.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end -}} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/cleanup.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/cleanup.yaml deleted file mode 100644 index 98675642..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/cleanup.yaml +++ /dev/null @@ -1,82 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "helm-project-operator.name" . }}-cleanup - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} - annotations: - "helm.sh/hook": pre-delete - "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed -spec: - template: - metadata: - name: {{ template "helm-project-operator.name" . }}-cleanup - labels: {{ include "helm-project-operator.labels" . | nindent 8 }} - app: {{ template "helm-project-operator.name" . }} - spec: - serviceAccountName: {{ template "helm-project-operator.name" . }} -{{- if .Values.cleanup.securityContext }} - securityContext: {{ toYaml .Values.cleanup.securityContext | nindent 8 }} -{{- end }} - initContainers: - - name: add-cleanup-annotations - image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - command: - - /bin/sh - - -c - - > - echo "Labeling all ProjectHelmCharts with helm.cattle.io/helm-project-operator-cleanup=true"; - EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; - IFS=$'\n'; - for namespace in $(kubectl get namespaces -l helm.cattle.io/helm-project-operated=true --no-headers -o=custom-columns=NAME:.metadata.name); do - for projectHelmChartAndHelmApiVersion in $(kubectl get projecthelmcharts -n ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name,HELMAPIVERSION:.spec.helmApiVersion); do - projectHelmChartAndHelmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | xargs); - projectHelmChart=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f1); - helmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f2); - if [[ ${helmApiVersion} != ${EXPECTED_HELM_API_VERSION} ]]; then - echo "Skipping marking ${namespace}/${projectHelmChart} with cleanup annotation since spec.helmApiVersion: ${helmApiVersion} is not ${EXPECTED_HELM_API_VERSION}"; - continue; - fi; - kubectl label projecthelmcharts -n ${namespace} ${projectHelmChart} helm.cattle.io/helm-project-operator-cleanup=true --overwrite; - done; - done; -{{- if .Values.cleanup.resources }} - resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} -{{- end }} -{{- if .Values.cleanup.containerSecurityContext }} - securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} -{{- end }} - containers: - - name: ensure-subresources-deleted - image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} - imagePullPolicy: IfNotPresent - command: - - /bin/sh - - -c - - > - SYSTEM_NAMESPACE={{ .Release.Namespace }} - EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; - HELM_API_VERSION_TRUNCATED=$(echo ${EXPECTED_HELM_API_VERSION} | cut -d'/' -f0); - echo "Ensuring HelmCharts and HelmReleases are deleted from ${SYSTEM_NAMESPACE}..."; - while [[ "$(kubectl get helmcharts,helmreleases -l helm.cattle.io/helm-api-version=${HELM_API_VERSION_TRUNCATED} -n ${SYSTEM_NAMESPACE} 2>&1)" != "No resources found in ${SYSTEM_NAMESPACE} namespace." ]]; do - echo "waiting for HelmCharts and HelmReleases to be deleted from ${SYSTEM_NAMESPACE}... sleeping 3 seconds"; - sleep 3; - done; - echo "Successfully deleted all HelmCharts and HelmReleases in ${SYSTEM_NAMESPACE}!"; -{{- if .Values.cleanup.resources }} - resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} -{{- end }} -{{- if .Values.cleanup.containerSecurityContext }} - securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} -{{- end }} - restartPolicy: OnFailure - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} - {{- if .Values.cleanup.nodeSelector }} - {{- toYaml .Values.cleanup.nodeSelector | nindent 8 }} - {{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} - {{- if .Values.cleanup.tolerations }} - {{- toYaml .Values.cleanup.tolerations | nindent 8 }} - {{- end }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/clusterrole.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/clusterrole.yaml deleted file mode 100644 index 60ed263b..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/clusterrole.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-admin - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-admin: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/finalizers - - projecthelmcharts/status - verbs: - - '*' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-edit - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-edit: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/status - verbs: - - 'get' - - 'list' - - 'watch' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-view - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-view: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/status - verbs: - - 'get' - - 'list' - - 'watch' -{{- end }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/configmap.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/configmap.yaml deleted file mode 100644 index d4def157..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/configmap.yaml +++ /dev/null @@ -1,14 +0,0 @@ -## Note: If you add another entry to this ConfigMap, make sure a corresponding env var is set -## in the deployment of the operator to ensure that a Helm upgrade will force the operator -## to reload the values in the ConfigMap and redeploy -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "helm-project-operator.name" . }}-config - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -data: - hardened.yaml: |- -{{ .Values.hardenedNamespaces.configuration | toYaml | indent 4 }} - values.yaml: |- -{{ .Values.valuesOverride | toYaml | indent 4 }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/deployment.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/deployment.yaml deleted file mode 100644 index c7309805..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/deployment.yaml +++ /dev/null @@ -1,124 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ template "helm-project-operator.name" . }} - release: {{ $.Release.Name | quote }} - template: - metadata: - labels: {{ include "helm-project-operator.labels" . | nindent 8 }} - app: {{ template "helm-project-operator.name" . }} - spec: - containers: - - name: {{ template "helm-project-operator.name" . }} - image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - args: - - {{ template "helm-project-operator.name" . }} - - --namespace={{ template "helm-project-operator.namespace" . }} - - --controller-name={{ template "helm-project-operator.name" . }} - - --values-override-file=/etc/helmprojectoperator/config/values.yaml -{{- if .Values.global.cattle.systemDefaultRegistry }} - - --system-default-registry={{ .Values.global.cattle.systemDefaultRegistry }} -{{- end }} -{{- if .Values.global.cattle.url }} - - --cattle-url={{ .Values.global.cattle.url }} -{{- end }} -{{- if .Values.global.cattle.projectLabel }} - - --project-label={{ .Values.global.cattle.projectLabel }} -{{- end }} -{{- if not .Values.projectReleaseNamespaces.enabled }} - - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} -{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} - - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} -{{- else if len .Values.otherSystemProjectLabelValues }} - - --system-project-label-values={{ join "," .Values.otherSystemProjectLabelValues }} -{{- end }} -{{- if .Values.projectReleaseNamespaces.enabled }} -{{- if .Values.projectReleaseNamespaces.labelValue }} - - --project-release-label-value={{ .Values.projectReleaseNamespaces.labelValue }} -{{- else if .Values.global.cattle.systemProjectId }} - - --project-release-label-value={{ .Values.global.cattle.systemProjectId }} -{{- end }} -{{- end }} -{{- if .Values.global.cattle.clusterId }} - - --cluster-id={{ .Values.global.cattle.clusterId }} -{{- end }} -{{- if .Values.releaseRoleBindings.aggregate }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.admin }} - - --admin-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.admin }} -{{- end }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.edit }} - - --edit-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.edit }} -{{- end }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.view }} - - --view-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.view }} -{{- end }} -{{- end }} -{{- end }} -{{- if .Values.hardenedNamespaces.enabled }} - - --hardening-options-file=/etc/helmprojectoperator/config/hardening.yaml -{{- else }} - - --disable-hardening -{{- end }} -{{- if .Values.debug }} - - --debug - - --debug-level={{ .Values.debugLevel }} -{{- end }} -{{- if not .Values.helmController.enabled }} - - --disable-embedded-helm-controller -{{- else }} - - --helm-job-image={{ template "system_default_registry" . }}{{ .Values.helmController.job.image.repository }}:{{ .Values.helmController.job.image.tag }} -{{- end }} -{{- if not .Values.helmLocker.enabled }} - - --disable-embedded-helm-locker -{{- end }} -{{- if .Values.additionalArgs }} -{{- toYaml .Values.additionalArgs | nindent 10 }} -{{- end }} - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - ## Note: The below two values only exist to force Helm to upgrade the deployment on - ## a change to the contents of the ConfigMap during an upgrade. Neither serve - ## any practical purpose and can be removed and replaced with a configmap reloader - ## in a future change if dynamic updates are required. - - name: HARDENING_OPTIONS_SHA_256_HASH - value: {{ .Values.hardenedNamespaces.configuration | toYaml | sha256sum }} - - name: VALUES_OVERRIDE_SHA_256_HASH - value: {{ .Values.valuesOverride | toYaml | sha256sum }} -{{- if .Values.resources }} - resources: {{ toYaml .Values.resources | nindent 12 }} -{{- end }} -{{- if .Values.containerSecurityContext }} - securityContext: {{ toYaml .Values.containerSecurityContext | nindent 12 }} -{{- end }} - volumeMounts: - - name: config - mountPath: "/etc/helmprojectoperator/config" - serviceAccountName: {{ template "helm-project-operator.name" . }} -{{- if .Values.securityContext }} - securityContext: {{ toYaml .Values.securityContext | nindent 8 }} -{{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} -{{- if .Values.nodeSelector }} -{{- toYaml .Values.nodeSelector | nindent 8 }} -{{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} -{{- if .Values.tolerations }} -{{- toYaml .Values.tolerations | nindent 8 }} -{{- end }} - volumes: - - name: config - configMap: - name: {{ template "helm-project-operator.name" . }}-config diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/psp.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/psp.yaml deleted file mode 100644 index 73dcc456..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/psp.yaml +++ /dev/null @@ -1,68 +0,0 @@ -{{- if .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -{{- if .Values.global.rbac.pspAnnotations }} - annotations: {{ toYaml .Values.global.rbac.pspAnnotations | nindent 4 }} -{{- end }} -spec: - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -rules: -{{- if semverCompare "> 1.15.0-0" .Capabilities.KubeVersion.GitVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "helm-project-operator.name" . }}-psp ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "helm-project-operator.name" . }}-psp -subjects: - - kind: ServiceAccount - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} -{{- end }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/rbac.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/rbac.yaml deleted file mode 100644 index b1c40920..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/rbac.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "helm-project-operator.name" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: "cluster-admin" # see note below -subjects: -- kind: ServiceAccount - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }} -{{- end }} -# --- -# NOTE: -# As of now, due to the fact that the k3s-io/helm-controller can only deploy jobs that are cluster-bound to the cluster-admin -# ClusterRole, the only way for this operator to be able to perform that binding is if it is also bound to the cluster-admin ClusterRole. -# -# As a result, this ClusterRoleBinding will be left as a work-in-progress until changes are made in k3s-io/helm-controller to allow us to grant -# only scoped down permissions to the Job that is deployed. diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml deleted file mode 100644 index f4c85254..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml +++ /dev/null @@ -1,62 +0,0 @@ -{{- if .Values.systemNamespacesConfigMap.create }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -data: - system-namespaces.json: |- - { -{{- if .Values.projectReleaseNamespaces.enabled }} -{{- if .Values.projectReleaseNamespaces.labelValue }} - "projectReleaseLabelValue": {{ .Values.projectReleaseNamespaces.labelValue | quote }}, -{{- else if .Values.global.cattle.systemProjectId }} - "projectReleaseLabelValue": {{ .Values.global.cattle.systemProjectId | quote }}, -{{- else }} - "projectReleaseLabelValue": "", -{{- end }} -{{- else }} - "projectReleaseLabelValue": "", -{{- end }} -{{- if not .Values.projectReleaseNamespaces.enabled }} - "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} -{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} - "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} -{{- else if len .Values.otherSystemProjectLabelValues }} - "systemProjectLabelValues": {{ .Values.otherSystemProjectLabelValues | toJson }} -{{- else }} - "systemProjectLabelValues": [] -{{- end }} - } ---- -{{- if (and .Values.systemNamespacesConfigMap.rbac.enabled .Values.systemNamespacesConfigMap.rbac.subjects) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -rules: -- apiGroups: - - "" - resources: - - configmaps - resourceNames: - - "{{ template "helm-project-operator.name" . }}-system-namespaces" - verbs: - - 'get' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "helm-project-operator.name" . }}-system-namespaces -subjects: {{ .Values.systemNamespacesConfigMap.rbac.subjects | toYaml | nindent 2 }} -{{- end }} -{{- end }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/validate-psp-install.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/validate-psp-install.yaml deleted file mode 100644 index a30c59d3..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/templates/validate-psp-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} -#{{- if .Values.global.cattle.psp.enabled }} -#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} -#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} -#{{- end }} -#{{- end }} -#{{- end }} diff --git a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/values.yaml b/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/values.yaml deleted file mode 100644 index 4905bf1a..00000000 --- a/charts/prometheus-federator/0.2.3/charts/helmProjectOperator/values.yaml +++ /dev/null @@ -1,226 +0,0 @@ -# Default values for helm-project-operator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Helm Project Operator Configuration - -global: - cattle: - clusterId: "" - psp: - enabled: false - projectLabel: field.cattle.io/projectId - systemDefaultRegistry: "" - systemProjectId: "" - url: "" - rbac: - ## Create RBAC resources for ServiceAccounts and users - ## - create: true - - userRoles: - ## Create default user ClusterRoles to allow users to interact with ProjectHelmCharts - create: true - ## Aggregate default user ClusterRoles into default k8s ClusterRoles - aggregateToDefaultRoles: true - - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - -helmApiVersion: dummy.cattle.io/v1alpha1 - -## valuesOverride overrides values that are set on each ProjectHelmChart deployment on an operator-level -## User-provided values will be overwritten based on the values provided here -valuesOverride: {} - -## projectReleaseNamespaces are auto-generated namespaces that are created to host Helm Releases -## managed by this operator on behalf of a ProjectHelmChart -projectReleaseNamespaces: - ## Enabled determines whether Project Release Namespaces should be created. If false, the underlying - ## Helm release will be deployed in the Project Registration Namespace - enabled: true - ## labelValue is the value of the Project that the projectReleaseNamespace should be created within - ## If empty, this will be set to the value of global.cattle.systemProjectId - ## If global.cattle.systemProjectId is also empty, project release namespaces will be disabled - labelValue: "" - -## otherSystemProjectLabelValues are project labels that identify namespaces as those that should be treated as system projects -## i.e. they will be entirely ignored by the operator -## By default, the global.cattle.systemProjectId will be in this list -otherSystemProjectLabelValues: [] - -## releaseRoleBindings configures RoleBindings automatically created by the Helm Project Operator -## in Project Release Namespaces where underlying Helm charts are deployed -releaseRoleBindings: - ## aggregate enables creating these RoleBindings off aggregating RoleBindings in the - ## Project Registration Namespace or ClusterRoleBindings that bind users to the ClusterRoles - ## specified under clusterRoleRefs - aggregate: true - - ## clusterRoleRefs are the ClusterRoles whose RoleBinding or ClusterRoleBindings should determine - ## the RoleBindings created in the Project Release Namespace - ## - ## By default, these are set to create RoleBindings based on the RoleBindings / ClusterRoleBindings - ## attached to the default K8s user-facing ClusterRoles of admin, edit, and view. - ## ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles - ## - clusterRoleRefs: - admin: admin - edit: edit - view: view - -hardenedNamespaces: - # Whether to automatically manage the configuration of the default ServiceAccount and - # auto-create a NetworkPolicy for each namespace created by this operator - enabled: true - - configuration: - # Values to be applied to each default ServiceAccount created in a managed namespace - serviceAccountSpec: - secrets: [] - imagePullSecrets: [] - automountServiceAccountToken: false - # Values to be applied to each default generated NetworkPolicy created in a managed namespace - networkPolicySpec: - podSelector: {} - egress: [] - ingress: [] - policyTypes: ["Ingress", "Egress"] - -## systemNamespacesConfigMap is a ConfigMap created to allow users to see valid entries -## for registering a ProjectHelmChart for a given Project on the Rancher Dashboard UI. -## It does not need to be enabled for a non-Rancher use case. -systemNamespacesConfigMap: - ## Create indicates whether the system namespaces configmap should be created - ## This is a required value for integration with Rancher Dashboard - create: true - - ## RBAC provides options around the RBAC created to allow users to be able to view - ## the systemNamespacesConfigMap; if not specified, only users with the ability to - ## view ConfigMaps in the namespace where this chart is deployed will be able to - ## properly view the system namespaces on the Rancher Dashboard UI - rbac: - ## enabled indicates that we should deploy a RoleBinding and Role to view this ConfigMap - enabled: true - ## subjects are the subjects that should be bound to this default RoleBinding - ## By default, we allow anyone who is authenticated to the system to be able to view - ## this ConfigMap in the deployment namespace - subjects: - - kind: Group - name: system:authenticated - -nameOverride: "" - -namespaceOverride: "" - -image: - repository: rancher/helm-project-operator - tag: v0.1.0 - pullPolicy: IfNotPresent - -helmController: - # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components - enabled: true - - job: - image: - repository: rancher/klipper-helm - tag: v0.7.0-build20220315 - -helmLocker: - enabled: true - -# Additional arguments to be passed into the Helm Project Operator image -additionalArgs: [] - -## Define which Nodes the Pods are scheduled on. -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for use with node taints -## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] -# - key: "key" -# operator: "Equal" -# value: "value" -# effect: "NoSchedule" - -resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m - -containerSecurityContext: {} - # allowPrivilegeEscalation: false - # capabilities: - # drop: - # - ALL - # privileged: false - # readOnlyRootFilesystem: true - -securityContext: {} - # runAsGroup: 1000 - # runAsUser: 1000 - # supplementalGroups: - # - 1000 - -debug: false -debugLevel: 0 - -cleanup: - image: - repository: rancher/shell - tag: v0.1.19 - pullPolicy: IfNotPresent - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - containerSecurityContext: {} - # allowPrivilegeEscalation: false - # capabilities: - # drop: - # - ALL - # privileged: false - # readOnlyRootFilesystem: true - - securityContext: - runAsNonRoot: false - runAsUser: 0 - - resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m diff --git a/charts/prometheus-federator/0.2.3/questions.yaml b/charts/prometheus-federator/0.2.3/questions.yaml deleted file mode 100644 index 87cf1339..00000000 --- a/charts/prometheus-federator/0.2.3/questions.yaml +++ /dev/null @@ -1,43 +0,0 @@ -questions: -- variable: global.cattle.psp.enabled - default: "false" - description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." - label: "Enable PodSecurityPolicies" - type: boolean - group: "Security Settings" -- variable: helmProjectOperator.helmController.enabled - label: Enable Embedded Helm Controller - description: 'Note: If you are running Prometheus Federator in an RKE2 / K3s cluster before v1.23.14 / v1.24.8 / v1.25.4, this should be disabled.' - type: boolean - group: Helm Controller -- variable: helmProjectOperator.helmLocker.enabled - label: Enable Embedded Helm Locker - type: boolean - group: Helm Locker -- variable: helmProjectOperator.projectReleaseNamespaces.labelValue - label: Project Release Namespace Project ID - description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) - type: string - required: false - group: Namespaces -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin - label: Admin ClusterRole - description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: admin - required: false - group: RBAC -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit - label: Edit ClusterRole - description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: edit - required: false - group: RBAC -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view - label: View ClusterRole - description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: view - required: false - group: RBAC \ No newline at end of file diff --git a/charts/prometheus-federator/0.2.3/templates/NOTES.txt b/charts/prometheus-federator/0.2.3/templates/NOTES.txt deleted file mode 100644 index f551f366..00000000 --- a/charts/prometheus-federator/0.2.3/templates/NOTES.txt +++ /dev/null @@ -1,3 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "prometheus-federator.namespace" . }} get pods -l "release={{ $.Release.Name }}" - diff --git a/charts/prometheus-federator/0.2.3/templates/_helpers.tpl b/charts/prometheus-federator/0.2.3/templates/_helpers.tpl deleted file mode 100644 index 15ea4e5c..00000000 --- a/charts/prometheus-federator/0.2.3/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -# Helm Project Operator - -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "prometheus-federator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "prometheus-federator.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "prometheus-federator.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "prometheus-federator.labels" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" -app.kubernetes.io/part-of: {{ template "prometheus-federator.name" . }} -chart: {{ template "prometheus-federator.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end }} diff --git a/charts/prometheus-federator/0.2.3/values.yaml b/charts/prometheus-federator/0.2.3/values.yaml deleted file mode 100644 index e9925f52..00000000 --- a/charts/prometheus-federator/0.2.3/values.yaml +++ /dev/null @@ -1,94 +0,0 @@ -# Default values for helm-project-operator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Prometheus Federator Configuration - -global: - cattle: - psp: - enabled: false - systemDefaultRegistry: "" - projectLabel: field.cattle.io/projectId - clusterId: "" - systemProjectId: "" - url: "" - rbac: - pspEnabled: true - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - -helmProjectOperator: - enabled: true - - # ensures that all resources created by subchart show up as prometheus-federator - helmApiVersion: monitoring.cattle.io/v1alpha1 - - nameOverride: prometheus-federator - - helmController: - # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components - enabled: true - - helmLocker: - enabled: true - - ## valuesOverride overrides values that are set on each Project Prometheus Stack Helm Chart deployment on an operator level - ## all values provided here will override any user-provided values automatically - valuesOverride: - - federate: - # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from - # By default, this matches the default deployment of Rancher Monitoring - targets: - - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 - - image: - repository: rancher/prometheus-federator - tag: v0.2.2 - pullPolicy: IfNotPresent - - # Additional arguments to be passed into the Prometheus Federator image - additionalArgs: [] - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m - - securityContext: {} - # allowPrivilegeEscalation: false - # readOnlyRootFilesystem: true - - debug: false - debugLevel: 0 \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/Chart.yaml b/charts/prometheus-federator/0.3.0/Chart.yaml deleted file mode 100644 index ba842552..00000000 --- a/charts/prometheus-federator/0.3.0/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Prometheus Federator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-monitoring-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' - catalog.cattle.io/release-name: prometheus-federator -apiVersion: v2 -appVersion: 0.3.0 -dependencies: -- condition: helmProjectOperator.enabled - name: helmProjectOperator - repository: file://./charts/helmProjectOperator -description: Prometheus Federator -icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg -name: prometheus-federator -version: 0.3.0 diff --git a/charts/prometheus-federator/0.3.0/README.md b/charts/prometheus-federator/0.3.0/README.md deleted file mode 100644 index 7da4edfc..00000000 --- a/charts/prometheus-federator/0.3.0/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Prometheus Federator - -This chart is deploys a Helm Project Operator (based on the [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator)), an operator that manages deploying Helm charts each containing a Project Monitoring Stack, where each stack contains: -- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) -- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) -- Default ServiceMonitors that watch the deployed resources - -> **Important Note: Prometheus Federator is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs.** - -By default, the chart is configured and intended to be deployed alongside [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that each Project Monitoring Stack is configured to federate namespace-scoped metrics from by default. - -## Pre-Installation: Using Prometheus Federator with Rancher and rancher-monitoring - -If you are running your cluster on [Rancher](https://rancher.com/) and already have [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) deployed onto your cluster, Prometheus Federator's default configuration should already be configured to work with your existing Cluster Monitoring Stack; however, here are some notes on how we recommend you configure rancher-monitoring to optimize the security and usability of Prometheus Federator in your cluster: - -### Ensure the cattle-monitoring-system namespace is placed into the System Project (or a similarly locked down Project that has access to other Projects in the cluster) - -Prometheus Operator's security model expects that the namespace it is deployed into (`cattle-monitoring-system`) has limited access for anyone except Cluster Admins to avoid privilege escalation via execing into Pods (such as the Jobs executing Helm operations). In addition, deploying Prometheus Federator and all Project Prometheus stacks into the System Project ensures that the each Project Prometheus is able to reach out to scrape workloads across all Projects (even if Network Policies are defined via Project Network Isolation) but has limited access for Project Owners, Project Members, and other users to be able to access data they shouldn't have access to (i.e. being allowed to exec into pods, set up the ability to scrape namespaces outside of a given Project, etc.). - -### Configure rancher-monitoring to only watch for resources created by the Helm chart itself - -Since each Project Monitoring Stack will watch the other namespaces and collect additional custom workload metrics or dashboards already, it's recommended to configure the following settings on all selectors to ensure that the Cluster Prometheus Stack only monitors resources created by the Helm Chart itself: - -``` -matchLabels: - release: "rancher-monitoring" -``` - -The following selector fields are recommended to have this value: -- `.Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector` -- `.Values.prometheus.prometheusSpec.serviceMonitorSelector` -- `.Values.prometheus.prometheusSpec.podMonitorSelector` -- `.Values.prometheus.prometheusSpec.ruleSelector` -- `.Values.prometheus.prometheusSpec.probeSelector` - -Once this setting is turned on, you can always create ServiceMonitors or PodMonitors that are picked up by the Cluster Prometheus by adding the label `release: "rancher-monitoring"` to them (in which case they will be ignored by Project Monitoring Stacks automatically by default, even if the namespace in which those ServiceMonitors or PodMonitors reside in are not system namespaces). - -> Note: If you don't want to allow users to be able to create ServiceMonitors and PodMonitors that aggregate into the Cluster Prometheus in Project namespaces, you can additionally set the namespaceSelectors on the chart to only target system namespaces (which must contain `cattle-monitoring-system` and `cattle-dashboards`, where resources are deployed into by default by rancher-monitoring; you will also need to monitor the `default` namespace to get apiserver metrics or create a custom ServiceMonitor to scrape apiserver metrics from the Service residing in the default namespace) to limit your Cluster Prometheus from picking up other Prometheus Operator CRs; in that case, it would be recommended to turn `.Values.prometheus.prometheusSpec.ignoreNamespaceSelectors=true` to allow you to define ServiceMonitors that can monitor non-system namespaces from within a system namespace. - -In addition, if you modified the default `.Values.grafana.sidecar.*.searchNamespace` values on the Grafana Helm subchart for Monitoring V2, it is also recommended to remove the overrides or ensure that your defaults are scoped to only system namespaces for the following values: -- `.Values.grafana.sidecar.dashboards.searchNamespace` (default `cattle-dashboards`) -- `.Values.grafana.sidecar.datasources.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) -- `.Values.grafana.sidecar.plugins.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) -- `.Values.grafana.sidecar.notifiers.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) - -### Increase the CPU / memory limits of the Cluster Prometheus - -Depending on a cluster's setup, it's generally recommended to give a large amount of dedicated memory to the Cluster Prometheus to avoid restarts due to out-of-memory errors (OOMKilled), usually caused by churn created in the cluster that causes a large number of high cardinality metrics to be generated and ingested by Prometheus within one block of time; this is one of the reasons why the default Rancher Monitoring stack expects around 4GB of RAM to be able to operate in a normal-sized cluster. However, when introducing Project Monitoring Stacks that are all sending `/federate` requests to the same Cluster Prometheus and are reliant on the Cluster Prometheus being "up" to federate that system data on their namespaces, it's even more important that the Cluster Prometheus has an ample amount of CPU / memory assigned to it to prevent an outage that can cause data gaps across all Project Prometheis in the cluster. - -> Note: There are no specific recommendations on how much memory the Cluster Prometheus should be configured with since it depends entirely on the user's setup (namely the likelihood of encountering a high churn rate and the scale of metrics that could be generated at that time); it generally varies per setup. - -## How does the operator work? - -1. On deploying this chart, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `monitoring.cattle.io/v1alpha1` (also known as "Project Monitors" in the Rancher UI) in a **Project Registration Namespace (`cattle-project-`)**. -2. On seeing each ProjectHelmChartCR, the operator will automatically deploy a Project Prometheus stack on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--monitoring`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. -3. RBAC will automatically be assigned in the Project Release Namespace to allow users to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack deployed; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). - -### What is a Project? - -In Prometheus Federator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. - -### Configuring the Helm release created by a ProjectHelmChart - -The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: -- View to the chart's definition located at [`rancher/prometheus-federator` under `charts/rancher-project-monitoring`](https://github.com/rancher/prometheus-federator/blob/main/charts/rancher-project-monitoring) (where the chart version will be tied to the version of this operator) -- Look for the ConfigMap named `monitoring.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `prometheus-federator` binary). - -### Namespaces - -As a Project Operator based on [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator), Prometheus Federator has three different classifications of namespaces that the operator looks out for: -1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-monitoring-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** -2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. -> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project -> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace -3. **Project Release Namespace (`cattle-project--monitoring`)**: this is the set of namespaces that the operator deploys Project Monitoring Stacks within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Project Monitoring Stack based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Prometheus Federator.** -> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace -> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) -> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace - -### Helm Resources (HelmChart, HelmRelease) - -On deploying a ProjectHelmChart, the Prometheus Federator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: -- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). -> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** -- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). -> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified - -Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. - -### RBAC - -As described in the section on namespaces above, Prometheus Federator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: -- ClusterRoleBindings -- RoleBindings in the Project Release Namespace - -On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). - -> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. - -If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: -- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` -- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` - -By default, the `rancher-project-monitoring` (the underlying chart deployed by Prometheus Federator) creates three default Roles per Project Release Namespace that provide `admin`, `edit`, and `view` users to permissions to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack to provide least privilege; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. - -### Advanced Helm Project Operator Configuration - -|Value|Configuration| -|---|---------------------------| -|`helmProjectOperator.valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | -|`helmProjectOperator.projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | -|`helmProjectOperator.otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `cattle-monitoring-system`, `cattle-dashboards`, and `kube-system` are explicitly marked as system namespaces as well, regardless of label or annotation. | -|`helmProjectOperator.releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces -|`helmProjectOperator.releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | -|`helmProjectOperator.hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | -|`helmProjectOperator.hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | -|`helmProjectOperator.helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2/K3s clusters before v1.23.14 / v1.24.8 / v1.25.4 since RKE2/K3s clusters already run Helm Controller at a cluster-wide level to manage internal Kubernetes components | -|`helmProjectOperator.helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.0/app-README.md b/charts/prometheus-federator/0.3.0/app-README.md deleted file mode 100644 index 99fa7ca1..00000000 --- a/charts/prometheus-federator/0.3.0/app-README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Prometheus Federator - -This chart deploys an operator that manages Project Monitoring Stacks composed of the following set of resources that are scoped to project namespaces: -- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) -- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) -- Default ServiceMonitors that watch the deployed Prometheus, Grafana, and Alertmanager - -Since this Project Monitoring Stack deploys Prometheus Operator CRs, an existing Prometheus Operator instance must already be deployed in the cluster for Prometheus Federator to successfully be able to deploy Project Monitoring Stacks. It is recommended to use [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) for this. For more information on how the chart works or advanced configurations, please read the `README.md`. - -## Upgrading to Kubernetes v1.25+ - -Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. - -As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. -​ -> **Note:** -> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. - ​ -> **Note:** -> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** -> -> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. -Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. -​ -As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml deleted file mode 100644 index 421aabb1..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml +++ /dev/null @@ -1,15 +0,0 @@ -annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Helm Project Operator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-helm-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.0-0' - catalog.cattle.io/release-name: helm-project-operator -apiVersion: v2 -appVersion: 0.1.0 -description: Helm Project Operator -name: helmProjectOperator -version: 0.1.1 diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md deleted file mode 100644 index fc1d39e8..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Helm Project Operator - -## How does the operator work? - -1. On deploying a Helm Project Operator, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `dummy.cattle.io/v1alpha1` in a **Project Registration Namespace (`cattle-project-`)**. -2. On seeing each ProjectHelmChartCR, the operator will automatically deploy the embedded Helm chart on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--dummy`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. -3. RBAC will automatically be assigned in the Project Release Namespace to allow users to based on Role created in the Project Release Namespace with a given set of labels; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). - -### What is a Project? - -In Helm Project Operator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. - -### What is a ProjectHelmChart? - -A ProjectHelmChart is an instance of a (project-scoped) Helm chart deployed on behalf of a user who has permissions to create ProjectHelmChart resources in a Project Registration namespace. - -Generally, the best way to think about the ProjectHelmChart model is by comparing it to two other models: -1. Managed Kubernetes providers (EKS, GKE, AKS, etc.): in this model, a user has the ability to say "I want a Kubernetes cluster" but the underlying cloud provider is responsible for provisioning the infrastructure and offering **limited view and access** of the underlying resources created on their behalf; similarly, Helm Project Operator allows a Project Owner to say "I want this Helm chart deployed", but the underlying Operator is responsible for "provisioning" (deploying) the Helm chart and offering **limited view and access** of the underlying Kubernetes resources created on their behalf (based on configuring "least-privilege" Kubernetes RBAC for the Project Owners / Members in the newly created Project Release Namespace). -2. Dynamically-provisioned Persistent Volumes: in this model, a single resource (PersistentVolume) exists that allows you to specify a Storage Class that actually implements provisioning the underlying storage via a Storage Class Provisioner (e.g. Longhorn). Similarly, the ProjectHelmChart exists that allows you to specify a `spec.helmApiVersion` ("storage class") that actually implements deploying the underlying Helm chart via a Helm Project Operator (e.g. [`rancher/prometheus-federator`](https://github.com/rancher/prometheus-federator)). - -### Configuring the Helm release created by a ProjectHelmChart - -The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: -- View to the chart's definition located at [`rancher/helm-project-operator` under `charts/example-chart`](https://github.com/rancher/helm-project-operator/blob/main/charts/example-chart) (where the chart version will be tied to the version of this operator) -- Look for the ConfigMap named `dummy.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `helm-project-operator` binary). - -### Namespaces - -All Helm Project Operators have three different classifications of namespaces that the operator looks out for: -1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-helm-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** -2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. -> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project -> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace -3. **Project Release Namespace (`cattle-project--dummy`)**: this is the set of namespaces that the operator deploys Helm charts within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Helm charts based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Helm Project Operator.** -> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace -> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) -> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace - -### Helm Resources (HelmChart, HelmRelease) - -On deploying a ProjectHelmChart, the Helm Project Operator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: -- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). -> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** -- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). -> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified - -Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. - -### RBAC - -As described in the section on namespaces above, Helm Project Operator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: -- ClusterRoleBindings -- RoleBindings in the Project Release Namespace - -On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). - -> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. - -If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: -- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` -- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` - -By default, the `example-chart` (the underlying chart deployed by Helm Project Operator) does not create any default roles; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. - -### Advanced Helm Project Operator Configuration - -|Value|Configuration| -|---|---------------------------| -|`valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | -|`projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | -|`otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `kube-system` is explicitly marked as a system namespace as well, regardless of label or annotation. | -|`releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces -|`releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | -|`hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | -|`hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | -|`helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2 clusters since RKE2 clusters already run Helm Controller to manage internal Kubernetes components | -|`helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md deleted file mode 100644 index fd551467..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md +++ /dev/null @@ -1,20 +0,0 @@ -# Helm Project Operator - -This chart installs the example [Helm Project Operator](https://github.com/rancher/helm-project-operator) onto your cluster. - -## Upgrading to Kubernetes v1.25+ - -Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. - -As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. -​ -> **Note:** -> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. - ​ -> **Note:** -> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** -> -> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. -Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. -​ -As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml deleted file mode 100644 index 054361a7..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml +++ /dev/null @@ -1,43 +0,0 @@ -questions: -- variable: global.cattle.psp.enabled - default: "false" - description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." - label: "Enable PodSecurityPolicies" - type: boolean - group: "Security Settings" -- variable: helmController.enabled - label: Enable Embedded Helm Controller - description: 'Note: If you are running this chart in an RKE2 cluster, this should be disabled.' - type: boolean - group: Helm Controller -- variable: helmLocker.enabled - label: Enable Embedded Helm Locker - type: boolean - group: Helm Locker -- variable: projectReleaseNamespaces.labelValue - label: Project Release Namespace Project ID - description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) - type: string - required: false - group: Namespaces -- variable: releaseRoleBindings.clusterRoleRefs.admin - label: Admin ClusterRole - description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: admin - required: false - group: RBAC -- variable: releaseRoleBindings.clusterRoleRefs.edit - label: Edit ClusterRole - description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: edit - required: false - group: RBAC -- variable: releaseRoleBindings.clusterRoleRefs.view - label: View ClusterRole - description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: view - required: false - group: RBAC diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt deleted file mode 100644 index 32baeebc..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "helm-project-operator.namespace" . }} get pods -l "release={{ $.Release.Name }}" diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl deleted file mode 100644 index 97dd6b36..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -# Helm Project Operator - -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "helm-project-operator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "helm-project-operator.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "helm-project-operator.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "helm-project-operator.labels" -}} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" -app.kubernetes.io/part-of: {{ template "helm-project-operator.name" . }} -chart: {{ template "helm-project-operator.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end -}} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml deleted file mode 100644 index 98675642..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml +++ /dev/null @@ -1,82 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "helm-project-operator.name" . }}-cleanup - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} - annotations: - "helm.sh/hook": pre-delete - "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed -spec: - template: - metadata: - name: {{ template "helm-project-operator.name" . }}-cleanup - labels: {{ include "helm-project-operator.labels" . | nindent 8 }} - app: {{ template "helm-project-operator.name" . }} - spec: - serviceAccountName: {{ template "helm-project-operator.name" . }} -{{- if .Values.cleanup.securityContext }} - securityContext: {{ toYaml .Values.cleanup.securityContext | nindent 8 }} -{{- end }} - initContainers: - - name: add-cleanup-annotations - image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - command: - - /bin/sh - - -c - - > - echo "Labeling all ProjectHelmCharts with helm.cattle.io/helm-project-operator-cleanup=true"; - EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; - IFS=$'\n'; - for namespace in $(kubectl get namespaces -l helm.cattle.io/helm-project-operated=true --no-headers -o=custom-columns=NAME:.metadata.name); do - for projectHelmChartAndHelmApiVersion in $(kubectl get projecthelmcharts -n ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name,HELMAPIVERSION:.spec.helmApiVersion); do - projectHelmChartAndHelmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | xargs); - projectHelmChart=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f1); - helmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f2); - if [[ ${helmApiVersion} != ${EXPECTED_HELM_API_VERSION} ]]; then - echo "Skipping marking ${namespace}/${projectHelmChart} with cleanup annotation since spec.helmApiVersion: ${helmApiVersion} is not ${EXPECTED_HELM_API_VERSION}"; - continue; - fi; - kubectl label projecthelmcharts -n ${namespace} ${projectHelmChart} helm.cattle.io/helm-project-operator-cleanup=true --overwrite; - done; - done; -{{- if .Values.cleanup.resources }} - resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} -{{- end }} -{{- if .Values.cleanup.containerSecurityContext }} - securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} -{{- end }} - containers: - - name: ensure-subresources-deleted - image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} - imagePullPolicy: IfNotPresent - command: - - /bin/sh - - -c - - > - SYSTEM_NAMESPACE={{ .Release.Namespace }} - EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; - HELM_API_VERSION_TRUNCATED=$(echo ${EXPECTED_HELM_API_VERSION} | cut -d'/' -f0); - echo "Ensuring HelmCharts and HelmReleases are deleted from ${SYSTEM_NAMESPACE}..."; - while [[ "$(kubectl get helmcharts,helmreleases -l helm.cattle.io/helm-api-version=${HELM_API_VERSION_TRUNCATED} -n ${SYSTEM_NAMESPACE} 2>&1)" != "No resources found in ${SYSTEM_NAMESPACE} namespace." ]]; do - echo "waiting for HelmCharts and HelmReleases to be deleted from ${SYSTEM_NAMESPACE}... sleeping 3 seconds"; - sleep 3; - done; - echo "Successfully deleted all HelmCharts and HelmReleases in ${SYSTEM_NAMESPACE}!"; -{{- if .Values.cleanup.resources }} - resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} -{{- end }} -{{- if .Values.cleanup.containerSecurityContext }} - securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} -{{- end }} - restartPolicy: OnFailure - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} - {{- if .Values.cleanup.nodeSelector }} - {{- toYaml .Values.cleanup.nodeSelector | nindent 8 }} - {{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} - {{- if .Values.cleanup.tolerations }} - {{- toYaml .Values.cleanup.tolerations | nindent 8 }} - {{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml deleted file mode 100644 index 60ed263b..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-admin - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-admin: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/finalizers - - projecthelmcharts/status - verbs: - - '*' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-edit - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-edit: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/status - verbs: - - 'get' - - 'list' - - 'watch' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "helm-project-operator.name" . }}-view - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - rbac.authorization.k8s.io/aggregate-to-view: "true" - {{- end }} -rules: -- apiGroups: - - helm.cattle.io - resources: - - projecthelmcharts - - projecthelmcharts/status - verbs: - - 'get' - - 'list' - - 'watch' -{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml deleted file mode 100644 index d4def157..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml +++ /dev/null @@ -1,14 +0,0 @@ -## Note: If you add another entry to this ConfigMap, make sure a corresponding env var is set -## in the deployment of the operator to ensure that a Helm upgrade will force the operator -## to reload the values in the ConfigMap and redeploy -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "helm-project-operator.name" . }}-config - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -data: - hardened.yaml: |- -{{ .Values.hardenedNamespaces.configuration | toYaml | indent 4 }} - values.yaml: |- -{{ .Values.valuesOverride | toYaml | indent 4 }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml deleted file mode 100644 index c7309805..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml +++ /dev/null @@ -1,124 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ template "helm-project-operator.name" . }} - release: {{ $.Release.Name | quote }} - template: - metadata: - labels: {{ include "helm-project-operator.labels" . | nindent 8 }} - app: {{ template "helm-project-operator.name" . }} - spec: - containers: - - name: {{ template "helm-project-operator.name" . }} - image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - args: - - {{ template "helm-project-operator.name" . }} - - --namespace={{ template "helm-project-operator.namespace" . }} - - --controller-name={{ template "helm-project-operator.name" . }} - - --values-override-file=/etc/helmprojectoperator/config/values.yaml -{{- if .Values.global.cattle.systemDefaultRegistry }} - - --system-default-registry={{ .Values.global.cattle.systemDefaultRegistry }} -{{- end }} -{{- if .Values.global.cattle.url }} - - --cattle-url={{ .Values.global.cattle.url }} -{{- end }} -{{- if .Values.global.cattle.projectLabel }} - - --project-label={{ .Values.global.cattle.projectLabel }} -{{- end }} -{{- if not .Values.projectReleaseNamespaces.enabled }} - - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} -{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} - - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} -{{- else if len .Values.otherSystemProjectLabelValues }} - - --system-project-label-values={{ join "," .Values.otherSystemProjectLabelValues }} -{{- end }} -{{- if .Values.projectReleaseNamespaces.enabled }} -{{- if .Values.projectReleaseNamespaces.labelValue }} - - --project-release-label-value={{ .Values.projectReleaseNamespaces.labelValue }} -{{- else if .Values.global.cattle.systemProjectId }} - - --project-release-label-value={{ .Values.global.cattle.systemProjectId }} -{{- end }} -{{- end }} -{{- if .Values.global.cattle.clusterId }} - - --cluster-id={{ .Values.global.cattle.clusterId }} -{{- end }} -{{- if .Values.releaseRoleBindings.aggregate }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.admin }} - - --admin-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.admin }} -{{- end }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.edit }} - - --edit-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.edit }} -{{- end }} -{{- if .Values.releaseRoleBindings.clusterRoleRefs.view }} - - --view-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.view }} -{{- end }} -{{- end }} -{{- end }} -{{- if .Values.hardenedNamespaces.enabled }} - - --hardening-options-file=/etc/helmprojectoperator/config/hardening.yaml -{{- else }} - - --disable-hardening -{{- end }} -{{- if .Values.debug }} - - --debug - - --debug-level={{ .Values.debugLevel }} -{{- end }} -{{- if not .Values.helmController.enabled }} - - --disable-embedded-helm-controller -{{- else }} - - --helm-job-image={{ template "system_default_registry" . }}{{ .Values.helmController.job.image.repository }}:{{ .Values.helmController.job.image.tag }} -{{- end }} -{{- if not .Values.helmLocker.enabled }} - - --disable-embedded-helm-locker -{{- end }} -{{- if .Values.additionalArgs }} -{{- toYaml .Values.additionalArgs | nindent 10 }} -{{- end }} - env: - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - ## Note: The below two values only exist to force Helm to upgrade the deployment on - ## a change to the contents of the ConfigMap during an upgrade. Neither serve - ## any practical purpose and can be removed and replaced with a configmap reloader - ## in a future change if dynamic updates are required. - - name: HARDENING_OPTIONS_SHA_256_HASH - value: {{ .Values.hardenedNamespaces.configuration | toYaml | sha256sum }} - - name: VALUES_OVERRIDE_SHA_256_HASH - value: {{ .Values.valuesOverride | toYaml | sha256sum }} -{{- if .Values.resources }} - resources: {{ toYaml .Values.resources | nindent 12 }} -{{- end }} -{{- if .Values.containerSecurityContext }} - securityContext: {{ toYaml .Values.containerSecurityContext | nindent 12 }} -{{- end }} - volumeMounts: - - name: config - mountPath: "/etc/helmprojectoperator/config" - serviceAccountName: {{ template "helm-project-operator.name" . }} -{{- if .Values.securityContext }} - securityContext: {{ toYaml .Values.securityContext | nindent 8 }} -{{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} -{{- if .Values.nodeSelector }} -{{- toYaml .Values.nodeSelector | nindent 8 }} -{{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} -{{- if .Values.tolerations }} -{{- toYaml .Values.tolerations | nindent 8 }} -{{- end }} - volumes: - - name: config - configMap: - name: {{ template "helm-project-operator.name" . }}-config diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml deleted file mode 100644 index 73dcc456..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml +++ /dev/null @@ -1,68 +0,0 @@ -{{- if .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -{{- if .Values.global.rbac.pspAnnotations }} - annotations: {{ toYaml .Values.global.rbac.pspAnnotations | nindent 4 }} -{{- end }} -spec: - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -rules: -{{- if semverCompare "> 1.15.0-0" .Capabilities.KubeVersion.GitVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "helm-project-operator.name" . }}-psp ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "helm-project-operator.name" . }}-psp - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "helm-project-operator.name" . }}-psp -subjects: - - kind: ServiceAccount - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} -{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml deleted file mode 100644 index b1c40920..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "helm-project-operator.name" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: "cluster-admin" # see note below -subjects: -- kind: ServiceAccount - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "helm-project-operator.name" . }} - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} - app: {{ template "helm-project-operator.name" . }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }} -{{- end }} -# --- -# NOTE: -# As of now, due to the fact that the k3s-io/helm-controller can only deploy jobs that are cluster-bound to the cluster-admin -# ClusterRole, the only way for this operator to be able to perform that binding is if it is also bound to the cluster-admin ClusterRole. -# -# As a result, this ClusterRoleBinding will be left as a work-in-progress until changes are made in k3s-io/helm-controller to allow us to grant -# only scoped down permissions to the Job that is deployed. diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml deleted file mode 100644 index f4c85254..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml +++ /dev/null @@ -1,62 +0,0 @@ -{{- if .Values.systemNamespacesConfigMap.create }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -data: - system-namespaces.json: |- - { -{{- if .Values.projectReleaseNamespaces.enabled }} -{{- if .Values.projectReleaseNamespaces.labelValue }} - "projectReleaseLabelValue": {{ .Values.projectReleaseNamespaces.labelValue | quote }}, -{{- else if .Values.global.cattle.systemProjectId }} - "projectReleaseLabelValue": {{ .Values.global.cattle.systemProjectId | quote }}, -{{- else }} - "projectReleaseLabelValue": "", -{{- end }} -{{- else }} - "projectReleaseLabelValue": "", -{{- end }} -{{- if not .Values.projectReleaseNamespaces.enabled }} - "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} -{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} - "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} -{{- else if len .Values.otherSystemProjectLabelValues }} - "systemProjectLabelValues": {{ .Values.otherSystemProjectLabelValues | toJson }} -{{- else }} - "systemProjectLabelValues": [] -{{- end }} - } ---- -{{- if (and .Values.systemNamespacesConfigMap.rbac.enabled .Values.systemNamespacesConfigMap.rbac.subjects) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -rules: -- apiGroups: - - "" - resources: - - configmaps - resourceNames: - - "{{ template "helm-project-operator.name" . }}-system-namespaces" - verbs: - - 'get' ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "helm-project-operator.name" . }}-system-namespaces - namespace: {{ template "helm-project-operator.namespace" . }} - labels: {{ include "helm-project-operator.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "helm-project-operator.name" . }}-system-namespaces -subjects: {{ .Values.systemNamespacesConfigMap.rbac.subjects | toYaml | nindent 2 }} -{{- end }} -{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml deleted file mode 100644 index a30c59d3..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} -#{{- if .Values.global.cattle.psp.enabled }} -#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} -#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} -#{{- end }} -#{{- end }} -#{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml deleted file mode 100644 index 4905bf1a..00000000 --- a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml +++ /dev/null @@ -1,226 +0,0 @@ -# Default values for helm-project-operator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Helm Project Operator Configuration - -global: - cattle: - clusterId: "" - psp: - enabled: false - projectLabel: field.cattle.io/projectId - systemDefaultRegistry: "" - systemProjectId: "" - url: "" - rbac: - ## Create RBAC resources for ServiceAccounts and users - ## - create: true - - userRoles: - ## Create default user ClusterRoles to allow users to interact with ProjectHelmCharts - create: true - ## Aggregate default user ClusterRoles into default k8s ClusterRoles - aggregateToDefaultRoles: true - - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - -helmApiVersion: dummy.cattle.io/v1alpha1 - -## valuesOverride overrides values that are set on each ProjectHelmChart deployment on an operator-level -## User-provided values will be overwritten based on the values provided here -valuesOverride: {} - -## projectReleaseNamespaces are auto-generated namespaces that are created to host Helm Releases -## managed by this operator on behalf of a ProjectHelmChart -projectReleaseNamespaces: - ## Enabled determines whether Project Release Namespaces should be created. If false, the underlying - ## Helm release will be deployed in the Project Registration Namespace - enabled: true - ## labelValue is the value of the Project that the projectReleaseNamespace should be created within - ## If empty, this will be set to the value of global.cattle.systemProjectId - ## If global.cattle.systemProjectId is also empty, project release namespaces will be disabled - labelValue: "" - -## otherSystemProjectLabelValues are project labels that identify namespaces as those that should be treated as system projects -## i.e. they will be entirely ignored by the operator -## By default, the global.cattle.systemProjectId will be in this list -otherSystemProjectLabelValues: [] - -## releaseRoleBindings configures RoleBindings automatically created by the Helm Project Operator -## in Project Release Namespaces where underlying Helm charts are deployed -releaseRoleBindings: - ## aggregate enables creating these RoleBindings off aggregating RoleBindings in the - ## Project Registration Namespace or ClusterRoleBindings that bind users to the ClusterRoles - ## specified under clusterRoleRefs - aggregate: true - - ## clusterRoleRefs are the ClusterRoles whose RoleBinding or ClusterRoleBindings should determine - ## the RoleBindings created in the Project Release Namespace - ## - ## By default, these are set to create RoleBindings based on the RoleBindings / ClusterRoleBindings - ## attached to the default K8s user-facing ClusterRoles of admin, edit, and view. - ## ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles - ## - clusterRoleRefs: - admin: admin - edit: edit - view: view - -hardenedNamespaces: - # Whether to automatically manage the configuration of the default ServiceAccount and - # auto-create a NetworkPolicy for each namespace created by this operator - enabled: true - - configuration: - # Values to be applied to each default ServiceAccount created in a managed namespace - serviceAccountSpec: - secrets: [] - imagePullSecrets: [] - automountServiceAccountToken: false - # Values to be applied to each default generated NetworkPolicy created in a managed namespace - networkPolicySpec: - podSelector: {} - egress: [] - ingress: [] - policyTypes: ["Ingress", "Egress"] - -## systemNamespacesConfigMap is a ConfigMap created to allow users to see valid entries -## for registering a ProjectHelmChart for a given Project on the Rancher Dashboard UI. -## It does not need to be enabled for a non-Rancher use case. -systemNamespacesConfigMap: - ## Create indicates whether the system namespaces configmap should be created - ## This is a required value for integration with Rancher Dashboard - create: true - - ## RBAC provides options around the RBAC created to allow users to be able to view - ## the systemNamespacesConfigMap; if not specified, only users with the ability to - ## view ConfigMaps in the namespace where this chart is deployed will be able to - ## properly view the system namespaces on the Rancher Dashboard UI - rbac: - ## enabled indicates that we should deploy a RoleBinding and Role to view this ConfigMap - enabled: true - ## subjects are the subjects that should be bound to this default RoleBinding - ## By default, we allow anyone who is authenticated to the system to be able to view - ## this ConfigMap in the deployment namespace - subjects: - - kind: Group - name: system:authenticated - -nameOverride: "" - -namespaceOverride: "" - -image: - repository: rancher/helm-project-operator - tag: v0.1.0 - pullPolicy: IfNotPresent - -helmController: - # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components - enabled: true - - job: - image: - repository: rancher/klipper-helm - tag: v0.7.0-build20220315 - -helmLocker: - enabled: true - -# Additional arguments to be passed into the Helm Project Operator image -additionalArgs: [] - -## Define which Nodes the Pods are scheduled on. -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for use with node taints -## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] -# - key: "key" -# operator: "Equal" -# value: "value" -# effect: "NoSchedule" - -resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m - -containerSecurityContext: {} - # allowPrivilegeEscalation: false - # capabilities: - # drop: - # - ALL - # privileged: false - # readOnlyRootFilesystem: true - -securityContext: {} - # runAsGroup: 1000 - # runAsUser: 1000 - # supplementalGroups: - # - 1000 - -debug: false -debugLevel: 0 - -cleanup: - image: - repository: rancher/shell - tag: v0.1.19 - pullPolicy: IfNotPresent - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - containerSecurityContext: {} - # allowPrivilegeEscalation: false - # capabilities: - # drop: - # - ALL - # privileged: false - # readOnlyRootFilesystem: true - - securityContext: - runAsNonRoot: false - runAsUser: 0 - - resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m diff --git a/charts/prometheus-federator/0.3.0/questions.yaml b/charts/prometheus-federator/0.3.0/questions.yaml deleted file mode 100644 index 87cf1339..00000000 --- a/charts/prometheus-federator/0.3.0/questions.yaml +++ /dev/null @@ -1,43 +0,0 @@ -questions: -- variable: global.cattle.psp.enabled - default: "false" - description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." - label: "Enable PodSecurityPolicies" - type: boolean - group: "Security Settings" -- variable: helmProjectOperator.helmController.enabled - label: Enable Embedded Helm Controller - description: 'Note: If you are running Prometheus Federator in an RKE2 / K3s cluster before v1.23.14 / v1.24.8 / v1.25.4, this should be disabled.' - type: boolean - group: Helm Controller -- variable: helmProjectOperator.helmLocker.enabled - label: Enable Embedded Helm Locker - type: boolean - group: Helm Locker -- variable: helmProjectOperator.projectReleaseNamespaces.labelValue - label: Project Release Namespace Project ID - description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) - type: string - required: false - group: Namespaces -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin - label: Admin ClusterRole - description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: admin - required: false - group: RBAC -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit - label: Edit ClusterRole - description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: edit - required: false - group: RBAC -- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view - label: View ClusterRole - description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) - type: string - default: view - required: false - group: RBAC \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/templates/NOTES.txt b/charts/prometheus-federator/0.3.0/templates/NOTES.txt deleted file mode 100644 index f551f366..00000000 --- a/charts/prometheus-federator/0.3.0/templates/NOTES.txt +++ /dev/null @@ -1,3 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "prometheus-federator.namespace" . }} get pods -l "release={{ $.Release.Name }}" - diff --git a/charts/prometheus-federator/0.3.0/templates/_helpers.tpl b/charts/prometheus-federator/0.3.0/templates/_helpers.tpl deleted file mode 100644 index 15ea4e5c..00000000 --- a/charts/prometheus-federator/0.3.0/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -# Helm Project Operator - -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "prometheus-federator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "prometheus-federator.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "prometheus-federator.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "prometheus-federator.labels" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" -app.kubernetes.io/part-of: {{ template "prometheus-federator.name" . }} -chart: {{ template "prometheus-federator.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end }} diff --git a/charts/prometheus-federator/0.3.0/values.yaml b/charts/prometheus-federator/0.3.0/values.yaml deleted file mode 100644 index 4f22c1dd..00000000 --- a/charts/prometheus-federator/0.3.0/values.yaml +++ /dev/null @@ -1,94 +0,0 @@ -# Default values for helm-project-operator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Prometheus Federator Configuration - -global: - cattle: - psp: - enabled: false - systemDefaultRegistry: "" - projectLabel: field.cattle.io/projectId - clusterId: "" - systemProjectId: "" - url: "" - rbac: - pspEnabled: true - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - -helmProjectOperator: - enabled: true - - # ensures that all resources created by subchart show up as prometheus-federator - helmApiVersion: monitoring.cattle.io/v1alpha1 - - nameOverride: prometheus-federator - - helmController: - # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components - enabled: true - - helmLocker: - enabled: true - - ## valuesOverride overrides values that are set on each Project Prometheus Stack Helm Chart deployment on an operator level - ## all values provided here will override any user-provided values automatically - valuesOverride: - - federate: - # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from - # By default, this matches the default deployment of Rancher Monitoring - targets: - - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 - - image: - repository: rancher/prometheus-federator - tag: v0.3.0 - pullPolicy: IfNotPresent - - # Additional arguments to be passed into the Prometheus Federator image - additionalArgs: [] - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - resources: {} - # limits: - # memory: 500Mi - # cpu: 1000m - # requests: - # memory: 100Mi - # cpu: 100m - - securityContext: {} - # allowPrivilegeEscalation: false - # readOnlyRootFilesystem: true - - debug: false - debugLevel: 0 \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.2.2/questions.yaml b/charts/rancher-project-monitoring/0.2.2/questions.yaml index c15f36e7..0e9bc69d 100644 --- a/charts/rancher-project-monitoring/0.2.2/questions.yaml +++ b/charts/rancher-project-monitoring/0.2.2/questions.yaml @@ -30,7 +30,7 @@ questions: - variable: grafana.persistence.enabled type: boolean required: true - label: Enable Persistent Volume + label: Grafana Persistent Volume Enabled show_subquestion_if: true group: Grafana subquestions: @@ -101,7 +101,7 @@ questions: - variable: prometheus.prometheusSpec.storage.enabled type: boolean required: true - label: Enable Persistent Volume + label: Prometheus Persistent Volume Enabled show_subquestion_if: true group: Prometheus subquestions: diff --git a/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl index 5333d28b..59f8e6c6 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl +++ b/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl @@ -231,22 +231,3 @@ global: {{- end }} {{- end }} {{- end -}} - - -{{/* Define ingress for all hardened namespaces */}} -{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} -{{- $root := index . 0 }} -{{- $ns := index . 1 }} -{{- if $root.Values.global.networkPolicy.ingress -}} -{{ toYaml $root.Values.global.networkPolicy.ingress }} -{{- end }} -{{- if $root.Values.global.networkPolicy.limitIngressToProject }} -- from: -{{- if $root.Values.global.cattle.projectNamespaceSelector }} - - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} -{{- end }} - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: {{ $ns }} -{{- end }} -{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml index 535bc94e..b42c6626 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml @@ -17,10 +17,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -37,15 +35,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -59,7 +54,6 @@ rules: - update - patch - delete -{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -79,10 +73,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -99,15 +91,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -120,7 +109,6 @@ rules: - watch - update - patch -{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -140,10 +128,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -156,15 +142,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -176,4 +159,3 @@ rules: - list - watch {{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml index 2f0a6bfa..08279580 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml @@ -8,16 +8,16 @@ https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-promet apiVersion: v1 kind: ConfigMap metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + namespace: {{ .Values.grafana.defaultDashboards.namespace }} + name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} annotations: {{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} labels: {{- if $.Values.grafana.sidecar.dashboards.label }} {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} + app: {{ template "kube-prometheus-stack.name" $ }}-grafana +{{ include "kube-prometheus-stack.labels" $ | indent 4 }} data: prometheus-remote-write.json: |- { diff --git a/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml index 2ea6b1f8..508e4cc3 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml @@ -117,12 +117,14 @@ spec: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: project-monitoring-policy + name: default-allow-all namespace: {{ $ns }} spec: podSelector: {} - ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} - egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} + ingress: + - {} + egress: + - {} policyTypes: - Ingress - Egress diff --git a/charts/rancher-project-monitoring/0.2.2/values.yaml b/charts/rancher-project-monitoring/0.2.2/values.yaml index 23f317ff..cb2b3695 100644 --- a/charts/rancher-project-monitoring/0.2.2/values.yaml +++ b/charts/rancher-project-monitoring/0.2.2/values.yaml @@ -78,17 +78,6 @@ global: securityContext: runAsNonRoot: true runAsUser: 1000 - networkPolicy: - # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. - # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, - # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs - # through the Rancher/Kubernetes API Proxy in the Rancher UI. - limitIngressToProject: false - # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. - ingress: null - # By default, all egress traffic is allowed. - egress: - - {} rbac: ## Create RBAC resources for ServiceAccounts and users ## @@ -759,9 +748,6 @@ grafana: ## Annotations for Grafana dashboard configmaps ## annotations: {} - multicluster: - global: - enabled: false provider: allowUiUpdates: false datasources: diff --git a/charts/rancher-project-monitoring/0.3.0/Chart.yaml b/charts/rancher-project-monitoring/0.3.0/Chart.yaml deleted file mode 100644 index 8d20806d..00000000 --- a/charts/rancher-project-monitoring/0.3.0/Chart.yaml +++ /dev/null @@ -1,33 +0,0 @@ -annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Project Monitoring - catalog.cattle.io/hidden: "true" - catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' - catalog.cattle.io/release-name: rancher-project-monitoring -apiVersion: v2 -appVersion: 0.59.1 -dependencies: -- condition: grafana.enabled - name: grafana - repository: file://./charts/grafana -description: Collects several related Helm charts, Grafana dashboards, and Prometheus - rules combined with documentation and scripts to provide easy to operate end-to-end - Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster - Prometheus deployed via Prometheus Operator -home: https://github.com/prometheus-operator/kube-prometheus -icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png -keywords: -- prometheus -- monitoring -kubeVersion: '>=1.16.0-0' -maintainers: -- email: arvind.iyengar@suse.com - name: Arvind -- email: amangeet.samra@suse.com - name: Geet - url: https://github.com/geethub97 -name: rancher-project-monitoring -type: application -version: 0.3.0 diff --git a/charts/rancher-project-monitoring/0.3.0/README.md b/charts/rancher-project-monitoring/0.3.0/README.md deleted file mode 100644 index eab333c3..00000000 --- a/charts/rancher-project-monitoring/0.3.0/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# rancher-project-monitoring - -This chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting), a Helm chart based off of [`kube-prometheus stack`](https://github.com/prometheus-operator/kube-prometheus). It deploys a collection of Kubernetes manifests, [Grafana](http://grafana.com/) dashboards, and [Prometheus rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) combined with documentation and scripts to provide easy to operate end-to-end Kubernetes project monitoring with [Prometheus](https://prometheus.io/) using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator). See the [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus) README for details about components, dashboards, and alerts. - -## Prerequisites - -- Kubernetes 1.16+ -- Helm 3+ - -## Install Chart - -This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). For a Prometheus Stack intended to be deployed standalone, please use [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) or the upstream [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) project. - -## Dependencies - -This chart is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs. Specifically, the chart is configured and intended to be deployed alongside [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that `rancher-project-monitoring` is configured to federate namespace-scoped metrics from by default. - -### Configuration - -Since this chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), a Helm chart based off of [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack), most of the options that apply to either of those charts will apply to this chart (e.g. support for configuring persistent volumes, ingresses, etc.) and can be passed in as part of the `spec.values` of the ProjectHelmChart that deploys this chart; however, certain advanced functionality (such as Thanos support) and options that pose security risks in Project environments (e.g. ability to `ignoreNamespaceSelectors` or modify the existing namepaceSelectors of the Cluster Prometheus, ability to mount additional scrape configs, etc.) have been removed from the `values.yaml` of the chart. For more information on how to configure values and what they mean, please see the comments and options provided on the `values.yaml` packaged with this chart. - -## Further Information - -For more in-depth documentation of configuration options meanings, please see - -- [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) -- [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) -- [Prometheus](https://prometheus.io/docs/introduction/overview/) -- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana#grafana-helm-chart) \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/app-README.md b/charts/rancher-project-monitoring/0.3.0/app-README.md deleted file mode 100644 index 6b833291..00000000 --- a/charts/rancher-project-monitoring/0.3.0/app-README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Rancher Project Monitoring and Alerting - -The chart installs a Project Monitoring Stack, which contains: -- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) -- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) -- Default ServiceMonitors that watch the deployed resources - -Note: This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore b/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore deleted file mode 100644 index 8cade131..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.vscode -.project -.idea/ -*.tmproj -OWNERS diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml deleted file mode 100644 index 9b0ca179..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml +++ /dev/null @@ -1,29 +0,0 @@ -annotations: - catalog.cattle.io/hidden: "true" - catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' - catalog.cattle.io/os: linux - catalog.rancher.io/certified: rancher - catalog.rancher.io/namespace: cattle-monitoring-system - catalog.rancher.io/release-name: rancher-grafana -apiVersion: v2 -appVersion: 9.1.5 -description: The leading tool for querying and visualizing time series and metrics. -home: https://grafana.net -icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png -kubeVersion: ^1.8.0-0 -maintainers: -- email: zanhsieh@gmail.com - name: zanhsieh -- email: rluckie@cisco.com - name: rtluckie -- email: maor.friedman@redhat.com - name: maorfr -- email: miroslav.hadzhiev@gmail.com - name: Xtigyro -- email: mail@torstenwalter.de - name: torstenwalter -name: grafana -sources: -- https://github.com/grafana/grafana -type: application -version: 6.38.6 diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md b/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md deleted file mode 100644 index f3d31768..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md +++ /dev/null @@ -1,571 +0,0 @@ -# Grafana Helm Chart - -* Installs the web dashboarding system [Grafana](http://grafana.org/) - -## Get Repo Info - -```console -helm repo add grafana https://grafana.github.io/helm-charts -helm repo update -``` - -_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -helm install my-release grafana/grafana -``` - -## Uninstalling the Chart - -To uninstall/delete the my-release deployment: - -```console -helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Upgrading an existing Release to a new major version - -A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an -incompatible breaking change needing manual actions. - -### To 4.0.0 (And 3.12.1) - -This version requires Helm >= 2.12.0. - -### To 5.0.0 - -You have to add --force to your helm upgrade command as the labels of the chart have changed. - -### To 6.0.0 - -This version requires Helm >= 3.1.0. - -## Configuration - -| Parameter | Description | Default | -|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| -| `replicas` | Number of nodes | `1` | -| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | -| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | -| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | -| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | -| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| -| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | -| `priorityClassName` | Name of Priority Class to assign pods | `nil` | -| `image.repository` | Image repository | `grafana/grafana` | -| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` | -| `image.sha` | Image sha (optional) | `` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` | -| `service.enabled` | Enable grafana service | `true` | -| `service.type` | Kubernetes service type | `ClusterIP` | -| `service.port` | Kubernetes port where service is exposed | `80` | -| `service.portName` | Name of the port on the service | `service` | -| `service.appProtocol` | Adds the appProtocol field to the service | `` | -| `service.targetPort` | Internal service is port | `3000` | -| `service.nodePort` | Kubernetes service nodePort | `nil` | -| `service.annotations` | Service annotations (can be templated) | `{}` | -| `service.labels` | Custom labels | `{}` | -| `service.clusterIP` | internal cluster service IP | `nil` | -| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | -| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | -| `service.externalIPs` | service external IP addresses | `[]` | -| `headlessService` | Create a headless service | `false` | -| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | -| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | -| `ingress.enabled` | Enables Ingress | `false` | -| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | -| `ingress.labels` | Custom labels | `{}` | -| `ingress.path` | Ingress accepted path | `/` | -| `ingress.pathType` | Ingress type of path | `Prefix` | -| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | -| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | -| `ingress.tls` | Ingress TLS configuration | `[]` | -| `resources` | CPU/Memory resource requests/limits | `{}` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `tolerations` | Toleration labels for pod assignment | `[]` | -| `affinity` | Affinity settings for pod assignment | `{}` | -| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | -| `extraContainers` | Sidecar containers to add to the grafana pod | `""` | -| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | -| `extraLabels` | Custom labels for all manifests | `{}` | -| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | -| `persistence.enabled` | Use persistent volume to store data | `false` | -| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | -| `persistence.size` | Size of persistent volume claim | `10Gi` | -| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` | -| `persistence.storageClassName` | Type of persistent volume claim | `nil` | -| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | -| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | -| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | -| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` | -| `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` | -| `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` | -| `initChownData.enabled` | If false, don't reset data ownership at startup | true | -| `initChownData.image.repository` | init-chown-data container image repository | `busybox` | -| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | -| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | -| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | -| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | -| `schedulerName` | Alternate scheduler name | `nil` | -| `env` | Extra environment variables passed to pods | `{}` | -| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | -| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | -| `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | -| `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | -| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret | `{}` | -| `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` | -| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | -| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | -| `createConfigmap` | Enable creating the grafana configmap | `true` | -| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` | -| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | -| `plugins` | Plugins to be loaded along with Grafana | `[]` | -| `datasources` | Configure grafana datasources (passed through tpl) | `{}` | -| `alerting` | Configure grafana alerting (passed through tpl) | `{}` | -| `notifiers` | Configure grafana notifiers | `{}` | -| `dashboardProviders` | Configure grafana dashboard providers | `{}` | -| `dashboards` | Dashboards to import | `{}` | -| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | -| `grafana.ini` | Grafana's primary configuration | `{}` | -| `ldap.enabled` | Enable LDAP authentication | `false` | -| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | -| `ldap.config` | Grafana's LDAP configuration | `""` | -| `annotations` | Deployment annotations | `{}` | -| `labels` | Deployment labels | `{}` | -| `podAnnotations` | Pod annotations | `{}` | -| `podLabels` | Pod labels | `{}` | -| `podPortName` | Name of the grafana port on the pod | `grafana` | -| `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` | -| `sidecar.image.repository` | Sidecar image repository | `quay.io/kiwigrid/k8s-sidecar` | -| `sidecar.image.tag` | Sidecar image tag | `1.19.2` | -| `sidecar.image.sha` | Sidecar image sha (optional) | `""` | -| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | -| `sidecar.resources` | Sidecar resources | `{}` | -| `sidecar.securityContext` | Sidecar securityContext | `{}` | -| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` | -| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | -| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | -| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | -| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | -| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | -| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | -| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | -| `sidecar.dashboards.provider.type` | Provider type | `file` | -| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | -| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | -| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | -| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | -| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` | -| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | -| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | -| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | -| `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` | -| `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | -| `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` | -| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | -| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | -| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` | -| `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | -| `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` | -| `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | -| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` | -| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | -| `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | -| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | -| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | -| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | -| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` | -| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | -| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | -| `serviceAccount.autoMount` | Automount the service account token in the pod| `true` | -| `serviceAccount.annotations` | ServiceAccount annotations | | -| `serviceAccount.create` | Create service account | `true` | -| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | -| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | -| `rbac.create` | Create and use RBAC resources | `true` | -| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | -| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | -| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `true` | -| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `true` | -| `rbac.extraRoleRules` | Additional rules to add to the Role | [] | -| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | -| `command` | Define command to be executed by grafana container at startup | `nil` | -| `testFramework.enabled` | Whether to create test-related resources | `true` | -| `testFramework.image` | `test-framework` image repository. | `bats/bats` | -| `testFramework.tag` | `test-framework` image tag. | `v1.4.1` | -| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | -| `testFramework.securityContext` | `test-framework` securityContext | `{}` | -| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | -| `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | -| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | -| `downloadDashboardsImage.repository` | Curl docker image repo | `curlimages/curl` | -| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | -| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | -| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | -| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | -| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | -| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | -| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | -| `serviceMonitor.path` | Path to scrape | `/metrics` | -| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` | -| `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` | -| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | -| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | -| `serviceMonitor.relabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | -| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | -| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | -| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | -| `imageRenderer.image.tag` | image-renderer Image tag | `latest` | -| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | -| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | -| `imageRenderer.env` | extra env-vars for image-renderer | `{}` | -| `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | -| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | -| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | -| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | -| `imageRenderer.service.enabled` | Enable the image-renderer service | `true` | -| `imageRenderer.service.portName` | image-renderer service port name | `http` | -| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` | -| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` | -| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` | -| `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` | -| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | -| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | -| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | -| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | -| `imageRenderer.resources` | Set resource limits for image-renderer pdos | `{}` | -| `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` | -| `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` | -| `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` | -| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | -| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` | -| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` | -| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` | -| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` | -| `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` | - - - -### Example ingress with path - -With grafana 6.3 and above -```yaml -grafana.ini: - server: - domain: monitoring.example.com - root_url: "%(protocol)s://%(domain)s/grafana" - serve_from_sub_path: true -ingress: - enabled: true - hosts: - - "monitoring.example.com" - path: "/grafana" -``` - -### Example of extraVolumeMounts - -Volume can be type persistentVolumeClaim or hostPath but not both at same time. -If neither existingClaim or hostPath argument is given then type is emptyDir. - -```yaml -- extraVolumeMounts: - - name: plugins - mountPath: /var/lib/grafana/plugins - subPath: configs/grafana/plugins - existingClaim: existing-grafana-claim - readOnly: false - - name: dashboards - mountPath: /var/lib/grafana/dashboards - hostPath: /usr/shared/grafana/dashboards - readOnly: false -``` - -## Import dashboards - -There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: - -```yaml -dashboards: - default: - some-dashboard: - json: | - { - "annotations": - - ... - # Complete json file here - ... - - "title": "Some Dashboard", - "uid": "abcd1234", - "version": 1 - } - custom-dashboard: - # This is a path to a file inside the dashboards directory inside the chart directory - file: dashboards/custom-dashboard.json - prometheus-stats: - # Ref: https://grafana.com/dashboards/2 - gnetId: 2 - revision: 2 - datasource: Prometheus - local-dashboard: - url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json -``` - -## BASE64 dashboards - -Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) -A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. -If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. - -### Gerrit use case - -Gerrit API for download files has the following schema: where {project-name} and -{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard -the url value is - -## Sidecar for dashboards - -If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana -pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with -a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written -to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported -dashboards are deleted/updated. - -A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside -one configmap is currently not properly mirrored in grafana. - -Example dashboard config: - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sample-grafana-dashboard - labels: - grafana_dashboard: "1" -data: - k8s-dashboard.json: |- - [...] -``` - -## Sidecar for datasources - -If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in -those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, -the data sources in grafana can be imported. - -Secrets are recommended over configmaps for this usecase because datasources usually contain private -data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. - -Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): - -```yaml -datasources: - datasources.yaml: - apiVersion: 1 - datasources: - # name of the datasource. Required - - name: Graphite - # datasource type. Required - type: graphite - # access mode. proxy or direct (Server or Browser in the UI). Required - access: proxy - # org id. will default to orgId 1 if not specified - orgId: 1 - # url - url: http://localhost:8080 - # database password, if used - password: - # database user, if used - user: - # database name, if used - database: - # enable/disable basic auth - basicAuth: - # basic auth username - basicAuthUser: - # basic auth password - basicAuthPassword: - # enable/disable with credentials headers - withCredentials: - # mark as default datasource. Max one per org - isDefault: - # fields that will be converted to json and stored in json_data - jsonData: - graphiteVersion: "1.1" - tlsAuth: true - tlsAuthWithCACert: true - # json object of data that will be encrypted. - secureJsonData: - tlsCACert: "..." - tlsClientCert: "..." - tlsClientKey: "..." - version: 1 - # allow users to edit datasources from the UI. - editable: false -``` - -## Sidecar for notifiers - -If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in -those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, -the notification channels in grafana can be imported. The secrets must be created before -`helm install` so that the notifiers init container can list the secrets. - -Secrets are recommended over configmaps for this usecase because alert notification channels usually contain -private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. - -Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): - -```yaml -notifiers: - - name: notification-channel-1 - type: slack - uid: notifier1 - # either - org_id: 2 - # or - org_name: Main Org. - is_default: true - send_reminder: true - frequency: 1h - disable_resolve_message: false - # See `Supported Settings` section for settings supporter for each - # alert notification type. - settings: - recipient: 'XXX' - token: 'xoxb' - uploadImage: true - url: https://slack.com - -delete_notifiers: - - name: notification-channel-1 - uid: notifier1 - org_id: 2 - - name: notification-channel-2 - # default org_id: 1 -``` - -## How to serve Grafana with a path prefix (/grafana) - -In order to serve Grafana with a prefix (e.g., ), add the following to your values.yaml. - -```yaml -ingress: - enabled: true - annotations: - kubernetes.io/ingress.class: "nginx" - nginx.ingress.kubernetes.io/rewrite-target: /$1 - nginx.ingress.kubernetes.io/use-regex: "true" - - path: /grafana/?(.*) - hosts: - - k8s.example.dev - -grafana.ini: - server: - root_url: http://localhost:3000/grafana # this host can be localhost -``` - -## How to securely reference secrets in grafana.ini - -This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. - -In grafana.ini: - -```yaml -grafana.ini: - [auth.generic_oauth] - enabled = true - client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} - client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} -``` - -Existing secret, or created along with helm: - -```yaml ---- -apiVersion: v1 -kind: Secret -metadata: - name: auth-generic-oauth-secret -type: Opaque -stringData: - client_id: - client_secret: -``` - -Include in the `extraSecretMounts` configuration flag: - -```yaml -- extraSecretMounts: - - name: auth-generic-oauth-secret-mount - secretName: auth-generic-oauth-secret - defaultMode: 0440 - mountPath: /etc/secrets/auth_generic_oauth - readOnly: true -``` - -### extraSecretMounts using a Container Storage Interface (CSI) provider - -This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure) - -```yaml -- extraSecretMounts: - - name: secrets-store-inline - mountPath: /run/secrets - readOnly: true - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: "my-provider" - nodePublishSecretRef: - name: akv-creds -``` - -## Image Renderer Plug-In - -This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker) - -```yaml -imageRenderer: - enabled: true -``` - -### Image Renderer NetworkPolicy - -By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance - -### High Availability for unified alerting - -If you want to run Grafana in a high availability cluster you need to enable -the headless service by setting `headlessService: true` in your `values.yaml` -file. - -As next step you have to setup the `grafana.ini` in your `values.yaml` in a way -that it will make use of the headless service to obtain all the IPs of the -cluster. You should replace ``{{ Name }}`` with the name of your helm deployment. - -```yaml -grafana.ini: - ... - unified_alerting: - enabled: true - ha_peers: {{ Name }}-headless:9094 - alerting: - enabled: false -``` diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json b/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json deleted file mode 100644 index 9e26dfee..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt deleted file mode 100644 index 1fc8436d..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt +++ /dev/null @@ -1,54 +0,0 @@ -1. Get your '{{ .Values.adminUser }}' user password by running: - - kubectl get secret --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo - -2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: - - {{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}.svc.cluster.local -{{ if .Values.ingress.enabled }} - If you bind grafana to 80, please update values in values.yaml and reinstall: - ``` - securityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - - command: - - "setcap" - - "'cap_net_bind_service=+ep'" - - "/usr/sbin/grafana-server &&" - - "sh" - - "/run.sh" - ``` - Details refer to https://grafana.com/docs/installation/configuration/#http-port. - Or grafana would always crash. - - From outside the cluster, the server URL(s) are: -{{- range .Values.ingress.hosts }} - http://{{ . }} -{{- end }} -{{ else }} - Get the Grafana URL to visit by running these commands in the same shell: -{{ if contains "NodePort" .Values.service.type -}} - export NODE_PORT=$(kubectl get --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{ else if contains "LoadBalancer" .Values.service.type -}} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ template "grafana.namespace" . }} -w {{ template "grafana.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - http://$SERVICE_IP:{{ .Values.service.port -}} -{{ else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ template "grafana.namespace" . }} -l "app.kubernetes.io/name={{ template "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ template "grafana.namespace" . }} port-forward $POD_NAME 3000 -{{- end }} -{{- end }} - -3. Login with the password from step 1 and the username: {{ .Values.adminUser }} - -{{- if not .Values.persistence.enabled }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the Grafana pod is terminated. ##### -################################################################################# -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl deleted file mode 100644 index e5e3b287..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl +++ /dev/null @@ -1,214 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "grafana.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "grafana.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "grafana.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create the name of the service account -*/}} -{{- define "grafana.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "grafana.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{- define "grafana.serviceAccountNameTest" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} -{{- else -}} - {{ default "default" .Values.serviceAccount.nameTest }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "grafana.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "grafana.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- if .Values.extraLabels }} -{{ toYaml .Values.extraLabels }} -{{- end }} -{{- end -}} - -{{/* -Selector labels -*/}} -{{- define "grafana.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "grafana.imageRenderer.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.imageRenderer.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Selector labels ImageRenderer -*/}} -{{- define "grafana.imageRenderer.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Looks if there's an existing secret and reuse its password. If not it generates -new password and use it. -*/}} -{{- define "grafana.password" -}} -{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) -}} - {{- if $secret -}} - {{- index $secret "data" "admin-password" -}} - {{- else -}} - {{- (randAlphaNum 40) | b64enc | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for rbac. -*/}} -{{- define "grafana.rbac.apiVersion" -}} - {{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} - {{- print "rbac.authorization.k8s.io/v1" -}} - {{- else -}} - {{- print "rbac.authorization.k8s.io/v1beta1" -}} - {{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for HorizontalPodAutoscaler. -*/}} -{{- define "grafana.hpa.apiVersion" -}} - {{- if .Capabilities.APIVersions.Has "autoscaling/v2" }} - {{- print "autoscaling/v2" -}} - {{- else if .Capabilities.APIVersions.Has "autoscaling/v1" }} - {{- print "autoscaling/v1" -}} - {{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for ingress. -*/}} -{{- define "grafana.ingress.apiVersion" -}} - {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) -}} - {{- print "networking.k8s.io/v1" -}} - {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} - {{- print "networking.k8s.io/v1beta1" -}} - {{- else -}} - {{- print "extensions/v1beta1" -}} - {{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for podDisruptionBudget. -*/}} -{{- define "grafana.podDisruptionBudget.apiVersion" -}} - {{- if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" -}} - {{- print "policy/v1" -}} - {{- else -}} - {{- print "policy/v1beta1" -}} - {{- end -}} -{{- end -}} - -{{/* -Return if ingress is stable. -*/}} -{{- define "grafana.ingress.isStable" -}} - {{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" -}} -{{- end -}} - -{{/* -Return if ingress supports ingressClassName. -*/}} -{{- define "grafana.ingress.supportsIngressClassName" -}} - {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} -{{- end -}} - -{{/* -Return if ingress supports pathType. -*/}} -{{- define "grafana.ingress.supportsPathType" -}} - {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl deleted file mode 100644 index ae36c28a..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl +++ /dev/null @@ -1,885 +0,0 @@ -{{- define "grafana.pod" -}} -{{- if .Values.schedulerName }} -schedulerName: "{{ .Values.schedulerName }}" -{{- end }} -serviceAccountName: {{ template "grafana.serviceAccountName" . }} -automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} -{{- with .Values.securityContext }} -securityContext: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.hostAliases }} -hostAliases: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- if .Values.priorityClassName }} -priorityClassName: {{ .Values.priorityClassName }} -{{- end }} -{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.notifiers.enabled .Values.extraInitContainers (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources)) }} -initContainers: -{{- end }} -{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} - - name: init-chown-data - {{- if .Values.initChownData.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} - securityContext: - runAsNonRoot: false - runAsUser: 0 - command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] - {{- with .Values.initChownData.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ tpl .Values.persistence.subPath . }} -{{- end }} -{{- end }} -{{- if .Values.dashboards }} - - name: download-dashboards - {{- if .Values.downloadDashboardsImage.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} - command: ["/bin/sh"] - args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] - {{- with .Values.downloadDashboards.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - env: -{{- range $key, $value := .Values.downloadDashboards.env }} - - name: "{{ $key }}" - value: "{{ $value }}" -{{- end }} - {{- with .Values.downloadDashboards.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} -{{- if .Values.downloadDashboards.envFromSecret }} - envFrom: - - secretRef: - name: {{ tpl .Values.downloadDashboards.envFromSecret . }} -{{- end }} - volumeMounts: - - name: config - mountPath: "/etc/grafana/download_dashboards.sh" - subPath: download_dashboards.sh - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ tpl .Values.persistence.subPath . }} -{{- end }} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - {{- end }} -{{- end }} -{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} - - name: {{ template "grafana.name" . }}-init-sc-datasources - {{- if .Values.sidecar.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.datasources.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: "LIST" - - name: LABEL - value: "{{ .Values.sidecar.datasources.label }}" - {{- if .Values.sidecar.datasources.labelValue }} - - name: LABEL_VALUE - value: {{ quote .Values.sidecar.datasources.labelValue }} - {{- end }} - {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} - - name: LOG_LEVEL - value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} - {{- end }} - - name: FOLDER - value: "/etc/grafana/provisioning/datasources" - - name: RESOURCE - value: {{ quote .Values.sidecar.datasources.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - - name: NAMESPACE - value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end }} -{{- if .Values.sidecar.notifiers.enabled }} - - name: {{ template "grafana.name" . }}-sc-notifiers - {{- if .Values.sidecar.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.notifiers.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: LIST - - name: LABEL - value: "{{ .Values.sidecar.notifiers.label }}" - {{- if .Values.sidecar.notifiers.labelValue }} - - name: LABEL_VALUE - value: {{ quote .Values.sidecar.notifiers.labelValue }} - {{- end }} - {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} - - name: LOG_LEVEL - value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} - {{- end }} - - name: FOLDER - value: "/etc/grafana/provisioning/notifiers" - - name: RESOURCE - value: {{ quote .Values.sidecar.notifiers.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - - name: NAMESPACE - value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- with .Values.sidecar.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} -{{- if .Values.extraInitContainers }} -{{ tpl (toYaml .Values.extraInitContainers) . | indent 2 }} -{{- end }} -{{- if .Values.image.pullSecrets }} -imagePullSecrets: -{{- $root := . }} -{{- range .Values.image.pullSecrets }} - - name: {{ tpl . $root }} -{{- end }} -{{- end }} -{{- if not .Values.enableKubeBackwardCompatibility }} -enableServiceLinks: {{ .Values.enableServiceLinks }} -{{- end }} -containers: -{{- if .Values.sidecar.dashboards.enabled }} - - name: {{ template "grafana.name" . }}-sc-dashboard - {{- if .Values.sidecar.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.dashboards.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.dashboards.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: {{ .Values.sidecar.dashboards.watchMethod }} - - name: LABEL - value: "{{ .Values.sidecar.dashboards.label }}" - {{- if .Values.sidecar.dashboards.labelValue }} - - name: LABEL_VALUE - value: {{ quote .Values.sidecar.dashboards.labelValue }} - {{- end }} - {{- if or .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} - - name: LOG_LEVEL - value: {{ default .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} - {{- end }} - - name: FOLDER - value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" - - name: RESOURCE - value: {{ quote .Values.sidecar.dashboards.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - - name: NAMESPACE - value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- if .Values.sidecar.dashboards.folderAnnotation }} - - name: FOLDER_ANNOTATION - value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" - {{- end }} - {{- if .Values.sidecar.dashboards.script }} - - name: SCRIPT - value: "{{ .Values.sidecar.dashboards.script }}" - {{- end }} - {{- if .Values.sidecar.dashboards.watchServerTimeout }} - {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchServerTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} - {{- end }} - - name: WATCH_SERVER_TIMEOUT - value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" - {{- end }} - {{- if .Values.sidecar.dashboards.watchClientTimeout }} - {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchClientTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} - {{- end }} - - name: WATCH_CLIENT_TIMEOUT - value: "{{ .Values.sidecar.dashboards.watchClientTimeout }}" - {{- end }} - {{- with .Values.sidecar.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-dashboard-volume - mountPath: {{ .Values.sidecar.dashboards.folder | quote }} - {{- if .Values.sidecar.dashboards.extraMounts }} - {{- toYaml .Values.sidecar.dashboards.extraMounts | trim | nindent 6}} - {{- end }} -{{- end}} -{{- if .Values.sidecar.datasources.enabled }} - - name: {{ template "grafana.name" . }}-sc-datasources - {{- if .Values.sidecar.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.datasources.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: {{ .Values.sidecar.datasources.watchMethod }} - - name: LABEL - value: "{{ .Values.sidecar.datasources.label }}" - {{- if .Values.sidecar.datasources.labelValue }} - - name: LABEL_VALUE - value: {{ quote .Values.sidecar.datasources.labelValue }} - {{- end }} - {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} - - name: LOG_LEVEL - value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} - {{- end }} - - name: FOLDER - value: "/etc/grafana/provisioning/datasources" - - name: RESOURCE - value: {{ quote .Values.sidecar.datasources.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - - name: NAMESPACE - value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- if .Values.sidecar.datasources.script }} - - name: SCRIPT - value: "{{ .Values.sidecar.datasources.script }}" - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_USERNAME - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if not .Values.sidecar.datasources.skipReload }} - - name: REQ_URL - value: {{ .Values.sidecar.datasources.reloadURL }} - - name: REQ_METHOD - value: POST - {{- end }} - {{- if .Values.sidecar.datasources.watchServerTimeout }} - {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.datasources.watchServerTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} - {{- end }} - - name: WATCH_SERVER_TIMEOUT - value: "{{ .Values.sidecar.datasources.watchServerTimeout }}" - {{- end }} - {{- if .Values.sidecar.datasources.watchClientTimeout }} - {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.datasources.watchClientTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} - {{- end }} - - name: WATCH_CLIENT_TIMEOUT - value: "{{ .Values.sidecar.datasources.watchClientTimeout }}" - {{- end }} - {{- with .Values.sidecar.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end}} -{{- if .Values.sidecar.plugins.enabled }} - - name: {{ template "grafana.name" . }}-sc-plugins - {{- if .Values.sidecar.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.plugins.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.plugins.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: {{ .Values.sidecar.plugins.watchMethod }} - - name: LABEL - value: "{{ .Values.sidecar.plugins.label }}" - {{- if .Values.sidecar.plugins.labelValue }} - - name: LABEL_VALUE - value: {{ quote .Values.sidecar.plugins.labelValue }} - {{- end }} - {{- if or .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} - - name: LOG_LEVEL - value: {{ default .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} - {{- end }} - - name: FOLDER - value: "/etc/grafana/provisioning/plugins" - - name: RESOURCE - value: {{ quote .Values.sidecar.plugins.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - - name: NAMESPACE - value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" - {{- if .Values.sidecar.plugins.script }} - - name: SCRIPT - value: "{{ .Values.sidecar.plugins.script }}" - {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_USERNAME - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if not .Values.sidecar.plugins.skipReload }} - - name: REQ_URL - value: {{ .Values.sidecar.plugins.reloadURL }} - - name: REQ_METHOD - value: POST - {{- end }} - {{- if .Values.sidecar.plugins.watchServerTimeout }} - {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.plugins.watchServerTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} - {{- end }} - - name: WATCH_SERVER_TIMEOUT - value: "{{ .Values.sidecar.plugins.watchServerTimeout }}" - {{- end }} - {{- if .Values.sidecar.plugins.watchClientTimeout }} - {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} - {{- fail (printf "Cannot use .Values.sidecar.plugins.watchClientTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} - {{- end }} - - name: WATCH_CLIENT_TIMEOUT - value: "{{ .Values.sidecar.plugins.watchClientTimeout }}" - {{- end }} - {{- with .Values.sidecar.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-plugins-volume - mountPath: "/etc/grafana/provisioning/plugins" -{{- end}} - - name: {{ .Chart.Name }} - {{- if .Values.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - {{- end }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.command }} - command: - {{- range .Values.command }} - - {{ . }} - {{- end }} - {{- end}} - {{- with .Values.containerSecurityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: config - mountPath: "/etc/grafana/grafana.ini" - subPath: grafana.ini - {{- if .Values.ldap.enabled }} - - name: ldap - mountPath: "/etc/grafana/ldap.toml" - subPath: ldap.toml - {{- end }} - {{- $root := . }} - {{- range .Values.extraConfigmapMounts }} - - name: {{ tpl .name $root }} - mountPath: {{ tpl .mountPath $root }} - subPath: {{ (tpl .subPath $root) | default "" }} - readOnly: {{ .readOnly }} - {{- end }} - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ tpl .Values.persistence.subPath . }} -{{- end }} -{{- if .Values.dashboards }} -{{- range $provider, $dashboards := .Values.dashboards }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} - - name: dashboards-{{ $provider }} - mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" - subPath: "{{ $key }}.json" -{{- end }} -{{- end }} -{{- end }} -{{- end -}} -{{- if .Values.dashboardsConfigMaps }} -{{- range (keys .Values.dashboardsConfigMaps | sortAlpha) }} - - name: dashboards-{{ . }} - mountPath: "/var/lib/grafana/dashboards/{{ . }}" -{{- end }} -{{- end }} -{{- if .Values.datasources }} -{{- range (keys .Values.datasources | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" - subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.notifiers }} -{{- range (keys .Values.notifiers | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" - subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.alerting }} -{{- range (keys .Values.alerting | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" - subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.dashboardProviders }} -{{- range (keys .Values.dashboardProviders | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" - subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.sidecar.dashboards.enabled }} - - name: sc-dashboard-volume - mountPath: {{ .Values.sidecar.dashboards.folder | quote }} -{{ if .Values.sidecar.dashboards.SCProvider }} - - name: sc-dashboard-provider - mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" - subPath: provider.yaml -{{- end}} -{{- end}} -{{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end}} -{{- if .Values.sidecar.plugins.enabled }} - - name: sc-plugins-volume - mountPath: "/etc/grafana/provisioning/plugins" -{{- end}} -{{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - subPath: {{ .subPath | default "" }} - {{- end }} - {{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - subPath: {{ .subPath | default "" }} - readOnly: {{ .readOnly }} - {{- end }} - {{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - {{- end }} - ports: - - name: {{ .Values.podPortName }} - containerPort: {{ .Values.service.targetPort }} - protocol: TCP - env: - {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: GF_SECURITY_ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: GF_SECURITY_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if .Values.plugins }} - - name: GF_INSTALL_PLUGINS - valueFrom: - configMapKeyRef: - name: {{ template "grafana.fullname" . }} - key: plugins - {{- end }} - {{- if .Values.smtp.existingSecret }} - - name: GF_SMTP_USER - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.userKey | default "user" }} - - name: GF_SMTP_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.passwordKey | default "password" }} - {{- end }} - {{- if .Values.imageRenderer.enabled }} - - name: GF_RENDERING_SERVER_URL - value: http://{{ template "grafana.fullname" . }}-image-renderer.{{ template "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render - - name: GF_RENDERING_CALLBACK_URL - value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} - {{- end }} - - name: GF_PATHS_DATA - value: {{ (get .Values "grafana.ini").paths.data }} - - name: GF_PATHS_LOGS - value: {{ (get .Values "grafana.ini").paths.logs }} - - name: GF_PATHS_PLUGINS - value: {{ (get .Values "grafana.ini").paths.plugins }} - - name: GF_PATHS_PROVISIONING - value: {{ (get .Values "grafana.ini").paths.provisioning }} - {{- range $key, $value := .Values.envValueFrom }} - - name: {{ $key | quote }} - valueFrom: -{{ tpl (toYaml $value) $ | indent 10 }} - {{- end }} -{{- range $key, $value := .Values.env }} - - name: "{{ tpl $key $ }}" - value: "{{ tpl (print $value) $ }}" -{{- end }} - {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} - envFrom: - {{- if .Values.envFromSecret }} - - secretRef: - name: {{ tpl .Values.envFromSecret . }} - {{- end }} - {{- if .Values.envRenderSecret }} - - secretRef: - name: {{ template "grafana.fullname" . }}-env - {{- end }} - {{- range .Values.envFromSecrets }} - - secretRef: - name: {{ tpl .name $ }} - optional: {{ .optional | default false }} - {{- end }} - {{- range .Values.envFromConfigMaps }} - - configMapRef: - name: {{ tpl .name $ }} - optional: {{ .optional | default false }} - {{- end }} - {{- end }} - {{- with .Values.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} -{{- if .Values.lifecycleHooks }} - lifecycle: {{ tpl (.Values.lifecycleHooks | toYaml) . | nindent 6 }} -{{- end }} - {{- with .Values.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} -{{- with .Values.extraContainers }} -{{ tpl . $ | indent 2 }} -{{- end }} -nodeSelector: {{ include "linux-node-selector" . | nindent 2 }} -{{- if .Values.nodeSelector }} -{{ toYaml .Values.nodeSelector | indent 2 }} -{{- end }} -{{- $root := . }} -{{- with .Values.affinity }} -affinity: -{{ tpl (toYaml .) $root | indent 2 }} -{{- end }} -{{- with .Values.topologySpreadConstraints }} -topologySpreadConstraints: - {{- toYaml . | nindent 2 }} -{{- end }} -tolerations: {{ include "linux-node-tolerations" . | nindent 2 }} -{{- if .Values.tolerations }} -{{ toYaml .Values.tolerations | indent 2 }} -{{- end }} -volumes: - - name: config - configMap: - name: {{ template "grafana.fullname" . }} -{{- $root := . }} -{{- range .Values.extraConfigmapMounts }} - - name: {{ tpl .name $root }} - configMap: - name: {{ tpl .configMap $root }} - {{- if .items }} - items: {{ toYaml .items | nindent 6 }} - {{- end }} -{{- end }} - {{- if .Values.dashboards }} - {{- range (keys .Values.dashboards | sortAlpha) }} - - name: dashboards-{{ . }} - configMap: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} - {{- end }} - {{- end }} - {{- if .Values.dashboardsConfigMaps }} - {{ $root := . }} - {{- range $provider, $name := .Values.dashboardsConfigMaps }} - - name: dashboards-{{ $provider }} - configMap: - name: {{ tpl $name $root }} - {{- end }} - {{- end }} - {{- if .Values.ldap.enabled }} - - name: ldap - secret: - {{- if .Values.ldap.existingSecret }} - secretName: {{ .Values.ldap.existingSecret }} - {{- else }} - secretName: {{ template "grafana.fullname" . }} - {{- end }} - items: - - key: ldap-toml - path: ldap.toml - {{- end }} -{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} - - name: storage - persistentVolumeClaim: - claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} -{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} -# nothing -{{- else }} - - name: storage -{{- if .Values.persistence.inMemory.enabled }} - emptyDir: - medium: Memory -{{- if .Values.persistence.inMemory.sizeLimit }} - sizeLimit: {{ .Values.persistence.inMemory.sizeLimit }} -{{- end -}} -{{- else }} - emptyDir: {} -{{- end -}} -{{- end -}} -{{- if .Values.sidecar.dashboards.enabled }} - - name: sc-dashboard-volume -{{- if .Values.sidecar.dashboards.sizeLimit }} - emptyDir: - sizeLimit: {{ .Values.sidecar.dashboards.sizeLimit }} -{{- else }} - emptyDir: {} -{{- end -}} -{{- if .Values.sidecar.dashboards.SCProvider }} - - name: sc-dashboard-provider - configMap: - name: {{ template "grafana.fullname" . }}-config-dashboards -{{- end }} -{{- end }} -{{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume -{{- if .Values.sidecar.datasources.sizeLimit }} - emptyDir: - sizeLimit: {{ .Values.sidecar.datasources.sizeLimit }} -{{- else }} - emptyDir: {} -{{- end -}} -{{- end -}} -{{- if .Values.sidecar.plugins.enabled }} - - name: sc-plugins-volume -{{- if .Values.sidecar.plugins.sizeLimit }} - emptyDir: - sizeLimit: {{ .Values.sidecar.plugins.sizeLimit }} -{{- else }} - emptyDir: {} -{{- end -}} -{{- end -}} -{{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume -{{- if .Values.sidecar.notifiers.sizeLimit }} - emptyDir: - sizeLimit: {{ .Values.sidecar.notifiers.sizeLimit }} -{{- else }} - emptyDir: {} -{{- end -}} -{{- end -}} -{{- range .Values.extraSecretMounts }} -{{- if .secretName }} - - name: {{ .name }} - secret: - secretName: {{ .secretName }} - defaultMode: {{ .defaultMode }} - {{- if .items }} - items: {{ toYaml .items | nindent 6 }} - {{- end }} -{{- else if .projected }} - - name: {{ .name }} - projected: {{- toYaml .projected | nindent 6 }} -{{- else if .csi }} - - name: {{ .name }} - csi: {{- toYaml .csi | nindent 6 }} -{{- end }} -{{- end }} -{{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - {{- if .existingClaim }} - persistentVolumeClaim: - claimName: {{ .existingClaim }} - {{- else if .hostPath }} - hostPath: - path: {{ .hostPath }} - {{- else if .csi }} - csi: - data: - {{ toYaml .data | nindent 6 }} - {{- else }} - emptyDir: {} - {{- end }} -{{- end }} -{{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - emptyDir: {} -{{- end -}} -{{- if .Values.extraContainerVolumes }} -{{ tpl (toYaml .Values.extraContainerVolumes) . | indent 2 }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml deleted file mode 100644 index 154658b5..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.fullname" . }}-clusterrole -{{- if or .Values.sidecar.dashboards.enabled (or .Values.rbac.extraClusterRoleRules (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} -rules: -{{- if or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled) }} -- apiGroups: [""] # "" indicates the core API group - resources: ["configmaps", "secrets"] - verbs: ["get", "watch", "list"] -{{- end}} -{{- with .Values.rbac.extraClusterRoleRules }} -{{ toYaml . | indent 0 }} -{{- end}} -{{- else }} -rules: [] -{{- end}} -{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml deleted file mode 100644 index 4accbfac..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "grafana.fullname" . }}-clusterrolebinding - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -subjects: - - kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -roleRef: - kind: ClusterRole -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }}-clusterrole -{{- else }} - name: {{ .Values.rbac.useExistingRole }} -{{- end }} - apiGroup: rbac.authorization.k8s.io -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml deleted file mode 100644 index 65d73858..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.sidecar.dashboards.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.fullname" . }}-config-dashboards - namespace: {{ template "grafana.namespace" . }} -data: - provider.yaml: |- - apiVersion: 1 - providers: - - name: '{{ .Values.sidecar.dashboards.provider.name }}' - orgId: {{ .Values.sidecar.dashboards.provider.orgid }} - {{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} - folder: '{{ .Values.sidecar.dashboards.provider.folder }}' - {{- end}} - type: {{ .Values.sidecar.dashboards.provider.type }} - disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} - allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} - updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }} - options: - foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} - path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} -{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml deleted file mode 100644 index 2461d175..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml +++ /dev/null @@ -1,117 +0,0 @@ -{{- if .Values.createConfigmap }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -data: -{{- if .Values.plugins }} - plugins: {{ join "," .Values.plugins }} -{{- end }} - grafana.ini: | -{{- range $elem, $elemVal := index .Values "grafana.ini" }} - {{- if not (kindIs "map" $elemVal) }} - {{- if kindIs "invalid" $elemVal }} - {{ $elem }} = - {{- else if kindIs "string" $elemVal }} - {{ $elem }} = {{ tpl $elemVal $ }} - {{- else }} - {{ $elem }} = {{ $elemVal }} - {{- end }} - {{- end }} -{{- end }} -{{- range $key, $value := index .Values "grafana.ini" }} - {{- if kindIs "map" $value }} - [{{ $key }}] - {{- range $elem, $elemVal := $value }} - {{- if kindIs "invalid" $elemVal }} - {{ $elem }} = - {{- else if kindIs "string" $elemVal }} - {{ $elem }} = {{ tpl $elemVal $ }} - {{- else }} - {{ $elem }} = {{ $elemVal }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} - -{{- if .Values.datasources }} -{{ $root := . }} - {{- range $key, $value := .Values.datasources }} - {{ $key }}: | -{{ tpl (toYaml $value | indent 4) $root }} - {{- end -}} -{{- end -}} - -{{- if .Values.notifiers }} - {{- range $key, $value := .Values.notifiers }} - {{ $key }}: | -{{ toYaml $value | indent 4 }} - {{- end -}} -{{- end -}} - -{{- if .Values.alerting }} -{{ $root := . }} - {{- range $key, $value := .Values.alerting }} - {{ $key }}: | -{{ tpl (toYaml $value | indent 4) $root }} - {{- end -}} -{{- end -}} - -{{- if .Values.dashboardProviders }} - {{- range $key, $value := .Values.dashboardProviders }} - {{ $key }}: | -{{ toYaml $value | indent 4 }} - {{- end -}} -{{- end -}} - -{{- if .Values.dashboards }} - download_dashboards.sh: | - #!/usr/bin/env sh - set -euf - {{- if .Values.dashboardProviders }} - {{- range $key, $value := .Values.dashboardProviders }} - {{- range $value.providers }} - mkdir -p {{ .options.path }} - {{- end }} - {{- end }} - {{- end }} - {{ $dashboardProviders := .Values.dashboardProviders }} - {{- range $provider, $dashboards := .Values.dashboards }} - {{- range $key, $value := $dashboards }} - {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} - curl -skf \ - --connect-timeout 60 \ - --max-time 60 \ - {{- if not $value.b64content }} - -H "Accept: application/json" \ - {{- if $value.token }} - -H "Authorization: token {{ $value.token }}" \ - {{- end }} - {{- if $value.bearerToken }} - -H "Authorization: Bearer {{ $value.bearerToken }}" \ - {{- end }} - {{- if $value.gitlabToken }} - -H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \ - {{- end }} - -H "Content-Type: application/json;charset=UTF-8" \ - {{ end }} - {{- $dpPath := "" -}} - {{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers }} - {{- if eq $kd.name $provider -}} - {{- $dpPath = $kd.options.path -}} - {{- end -}} - {{- end -}} - {{- if $value.url -}}"{{ $value.url }}"{{- else -}}"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download"{{- end -}}{{ if $value.datasource }} | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g'{{ end }}{{- if $value.b64content -}} | base64 -d {{- end -}} \ - > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" - {{- end }} - {{- end -}} - {{- end }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml deleted file mode 100644 index 59e0be64..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.dashboards }} -{{ $files := .Files }} -{{- range $provider, $dashboards := .Values.dashboards }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} - namespace: {{ template "grafana.namespace" $ }} - labels: - {{- include "grafana.labels" $ | nindent 4 }} - dashboard-provider: {{ $provider }} -{{- if $dashboards }} -data: -{{- $dashboardFound := false }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} -{{- $dashboardFound = true }} -{{ print $key | indent 2 }}.json: -{{- if hasKey $value "json" }} - |- -{{ $value.json | indent 6 }} -{{- end }} -{{- if hasKey $value "file" }} -{{ toYaml ( $files.Get $value.file ) | indent 4}} -{{- end }} -{{- end }} -{{- end }} -{{- if not $dashboardFound }} - {} -{{- end }} -{{- end }} ---- -{{- end }} - -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml deleted file mode 100644 index fee9c335..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml +++ /dev/null @@ -1,50 +0,0 @@ -{{ if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} - replicas: {{ .Values.replicas }} - {{- end }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- with .Values.deploymentStrategy }} - strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} - checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} -{{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} -{{- end }} -{{- if .Values.envRenderSecret }} - checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }} -{{- end }} -{{- with .Values.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - {{- include "grafana.pod" . | indent 6 }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml deleted file mode 100644 index b5faddcf..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset"))}} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }}-headless - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - clusterIP: None - selector: - {{- include "grafana.selectorLabels" . | nindent 4 }} - type: ClusterIP - ports: - - protocol: TCP - port: 3000 - targetPort: {{ .Values.service.targetPort }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml deleted file mode 100644 index 236a06d6..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: {{ template "grafana.hpa.apiVersion" . }} -kind: HorizontalPodAutoscaler -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "grafana.name" . }} - helm.sh/chart: {{ template "grafana.chart" . }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ template "grafana.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: -{{ toYaml .Values.autoscaling.metrics | indent 4 }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml deleted file mode 100644 index 97a8675b..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml +++ /dev/null @@ -1,123 +0,0 @@ -{{ if .Values.imageRenderer.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} -{{- if .Values.imageRenderer.labels }} -{{ toYaml .Values.imageRenderer.labels | indent 4 }} -{{- end }} -{{- with .Values.imageRenderer.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - replicas: {{ .Values.imageRenderer.replicas }} - revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} - selector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} -{{- with .Values.imageRenderer.deploymentStrategy }} - strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} - template: - metadata: - labels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} -{{- with .Values.imageRenderer.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} -{{- with .Values.imageRenderer.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - - {{- if .Values.imageRenderer.schedulerName }} - schedulerName: "{{ .Values.imageRenderer.schedulerName }}" - {{- end }} - {{- if .Values.imageRenderer.serviceAccountName }} - serviceAccountName: "{{ .Values.imageRenderer.serviceAccountName }}" - {{- else }} - serviceAccountName: {{ template "grafana.serviceAccountName" . }} - {{- end }} - {{- if .Values.imageRenderer.securityContext }} - securityContext: - {{- toYaml .Values.imageRenderer.securityContext | nindent 8 }} - {{- end }} - {{- if .Values.imageRenderer.hostAliases }} - hostAliases: - {{- toYaml .Values.imageRenderer.hostAliases | nindent 8 }} - {{- end }} - {{- if .Values.imageRenderer.priorityClassName }} - priorityClassName: {{ .Values.imageRenderer.priorityClassName }} - {{- end }} - {{- if .Values.imageRenderer.image.pullSecrets }} - imagePullSecrets: - {{- $root := . }} - {{- range .Values.imageRenderer.image.pullSecrets }} - - name: {{ tpl . $root }} - {{- end}} - {{- end }} - containers: - - name: {{ .Chart.Name }}-image-renderer - {{- if .Values.imageRenderer.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} - {{- if .Values.imageRenderer.command }} - command: - {{- range .Values.imageRenderer.command }} - - {{ . }} - {{- end }} - {{- end}} - ports: - - name: {{ .Values.imageRenderer.service.portName }} - containerPort: {{ .Values.imageRenderer.service.targetPort }} - protocol: TCP - livenessProbe: - httpGet: - path: / - port: {{ .Values.imageRenderer.service.portName }} - env: - - name: HTTP_PORT - value: {{ .Values.imageRenderer.service.targetPort | quote }} - {{- range $key, $value := .Values.imageRenderer.env }} - - name: {{ $key | quote }} - value: {{ $value | quote }} - {{- end }} - securityContext: - capabilities: - drop: ['all'] - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /tmp - name: image-renderer-tmpfs - {{- with .Values.imageRenderer.resources }} - resources: -{{ toYaml . | indent 12 }} - {{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} - {{- if .Values.imageRenderer.nodeSelector }} -{{ toYaml . | indent 8 }} - {{- end }} - {{- $root := . }} - {{- with .Values.imageRenderer.affinity }} - affinity: -{{ tpl (toYaml .) $root | indent 8 }} - {{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} - {{- if .Values.imageRenderer.tolerations }} -{{ toYaml . | indent 8 }} - {{- end }} - volumes: - - name: image-renderer-tmpfs - emptyDir: {} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml deleted file mode 100644 index 0d9bdfe4..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml +++ /dev/null @@ -1,73 +0,0 @@ -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer-ingress - namespace: {{ template "grafana.namespace" . }} - annotations: - comment: Limit image-renderer ingress traffic from grafana -spec: - podSelector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} - {{- if .Values.imageRenderer.podLabels }} - {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} - {{- end }} - - policyTypes: - - Ingress - ingress: - - ports: - - port: {{ .Values.imageRenderer.service.targetPort }} - protocol: TCP - from: - - namespaceSelector: - matchLabels: - name: {{ template "grafana.namespace" . }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} - {{- end }} -{{ end }} - -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer-egress - namespace: {{ template "grafana.namespace" . }} - annotations: - comment: Limit image-renderer egress traffic to grafana -spec: - podSelector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} - {{- if .Values.imageRenderer.podLabels }} - {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} - {{- end }} - - policyTypes: - - Egress - egress: - # allow dns resolution - - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP - # talk only to grafana - - ports: - - port: {{ .Values.service.port }} - protocol: TCP - to: - - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} - {{- end }} -{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml deleted file mode 100644 index fcf707a3..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{ if .Values.imageRenderer.enabled }} -{{ if .Values.imageRenderer.service.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} -{{- if .Values.imageRenderer.service.labels }} -{{ toYaml .Values.imageRenderer.service.labels | indent 4 }} -{{- end }} -{{- with .Values.imageRenderer.service.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - type: ClusterIP - {{- if .Values.imageRenderer.service.clusterIP }} - clusterIP: {{ .Values.imageRenderer.service.clusterIP }} - {{end}} - ports: - - name: {{ .Values.imageRenderer.service.portName }} - port: {{ .Values.imageRenderer.service.port }} - protocol: TCP - targetPort: {{ .Values.imageRenderer.service.targetPort }} - {{- if .Values.imageRenderer.appProtocol }} - appProtocol: {{ .Values.imageRenderer.appProtocol }} - {{- end }} - selector: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} -{{ end }} -{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml deleted file mode 100644 index 7699ceca..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml +++ /dev/null @@ -1,78 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} -{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} -{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} -{{- $fullName := include "grafana.fullname" . -}} -{{- $servicePort := .Values.service.port -}} -{{- $ingressPath := .Values.ingress.path -}} -{{- $ingressPathType := .Values.ingress.pathType -}} -{{- $extraPaths := .Values.ingress.extraPaths -}} -apiVersion: {{ include "grafana.ingress.apiVersion" . }} -kind: Ingress -metadata: - name: {{ $fullName }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.ingress.labels }} -{{ toYaml .Values.ingress.labels | indent 4 }} -{{- end }} - {{- if .Values.ingress.annotations }} - annotations: - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ tpl $value $ | quote }} - {{- end }} - {{- end }} -spec: - {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} - ingressClassName: {{ .Values.ingress.ingressClassName }} - {{- end -}} -{{- if .Values.ingress.tls }} - tls: -{{ tpl (toYaml .Values.ingress.tls) $ | indent 4 }} -{{- end }} - rules: - {{- if .Values.ingress.hosts }} - {{- range .Values.ingress.hosts }} - - host: {{ tpl . $}} - http: - paths: -{{- if $extraPaths }} -{{ toYaml $extraPaths | indent 10 }} -{{- end }} - - path: {{ $ingressPath }} - {{- if $ingressSupportsPathType }} - pathType: {{ $ingressPathType }} - {{- end }} - backend: - {{- if $ingressApiIsStable }} - service: - name: {{ $fullName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end }} - {{- else }} - - http: - paths: - - backend: - {{- if $ingressApiIsStable }} - service: - name: {{ $fullName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- if $ingressPath }} - path: {{ $ingressPath }} - {{- end }} - {{- if $ingressSupportsPathType }} - pathType: {{ $ingressPathType }} - {{- end }} - {{- end -}} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml deleted file mode 100644 index b751d943..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.labels }} - {{ toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - policyTypes: - {{- if .Values.networkPolicy.ingress }} - - Ingress - {{- end }} - {{- if .Values.networkPolicy.egress.enabled }} - - Egress - {{- end }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - - {{- if .Values.networkPolicy.egress.enabled }} - egress: - - ports: - {{ .Values.networkPolicy.egress.ports | toJson }} - {{- end }} - {{- if .Values.networkPolicy.ingress }} - ingress: - - ports: - - port: {{ .Values.service.targetPort }} - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ template "grafana.fullname" . }}-client: "true" - {{- with .Values.networkPolicy.explicitNamespacesSelector }} - - namespaceSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - - podSelector: - matchLabels: - {{- include "grafana.labels" . | nindent 14 }} - role: read - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml deleted file mode 100644 index 6b1e8ede..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml +++ /dev/null @@ -1,93 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: grafana-nginx-proxy-config - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -data: - nginx.conf: |- - worker_processes auto; - error_log /dev/stdout warn; - pid /var/cache/nginx/nginx.pid; - - events { - worker_connections 1024; - } - - http { - include /etc/nginx/mime.types; - log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; - - proxy_connect_timeout 10; - proxy_read_timeout 180; - proxy_send_timeout 5; - proxy_buffering off; - proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - server { - listen 8080; - access_log off; - - gzip on; - gzip_min_length 1k; - gzip_comp_level 2; - gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; - gzip_vary on; - gzip_disable "MSIE [1-6]\."; - - proxy_set_header Host $http_host; - - location /api/dashboards { - proxy_pass http://localhost:3000; - } - - location /api/search { - proxy_pass http://localhost:3000; - - sub_filter_types application/json; - sub_filter_once off; - } - - location /api/live/ { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $http_host; - proxy_pass http://localhost:3000; - } - - location / { - proxy_cache my_zone; - proxy_cache_valid 200 302 1d; - proxy_cache_valid 301 30d; - proxy_cache_valid any 5m; - proxy_cache_bypass $http_cache_control; - add_header X-Proxy-Cache $upstream_cache_status; - add_header Cache-Control "public"; - - proxy_pass http://localhost:3000/; - - sub_filter_once off; -{{- if not (empty .Values.global.cattle.clusterId) }} - sub_filter '"appSubUrl":""' '"appSubUrl":"/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; -{{- else }} - sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; -{{- end }} - sub_filter '"url":"/' '"url":"./'; - sub_filter ':"/avatar/' ':"avatar/'; - - if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { - expires 90d; - } - - rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; - - } - } - } diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml deleted file mode 100644 index 70901b70..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.podDisruptionBudget }} -apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} -kind: PodDisruptionBudget -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -spec: -{{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} -{{- end }} -{{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} -{{- end }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml deleted file mode 100644 index 82d295ad..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "grafana.fullname" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.rbac.pspAnnotations }} - annotations: {{ toYaml .Values.rbac.pspAnnotations | nindent 4 }} -{{- end }} -spec: - privileged: false - allowPrivilegeEscalation: false - requiredDropCapabilities: - # Default set from Docker, with DAC_OVERRIDE and CHOWN - - ALL - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'csi' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'RunAsAny' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml deleted file mode 100644 index 8a3ee122..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.persistence.annotations }} - annotations: -{{ toYaml . | indent 4 }} - {{- end }} - {{- with .Values.persistence.finalizers }} - finalizers: -{{ toYaml . | indent 4 }} - {{- end }} -spec: - accessModes: -{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} -{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size | quote }} - {{- if .Values.persistence.storageClassName }} - storageClassName: {{ .Values.persistence.storageClassName }} - {{- end -}} - {{- with .Values.persistence.selectorLabels }} - selector: - matchLabels: -{{ toYaml . | indent 6 }} - {{- end }} -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml deleted file mode 100644 index 80e2c596..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} -apiVersion: {{ template "grafana.rbac.apiVersion" . }} -kind: Role -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if or .Values.global.cattle.psp.enabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled (or .Values.sidecar.plugins.enabled .Values.rbac.extraRoleRules)))) }} -rules: -{{- if .Values.global.cattle.psp.enabled }} -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "grafana.fullname" . }}] -{{- end }} -{{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} -- apiGroups: [""] # "" indicates the core API group - resources: ["configmaps", "secrets"] - verbs: ["get", "watch", "list"] -{{- end }} -{{- with .Values.rbac.extraRoleRules }} -{{ toYaml . | indent 0 }} -{{- end}} -{{- else }} -rules: [] -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml deleted file mode 100644 index e0107255..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: {{ template "grafana.rbac.apiVersion" . }} -kind: RoleBinding -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }} -{{- else }} - name: {{ .Values.rbac.useExistingRole }} -{{- end }} -subjects: -- kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml deleted file mode 100644 index 5c09313e..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.envRenderSecret }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "grafana.fullname" . }}-env - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -type: Opaque -data: -{{- range $key, $val := .Values.envRenderSecret }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end -}} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml deleted file mode 100644 index c8aa750a..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -type: Opaque -data: - {{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} - admin-user: {{ .Values.adminUser | b64enc | quote }} - {{- if .Values.adminPassword }} - admin-password: {{ .Values.adminPassword | b64enc | quote }} - {{- else }} - admin-password: {{ template "grafana.password" . }} - {{- end }} - {{- end }} - {{- if not .Values.ldap.existingSecret }} - ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} - {{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml deleted file mode 100644 index d0a1756c..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{ if .Values.service.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.service.labels }} -{{ toYaml .Values.service.labels | indent 4 }} -{{- end }} -{{- $root := . }} -{{- with .Values.service.annotations }} - annotations: -{{ tpl (toYaml . | indent 4) $root }} -{{- end }} -spec: -{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} - type: ClusterIP - {{- if .Values.service.clusterIP }} - clusterIP: {{ .Values.service.clusterIP }} - {{end}} -{{- else if eq .Values.service.type "LoadBalancer" }} - type: {{ .Values.service.type }} - {{- if .Values.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.service.loadBalancerIP }} - {{- end }} - {{- if .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: -{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} - {{- end -}} -{{- else }} - type: {{ .Values.service.type }} -{{- end }} -{{- if .Values.service.externalIPs }} - externalIPs: -{{ toYaml .Values.service.externalIPs | indent 4 }} -{{- end }} - ports: - - name: {{ .Values.service.portName }} - port: {{ .Values.service.port }} - protocol: TCP - targetPort: {{ .Values.service.targetPort }} - {{- if .Values.service.appProtocol }} - appProtocol: {{ .Values.service.appProtocol }} - {{- end }} - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} - nodePort: {{.Values.service.nodePort}} - {{ end }} - {{- if .Values.extraExposePorts }} - {{- tpl (toYaml .Values.extraExposePorts) . | nindent 4 }} - {{- end }} - selector: - {{- include "grafana.selectorLabels" . | nindent 4 }} -{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml deleted file mode 100644 index 4ccee15e..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- $root := . }} -{{- with .Values.serviceAccount.annotations }} - annotations: -{{ tpl (toYaml . | indent 4) $root }} -{{- end }} - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml deleted file mode 100644 index 31ab6b88..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if .Values.serviceMonitor.enabled }} ---- -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "grafana.fullname" . }} - {{- if .Values.serviceMonitor.namespace }} - namespace: {{ tpl .Values.serviceMonitor.namespace . }} - {{- else }} - namespace: {{ template "grafana.namespace" . }} - {{- end }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- if .Values.serviceMonitor.labels }} - {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} - {{- end }} -spec: - endpoints: - - port: {{ .Values.service.portName }} - {{- with .Values.serviceMonitor.interval }} - interval: {{ . }} - {{- end }} - {{- with .Values.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ . }} - {{- end }} - honorLabels: true - path: {{ .Values.serviceMonitor.path }} - scheme: {{ .Values.serviceMonitor.scheme }} - {{- if .Values.serviceMonitor.tlsConfig }} - tlsConfig: - {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - metricRelabelings: - {{- if .Values.serviceMonitor.metricRelabelings }} - {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 6 }} - {{- end }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName }} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} - {{- if .Values.serviceMonitor.relabelings }} - relabelings: - {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} - {{- end }} - jobLabel: "{{ .Release.Name }}" - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 8 }} - namespaceSelector: - matchNames: - - {{ template "grafana.namespace" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml deleted file mode 100644 index aa6f305e..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml +++ /dev/null @@ -1,56 +0,0 @@ -{{- if (or (.Values.useStatefulSet) (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")))}} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - replicas: {{ .Values.replicas }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - serviceName: {{ template "grafana.fullname" . }}-headless - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} - checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} - {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} -{{- end }} -{{- with .Values.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - {{- include "grafana.pod" . | nindent 6 }} - {{- if .Values.persistence.enabled}} - volumeClaimTemplates: - - metadata: - name: storage - spec: -{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} -{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} - accessModes: {{ .Values.persistence.accessModes }} - storageClassName: {{ .Values.persistence.storageClassName }} - resources: - requests: - storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size }} - {{- with .Values.persistence.selectorLabels }} - selector: - matchLabels: -{{ toYaml . | indent 10 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml deleted file mode 100644 index ff53aaf1..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.testFramework.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -data: - run.sh: |- - @test "Test Health" { - url="http://{{ template "grafana.fullname" . }}/api/health" - - code=$(wget --server-response --spider --timeout 10 --tries 1 ${url} 2>&1 | awk '/^ HTTP/{print $2}') - [ "$code" == "200" ] - } -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml deleted file mode 100644 index 5dd736ef..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "grafana.fullname" . }}-test - labels: - {{- include "grafana.labels" . | nindent 4 }} -spec: - allowPrivilegeEscalation: true - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - fsGroup: - rule: RunAsAny - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - runAsUser: - rule: RunAsAny - volumes: - - configMap - - downwardAPI - - emptyDir - - projected - - csi - - secret -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml deleted file mode 100644 index ea2f8c6b..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -rules: -- apiGroups: ['policy'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "grafana.fullname" . }}-test] -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml deleted file mode 100644 index 7eda2651..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "grafana.fullname" . }}-test -subjects: -- kind: ServiceAccount - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml deleted file mode 100644 index 5c335073..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml +++ /dev/null @@ -1,9 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml deleted file mode 100644 index 3a84fbe0..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if .Values.testFramework.enabled }} -apiVersion: v1 -kind: Pod -metadata: - name: {{ template "grafana.fullname" . }}-test - labels: - {{- include "grafana.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test-success - "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" - namespace: {{ template "grafana.namespace" . }} -spec: - serviceAccountName: {{ template "grafana.serviceAccountNameTest" . }} - {{- if .Values.testFramework.securityContext }} - securityContext: {{ toYaml .Values.testFramework.securityContext | nindent 4 }} - {{- end }} - {{- $root := . }} - {{- if .Values.image.pullSecrets }} - imagePullSecrets: - {{- range .Values.image.pullSecrets }} - - name: {{ tpl . $root }} - {{- end}} - {{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} - {{- if .Values.nodeSelector }} -{{ toYaml .Values.nodeSelector | indent 4 }} - {{- end }} - {{- $root := . }} - {{- with .Values.affinity }} - affinity: -{{ tpl (toYaml .) $root | indent 4 }} - {{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} -{{- if .Values.tolerations }} -{{ toYaml .Values.tolerations | indent 4 }} -{{- end }} - containers: - - name: {{ .Release.Name }}-test - image: "{{ template "system_default_registry" . }}{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" - imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" - command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] - volumeMounts: - - mountPath: /tests - name: tests - readOnly: true - volumes: - - name: tests - configMap: - name: {{ template "grafana.fullname" . }}-test - restartPolicy: Never -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml deleted file mode 100644 index 196a07bf..00000000 --- a/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml +++ /dev/null @@ -1,1062 +0,0 @@ -global: - cattle: - psp: - enabled: false - systemDefaultRegistry: "" - projectNamespaces: [] - -rbac: - create: true - ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) - # useExistingRole: name-of-some-(cluster)role - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - namespaced: false - extraRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] - extraClusterRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] -serviceAccount: - create: true - name: - nameTest: -## Service account annotations. Can be templated. -# annotations: -# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here - autoMount: true - -replicas: 1 - -## Create a headless service for the deployment -headlessService: false - -## Create HorizontalPodAutoscaler object for deployment type -# -autoscaling: - enabled: false -# minReplicas: 1 -# maxReplicas: 10 -# metrics: -# - type: Resource -# resource: -# name: cpu -# targetAverageUtilization: 60 -# - type: Resource -# resource: -# name: memory -# targetAverageUtilization: 60 - -## See `kubectl explain poddisruptionbudget.spec` for more -## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ -podDisruptionBudget: {} -# minAvailable: 1 -# maxUnavailable: 1 - -## See `kubectl explain deployment.spec.strategy` for more -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy -deploymentStrategy: - type: RollingUpdate - -readinessProbe: - httpGet: - path: /api/health - port: 3000 - -livenessProbe: - httpGet: - path: /api/health - port: 3000 - initialDelaySeconds: 60 - timeoutSeconds: 30 - failureThreshold: 10 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: "default-scheduler" - -image: - repository: rancher/mirrored-grafana-grafana - # Overrides the Grafana image tag whose default is the chart appVersion - tag: 9.1.5 - sha: "" - pullPolicy: IfNotPresent - - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Can be templated. - ## - # pullSecrets: - # - myRegistrKeySecretName - -testFramework: - enabled: false - image: "rancher/mirrored-bats-bats" - tag: "v1.4.1" - imagePullPolicy: IfNotPresent - securityContext: - runAsNonRoot: true - runAsUser: 1000 - -securityContext: - runAsNonRoot: true - runAsUser: 472 - runAsGroup: 472 - fsGroup: 472 - -containerSecurityContext: - {} - -# Enable creating the grafana configmap -createConfigmap: true - -# Extra configmaps to mount in grafana pods -# Values are templated. -extraConfigmapMounts: [] - # - name: certs-configmap - # mountPath: /etc/grafana/ssl/ - # subPath: certificates.crt # (optional) - # configMap: certs-configmap - # readOnly: true - - -extraEmptyDirMounts: [] - # - name: provisioning-notifiers - # mountPath: /etc/grafana/provisioning/notifiers - - -# Apply extra labels to common labels. -extraLabels: {} - -## Assign a PriorityClassName to pods if set -# priorityClassName: - -downloadDashboardsImage: - repository: rancher/mirrored-curlimages-curl - tag: 7.85.0 - sha: "" - pullPolicy: IfNotPresent - -downloadDashboards: - env: {} - envFromSecret: "" - resources: {} - securityContext: {} - -## Pod Annotations -# podAnnotations: {} - -## Pod Labels -# podLabels: {} - -podPortName: grafana - -## Deployment annotations -# annotations: {} - -## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). -## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. -## ref: http://kubernetes.io/docs/user-guide/services/ -## -service: - enabled: true - type: ClusterIP - port: 80 - targetPort: 3000 - # targetPort: 4181 To be used with a proxy extraContainer - ## Service annotations. Can be templated. - annotations: {} - labels: {} - portName: service - # Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" - appProtocol: "" - -serviceMonitor: - ## If true, a ServiceMonitor CRD is created for a prometheus operator - ## https://github.com/coreos/prometheus-operator - ## - enabled: false - path: /metrics - # namespace: monitoring (defaults to use the namespace this chart is deployed to) - labels: {} - interval: 1m - scheme: http - tlsConfig: {} - scrapeTimeout: 30s - relabelings: [] - -extraExposePorts: [] - # - name: keycloak - # port: 8080 - # targetPort: 8080 - # type: ClusterIP - -# overrides pod.spec.hostAliases in the grafana deployment's pods -hostAliases: [] - # - ip: "1.2.3.4" - # hostnames: - # - "my.host.com" - -ingress: - enabled: false - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - # Values can be templated - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - labels: {} - path: / - - # pathType is only for k8s >= 1.18 - pathType: Prefix - - hosts: - - chart-example.local - ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. - extraPaths: [] - # - path: /* - # backend: - # serviceName: ssl-redirect - # servicePort: use-annotation - ## Or for k8s > 1.19 - # - path: /* - # pathType: Prefix - # backend: - # service: - # name: ssl-redirect - # port: - # name: use-annotation - - - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi - -## Node labels for pod assignment -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -# -nodeSelector: {} - -## Tolerations for pod assignment -## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Affinity for pod assignment (evaluated as template) -## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Topology Spread Constraints -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ -## -topologySpreadConstraints: [] - -## Additional init containers (evaluated as template) -## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ -## -extraInitContainers: [] - -## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod -extraContainers: "" -# extraContainers: | -# - name: proxy -# image: quay.io/gambol99/keycloak-proxy:latest -# args: -# - -provider=github -# - -client-id= -# - -client-secret= -# - -github-org= -# - -email-domain=* -# - -cookie-secret= -# - -http-address=http://0.0.0.0:4181 -# - -upstream-url=http://127.0.0.1:3000 -# ports: -# - name: proxy-web -# containerPort: 4181 - -## Volumes that can be used in init containers that will not be mounted to deployment pods -extraContainerVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - type: pvc - enabled: false - # storageClassName: default - accessModes: - - ReadWriteOnce - size: 10Gi - # annotations: {} - finalizers: - - kubernetes.io/pvc-protection - # selectorLabels: {} - ## Sub-directory of the PV to mount. Can be templated. - # subPath: "" - ## Name of an existing PVC. Can be templated. - # existingClaim: - - ## If persistence is not enabled, this allows to mount the - ## local storage in-memory to improve performance - ## - inMemory: - enabled: false - ## The maximum usage on memory medium EmptyDir would be - ## the minimum value between the SizeLimit specified - ## here and the sum of memory limits of all containers in a pod - ## - # sizeLimit: 300Mi - -initChownData: - ## If false, data ownership will not be reset at startup - ## This allows the prometheus-server to be run with an arbitrary user - ## - enabled: true - - ## initChownData container image - ## - image: - repository: rancher/mirrored-library-busybox - tag: "1.31.1" - sha: "" - pullPolicy: IfNotPresent - - ## initChownData resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - - -# Administrator credentials when not using an existing secret (see below) -adminUser: admin -# adminPassword: strongpassword - -# Use an existing secret for the admin user. -admin: - ## Name of the secret. Can be templated. - existingSecret: "" - userKey: admin-user - passwordKey: admin-password - -## Define command to be executed at startup by grafana container -## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) -## Default is "run.sh" as defined in grafana's Dockerfile -# command: -# - "sh" -# - "/run.sh" - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: - -## Extra environment variables that will be pass onto deployment pods -## -## to provide grafana with access to CloudWatch on AWS EKS: -## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) -## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the -## same oidc eks provider as noted before (same as the existing line) -## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name -## -## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", -## -## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess -## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) -## -## env: -## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here -## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token -## AWS_REGION: us-east-1 -## -## 5. uncomment the EKS section in extraSecretMounts: below -## 6. uncomment the annotation section in the serviceAccount: above -## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn - -env: {} - -## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core -## Renders in container spec as: -## env: -## ... -## - name: -## valueFrom: -## -envValueFrom: {} - # ENV_NAME: - # configMapKeyRef: - # name: configmap-name - # key: value_key - -## The name of a secret in the same kubernetes namespace which contain values to be added to the environment -## This can be useful for auth tokens, etc. Value is templated. -envFromSecret: "" - -## Sensible environment variables that will be rendered as new secret object -## This can be useful for auth tokens, etc -envRenderSecret: {} - -## The names of secrets in the same kubernetes namespace which contain values to be added to the environment -## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. -## Name is templated. -envFromSecrets: [] -## - name: secret-name -## optional: true - -## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment -## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. -## Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core -envFromConfigMaps: [] -## - name: configmap-name -## optional: true - -# Inject Kubernetes services as environment variables. -# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables -enableServiceLinks: true - -## Additional grafana server secret mounts -# Defines additional mounts with secrets. Secrets must be manually created in the namespace. -extraSecretMounts: [] - # - name: secret-files - # mountPath: /etc/secrets - # secretName: grafana-secret-files - # readOnly: true - # subPath: "" - # - # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) - # - name: aws-iam-token - # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount - # readOnly: true - # projected: - # defaultMode: 420 - # sources: - # - serviceAccountToken: - # audience: sts.amazonaws.com - # expirationSeconds: 86400 - # path: token - # - # for CSI e.g. Azure Key Vault use the following - # - name: secrets-store-inline - # mountPath: /run/secrets - # readOnly: true - # csi: - # driver: secrets-store.csi.k8s.io - # readOnly: true - # volumeAttributes: - # secretProviderClass: "akv-grafana-spc" - # nodePublishSecretRef: # Only required when using service principal mode - # name: grafana-akv-creds # Only required when using service principal mode - -## Additional grafana server volume mounts -# Defines additional volume mounts. -extraVolumeMounts: [] - # - name: extra-volume-0 - # mountPath: /mnt/volume0 - # readOnly: true - # existingClaim: volume-claim - # - name: extra-volume-1 - # mountPath: /mnt/volume1 - # readOnly: true - # hostPath: /usr/shared/ - # - name: grafana-secrets - # csi: true - # data: - # driver: secrets-store.csi.k8s.io - # readOnly: true - # volumeAttributes: - # secretProviderClass: "grafana-env-spc" - -## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request -lifecycleHooks: {} - # postStart: - # exec: - # command: [] - -## Pass the plugins you want installed as a list. -## -plugins: [] - # - digrich-bubblechart-panel - # - grafana-clock-panel - -## Configure grafana datasources -## ref: http://docs.grafana.org/administration/provisioning/#datasources -## -datasources: {} -# datasources.yaml: -# apiVersion: 1 -# datasources: -# - name: Prometheus -# type: prometheus -# url: http://prometheus-prometheus-server -# access: proxy -# isDefault: true -# - name: CloudWatch -# type: cloudwatch -# access: proxy -# uid: cloudwatch -# editable: false -# jsonData: -# authType: default -# defaultRegion: us-east-1 - -## Configure grafana alerting (can be templated) -## ref: http://docs.grafana.org/administration/provisioning/#alerting -## -alerting: {} - # rules.yaml: - # apiVersion: 1 - # groups: - # - orgId: 1 - # name: '{{ .Chart.Name }}_my_rule_group' - # folder: my_first_folder - # interval: 60s - # rules: - # - uid: my_id_1 - # title: my_first_rule - # condition: A - # data: - # - refId: A - # datasourceUid: '-100' - # model: - # conditions: - # - evaluator: - # params: - # - 3 - # type: gt - # operator: - # type: and - # query: - # params: - # - A - # reducer: - # type: last - # type: query - # datasource: - # type: __expr__ - # uid: '-100' - # expression: 1==0 - # intervalMs: 1000 - # maxDataPoints: 43200 - # refId: A - # type: math - # dashboardUid: my_dashboard - # panelId: 123 - # noDataState: Alerting - # for: 60s - # annotations: - # some_key: some_value - # labels: - # team: sre_team_1 - # contactpoints.yaml: - # apiVersion: 1 - # contactPoints: - # - orgId: 1 - # name: cp_1 - # receivers: - # - uid: first_uid - # type: pagerduty - # settings: - # integrationKey: XXX - # severity: critical - # class: ping failure - # component: Grafana - # group: app-stack - # summary: | - # {{ `{{ template "default.message" . }}` }} - -## Configure notifiers -## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels -## -notifiers: {} -# notifiers.yaml: -# notifiers: -# - name: email-notifier -# type: email -# uid: email1 -# # either: -# org_id: 1 -# # or -# org_name: Main Org. -# is_default: true -# settings: -# addresses: an_email_address@example.com -# delete_notifiers: - -## Configure grafana dashboard providers -## ref: http://docs.grafana.org/administration/provisioning/#dashboards -## -## `path` must be /var/lib/grafana/dashboards/ -## -dashboardProviders: {} -# dashboardproviders.yaml: -# apiVersion: 1 -# providers: -# - name: 'default' -# orgId: 1 -# folder: '' -# type: file -# disableDeletion: false -# editable: true -# options: -# path: /var/lib/grafana/dashboards/default - -## Configure grafana dashboard to import -## NOTE: To use dashboards you must also enable/configure dashboardProviders -## ref: https://grafana.com/dashboards -## -## dashboards per provider, use provider name as key. -## -dashboards: {} - # default: - # some-dashboard: - # json: | - # $RAW_JSON - # custom-dashboard: - # file: dashboards/custom-dashboard.json - # prometheus-stats: - # gnetId: 2 - # revision: 2 - # datasource: Prometheus - # local-dashboard: - # url: https://example.com/repository/test.json - # token: '' - # local-dashboard-base64: - # url: https://example.com/repository/test-b64.json - # token: '' - # b64content: true - # local-dashboard-gitlab: - # url: https://example.com/repository/test-gitlab.json - # gitlabToken: '' - # local-dashboard-bitbucket: - # url: https://example.com/repository/test-bitbucket.json - # bearerToken: '' - -## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. -## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. -## ConfigMap data example: -## -## data: -## example-dashboard.json: | -## RAW_JSON -## -dashboardsConfigMaps: {} -# default: "" - -## Grafana's primary configuration -## NOTE: values in map will be converted to ini format -## ref: http://docs.grafana.org/installation/configuration/ -## -grafana.ini: - paths: - data: /var/lib/grafana/ - logs: /var/log/grafana - plugins: /var/lib/grafana/plugins - provisioning: /etc/grafana/provisioning - analytics: - check_for_updates: true - log: - mode: console - grafana_net: - url: https://grafana.net - server: - domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ end }}" -## grafana Authentication can be enabled with the following values on grafana.ini - # server: - # The full public facing url you use in browser, used for redirects and emails - # root_url: - # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana - # auth.github: - # enabled: false - # allow_sign_up: false - # scopes: user:email,read:org - # auth_url: https://github.com/login/oauth/authorize - # token_url: https://github.com/login/oauth/access_token - # api_url: https://api.github.com/user - # team_ids: - # allowed_organizations: - # client_id: - # client_secret: -## LDAP Authentication can be enabled with the following values on grafana.ini -## NOTE: Grafana will fail to start if the value for ldap.toml is invalid - # auth.ldap: - # enabled: true - # allow_sign_up: true - # config_file: /etc/grafana/ldap.toml - -## Grafana's LDAP configuration -## Templated by the template in _helpers.tpl -## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled -## ref: http://docs.grafana.org/installation/configuration/#auth-ldap -## ref: http://docs.grafana.org/installation/ldap/#configuration -ldap: - enabled: false - # `existingSecret` is a reference to an existing secret containing the ldap configuration - # for Grafana in a key `ldap-toml`. - existingSecret: "" - # `config` is the content of `ldap.toml` that will be stored in the created secret - config: "" - # config: |- - # verbose_logging = true - - # [[servers]] - # host = "my-ldap-server" - # port = 636 - # use_ssl = true - # start_tls = false - # ssl_skip_verify = false - # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" - -## Grafana's SMTP configuration -## NOTE: To enable, grafana.ini must be configured with smtp.enabled -## ref: http://docs.grafana.org/installation/configuration/#smtp -smtp: - # `existingSecret` is a reference to an existing secret containing the smtp configuration - # for Grafana. - existingSecret: "" - userKey: "user" - passwordKey: "password" - -## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders -## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards -sidecar: - image: - repository: rancher/mirrored-kiwigrid-k8s-sidecar - tag: 1.19.2 - sha: "" - imagePullPolicy: IfNotPresent - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - securityContext: {} - # skipTlsVerify Set to true to skip tls verification for kube api calls - # skipTlsVerify: true - enableUniqueFilenames: false - readinessProbe: {} - livenessProbe: {} - # Log level default for all sidecars. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. Defaults to INFO - # logLevel: INFO - dashboards: - enabled: false - # Additional environment variables for the dashboards sidecar - env: {} - # Do not reprocess already processed unchanged resources on k8s API reconnect. - # ignoreAlreadyProcessed: true - SCProvider: true - # label that the configmaps with dashboards are marked with - label: grafana_dashboard - # value of label that the configmaps with dashboards are set to - labelValue: "" - # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. - # logLevel: INFO - # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) - folder: /tmp/dashboards - # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead - defaultFolderName: null - # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. - watchMethod: WATCH - # search in configmap, secret or both - resource: both - # If specified, the sidecar will look for annotation with this name to create folder and put graph here. - # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. - folderAnnotation: null - # Absolute path to shell script to execute after a configmap got reloaded - script: null - # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. - # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S - # watchServerTimeout: 3600 - # - # watchClientTimeout: is a client-side timeout, configuring your local socket. - # If you have a network outage dropping all packets with no RST/FIN, - # this is how long your client waits before realizing & dropping the connection. - # defaults to 66sec (sic!) - # watchClientTimeout: 60 - # - # provider configuration that lets grafana manage the dashboards - provider: - # name of the provider, should be unique - name: sidecarProvider - # orgid as configured in grafana - orgid: 1 - # folder in which the dashboards should be imported in grafana - folder: '' - # type of the provider - type: file - # disableDelete to activate a import-only behaviour - disableDelete: false - # allow updating provisioned dashboards from the UI - allowUiUpdates: false - # allow Grafana to replicate dashboard structure from filesystem - foldersFromFilesStructure: false - # Additional dashboard sidecar volume mounts - extraMounts: [] - # Sets the size limit of the dashboard sidecar emptyDir volume - sizeLimit: {} - datasources: - enabled: false - # Additional environment variables for the datasourcessidecar - env: {} - # Do not reprocess already processed unchanged resources on k8s API reconnect. - # ignoreAlreadyProcessed: true - # label that the configmaps with datasources are marked with - label: grafana_datasource - # value of label that the configmaps with datasources are set to - labelValue: "" - # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. - # logLevel: INFO - # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. - watchMethod: WATCH - # search in configmap, secret or both - resource: both - # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. - # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S - # watchServerTimeout: 3600 - # - # watchClientTimeout: is a client-side timeout, configuring your local socket. - # If you have a network outage dropping all packets with no RST/FIN, - # this is how long your client waits before realizing & dropping the connection. - # defaults to 66sec (sic!) - # watchClientTimeout: 60 - # - # Endpoint to send request to reload datasources - reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" - # Absolute path to shell script to execute after a datasource got reloaded - script: null - skipReload: true - # Deploy the datasource sidecar as an initContainer in addition to a container. - # This is needed if skipReload is true, to load any datasources defined at startup time. - initDatasources: true - # Sets the size limit of the datasource sidecar emptyDir volume - sizeLimit: {} - plugins: - enabled: false - # Additional environment variables for the plugins sidecar - env: {} - # Do not reprocess already processed unchanged resources on k8s API reconnect. - # ignoreAlreadyProcessed: true - # label that the configmaps with plugins are marked with - label: grafana_plugin - # value of label that the configmaps with plugins are set to - labelValue: "" - # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. - # logLevel: INFO - # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. - watchMethod: WATCH - # search in configmap, secret or both - resource: both - # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. - # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S - # watchServerTimeout: 3600 - # - # watchClientTimeout: is a client-side timeout, configuring your local socket. - # If you have a network outage dropping all packets with no RST/FIN, - # this is how long your client waits before realizing & dropping the connection. - # defaults to 66sec (sic!) - # watchClientTimeout: 60 - # - # Endpoint to send request to reload plugins - reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" - # Absolute path to shell script to execute after a plugin got reloaded - script: null - skipReload: false - # Deploy the datasource sidecar as an initContainer in addition to a container. - # This is needed if skipReload is true, to load any plugins defined at startup time. - initPlugins: false - # Sets the size limit of the plugin sidecar emptyDir volume - sizeLimit: {} - notifiers: - enabled: false - # Additional environment variables for the notifierssidecar - env: {} - # Do not reprocess already processed unchanged resources on k8s API reconnect. - # ignoreAlreadyProcessed: true - # label that the configmaps with notifiers are marked with - label: grafana_notifier - # value of label that the configmaps with notifiers are set to - labelValue: "" - # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. - # logLevel: INFO - # search in configmap, secret or both - resource: both - # Sets the size limit of the notifier sidecar emptyDir volume - sizeLimit: {} - -## Override the deployment namespace -## -namespaceOverride: "" - -## Number of old ReplicaSets to retain -## -revisionHistoryLimit: 10 - -## Add a seperate remote image renderer deployment/service -imageRenderer: - # Enable the image-renderer deployment & service - enabled: false - replicas: 1 - image: - # image-renderer Image repository - repository: rancher/mirrored-grafana-grafana-image-renderer - # image-renderer Image tag - tag: 3.0.1 - # image-renderer Image sha (optional) - sha: "" - # image-renderer ImagePullPolicy - pullPolicy: Always - # extra environment variables - env: - HTTP_HOST: "0.0.0.0" - # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 - # RENDERING_MODE: clustered - # IGNORE_HTTPS_ERRORS: true - # image-renderer deployment serviceAccount - serviceAccountName: "" - # image-renderer deployment securityContext - securityContext: {} - # image-renderer deployment Host Aliases - hostAliases: [] - # image-renderer deployment priority class - priorityClassName: '' - service: - # Enable the image-renderer service - enabled: true - # image-renderer service port name - portName: 'http' - # image-renderer service port used by both service and deployment - port: 8081 - targetPort: 8081 - # Adds the appProtocol field to the image-renderer service. This allows to work with istio protocol selection. Ex: "http" or "tcp" - appProtocol: "" - # If https is enabled in Grafana, this needs to be set as 'https' to correctly configure the callback used in Grafana - grafanaProtocol: http - # In case a sub_path is used this needs to be added to the image renderer callback - grafanaSubPath: "" - # name of the image-renderer port on the pod - podPortName: http - # number of image-renderer replica sets to keep - revisionHistoryLimit: 10 - networkPolicy: - # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods - limitIngress: true - # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods - limitEgress: false - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - ## Node labels for pod assignment - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - # - nodeSelector: {} - - ## Tolerations for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - - ## Affinity for pod assignment (evaluated as template) - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## - affinity: {} - -networkPolicy: - ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. - ## - enabled: false - ## @param networkPolicy.allowExternal Don't require client label for connections - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to grafana port defined. - ## When true, grafana will accept connections from any source - ## (with the correct destination port). - ## - ingress: true - ## @param networkPolicy.ingress When true enables the creation - ## an ingress network policy - ## - allowExternal: true - ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed - ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace - ## and that match other criteria, the ones that have the good label, can reach the grafana. - ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this - ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. - ## - ## Example: - ## explicitNamespacesSelector: - ## matchLabels: - ## role: frontend - ## matchExpressions: - ## - {key: role, operator: In, values: [frontend]} - ## - explicitNamespacesSelector: {} - ## - ## - ## - ## - ## - ## - egress: - ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be - ## created allowing grafana to connect to external data sources from kubernetes cluster. - enabled: false - ## - ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress - ports: [] - ## Add ports to the egress by specifying - port: - ## E.X. - ## ports: - ## - port: 80 - ## - port: 443 - ## - ## - ## - ## - ## - ## - -# Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option -enableKubeBackwardCompatibility: false -useStatefulSet: false diff --git a/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml b/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml deleted file mode 100644 index b5ceb698..00000000 --- a/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml +++ /dev/null @@ -1,13 +0,0 @@ -- job_name: 'federate' - scrape_interval: {{ .Values.federate.interval }} - honor_labels: true - metrics_path: '/federate' - - params: - 'match[]': - - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=~"kube-state-metrics|kubelet|k3s-server"}' - - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=""}' - - static_configs: - - targets: {{ .Values.federate.targets | toYaml | nindent 6 }} - diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json deleted file mode 100644 index 9e53081a..00000000 --- a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json +++ /dev/null @@ -1,636 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 28, - "iteration": 1618265214337, - "links": [], - "panels": [ - { - "aliasColors": { - "{{container}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "CFS throttled ({{container}})", - "refId": "A" - }, - { - "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "System ({{container}})", - "refId": "B" - }, - { - "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Total ({{container}})", - "refId": "C" - }, - { - "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "User ({{container}})", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "cpu", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{container}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}) by (container)", - "interval": "", - "legendFormat": "({{container}})", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{container}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 0 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Receive Total ({{container}})", - "refId": "A" - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Transmit Total ({{container}})", - "refId": "B" - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Receive Dropped ({{container}})", - "refId": "C" - }, - { - "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Receive Errors ({{container}})", - "refId": "D" - }, - { - "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Transmit Errors ({{container}})", - "refId": "E" - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Transmit Dropped ({{container}})", - "refId": "F" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{container}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Receive Total ({{container}})", - "refId": "A" - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Transmit Total ({{container}})", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{container}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 7 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Write ({{container}})", - "refId": "A" - }, - { - "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", - "interval": "", - "legendFormat": "Read ({{container}})", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": false, - "schemaVersion": 26, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Rancher / Pod (Containers)", - "uid": "rancher-pod-containers-1", - "version": 8 -} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json deleted file mode 100644 index 65c6bf18..00000000 --- a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json +++ /dev/null @@ -1,636 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 28, - "iteration": 1618265214337, - "links": [], - "panels": [ - { - "aliasColors": { - "": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "CFS throttled", - "refId": "A" - }, - { - "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "System", - "refId": "B" - }, - { - "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Total", - "refId": "C" - }, - { - "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "User", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "cpu", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"})", - "interval": "", - "legendFormat": "Total", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 0 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Receive Total", - "refId": "A" - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Transmit Total", - "refId": "B" - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Receive Dropped", - "refId": "C" - }, - { - "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Receive Errors", - "refId": "D" - }, - { - "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Transmit Errors", - "refId": "E" - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Transmit Dropped", - "refId": "F" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Receive Total", - "refId": "A" - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Transmit Total", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 7 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Write", - "refId": "A" - }, - { - "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Read", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": false, - "schemaVersion": 26, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace!=\"\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace=\"$namespace\", pod!=\"\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Rancher / Pod", - "uid": "rancher-pod-1", - "version": 8 -} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json deleted file mode 100644 index f6b5078a..00000000 --- a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json +++ /dev/null @@ -1,652 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 28, - "iteration": 1618265214337, - "links": [], - "panels": [ - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "CFS throttled ({{pod}})", - "refId": "A" - }, - { - "expr": "(sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "System ({{pod}})", - "refId": "B" - }, - { - "expr": "(sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Total ({{pod}})", - "refId": "C" - }, - { - "expr": "(sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "User ({{pod}})", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "cpu", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "({{pod}})", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 0 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Receive Total ({{pod}})", - "refId": "A" - }, - { - "expr": "(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Transmit Total ({{pod}})", - "refId": "B" - }, - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Receive Dropped ({{pod}})", - "refId": "C" - }, - { - "expr": "(sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Receive Errors ({{pod}})", - "refId": "D" - }, - { - "expr": "(sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Transmit Errors ({{pod}})", - "refId": "E" - }, - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Transmit Dropped ({{pod}})", - "refId": "F" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Receive Total ({{pod}})", - "refId": "A" - }, - { - "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Transmit Total ({{pod}})", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 7 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Write ({{pod}})", - "refId": "A" - }, - { - "expr": "(sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", - "interval": "", - "legendFormat": "Read ({{pod}})", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": false, - "schemaVersion": 26, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*namespace=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "kind", - "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*created_by_kind=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*created_by_name=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Rancher / Workload (Pods)", - "uid": "rancher-workload-pods-1", - "version": 8 -} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json deleted file mode 100644 index 9f5317c2..00000000 --- a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json +++ /dev/null @@ -1,652 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 28, - "iteration": 1618265214337, - "links": [], - "panels": [ - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum((sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "CFS throttled", - "refId": "A" - }, - { - "expr": "sum((sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "System", - "refId": "B" - }, - { - "expr": "sum((sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Total", - "refId": "C" - }, - { - "expr": "sum((sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "User", - "refId": "D" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "cpu", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum((sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Total", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Utilization", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 0 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum((sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Receive Total", - "refId": "A" - }, - { - "expr": "sum((sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Transmit Total", - "refId": "B" - }, - { - "expr": "sum((sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Receive Dropped", - "refId": "C" - }, - { - "expr": "sum((sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Receive Errors", - "refId": "D" - }, - { - "expr": "sum((sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Transmit Errors", - "refId": "E" - }, - { - "expr": "sum((sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Transmit Dropped", - "refId": "F" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum((sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Receive Total", - "refId": "A" - }, - { - "expr": "sum((sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Transmit Total", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Network I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "{{pod}}": "#3797d5" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 7 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "percentage": false, - "pluginVersion": "7.1.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum((sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Write", - "refId": "A" - }, - { - "expr": "sum((sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", - "interval": "", - "legendFormat": "Read", - "refId": "B" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": false, - "schemaVersion": 26, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*namespace=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "kind", - "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*created_by_kind=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", - "refresh": 2, - "regex": "/.*created_by_name=\"([^\"]*)\"/", - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Rancher / Workload", - "uid": "rancher-workload-1", - "version": 8 -} diff --git a/charts/rancher-project-monitoring/0.3.0/questions.yaml b/charts/rancher-project-monitoring/0.3.0/questions.yaml deleted file mode 100644 index c15f36e7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/questions.yaml +++ /dev/null @@ -1,128 +0,0 @@ -questions: -- variable: alertmanager.enabled - label: Enable Alertmanager - default: true - type: boolean - group: Alertmanager -- variable: grafana.enabled - label: Enable Grafana - default: true - type: boolean - group: Grafana - show_subquestion_if: true - subquestions: - - variable: grafana.adminUser - label: Grafana Admin User - type: string - default: admin - group: Grafana - - variable: grafana.adminPassword - label: Grafana Admin Password - type: string - default: prom-operator - group: Grafana - - variable: grafana.sidecar.dashboards.label - label: Default Grafana Dashboard Label - default: grafana_dashboard - description: All ConfigMaps with this label are parsed as Grafana Dashboards - type: string - group: Grafana -- variable: grafana.persistence.enabled - type: boolean - required: true - label: Enable Persistent Volume - show_subquestion_if: true - group: Grafana - subquestions: - - variable: grafana.persistence.size - type: string - default: 1Gi - label: Size - - variable: grafana.persistence.storageClass - type: storageclass - label: Storage Class Name - - variable: grafana.persistence.accessModes - type: enum - default: - - ReadWriteOnce - options: - - [ReadWriteOnce] - - [ReadWriteMany] - - [ReadOnlyMany] - label: Access Mode -- variable: prometheus.prometheusSpec.scrapeInterval - type: string - required: true - label: Scrape Interval - default: 30s - group: Prometheus -- variable: prometheus.prometheusSpec.evaluationInterval - type: string - required: true - label: Evaluation Interval - default: 1m - group: Prometheus -- variable: prometheus.prometheusSpec.retention - type: string - required: true - label: Retention - default: 10d - group: Prometheus -- variable: prometheus.prometheusSpec.retentionSize - type: string - required: false - label: Retention Size - default: 50GB - group: Prometheus -- variable: prometheus.prometheusSpec.resources.requests.cpu - type: string - required: true - label: Requested CPU - default: 750m - group: Prometheus -- variable: prometheus.prometheusSpec.resources.requests.memory - type: string - required: true - label: Requested Memory - default: 750Mi - group: Prometheus -- variable: prometheus.prometheusSpec.resources.limits.cpu - type: string - required: true - label: CPU Limit - default: 1000m - group: Prometheus -- variable: prometheus.prometheusSpec.resources.limits.memory - type: string - required: true - label: Memory Limit - default: 3000Mi - group: Prometheus -- variable: prometheus.prometheusSpec.storage.enabled - type: boolean - required: true - label: Enable Persistent Volume - show_subquestion_if: true - group: Prometheus - subquestions: - - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage - type: string - default: 50Gi - label: Size - - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName - type: storageclass - label: Storage Class Name - - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.accessModes - type: enum - default: - - ReadWriteOnce - options: - - [ReadWriteOnce] - - [ReadWriteMany] - - [ReadOnlyMany] - label: Access Mode -- variable: federate.enabled - label: Enable Federated Metrics From Cluster Prometheus - default: true - type: boolean - group: Federation diff --git a/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt deleted file mode 100644 index 9e4d6d87..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt +++ /dev/null @@ -1,4 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "project-prometheus-stack.namespace" . }} get pods -l "release={{ $.Release.Name }}" - -Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator. diff --git a/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl deleted file mode 100644 index 5333d28b..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl +++ /dev/null @@ -1,252 +0,0 @@ -# Rancher -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- end -}} -{{- end -}} - -{{/* -https://github.com/helm/helm/issues/4535#issuecomment-477778391 -Usage: {{ include "call-nested" (list . "SUBCHART_NAME" "TEMPLATE") }} -e.g. {{ include "call-nested" (list . "grafana" "grafana.fullname") }} -*/}} -{{- define "call-nested" }} -{{- $dot := index . 0 }} -{{- $subchart := index . 1 | splitList "." }} -{{- $template := index . 2 }} -{{- $values := $dot.Values }} -{{- range $subchart }} -{{- $values = index $values . }} -{{- end }} -{{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }} -{{- end }} - -# Windows Support - -{{/* -Windows cluster will add default taint for linux nodes, -add below linux tolerations to workloads could be scheduled to those linux nodes -*/}} - -{{- define "linux-node-tolerations" -}} -- key: "cattle.io/os" - value: "linux" - effect: "NoSchedule" - operator: "Equal" -{{- end -}} - -{{- define "linux-node-selector" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -beta.kubernetes.io/os: linux -{{- else -}} -kubernetes.io/os: linux -{{- end -}} -{{- end -}} - -# Prometheus Operator - -{{/* Comma-delimited list of namespaces that need to be watched to configure Project Prometheus Stack components */}} -{{- define "project-prometheus-stack.projectNamespaceList" -}} -{{ append .Values.global.cattle.projectNamespaces .Release.Namespace | uniq | join "," }} -{{- end }} - -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "project-prometheus-stack.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -The components in this chart create additional resources that expand the longest created name strings. -The longest name that gets created adds and extra 37 characters, so truncation should be 63-35=26. -*/}} -{{- define "project-prometheus-stack.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 26 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* Prometheus custom resource instance name */}} -{{- define "project-prometheus-stack.prometheus.crname" -}} -{{- if .Values.cleanPrometheusOperatorObjectNames }} -{{- include "project-prometheus-stack.fullname" . }} -{{- else }} -{{- print (include "project-prometheus-stack.fullname" .) "-prometheus" }} -{{- end }} -{{- end }} - -{{/* Alertmanager custom resource instance name */}} -{{- define "project-prometheus-stack.alertmanager.crname" -}} -{{- if .Values.cleanPrometheusOperatorObjectNames }} -{{- include "project-prometheus-stack.fullname" . }} -{{- else }} -{{- print (include "project-prometheus-stack.fullname" .) "-alertmanager" -}} -{{- end }} -{{- end }} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "project-prometheus-stack.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "project-prometheus-stack.labels" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" -app.kubernetes.io/part-of: {{ template "project-prometheus-stack.name" . }} -chart: {{ template "project-prometheus-stack.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end }} - -{{/* Create the name of prometheus service account to use */}} -{{- define "project-prometheus-stack.prometheus.serviceAccountName" -}} -{{- if .Values.prometheus.serviceAccount.create -}} - {{ default (print (include "project-prometheus-stack.fullname" .) "-prometheus") .Values.prometheus.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.prometheus.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* Create the name of alertmanager service account to use */}} -{{- define "project-prometheus-stack.alertmanager.serviceAccountName" -}} -{{- if .Values.alertmanager.serviceAccount.create -}} - {{ default (print (include "project-prometheus-stack.fullname" .) "-alertmanager") .Values.alertmanager.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.alertmanager.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "project-prometheus-stack.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* -Use the grafana namespace override for multi-namespace deployments in combined charts -*/}} -{{- define "project-prometheus-stack-grafana.namespace" -}} - {{- if .Values.grafana.namespaceOverride -}} - {{- .Values.grafana.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* Allow KubeVersion to be overridden. */}} -{{- define "project-prometheus-stack.kubeVersion" -}} - {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} -{{- end -}} - -{{/* Get Ingress API Version */}} -{{- define "project-prometheus-stack.ingress.apiVersion" -}} - {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "project-prometheus-stack.kubeVersion" .)) -}} - {{- print "networking.k8s.io/v1" -}} - {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} - {{- print "networking.k8s.io/v1beta1" -}} - {{- else -}} - {{- print "extensions/v1beta1" -}} - {{- end -}} -{{- end -}} - -{{/* Check Ingress stability */}} -{{- define "project-prometheus-stack.ingress.isStable" -}} - {{- eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1" -}} -{{- end -}} - -{{/* Check Ingress supports pathType */}} -{{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}} -{{- define "project-prometheus-stack.ingress.supportsPathType" -}} - {{- or (eq (include "project-prometheus-stack.ingress.isStable" .) "true") (and (eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "project-prometheus-stack.kubeVersion" .))) -}} -{{- end -}} - -{{/* Get Policy API Version */}} -{{- define "project-prometheus-stack.pdb.apiVersion" -}} - {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">= 1.21-0" (include "project-prometheus-stack.kubeVersion" .)) -}} - {{- print "policy/v1" -}} - {{- else -}} - {{- print "policy/v1beta1" -}} - {{- end -}} - {{- end -}} - -{{/* Get value based on current Kubernetes version */}} -{{- define "project-prometheus-stack.kubeVersionDefaultValue" -}} - {{- $values := index . 0 }} - {{- $kubeVersion := index . 1 }} - {{- $old := index . 2 }} - {{- $new := index . 3 }} - {{- $default := index . 4 }} - {{- if kindIs "invalid" $default -}} - {{- if semverCompare $kubeVersion (include "project-prometheus-stack.kubeVersion" $values) -}} - {{- print $new -}} - {{- else -}} - {{- print $old -}} - {{- end -}} - {{- else -}} - {{- print $default }} - {{- end -}} -{{- end -}} - -{{/* -To help compatibility with other charts which use global.imagePullSecrets. -Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). -global: - imagePullSecrets: - - name: pullSecret1 - - name: pullSecret2 - -or - -global: - imagePullSecrets: - - pullSecret1 - - pullSecret2 -*/}} -{{- define "project-prometheus-stack.imagePullSecrets" -}} -{{- range .Values.global.imagePullSecrets }} - {{- if eq (typeOf .) "map[string]interface {}" }} -- {{ toYaml . | trim }} - {{- else }} -- name: {{ . }} - {{- end }} -{{- end }} -{{- end -}} - - -{{/* Define ingress for all hardened namespaces */}} -{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} -{{- $root := index . 0 }} -{{- $ns := index . 1 }} -{{- if $root.Values.global.networkPolicy.ingress -}} -{{ toYaml $root.Values.global.networkPolicy.ingress }} -{{- end }} -{{- if $root.Values.global.networkPolicy.limitIngressToProject }} -- from: -{{- if $root.Values.global.cattle.projectNamespaceSelector }} - - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} -{{- end }} - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: {{ $ns }} -{{- end }} -{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml deleted file mode 100644 index 6bc14320..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml +++ /dev/null @@ -1,165 +0,0 @@ -{{- if .Values.alertmanager.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: Alertmanager -metadata: - name: {{ template "project-prometheus-stack.alertmanager.crname" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.alertmanager.annotations }} - annotations: -{{ toYaml .Values.alertmanager.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.alertmanager.alertmanagerSpec.image }} - {{- if and .Values.alertmanager.alertmanagerSpec.image.tag .Values.alertmanager.alertmanagerSpec.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" - {{- else if .Values.alertmanager.alertmanagerSpec.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" - {{- else if .Values.alertmanager.alertmanagerSpec.image.tag }} - image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}" - {{- end }} - version: {{ .Values.alertmanager.alertmanagerSpec.image.tag }} - {{- if .Values.alertmanager.alertmanagerSpec.image.sha }} - sha: {{ .Values.alertmanager.alertmanagerSpec.image.sha }} - {{- end }} -{{- end }} - replicas: {{ .Values.alertmanager.alertmanagerSpec.replicas }} - listenLocal: {{ .Values.alertmanager.alertmanagerSpec.listenLocal }} - serviceAccountName: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} -{{- if .Values.alertmanager.alertmanagerSpec.externalUrl }} - externalUrl: "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}" -{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} - externalUrl: "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" -{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} - externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy" -{{- else }} - externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }} -{{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} -{{- if .Values.alertmanager.alertmanagerSpec.nodeSelector }} -{{ toYaml .Values.alertmanager.alertmanagerSpec.nodeSelector | indent 4 }} -{{- end }} - paused: {{ .Values.alertmanager.alertmanagerSpec.paused }} - logFormat: {{ .Values.alertmanager.alertmanagerSpec.logFormat | quote }} - logLevel: {{ .Values.alertmanager.alertmanagerSpec.logLevel | quote }} - retention: {{ .Values.alertmanager.alertmanagerSpec.retention | quote }} -{{- if .Values.alertmanager.alertmanagerSpec.secrets }} - secrets: -{{ toYaml .Values.alertmanager.alertmanagerSpec.secrets | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.configSecret }} - configSecret: {{ .Values.alertmanager.alertmanagerSpec.configSecret }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.configMaps }} - configMaps: -{{ toYaml .Values.alertmanager.alertmanagerSpec.configMaps | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector }} - alertmanagerConfigSelector: -{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector | indent 4}} -{{ else }} - alertmanagerConfigSelector: {} -{{- end }} - alertmanagerConfigNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} -{{- if .Values.alertmanager.alertmanagerSpec.web }} - web: -{{ toYaml .Values.alertmanager.alertmanagerSpec.web | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration }} - alertmanagerConfiguration: -{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.resources }} - resources: -{{ toYaml .Values.alertmanager.alertmanagerSpec.resources | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} - routePrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.securityContext }} - securityContext: -{{ toYaml .Values.alertmanager.alertmanagerSpec.securityContext | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.storage }} - storage: -{{ tpl (toYaml .Values.alertmanager.alertmanagerSpec.storage | indent 4) . }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.podMetadata }} - podMetadata: -{{ toYaml .Values.alertmanager.alertmanagerSpec.podMetadata | indent 4 }} -{{- end }} -{{- if or .Values.alertmanager.alertmanagerSpec.podAntiAffinity .Values.alertmanager.alertmanagerSpec.affinity }} - affinity: -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.affinity }} -{{ toYaml .Values.alertmanager.alertmanagerSpec.affinity | indent 4 }} -{{- end }} -{{- if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "hard" }} - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchExpressions: - - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} - - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} -{{- else if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "soft" }} - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchExpressions: - - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} - - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} -{{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} -{{- if .Values.alertmanager.alertmanagerSpec.tolerations }} -{{ toYaml .Values.alertmanager.alertmanagerSpec.tolerations | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints }} - topologySpreadConstraints: -{{ toYaml .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} - imagePullSecrets: -{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.containers }} - containers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.containers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.initContainers }} - initContainers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.initContainers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.priorityClassName }} - priorityClassName: {{.Values.alertmanager.alertmanagerSpec.priorityClassName }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.additionalPeers }} - additionalPeers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.additionalPeers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.volumes }} - volumes: -{{ toYaml .Values.alertmanager.alertmanagerSpec.volumes | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.volumeMounts }} - volumeMounts: -{{ toYaml .Values.alertmanager.alertmanagerSpec.volumeMounts | indent 4 }} -{{- end }} - portName: {{ .Values.alertmanager.alertmanagerSpec.portName }} -{{- if .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} - clusterAdvertiseAddress: {{ .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} - forceEnableClusterMode: {{ .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.minReadySeconds }} - minReadySeconds: {{ .Values.alertmanager.alertmanagerSpec.minReadySeconds }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml deleted file mode 100644 index af469be7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.alertmanager.extraSecret.data -}} -{{- $secretName := printf "alertmanager-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ default $secretName .Values.alertmanager.extraSecret.name }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- if .Values.alertmanager.extraSecret.annotations }} - annotations: -{{ toYaml .Values.alertmanager.extraSecret.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager - app.kubernetes.io/component: alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -data: -{{- range $key, $val := .Values.alertmanager.extraSecret.data }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml deleted file mode 100644 index 022922b0..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml +++ /dev/null @@ -1,77 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }} -{{- $pathType := .Values.alertmanager.ingress.pathType | default "ImplementationSpecific" }} -{{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} -{{- $servicePort := .Values.alertmanager.ingress.servicePort | default .Values.alertmanager.service.port -}} -{{- $routePrefix := list .Values.alertmanager.alertmanagerSpec.routePrefix }} -{{- $paths := .Values.alertmanager.ingress.paths | default $routePrefix -}} -{{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} -{{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} -apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} -kind: Ingress -metadata: - name: {{ $serviceName }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- if .Values.alertmanager.ingress.annotations }} - annotations: -{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{- if .Values.alertmanager.ingress.labels }} -{{ toYaml .Values.alertmanager.ingress.labels | indent 4 }} -{{- end }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if $apiIsStable }} - {{- if .Values.alertmanager.ingress.ingressClassName }} - ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }} - {{- end }} - {{- end }} - rules: - {{- if .Values.alertmanager.ingress.hosts }} - {{- range $host := .Values.alertmanager.ingress.hosts }} - - host: {{ tpl $host $ }} - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - {{- if and $pathType $ingressSupportsPathType }} - pathType: {{ $pathType }} - {{- end }} - backend: - {{- if $apiIsStable }} - service: - name: {{ $serviceName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end -}} - {{- end -}} - {{- else }} - - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - {{- if and $pathType $ingressSupportsPathType }} - pathType: {{ $pathType }} - {{- end }} - backend: - {{- if $apiIsStable }} - service: - name: {{ $serviceName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end -}} - {{- end -}} - {{- if .Values.alertmanager.ingress.tls }} - tls: -{{ tpl (toYaml .Values.alertmanager.ingress.tls | indent 4) . }} - {{- end -}} -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml deleted file mode 100644 index a8d7feaf..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.podDisruptionBudget.enabled }} -apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} -kind: PodDisruptionBudget -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if .Values.alertmanager.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.alertmanager.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.alertmanager.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - app.kubernetes.io/name: alertmanager - alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml deleted file mode 100644 index b959bf00..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml deleted file mode 100644 index d027f8e5..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager -subjects: - - kind: ServiceAccount - name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml deleted file mode 100644 index 138f1180..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Allow adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Allow adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml deleted file mode 100644 index 848d085f..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.alertmanager.enabled }} -{{/* This file is applied when the operation is helm install and the target secret does not exist. */}} -{{- $secretName := (printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .)) }} -{{- if (not (lookup "v1" "Secret" (include "project-prometheus-stack.namespace" .) $secretName)) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ $secretName }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": pre-install, pre-upgrade - "helm.sh/hook-weight": "3" - "helm.sh/resource-policy": keep -{{- if .Values.alertmanager.secret.annotations }} -{{ toYaml .Values.alertmanager.secret.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -data: -{{- if .Values.alertmanager.tplConfig }} -{{- if eq (typeOf .Values.alertmanager.config) "string" }} - alertmanager.yaml: {{ tpl (.Values.alertmanager.config) . | b64enc | quote }} -{{- else }} - alertmanager.yaml: {{ tpl (toYaml .Values.alertmanager.config) . | b64enc | quote }} -{{- end }} -{{- else }} - alertmanager.yaml: {{ toYaml .Values.alertmanager.config | b64enc | quote }} -{{- end}} -{{- range $key, $val := .Values.alertmanager.templateFiles }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end }} -{{- end }}{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml deleted file mode 100644 index 3fb5cb3c..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml +++ /dev/null @@ -1,53 +0,0 @@ -{{- if .Values.alertmanager.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager - self-monitor: {{ .Values.alertmanager.serviceMonitor.selfMonitor | quote }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.alertmanager.service.labels }} -{{ toYaml .Values.alertmanager.service.labels | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.service.annotations }} - annotations: -{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.alertmanager.service.clusterIP }} - clusterIP: {{ .Values.alertmanager.service.clusterIP }} -{{- end }} -{{- if .Values.alertmanager.service.externalIPs }} - externalIPs: -{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} -{{- if ne .Values.alertmanager.service.type "ClusterIP" }} - externalTrafficPolicy: {{ .Values.alertmanager.service.externalTrafficPolicy }} -{{- end }} - ports: - - name: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if eq .Values.alertmanager.service.type "NodePort" }} - nodePort: {{ .Values.alertmanager.service.nodePort }} - {{- end }} - port: {{ .Values.alertmanager.service.port }} - targetPort: {{ .Values.alertmanager.service.targetPort }} - protocol: TCP -{{- if .Values.alertmanager.service.additionalPorts }} -{{ toYaml .Values.alertmanager.service.additionalPorts | indent 2 }} -{{- end }} - selector: - app.kubernetes.io/name: alertmanager - alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} - type: "{{ .Values.alertmanager.service.type }}" -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml deleted file mode 100644 index 00b4b177..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager - app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-alertmanager - app.kubernetes.io/component: alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.alertmanager.serviceAccount.annotations }} - annotations: -{{ toYaml .Values.alertmanager.serviceAccount.annotations | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2}} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml deleted file mode 100644 index 1cc9c6f7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app: {{ template "project-prometheus-stack.name" . }}-alertmanager - release: {{ $.Release.Name | quote }} - self-monitor: "true" - namespaceSelector: - matchNames: - - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} - endpoints: - - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if .Values.alertmanager.serviceMonitor.interval }} - interval: {{ .Values.alertmanager.serviceMonitor.interval }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.proxyUrl }} - proxyUrl: {{ .Values.alertmanager.serviceMonitor.proxyUrl}} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.scheme }} - scheme: {{ .Values.alertmanager.serviceMonitor.scheme }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.bearerTokenFile }} - bearerTokenFile: {{ .Values.alertmanager.serviceMonitor.bearerTokenFile }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.tlsConfig }} - tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" - metricRelabelings: - {{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName }} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} -{{- if .Values.alertmanager.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml deleted file mode 100644 index 535bc94e..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml +++ /dev/null @@ -1,179 +0,0 @@ -{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-admin - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} - helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - helm.cattle.io/project-helm-chart-role-aggregate-from: admin - {{- end }} -rules: -- apiGroups: - - "" - resources: - - services/proxy - resourceNames: - - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} -{{- if .Values.grafana.enabled }} - - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" -{{- end }} - verbs: - - 'get' - - 'create' - - 'update' - - 'patch' - - 'delete' -- apiGroups: - - "" - resources: - - endpoints - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} -{{- if .Values.grafana.enabled }} - - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} -{{- end }} - verbs: - - list -{{- if .Values.alertmanager.enabled }} -- apiGroups: - - "" - resources: - - "secrets" - resourceNames: - - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} - verbs: - - get - - list - - watch - - update - - patch - - delete -{{- end }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-edit - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} - helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - helm.cattle.io/project-helm-chart-role-aggregate-from: edit - {{- end }} -rules: -- apiGroups: - - "" - resources: - - services/proxy - resourceNames: - - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} -{{- if .Values.grafana.enabled }} - - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" -{{- end }} - verbs: - - 'get' - - 'create' - - 'update' - - 'patch' - - 'delete' -- apiGroups: - - "" - resources: - - endpoints - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} -{{- if .Values.grafana.enabled }} - - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} -{{- end }} - verbs: - - list -{{- if .Values.alertmanager.enabled }} -- apiGroups: - - "" - resources: - - "secrets" - resourceNames: - - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} - verbs: - - get - - list - - watch - - update - - patch -{{- end }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-view - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} - helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} - {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} - helm.cattle.io/project-helm-chart-role-aggregate-from: view - {{- end }} -rules: -- apiGroups: - - "" - resources: - - services/proxy - resourceNames: - - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} -{{- if .Values.grafana.enabled }} - - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" -{{- end }} - verbs: - - 'get' -- apiGroups: - - "" - resources: - - endpoints - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} -{{- if .Values.grafana.enabled }} - - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} -{{- end }} - verbs: - - list -{{- if .Values.alertmanager.enabled }} -- apiGroups: - - "" - resources: - - "secrets" - resourceNames: - - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} - verbs: - - get - - list - - watch -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml deleted file mode 100644 index 16acc46d..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- $rancherDashboards := dict }} -{{- range $glob := tuple "files/rancher/workloads/*" "files/rancher/pods/*" -}} -{{- range $dashboard, $_ := ($.Files.Glob $glob) }} -{{- $dashboardMap := ($.Files.Get $dashboard | fromJson) }} -{{- $_ := set $rancherDashboards (get $dashboardMap "uid") (get $dashboardMap "title") -}} -{{- end }} -{{- end }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-dashboard-values - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} - helm.cattle.io/dashboard-values-configmap: {{ .Release.Name }} -data: - values.json: |- - { -{{- if not .Values.prometheus.enabled }} - "prometheusURL": "", -{{- else if .Values.prometheus.prometheusSpec.externalUrl }} - "prometheusURL": "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}", -{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} - "prometheusURL": "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}", -{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} - "prometheusURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy", -{{- else }} - "prometheusURL": "http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}", -{{- end }} - -{{- if not .Values.grafana.enabled }} - "grafanaURL": "", -{{- else if and .Values.grafana.ingress.enabled .Values.grafana.ingress.hosts }} - "grafanaURL": "http://{{ tpl (index .Values.grafana.ingress.hosts 0) . }}{{ .Values.grafana.grafanaSpec.ingress.path }}", -{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} - "grafanaURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}/proxy", -{{- else }} - "grafanaURL": "http://{{ include "call-nested" (list . "grafana" "grafana.fullname") }}.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.grafana.service.port }}", -{{- end }} - -{{- if not .Values.alertmanager.enabled }} - "alertmanagerURL": "", -{{- else if .Values.alertmanager.alertmanagerSpec.externalUrl }} - "alertmanagerURL": "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}", -{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} - "alertmanagerURL": "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}", -{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} - "alertmanagerURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy", -{{- else }} - "alertmanagerURL": "http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }}", -{{- end }} - -{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} - "rancherDashboards": {{- $rancherDashboards | toPrettyJson | nindent 8 }} -{{- else }} - "rancherDashboards": [] -{{- end }} - } \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml deleted file mode 100644 index 6214dc5c..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: rancher-default-dashboards-pods - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: -{{ (.Files.Glob "files/rancher/pods/*").AsConfig | indent 2 }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml deleted file mode 100644 index 7934818f..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: rancher-default-dashboards-workloads - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: -{{ (.Files.Glob "files/rancher/workloads/*").AsConfig | indent 2 }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml deleted file mode 100644 index c2763573..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if or (and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled) .Values.grafana.forceDeployDashboards }} -{{- $files := .Files.Glob "dashboards-1.14/*.json" }} -{{- if $files }} -apiVersion: v1 -kind: ConfigMapList -items: -{{- range $path, $fileContents := $files }} -{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} -- apiVersion: v1 - kind: ConfigMap - metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) $dashboardName | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 6 }} - data: - {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} -{{- end }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml deleted file mode 100644 index 7f2c5b55..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if or (and .Values.grafana.enabled .Values.grafana.sidecar.datasources.enabled) .Values.grafana.forceDeployDatasources }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-grafana-datasource - namespace: {{ include "project-prometheus-stack.namespace" . }} -{{- if .Values.grafana.sidecar.datasources.annotations }} - annotations: -{{ toYaml .Values.grafana.sidecar.datasources.annotations | indent 4 }} -{{- end }} - labels: - {{ $.Values.grafana.sidecar.datasources.label }}: "1" - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - datasource.yaml: |- - apiVersion: 1 -{{- if .Values.grafana.deleteDatasources }} - deleteDatasources: -{{ tpl (toYaml .Values.grafana.deleteDatasources | indent 6) . }} -{{- end }} - datasources: -{{- $scrapeInterval := .Values.grafana.sidecar.datasources.defaultDatasourceScrapeInterval | default .Values.prometheus.prometheusSpec.scrapeInterval | default "30s" }} -{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }} - - name: Prometheus - type: prometheus - uid: {{ .Values.grafana.sidecar.datasources.uid }} - {{- if .Values.grafana.sidecar.datasources.url }} - url: {{ .Values.grafana.sidecar.datasources.url }} - {{- else }} - url: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}/{{ trimPrefix "/" .Values.prometheus.prometheusSpec.routePrefix }} - {{- end }} - access: proxy - isDefault: true - jsonData: - timeInterval: {{ $scrapeInterval }} -{{- if .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations }} - exemplarTraceIdDestinations: - - datasourceUid: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.datasourceUid }} - name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} -{{- end }} -{{- end }} -{{- if .Values.grafana.additionalDataSources }} -{{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml deleted file mode 100644 index 8f8e6ffe..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml +++ /dev/null @@ -1,616 +0,0 @@ -{{- /* -Generated from 'alertmanager-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "alertmanager-overview" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - alertmanager-overview.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 1, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "30s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "current set of alerts stored in the Alertmanager", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(alertmanager_alerts{namespace=~\"$namespace\",service=~\"$service\"}) by (namespace,service,instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Alerts", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "rate of successful and invalid alerts received by the Alertmanager", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(alertmanager_alerts_received_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Received", - "refId": "A" - }, - { - "expr": "sum(rate(alertmanager_alerts_invalid_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Invalid", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Alerts receive rate", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Alerts", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "rate of successful and invalid notifications sent by the Alertmanager", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": "integration", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(alertmanager_notifications_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Total", - "refId": "A" - }, - { - "expr": "sum(rate(alertmanager_notifications_failed_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Failed", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "$integration: Notifications Send Rate", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "latency of notifications sent by the Alertmanager", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": "integration", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} 99th Percentile", - "refId": "A" - }, - { - "expr": "histogram_quantile(0.50,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Median", - "refId": "B" - }, - { - "expr": "sum(rate(alertmanager_notification_latency_seconds_sum{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n/\nsum(rate(alertmanager_notification_latency_seconds_count{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Average", - "refId": "C" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "$integration: Notification Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Notifications", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "alertmanager-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(alertmanager_alerts, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "service", - "multi": false, - "name": "service", - "options": [ - - ], - "query": "label_values(alertmanager_alerts, service)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "all", - "value": "$__all" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": true, - "label": null, - "multi": false, - "name": "integration", - "options": [ - - ], - "query": "label_values(alertmanager_notifications_total{integration=~\".*\"}, integration)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Alertmanager / Overview", - "uid": "alertmanager-overview", - "version": 0 - } -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml deleted file mode 100644 index 70764069..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml +++ /dev/null @@ -1,1646 +0,0 @@ -{{- /* -Generated from 'cluster-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "cluster-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - cluster-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "Value #G", - "value": "Value #G" - }, - { - "text": "Value #H", - "value": "Value #H" - }, - { - "text": "namespace", - "value": "namespace" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "90%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Current Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?orgId=1&refresh=30s&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 6, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 9, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth History", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 30 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 13, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 15, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 50 - }, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 59 - }, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Networking / Project", - "uid": "ff635a025bcfea7bc3dd4f508990a3e9", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml deleted file mode 100644 index ef663df7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml +++ /dev/null @@ -1,635 +0,0 @@ -{{- /* -Generated from 'grafana-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack-grafana.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "grafana-overview" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - grafana-overview.json: |- - { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [ - - ], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 3085, - "iteration": 1631554945276, - "links": [ - - ], - "panels": [ - { - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "mappings": [ - - ], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - - ] - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 0, - "y": 0 - }, - "id": 6, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "text": { - - }, - "textMode": "auto" - }, - "pluginVersion": "8.1.3", - "targets": [ - { - "expr": "grafana_alerting_result_total{job=~\"$job\", instance=~\"$instance\", state=\"alerting\"}", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Firing Alerts", - "type": "stat" - }, - { - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "mappings": [ - - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - - ] - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 6, - "y": 0 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "text": { - - }, - "textMode": "auto" - }, - "pluginVersion": "8.1.3", - "targets": [ - { - "expr": "sum(grafana_stat_totals_dashboard{job=~\"$job\", instance=~\"$instance\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Dashboards", - "type": "stat" - }, - { - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "custom": { - "align": null, - "displayMode": "auto" - }, - "mappings": [ - - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 10, - "options": { - "showHeader": true - }, - "pluginVersion": "8.1.3", - "targets": [ - { - "expr": "grafana_build_info{job=~\"$job\", instance=~\"$instance\"}", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Build Info", - "transformations": [ - { - "id": "labelsToFields", - "options": { - - } - }, - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "branch": true, - "container": true, - "goversion": true, - "namespace": true, - "pod": true, - "revision": true - }, - "indexByName": { - "Time": 7, - "Value": 11, - "branch": 4, - "container": 8, - "edition": 2, - "goversion": 6, - "instance": 1, - "job": 0, - "namespace": 9, - "pod": 10, - "revision": 5, - "version": 3 - }, - "renameByName": { - - } - } - } - ], - "type": "table" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "links": [ - - ] - }, - "overrides": [ - - ] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 5 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.1.3", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (status_code) (irate(grafana_http_request_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[1m])) ", - "interval": "", - "legendFormat": "{{`{{`}}status_code{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeRegions": [ - - ], - "timeShift": null, - "title": "RPS", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "$$hashKey": "object:157", - "format": "reqps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "$$hashKey": "object:158", - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fieldConfig": { - "defaults": { - "links": [ - - ] - }, - "overrides": [ - - ] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 5 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "8.1.3", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", - "interval": "", - "legendFormat": "99th Percentile", - "refId": "A" - }, - { - "exemplar": true, - "expr": "histogram_quantile(0.50, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", - "interval": "", - "legendFormat": "50th Percentile", - "refId": "B" - }, - { - "exemplar": true, - "expr": "sum(irate(grafana_http_request_duration_seconds_sum{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) * 1 / sum(irate(grafana_http_request_duration_seconds_count{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval]))", - "interval": "", - "legendFormat": "Average", - "refId": "C" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeRegions": [ - - ], - "timeShift": null, - "title": "Request Latency", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "$$hashKey": "object:210", - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "$$hashKey": "object:211", - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "schemaVersion": 30, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "description": null, - "error": null, - "hide": 0, - "includeAll": false, - "label": "Data Source", - "multi": false, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "allValue": ".*", - "current": { - "selected": false, - "text": [ - "default/grafana" - ], - "value": [ - "default/grafana" - ] - }, - "datasource": "$datasource", - "definition": "label_values(grafana_build_info, job)", - "description": null, - "error": null, - "hide": 0, - "includeAll": true, - "label": null, - "multi": true, - "name": "job", - "options": [ - - ], - "query": { - "query": "label_values(grafana_build_info, job)", - "refId": "Billing Admin-job-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".*", - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "definition": "label_values(grafana_build_info, instance)", - "description": null, - "error": null, - "hide": 0, - "includeAll": true, - "label": null, - "multi": true, - "name": "instance", - "options": [ - - ], - "query": { - "query": "label_values(grafana_build_info, instance)", - "refId": "Billing Admin-instance-Variable-Query" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Grafana Overview", - "uid": "6be0s85Mk", - "version": 2 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml deleted file mode 100644 index c87b4188..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml +++ /dev/null @@ -1,2770 +0,0 @@ -{{- /* -Generated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "100px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 1, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation (from requests)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation (from limits)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation (from requests)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation (from limits)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Headlines", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 6, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_cache{namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(container_memory_swap{namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 9, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Network Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 14, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 15, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets Dropped", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": -1, - "fill": 10, - "id": 16, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "IOPS(Reads+Writes)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 17, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "ThroughPut(Read+Write)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 18, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "sort": { - "col": 4, - "desc": true - }, - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "IOPS(Reads)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Reads + Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Throughput(Read)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Read + Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Storage IO", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO - Distribution", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Namespace (Pods)", - "uid": "85a562078cdf77779eaa1add43ccec1e", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml deleted file mode 100644 index e2e8d2aa..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml +++ /dev/null @@ -1,963 +0,0 @@ -{{- /* -Generated from 'k8s-resources-node' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-node" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-node.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_rss{node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_cache{node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_swap{node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": true, - "name": "node", - "options": [ - - ], - "query": "label_values(kube_pod_info, node)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Node (Pods)", - "uid": "200ac8fdbfbb74b39aff88118e4d1c2c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml deleted file mode 100644 index c8d57cfd..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml +++ /dev/null @@ -1,2442 +0,0 @@ -{{- /* -Generated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-pod" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-pod.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "requests", - "color": "#F2495C", - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "limits", - "color": "#FF9830", - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container) /sum(increase(container_cpu_cfs_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 0.25, - "yaxis": "left" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Throttling", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Throttling", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (WSS)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage (WSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_cache{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(container_memory_swap{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets Dropped", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": -1, - "fill": 10, - "id": 12, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Reads", - "legendLink": null, - "step": 10 - }, - { - "expr": "ceil(sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Writes", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "IOPS", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Reads", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Writes", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "ThroughPut", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO - Distribution(Pod - Read & Writes)", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": -1, - "fill": 10, - "id": 14, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "ceil(sum by(container) (rate(container_fs_reads_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "IOPS(Reads+Writes)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 15, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by(container) (rate(container_fs_reads_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "ThroughPut(Read+Write)", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO - Distribution(Containers)", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 16, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "sort": { - "col": 4, - "desc": true - }, - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "IOPS(Reads)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Reads + Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Throughput(Read)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Read + Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum by(container) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum by(container) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Storage IO", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO - Distribution", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Pod", - "uid": "6581e46e4e5c7ba40a07646395ef7b23", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml deleted file mode 100644 index 56d9c77f..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml +++ /dev/null @@ -1,2480 +0,0 @@ -{{- /* -Generated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-cluster" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-cluster.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to workloads", - "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(kube_pod_owner{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to workloads", - "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(kube_pod_owner{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Requests by Namespace", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Requests", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 11, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Network Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Namespace: Received", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 15, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Namespace: Transmitted", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Container Bandwidth by Namespace", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 17, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 18, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 19, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets Dropped", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": -1, - "fill": 10, - "id": 20, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "ceil(sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "IOPS(Reads+Writes)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 21, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "ThroughPut(Read+Write)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 22, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "sort": { - "col": 4, - "desc": true - }, - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "IOPS(Reads)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "IOPS(Reads + Writes)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": -1, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Throughput(Read)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Throughput(Read + Write)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum by(namespace) (rate(container_fs_writes_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum by(namespace) (rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Storage IO", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage IO - Distribution", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Project", - "uid": "efa86fd1d0c121a26444b636a3f509a8", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml deleted file mode 100644 index 4e72d70a..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml +++ /dev/null @@ -1,1997 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workload" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workload.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Network Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Pod: Received", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Pod: Transmitted", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Container Bandwidth by Pod", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets Dropped", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\"}, workload)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\"}, workload_type)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Workload", - "uid": "a164a7f0339f99e89cea5cb47e9be617", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml deleted file mode 100644 index c6548c43..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml +++ /dev/null @@ -1,2162 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workloads-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workloads-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hiddenSeries": true, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$type", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Network Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Workload: Received", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Workload: Transmitted", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Container Bandwidth by Workload", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Rate of Packets Dropped", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Compute Resources / Namespace (Workloads)", - "uid": "a87fb0d919ec0ea5f6543124e16c42a5", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml deleted file mode 100644 index 0d4fdc0f..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml +++ /dev/null @@ -1,1438 +0,0 @@ -{{- /* -Generated from 'namespace-by-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-pod" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - namespace-by-pod.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "height": 9, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "height": 9, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "pod", - "value": "pod" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "100%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?orgId=1&refresh=30s&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 6, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 20 - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 20 - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 29 - }, - "id": 9, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 30 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 30 - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 30 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 40 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total, namespace)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Networking / Namespace (Pods)", - "uid": "8b7a8b326d7a6f1f04244066368c67af", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml deleted file mode 100644 index aa2a3573..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml +++ /dev/null @@ -1,1710 +0,0 @@ -{{- /* -Generated from 'namespace-by-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-workload" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - namespace-by-workload.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "Value #G", - "value": "Value #G" - }, - { - "text": "Value #H", - "value": "Value #H" - }, - { - "text": "workload", - "value": "workload" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "90%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Current Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?orgId=1&refresh=30s&var-namespace=$namespace&var-type=$type&var-workload=$__cell", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 6, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 20 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 20 - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 29 - }, - "id": 9, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth HIstory", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 38 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 38 - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 39 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 40 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 15, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 17, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total, namespace)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total, namespace)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Networking / Namespace (Workload)", - "uid": "bbb2a765a623ae38130206c7d94a160f", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml deleted file mode 100644 index cd599c62..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml +++ /dev/null @@ -1,561 +0,0 @@ -{{- /* -Generated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "persistentvolumesusage" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - persistentvolumesusage.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used Space", - "refId": "A" - }, - { - "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Free Space", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume Space Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": "1m", - "legend": { - "alignAsTable": true, - "rightSide": true - }, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max without(instance,node) (\n(\n topk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n topk(1, kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n/\ntopk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume Space Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "interval": "1m", - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used inodes", - "refId": "A" - }, - { - "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": " Free inodes", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume inodes Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": "1m", - "legend": { - "alignAsTable": true, - "rightSide": true - }, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max without(instance,node) (\ntopk(1, kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n/\ntopk(1, kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume inodes Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "PersistentVolumeClaim", - "multi": false, - "name": "volume", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\"}, persistentvolumeclaim)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-7d", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Persistent Volumes", - "uid": "919b92a8e8041bd567af9edab12c840c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml deleted file mode 100644 index 48b0db9b..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml +++ /dev/null @@ -1,1202 +0,0 @@ -{{- /* -Generated from 'pod-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "pod-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - pod-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "height": 9, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace: $pod", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "height": 9, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace: $pod", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 20 - }, - "id": 8, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 21 - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 21 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 32 - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 32 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total, namespace)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Networking / Pod", - "uid": "7a18067ce943a40ae25454675c19ff5c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml deleted file mode 100644 index 2f0a6bfa..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ /dev/null @@ -1,1674 +0,0 @@ -{{- /* -Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - prometheus-remote-write.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "60s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(\n prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} \n- \n ignoring(remote_name, url) group_right(instance) (prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} != 0)\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Highest Timestamp In vs. Highest Timestamp Sent", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "clamp_min(\n rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) \n- \n ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n, 0)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate[5m]", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Timestamps", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(\n prometheus_remote_storage_samples_in_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n- \n ignoring(remote_name, url) group_right(instance) (rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n- \n (rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate, in vs. succeeded or dropped [5m]", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Samples", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 6, - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_max{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Max Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_min{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Min Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_desired{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Desired Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Shards", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shard_capacity{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Shard Capacity", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_pending_samples{cluster=~\"$cluster\", instance=~\"$instance\"} or prometheus_remote_storage_samples_pending{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Pending Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Shard Details", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_wal_segment_current{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "TSDB Current Segment", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_wal_watcher_current_segment{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}consumer{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Remote Write Current Segment", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Segments", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Dropped Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_failed_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Failed Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 15, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_retried_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_retried_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Retried Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Enqueue Retries", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Misc. Rates", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "prometheus-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "value": { - "selected": true, - "text": "All", - "value": "$__all" - } - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster.global.enabled }}0{{ else }}2{{ end }}, - "includeAll": true, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_container_info{image=~\".*prometheus.*\"}, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "value": { - "selected": true, - "text": "All", - "value": "$__all" - } - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(prometheus_build_info{cluster=~\"$cluster\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "url", - "options": [ - - ], - "query": "label_values(prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}, url)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Prometheus / Remote Write", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml deleted file mode 100644 index c94ce252..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml +++ /dev/null @@ -1,1235 +0,0 @@ -{{- /* -Generated from 'prometheus' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - prometheus.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "60s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Count", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Uptime", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Instance", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "instance", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Job", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "job", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Version", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "version", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count by (job, instance, version) (prometheus_build_info{job=~\"$job\", instance=~\"$instance\"})", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "max by (job, instance) (time() - process_start_time_seconds{job=~\"$job\", instance=~\"$instance\"})", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Prometheus Stats", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Prometheus Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(prometheus_target_sync_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m])) by (scrape_job) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}scrape_job{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Target Sync", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(prometheus_sd_discovered_targets{job=~\"$job\",instance=~\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Targets", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Targets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Discovery", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_target_interval_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{job=~\"$job\",instance=~\"$instance\"}[5m]) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}interval{{`}}`}} configured", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Scrape Interval Duration", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_body_size_limit_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "exceeded body size limit: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_sample_limit_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "exceeded sample limit: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "duplicate timestamp: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_bounds_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "out of bounds: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_order_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "out of order: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Scrape failures", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_tsdb_head_samples_appended_total{job=~\"$job\",instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Appended Samples", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Retrieval", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_head_series{job=~\"$job\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head series", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Head Series", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_head_chunks{job=~\"$job\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head chunks", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Head Chunks", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_engine_query_duration_seconds_count{job=~\"$job\",instance=~\"$instance\",slice=\"inner_eval\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Query Rate", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "max by (slice) (prometheus_engine_query_duration_seconds{quantile=\"0.9\",job=~\"$job\",instance=~\"$instance\"}) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}slice{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Stage Duration", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Query", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "prometheus-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": ".+", - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": "job", - "multi": true, - "name": "job", - "options": [ - - ], - "query": "label_values(prometheus_build_info{job=\"prometheus-k8s\",namespace=\"monitoring\"}, job)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": "instance", - "multi": true, - "name": "instance", - "options": [ - - ], - "query": "label_values(prometheus_build_info{job=~\"$job\"}, instance)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Prometheus / Overview", - "uid": "", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml deleted file mode 100644 index 0dfd208c..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml +++ /dev/null @@ -1,1412 +0,0 @@ -{{- /* -Generated from 'workload-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "workload-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} - app: {{ template "project-prometheus-stack.name" $ }}-grafana -{{ include "project-prometheus-stack.labels" $ | indent 4 }} -data: - workload-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 6, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 8, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth HIstory", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 12 - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 12 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 22 - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 22 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 22 - }, - "id": 14, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 15, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": "Data Source", - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total, namespace)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", - "title": "Kubernetes / Networking / Workload", - "uid": "728bf77cc1166d2f3133bf25846876cc", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl deleted file mode 100644 index d82cc2d3..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl +++ /dev/null @@ -1,8 +0,0 @@ -{{- define "rules.names" }} -rules: - - "alertmanager.rules" - - "general.rules" - - "kubernetes-storage" - - "prometheus" - - "kubernetes-apps" -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml deleted file mode 100644 index b5d97aec..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -rules: -# This permission are not in the kube-prometheus repo -# they're grabbed from https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml -- apiGroups: [""] - resources: - - nodes - - nodes/metrics - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] -- apiGroups: - - "networking.k8s.io" - resources: - - ingresses - verbs: ["get", "list", "watch"] -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml deleted file mode 100644 index 18249a0c..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus -subjects: - - kind: ServiceAccount - name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- end }} - diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml deleted file mode 100644 index 61664d01..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.prometheus.extraSecret.data -}} -{{- $secretName := printf "prometheus-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ default $secretName .Values.prometheus.extraSecret.name }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- if .Values.prometheus.extraSecret.annotations }} - annotations: -{{ toYaml .Values.prometheus.extraSecret.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus - app.kubernetes.io/component: prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -data: -{{- range $key, $val := .Values.prometheus.extraSecret.data }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml deleted file mode 100644 index 29d4ba20..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.federate.enabled }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-federate - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} -data: - federate-scrape-config.yaml: {{ tpl (.Files.Get "files/federate/federate-scrape-config.yaml" ) $ | b64enc | quote }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml deleted file mode 100644 index 387e2b5d..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml +++ /dev/null @@ -1,77 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.ingress.enabled -}} - {{- $pathType := .Values.prometheus.ingress.pathType | default "ImplementationSpecific" -}} - {{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" -}} - {{- $servicePort := .Values.prometheus.ingress.servicePort | default .Values.prometheus.service.port -}} - {{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix -}} - {{- $paths := .Values.prometheus.ingress.paths | default $routePrefix -}} - {{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} - {{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} -apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} -kind: Ingress -metadata: -{{- if .Values.prometheus.ingress.annotations }} - annotations: -{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }} -{{- end }} - name: {{ $serviceName }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.ingress.labels }} -{{ toYaml .Values.prometheus.ingress.labels | indent 4 }} -{{- end }} -spec: - {{- if $apiIsStable }} - {{- if .Values.prometheus.ingress.ingressClassName }} - ingressClassName: {{ .Values.prometheus.ingress.ingressClassName }} - {{- end }} - {{- end }} - rules: - {{- if .Values.prometheus.ingress.hosts }} - {{- range $host := .Values.prometheus.ingress.hosts }} - - host: {{ tpl $host $ }} - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - {{- if and $pathType $ingressSupportsPathType }} - pathType: {{ $pathType }} - {{- end }} - backend: - {{- if $apiIsStable }} - service: - name: {{ $serviceName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end -}} - {{- end -}} - {{- else }} - - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - {{- if and $pathType $ingressSupportsPathType }} - pathType: {{ $pathType }} - {{- end }} - backend: - {{- if $apiIsStable }} - service: - name: {{ $serviceName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end -}} - {{- end -}} - {{- if .Values.prometheus.ingress.tls }} - tls: -{{ tpl (toYaml .Values.prometheus.ingress.tls | indent 4) . }} - {{- end -}} -{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml deleted file mode 100644 index c28edc07..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml +++ /dev/null @@ -1,68 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: prometheus-nginx-proxy-config - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.annotations }} - annotations: -{{ toYaml .Values.prometheus.annotations | indent 4 }} -{{- end }} -data: - nginx.conf: |- - worker_processes auto; - error_log /dev/stdout warn; - pid /var/cache/nginx/nginx.pid; - - events { - worker_connections 1024; - } - - http { - include /etc/nginx/mime.types; - log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; - - proxy_connect_timeout 10; - proxy_read_timeout 180; - proxy_send_timeout 5; - proxy_buffering off; - proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; - - server { - listen 8081; - access_log off; - - gzip on; - gzip_min_length 1k; - gzip_comp_level 2; - gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; - gzip_vary on; - gzip_disable "MSIE [1-6]\."; - - proxy_set_header Host $host; - - location / { - proxy_cache my_zone; - proxy_cache_valid 200 302 1d; - proxy_cache_valid 301 30d; - proxy_cache_valid any 5m; - proxy_cache_bypass $http_cache_control; - add_header X-Proxy-Cache $upstream_cache_status; - add_header Cache-Control "public"; - - proxy_pass http://localhost:9090/; - - sub_filter_once off; - sub_filter 'var PATH_PREFIX = "";' 'var PATH_PREFIX = ".";'; - - if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { - expires 90d; - } - - rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; - - } - } - } diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml deleted file mode 100644 index 24e4c6a7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.podDisruptionBudget.enabled }} -apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} -kind: PodDisruptionBudget -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if .Values.prometheus.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.prometheus.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.prometheus.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.prometheus.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - app.kubernetes.io/name: prometheus - prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml deleted file mode 100644 index 2e4cfe52..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml +++ /dev/null @@ -1,319 +0,0 @@ -{{- if .Values.prometheus.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: Prometheus -metadata: - name: {{ template "project-prometheus-stack.prometheus.crname" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.annotations }} - annotations: -{{ toYaml .Values.prometheus.annotations | indent 4 }} -{{- end }} -spec: - alerting: - alertmanagers: -{{- if .Values.prometheus.prometheusSpec.alertingEndpoints }} -{{ toYaml .Values.prometheus.prometheusSpec.alertingEndpoints | indent 6 }} -{{- else if .Values.alertmanager.enabled }} - - namespace: {{ template "project-prometheus-stack.namespace" . }} - name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} - pathPrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" - {{- end }} - apiVersion: {{ .Values.alertmanager.apiVersion }} -{{- else }} - [] -{{- end }} -{{- if .Values.prometheus.prometheusSpec.apiserverConfig }} - apiserverConfig: -{{ toYaml .Values.prometheus.prometheusSpec.apiserverConfig | indent 4}} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.image }} - {{- if and .Values.prometheus.prometheusSpec.image.tag .Values.prometheus.prometheusSpec.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" - {{- else if .Values.prometheus.prometheusSpec.image.sha }} - image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" - {{- else if .Values.prometheus.prometheusSpec.image.tag }} - image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}" - {{- else }} - image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}" - {{- end }} - version: {{ .Values.prometheus.prometheusSpec.image.tag }} - {{- if .Values.prometheus.prometheusSpec.image.sha }} - sha: {{ .Values.prometheus.prometheusSpec.image.sha }} - {{- end }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.externalLabels }} - externalLabels: -{{ tpl (toYaml .Values.prometheus.prometheusSpec.externalLabels | indent 4) . }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.prometheusExternalLabelNameClear }} - prometheusExternalLabelName: "" -{{- else if .Values.prometheus.prometheusSpec.prometheusExternalLabelName }} - prometheusExternalLabelName: "{{ .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}" -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} - enableRemoteWriteReceiver: {{ .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.externalUrl }} - externalUrl: "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}" -{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} - externalUrl: "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}" -{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} - externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy" -{{- else }} - externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }} -{{- end }} - nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.nodeSelector }} -{{ toYaml .Values.prometheus.prometheusSpec.nodeSelector | indent 4 }} -{{- end }} - paused: {{ .Values.prometheus.prometheusSpec.paused }} - replicas: {{ .Values.prometheus.prometheusSpec.replicas }} - shards: {{ .Values.prometheus.prometheusSpec.shards }} - logLevel: {{ .Values.prometheus.prometheusSpec.logLevel }} - logFormat: {{ .Values.prometheus.prometheusSpec.logFormat }} - listenLocal: {{ .Values.prometheus.prometheusSpec.listenLocal }} - enableAdminAPI: {{ .Values.prometheus.prometheusSpec.enableAdminAPI }} -{{- if .Values.prometheus.prometheusSpec.web }} - web: -{{ toYaml .Values.prometheus.prometheusSpec.web | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.exemplars }} - exemplars: - {{ toYaml .Values.prometheus.prometheusSpec.exemplars | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enableFeatures }} - enableFeatures: -{{- range $enableFeatures := .Values.prometheus.prometheusSpec.enableFeatures }} - - {{ tpl $enableFeatures $ }} -{{- end }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.scrapeInterval }} - scrapeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.scrapeTimeout }} - scrapeTimeout: {{ .Values.prometheus.prometheusSpec.scrapeTimeout }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.evaluationInterval }} - evaluationInterval: {{ .Values.prometheus.prometheusSpec.evaluationInterval }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.resources }} - resources: -{{ toYaml .Values.prometheus.prometheusSpec.resources | indent 4 }} -{{- end }} - retention: {{ .Values.prometheus.prometheusSpec.retention | quote }} -{{- if .Values.prometheus.prometheusSpec.retentionSize }} - retentionSize: {{ .Values.prometheus.prometheusSpec.retentionSize | quote }} -{{- end }} -{{- if eq .Values.prometheus.prometheusSpec.walCompression false }} - walCompression: false -{{ else }} - walCompression: true -{{- end }} -{{- if .Values.prometheus.prometheusSpec.routePrefix }} - routePrefix: {{ .Values.prometheus.prometheusSpec.routePrefix | quote }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.secrets }} - secrets: -{{ toYaml .Values.prometheus.prometheusSpec.secrets | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.configMaps }} - configMaps: -{{ toYaml .Values.prometheus.prometheusSpec.configMaps | indent 4 }} -{{- end }} - serviceAccountName: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} -{{- if .Values.prometheus.prometheusSpec.serviceMonitorSelector }} - serviceMonitorSelector: -{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues }} - serviceMonitorSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - serviceMonitorSelector: {} -{{- end }} - serviceMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.podMonitorSelector }} - podMonitorSelector: -{{ toYaml .Values.prometheus.prometheusSpec.podMonitorSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues }} - podMonitorSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - podMonitorSelector: {} -{{- end }} - podMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.probeSelector }} - probeSelector: -{{ toYaml .Values.prometheus.prometheusSpec.probeSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.probeSelectorNilUsesHelmValues }} - probeSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - probeSelector: {} -{{- end }} -{{- if (or .Values.prometheus.prometheusSpec.remoteWrite .Values.prometheus.prometheusSpec.additionalRemoteWrite) }} - remoteWrite: -{{- if .Values.prometheus.prometheusSpec.remoteWrite }} -{{ tpl (toYaml .Values.prometheus.prometheusSpec.remoteWrite | indent 4) . }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalRemoteWrite }} -{{ toYaml .Values.prometheus.prometheusSpec.additionalRemoteWrite | indent 4 }} -{{- end }} -{{- end }} - probeNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.securityContext }} - securityContext: -{{ toYaml .Values.prometheus.prometheusSpec.securityContext | indent 4 }} -{{- end }} - ruleNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.ruleSelector }} - ruleSelector: -{{ toYaml .Values.prometheus.prometheusSpec.ruleSelector | indent 4}} -{{- else if .Values.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues }} - ruleSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - ruleSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.storage.enabled }} - storage: -{{ tpl (toYaml .Values.prometheus.prometheusSpec.storageSpec | indent 4) . }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.podMetadata }} - podMetadata: -{{ tpl (toYaml .Values.prometheus.prometheusSpec.podMetadata | indent 4) . }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.query }} - query: -{{ toYaml .Values.prometheus.prometheusSpec.query | indent 4}} -{{- end }} -{{- if or .Values.prometheus.prometheusSpec.podAntiAffinity .Values.prometheus.prometheusSpec.affinity }} - affinity: -{{- if .Values.prometheus.prometheusSpec.affinity }} -{{ toYaml .Values.prometheus.prometheusSpec.affinity | indent 4 }} -{{- end }} -{{- if eq .Values.prometheus.prometheusSpec.podAntiAffinity "hard" }} - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchExpressions: - - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} - - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} -{{- else if eq .Values.prometheus.prometheusSpec.podAntiAffinity "soft" }} - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchExpressions: - - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} - - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} -{{- end }} -{{- end }} - tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} -{{- if .Values.prometheus.prometheusSpec.tolerations }} -{{ toYaml .Values.prometheus.prometheusSpec.tolerations | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.topologySpreadConstraints }} - topologySpreadConstraints: -{{ toYaml .Values.prometheus.prometheusSpec.topologySpreadConstraints | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} - imagePullSecrets: -{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} -{{- end }} -{{- if .Values.federate.enabled }} - additionalScrapeConfigs: - name: {{ template "project-prometheus-stack.fullname" . }}-federate - key: federate-scrape-config.yaml -{{- end }} -{{- if .Values.prometheus.prometheusSpec.containers }} - containers: -{{ tpl .Values.prometheus.prometheusSpec.containers $ | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.initContainers }} - initContainers: -{{ toYaml .Values.prometheus.prometheusSpec.initContainers | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.priorityClassName }} - priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.disableCompaction }} - disableCompaction: {{ .Values.prometheus.prometheusSpec.disableCompaction }} -{{- end }} - portName: {{ .Values.prometheus.prometheusSpec.portName }} -{{- if .Values.prometheus.prometheusSpec.volumes }} - volumes: -{{ toYaml .Values.prometheus.prometheusSpec.volumes | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.volumeMounts }} - volumeMounts: -{{ toYaml .Values.prometheus.prometheusSpec.volumeMounts | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs }} - arbitraryFSAccessThroughSMs: -{{ toYaml .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.overrideHonorLabels }} - overrideHonorLabels: {{ .Values.prometheus.prometheusSpec.overrideHonorLabels }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} - overrideHonorTimestamps: {{ .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} -{{- end }} - ignoreNamespaceSelectors: true # always hard-coded to true for security reasons -{{- if .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} - enforcedNamespaceLabel: {{ .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} -{{- $prometheusDefaultRulesExcludedFromEnforce := (include "rules.names" .) | fromYaml }} - prometheusRulesExcludedFromEnforce: -{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} - - ruleNamespace: "{{ template "project-prometheus-stack.namespace" $ }}" - ruleName: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" -{{- end }} -{{- if .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce }} -{{ toYaml .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce | indent 4 }} -{{- end }} - excludedFromEnforcement: -{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} - - resource: prometheusrules - namespace: "{{ template "project-prometheus-stack.namespace" $ }}" - name: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" -{{- end }} -{{- if .Values.prometheus.prometheusSpec.excludedFromEnforcement }} -{{ tpl (toYaml .Values.prometheus.prometheusSpec.excludedFromEnforcement | indent 4) . }} -{{- end }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.queryLogFile }} - queryLogFile: {{ .Values.prometheus.prometheusSpec.queryLogFile }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedSampleLimit }} - enforcedSampleLimit: {{ .Values.prometheus.prometheusSpec.enforcedSampleLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedTargetLimit }} - enforcedTargetLimit: {{ .Values.prometheus.prometheusSpec.enforcedTargetLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedLabelLimit }} - enforcedLabelLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} - enforcedLabelNameLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit}} - enforcedLabelValueLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} - allowOverlappingBlocks: {{ .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.minReadySeconds }} - minReadySeconds: {{ .Values.prometheus.prometheusSpec.minReadySeconds }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml deleted file mode 100644 index 8a3cbea5..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml deleted file mode 100644 index 736525c9..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp -subjects: - - kind: ServiceAccount - name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} -{{- end }} - diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml deleted file mode 100644 index b0130af7..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' -{{- if .Values.prometheus.podSecurityPolicy.volumes }} -{{ toYaml .Values.prometheus.podSecurityPolicy.volumes | indent 4 }} -{{- end }} - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Allow adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Allow adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} - allowedCapabilities: -{{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml deleted file mode 100644 index 0cca1fb3..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml +++ /dev/null @@ -1,217 +0,0 @@ -{{- /* -Generated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/alertmanager-prometheusRule.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }} -{{- $alertmanagerJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} -{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: alertmanager.rules - rules: -{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedReload | default false) }} - - alert: AlertmanagerFailedReload - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Configuration has failed to load for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedreload - summary: Reloading an Alertmanager configuration has failed. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(alertmanager_config_last_reload_successful{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) == 0 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerMembersInconsistent | default false) }} - - alert: AlertmanagerMembersInconsistent - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} has only found {{`{{`}} $value {{`}}`}} members of the {{`{{`}}$labels.job{{`}}`}} cluster. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagermembersinconsistent - summary: A member of an Alertmanager cluster has not found all other cluster members. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) - < on (namespace,service) group_left - count by (namespace,service) (max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m])) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedToSendAlerts | default false) }} - - alert: AlertmanagerFailedToSendAlerts - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} failed to send {{`{{`}} $value | humanizePercentage {{`}}`}} of notifications to {{`{{`}} $labels.integration {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedtosendalerts - summary: An Alertmanager instance failed to send notifications. - expr: |- - ( - rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) - / - rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) - ) - > 0.01 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} - - alert: AlertmanagerClusterFailedToSendAlerts - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts - summary: All Alertmanager instances in a cluster failed to send notifications to a critical integration. - expr: |- - min by (namespace,service, integration) ( - rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) - / - rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) - ) - > 0.01 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} - - alert: AlertmanagerClusterFailedToSendAlerts - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts - summary: All Alertmanager instances in a cluster failed to send notifications to a non-critical integration. - expr: |- - min by (namespace,service, integration) ( - rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) - / - rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) - ) - > 0.01 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerConfigInconsistent | default false) }} - - alert: AlertmanagerConfigInconsistent - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have different configurations. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerconfiginconsistent - summary: Alertmanager instances within the same cluster have different configurations. - expr: |- - count by (namespace,service) ( - count_values by (namespace,service) ("config_hash", alertmanager_config_hash{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) - ) - != 1 - for: 20m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterDown | default false) }} - - alert: AlertmanagerClusterDown - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have been up for less than half of the last 5m.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterdown - summary: Half or more of the Alertmanager instances within the same cluster are down. - expr: |- - ( - count by (namespace,service) ( - avg_over_time(up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) < 0.5 - ) - / - count by (namespace,service) ( - up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} - ) - ) - >= 0.5 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterCrashlooping | default false) }} - - alert: AlertmanagerClusterCrashlooping - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have restarted at least 5 times in the last 10m.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclustercrashlooping - summary: Half or more of the Alertmanager instances within the same cluster are crashlooping. - expr: |- - ( - count by (namespace,service) ( - changes(process_start_time_seconds{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[10m]) > 4 - ) - / - count by (namespace,service) ( - up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} - ) - ) - >= 0.5 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml deleted file mode 100644 index 13c158c0..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml +++ /dev/null @@ -1,98 +0,0 @@ -{{- /* -Generated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubePrometheus-prometheusRule.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "general.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: general.rules - rules: -{{- if not (.Values.defaultRules.disabled.TargetDown | default false) }} - - alert: TargetDown - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} printf "%.4g" $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.service {{`}}`}} targets in {{`{{`}} $labels.namespace {{`}}`}} namespace are down.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/targetdown - summary: One or more targets are unreachable. - expr: 100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) > 10 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.Watchdog | default false) }} - - alert: Watchdog - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: 'This is an alert meant to ensure that the entire alerting pipeline is functional. - - This alert is always firing, therefore it should always be firing in Alertmanager - - and always fire against a receiver. There are integrations with various notification - - mechanisms that send a notification when this alert is not firing. For example the - - "DeadMansSnitch" integration in PagerDuty. - - ' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/watchdog - summary: An alert that should always be firing to certify that Alertmanager is working properly. - expr: vector(1) - labels: - severity: none -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.InfoInhibitor | default false) }} - - alert: InfoInhibitor - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: 'This is an alert that is used to inhibit info alerts. - - By themselves, the info-level alerts are sometimes very noisy, but they are relevant when combined with - - other alerts. - - This alert fires whenever there''s a severity="info" alert, and stops firing when another alert with a - - severity of ''warning'' or ''critical'' starts firing on the same namespace. - - This alert should be routed to a null receiver and configured to inhibit alerts with severity="info". - - ' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/infoinhibitor - summary: Info-level alert inhibition. - expr: ALERTS{severity = "info"} == 1 unless on(namespace) ALERTS{alertname != "InfoInhibitor", severity =~ "warning|critical", alertstate="firing"} == 1 - labels: - severity: none -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml deleted file mode 100644 index c956157e..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml +++ /dev/null @@ -1,375 +0,0 @@ -{{- /* -Generated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-apps" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-apps - rules: -{{- if not (.Values.defaultRules.disabled.KubePodCrashLooping | default false) }} - - alert: KubePodCrashLooping - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: 'Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is in waiting state (reason: "CrashLoopBackOff").' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodcrashlooping - summary: Pod is crash looping. - expr: max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) >= 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubePodNotReady | default false) }} - - alert: KubePodNotReady - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodnotready - summary: Pod has been in a non-ready state for more than 15 minutes. - expr: |- - sum by (namespace, pod, cluster) ( - max by(namespace, pod, cluster) ( - kube_pod_status_phase{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}", phase=~"Pending|Unknown"} - ) * on(namespace, pod, cluster) group_left(owner_kind) topk by(namespace, pod, cluster) ( - 1, max by(namespace, pod, owner_kind, cluster) (kube_pod_owner{owner_kind!="Job"}) - ) - ) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeDeploymentGenerationMismatch | default false) }} - - alert: KubeDeploymentGenerationMismatch - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentgenerationmismatch - summary: Deployment generation mismatch due to possible roll-back - expr: |- - kube_deployment_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_deployment_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeDeploymentReplicasMismatch | default false) }} - - alert: KubeDeploymentReplicasMismatch - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentreplicasmismatch - summary: Deployment has not matched the expected number of replicas. - expr: |- - ( - kube_deployment_spec_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - > - kube_deployment_status_replicas_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) and ( - changes(kube_deployment_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeStatefulSetReplicasMismatch | default false) }} - - alert: KubeStatefulSetReplicasMismatch - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetreplicasmismatch - summary: Deployment has not matched the expected number of replicas. - expr: |- - ( - kube_statefulset_status_replicas_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) and ( - changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeStatefulSetGenerationMismatch | default false) }} - - alert: KubeStatefulSetGenerationMismatch - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetgenerationmismatch - summary: StatefulSet generation mismatch due to possible roll-back - expr: |- - kube_statefulset_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeStatefulSetUpdateNotRolledOut | default false) }} - - alert: KubeStatefulSetUpdateNotRolledOut - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetupdatenotrolledout - summary: StatefulSet update has not been rolled out. - expr: |- - ( - max without (revision) ( - kube_statefulset_status_current_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - unless - kube_statefulset_status_update_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - * - ( - kube_statefulset_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - ) and ( - changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeDaemonSetRolloutStuck | default false) }} - - alert: KubeDaemonSetRolloutStuck - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} has not finished or progressed for at least 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetrolloutstuck - summary: DaemonSet rollout is stuck. - expr: |- - ( - ( - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) or ( - kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - 0 - ) or ( - kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) or ( - kube_daemonset_status_number_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - ) and ( - changes(kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeContainerWaiting | default false) }} - - alert: KubeContainerWaiting - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: pod/{{`{{`}} $labels.pod {{`}}`}} in namespace {{`{{`}} $labels.namespace {{`}}`}} on container {{`{{`}} $labels.container{{`}}`}} has been in waiting state for longer than 1 hour. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubecontainerwaiting - summary: Pod container waiting longer than 1 hour - expr: sum by (namespace, pod, container, cluster) (kube_pod_container_status_waiting_reason{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) > 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeDaemonSetNotScheduled | default false) }} - - alert: KubeDaemonSetNotScheduled - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetnotscheduled - summary: DaemonSet pods are not scheduled. - expr: |- - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - - - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeDaemonSetMisScheduled | default false) }} - - alert: KubeDaemonSetMisScheduled - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetmisscheduled - summary: DaemonSet pods are misscheduled. - expr: kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeJobNotCompleted | default false) }} - - alert: KubeJobNotCompleted - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than {{`{{`}} "43200" | humanizeDuration {{`}}`}} to complete. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobnotcompleted - summary: Job did not complete in time - expr: |- - time() - max by(namespace, job_name, cluster) (kube_job_status_start_time{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - and - kube_job_status_active{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0) > 43200 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeJobFailed | default false) }} - - alert: KubeJobFailed - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. Removing failed job after investigation should clear this alert. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobfailed - summary: Job failed to complete. - expr: kube_job_failed{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeHpaReplicasMismatch | default false) }} - - alert: KubeHpaReplicasMismatch - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has not matched the desired number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpareplicasmismatch - summary: HPA has not matched desired number of replicas. - expr: |- - (kube_horizontalpodautoscaler_status_desired_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - > - kube_horizontalpodautoscaler_spec_min_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - < - kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - changes(kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[15m]) == 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubeHpaMaxedOut | default false) }} - - alert: KubeHpaMaxedOut - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has been running at max replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpamaxedout - summary: HPA is running at max replicas - expr: |- - kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - == - kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml deleted file mode 100644 index b6fe43fb..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml +++ /dev/null @@ -1,160 +0,0 @@ -{{- /* -Generated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-storage" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-storage - rules: -{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} - - alert: KubePersistentVolumeFillingUp - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} $value | humanizePercentage {{`}}`}} free. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup - summary: PersistentVolume is filling up. - expr: |- - kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - < 0.03 - and - kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} - - alert: KubePersistentVolumeFillingUp - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} is available. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup - summary: PersistentVolume is filling up. - expr: |- - ( - kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - ) < 0.15 - and - kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 - and - predict_linear(kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} - - alert: KubePersistentVolumeInodesFillingUp - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} only has {{`{{`}} $value | humanizePercentage {{`}}`}} free inodes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup - summary: PersistentVolumeInodes are filling up. - expr: |- - ( - kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - ) < 0.03 - and - kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} - - alert: KubePersistentVolumeInodesFillingUp - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to run out of inodes within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} of its inodes are free. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup - summary: PersistentVolumeInodes are filling up. - expr: |- - ( - kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - ) < 0.15 - and - kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 - and - predict_linear(kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 - unless on(namespace, persistentvolumeclaim) - kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeErrors | default false) }} - - alert: KubePersistentVolumeErrors - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeerrors - summary: PersistentVolume is having issues with provisioning. - expr: kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml deleted file mode 100644 index d3aa167d..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml +++ /dev/null @@ -1,448 +0,0 @@ -{{- /* -Generated from 'prometheus' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-prometheusRule.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }} -{{- $prometheusJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" }} -{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: prometheus - rules: -{{- if not (.Values.defaultRules.disabled.PrometheusBadConfig | default false) }} - - alert: PrometheusBadConfig - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to reload its configuration. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusbadconfig - summary: Failed Prometheus configuration reload. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(prometheus_config_last_reload_successful{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) == 0 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusNotificationQueueRunningFull | default false) }} - - alert: PrometheusNotificationQueueRunningFull - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Alert notification queue of Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is running full. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotificationqueuerunningfull - summary: Prometheus alert notification queue predicted to run full in less than 30m. - expr: |- - # Without min_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - predict_linear(prometheus_notifications_queue_length{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m], 60 * 30) - > - min_over_time(prometheus_notifications_queue_capacity{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToSomeAlertmanagers | default false) }} - - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.alertmanager{{`}}`}}.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstosomealertmanagers - summary: Prometheus has encountered more than 1% errors sending alerts to a specific Alertmanager. - expr: |- - ( - rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - / - rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - * 100 - > 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusNotConnectedToAlertmanagers | default false) }} - - alert: PrometheusNotConnectedToAlertmanagers - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not connected to any Alertmanagers. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotconnectedtoalertmanagers - summary: Prometheus is not connected to any Alertmanagers. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(prometheus_notifications_alertmanagers_discovered{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) < 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusTSDBReloadsFailing | default false) }} - - alert: PrometheusTSDBReloadsFailing - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} reload failures over the last 3h. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbreloadsfailing - summary: Prometheus has issues reloading blocks from disk. - expr: increase(prometheus_tsdb_reloads_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 - for: 4h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusTSDBCompactionsFailing | default false) }} - - alert: PrometheusTSDBCompactionsFailing - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last 3h. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbcompactionsfailing - summary: Prometheus has issues compacting blocks. - expr: increase(prometheus_tsdb_compactions_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 - for: 4h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusNotIngestingSamples | default false) }} - - alert: PrometheusNotIngestingSamples - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not ingesting samples. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotingestingsamples - summary: Prometheus is not ingesting samples. - expr: |- - ( - rate(prometheus_tsdb_head_samples_appended_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) <= 0 - and - ( - sum without(scrape_job) (prometheus_target_metadata_cache_entries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 - or - sum without(rule_group) (prometheus_rule_group_rules{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 - ) - ) - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusDuplicateTimestamps | default false) }} - - alert: PrometheusDuplicateTimestamps - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with different values but duplicated timestamp. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusduplicatetimestamps - summary: Prometheus is dropping samples with duplicate timestamps. - expr: rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusOutOfOrderTimestamps | default false) }} - - alert: PrometheusOutOfOrderTimestamps - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with timestamps arriving out of order. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusoutofordertimestamps - summary: Prometheus drops samples with out-of-order timestamps. - expr: rate(prometheus_target_scrapes_sample_out_of_order_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusRemoteStorageFailures | default false) }} - - alert: PrometheusRemoteStorageFailures - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} failed to send {{`{{`}} printf "%.1f" $value {{`}}`}}% of the samples to {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}} - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotestoragefailures - summary: Prometheus fails to send samples to remote storage. - expr: |- - ( - (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) - / - ( - (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) - + - (rate(prometheus_remote_storage_succeeded_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) - ) - ) - * 100 - > 1 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteBehind | default false) }} - - alert: PrometheusRemoteWriteBehind - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write is {{`{{`}} printf "%.1f" $value {{`}}`}}s behind for {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritebehind - summary: Prometheus remote write is behind. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - - ignoring(remote_name, url) group_right - max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - > 120 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteDesiredShards | default false) }} - - alert: PrometheusRemoteWriteDesiredShards - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write desired shards calculation wants to run {{`{{`}} $value {{`}}`}} shards for queue {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}, which is more than the max of {{`{{`}} printf `prometheus_remote_storage_shards_max{instance="%s",job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}` $labels.instance | query | first | value {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritedesiredshards - summary: Prometheus remote write desired shards calculation wants to run more than configured max shards. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - max_over_time(prometheus_remote_storage_shards_desired{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - > - max_over_time(prometheus_remote_storage_shards_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusRuleFailures | default false) }} - - alert: PrometheusRuleFailures - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to evaluate {{`{{`}} printf "%.0f" $value {{`}}`}} rules in the last 5m. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusrulefailures - summary: Prometheus is failing rule evaluations. - expr: increase(prometheus_rule_evaluation_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusMissingRuleEvaluations | default false) }} - - alert: PrometheusMissingRuleEvaluations - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has missed {{`{{`}} printf "%.0f" $value {{`}}`}} rule group evaluations in the last 5m. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusmissingruleevaluations - summary: Prometheus is missing rule evaluations due to slow rule group evaluation. - expr: increase(prometheus_rule_group_iterations_missed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusTargetLimitHit | default false) }} - - alert: PrometheusTargetLimitHit - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because the number of targets exceeded the configured target_limit. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetlimithit - summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit. - expr: increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusLabelLimitHit | default false) }} - - alert: PrometheusLabelLimitHit - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because some samples exceeded the configured label_limit, label_name_length_limit or label_value_length_limit. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuslabellimithit - summary: Prometheus has dropped targets because some scrape configs have exceeded the labels limit. - expr: increase(prometheus_target_scrape_pool_exceeded_label_limits_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusScrapeBodySizeLimitHit | default false) }} - - alert: PrometheusScrapeBodySizeLimitHit - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured body_size_limit. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapebodysizelimithit - summary: Prometheus has dropped some targets that exceeded body size limit. - expr: increase(prometheus_target_scrapes_exceeded_body_size_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusScrapeSampleLimitHit | default false) }} - - alert: PrometheusScrapeSampleLimitHit - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured sample_limit. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapesamplelimithit - summary: Prometheus has failed scrapes that have exceeded the configured sample limit. - expr: increase(prometheus_target_scrapes_exceeded_sample_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusTargetSyncFailure | default false) }} - - alert: PrometheusTargetSyncFailure - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} printf "%.0f" $value {{`}}`}} targets in Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} have failed to sync because invalid configuration was supplied.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetsyncfailure - summary: Prometheus has failed to sync targets. - expr: increase(prometheus_target_sync_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[30m]) > 0 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusHighQueryLoad | default false) }} - - alert: PrometheusHighQueryLoad - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} query API has less than 20% available capacity in its query engine for the last 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheushighqueryload - summary: Prometheus is reaching its maximum capacity serving concurrent requests. - expr: avg_over_time(prometheus_engine_queries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) / max_over_time(prometheus_engine_queries_concurrent_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0.8 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToAnyAlertmanager | default false) }} - - alert: PrometheusErrorSendingAlertsToAnyAlertmanager - annotations: -{{- if .Values.defaultRules.additionalRuleAnnotations }} -{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} -{{- end }} - description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% minimum errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to any Alertmanager.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstoanyalertmanager - summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager. - expr: |- - min without (alertmanager) ( - rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) - / - rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) - ) - * 100 - > 3 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml deleted file mode 100644 index 411ec5fa..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml +++ /dev/null @@ -1,56 +0,0 @@ -{{- if .Values.prometheus.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus - self-monitor: {{ .Values.prometheus.serviceMonitor.selfMonitor | quote }} -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.service.labels }} -{{ toYaml .Values.prometheus.service.labels | indent 4 }} -{{- end }} -{{- if .Values.prometheus.service.annotations }} - annotations: -{{ toYaml .Values.prometheus.service.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.prometheus.service.clusterIP }} - clusterIP: {{ .Values.prometheus.service.clusterIP }} -{{- end }} -{{- if .Values.prometheus.service.externalIPs }} - externalIPs: -{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.prometheus.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }} -{{- end }} -{{- if .Values.prometheus.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} -{{- if ne .Values.prometheus.service.type "ClusterIP" }} - externalTrafficPolicy: {{ .Values.prometheus.service.externalTrafficPolicy }} -{{- end }} - ports: - - name: {{ .Values.prometheus.prometheusSpec.portName }} - {{- if eq .Values.prometheus.service.type "NodePort" }} - nodePort: {{ .Values.prometheus.service.nodePort }} - {{- end }} - port: {{ .Values.prometheus.service.port }} - targetPort: {{ .Values.prometheus.service.targetPort }} -{{- if .Values.prometheus.service.additionalPorts }} -{{ toYaml .Values.prometheus.service.additionalPorts | indent 2 }} -{{- end }} - publishNotReadyAddresses: {{ .Values.prometheus.service.publishNotReadyAddresses }} - selector: - app.kubernetes.io/name: prometheus - prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} -{{- if .Values.prometheus.service.sessionAffinity }} - sessionAffinity: {{ .Values.prometheus.service.sessionAffinity }} -{{- end }} - type: "{{ .Values.prometheus.service.type }}" -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml deleted file mode 100644 index b4d44164..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus - app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-prometheus - app.kubernetes.io/component: prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.serviceAccount.annotations }} - annotations: -{{ toYaml .Values.prometheus.serviceAccount.annotations | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2 }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml deleted file mode 100644 index 2d995511..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "project-prometheus-stack.namespace" . }} - labels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus -{{ include "project-prometheus-stack.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app: {{ template "project-prometheus-stack.name" . }}-prometheus - release: {{ $.Release.Name | quote }} - self-monitor: "true" - namespaceSelector: - matchNames: - - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} - endpoints: - - port: {{ .Values.prometheus.prometheusSpec.portName }} - {{- if .Values.prometheus.serviceMonitor.interval }} - interval: {{ .Values.prometheus.serviceMonitor.interval }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.scheme }} - scheme: {{ .Values.prometheus.serviceMonitor.scheme }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.tlsConfig }} - tlsConfig: {{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.bearerTokenFile }} - bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} - {{- end }} - path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" - metricRelabelings: - {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} -{{- if .Values.prometheus.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml deleted file mode 100644 index 2ea6b1f8..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml +++ /dev/null @@ -1,129 +0,0 @@ -{{- $namespaces := dict "_0" .Release.Namespace -}} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - namespace: {{ .Release.Namespace }} - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - annotations: - "helm.sh/hook": post-install, post-upgrade - "helm.sh/hook-delete-policy": hook-succeeded, before-hook-creation -spec: - template: - metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - spec: - serviceAccountName: {{ template "project-prometheus-stack.fullname" . }}-patch-sa -{{- if .Values.global.kubectl.securityContext }} - securityContext: {{ toYaml .Values.global.kubectl.securityContext | nindent 8 }} -{{- end }} - restartPolicy: Never - nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} - tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} - containers: - {{- range $_, $ns := $namespaces }} - - name: patch-sa-{{ $ns }} - image: {{ template "system_default_registry" $ }}{{ $.Values.global.kubectl.repository }}:{{ $.Values.global.kubectl.tag }} - imagePullPolicy: {{ $.Values.global.kubectl.pullPolicy }} - command: ["kubectl", "patch", "serviceaccount", "default", "-p", "{\"automountServiceAccountToken\": false}"] - args: ["-n", "{{ $ns }}"] -{{- if $.Values.global.kubectl.resources }} - resources: {{ toYaml $.Values.global.kubectl.resources | nindent 10 }} -{{- end }} -{{- if $.Values.global.kubectl.containerSecurityContext }} - securityContext: {{ toYaml $.Values.global.kubectl.containerSecurityContext | nindent 10 }} -{{- end }} - {{- end }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa -rules: -- apiGroups: - - "" - resources: - - serviceaccounts - verbs: ['get', 'patch'] -{{- if .Values.global.cattle.psp.enabled }} -- apiGroups: ['policy'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "project-prometheus-stack.fullname" . }}-patch-sa -{{- end }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa -subjects: -- kind: ServiceAccount - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - namespace: {{ .Release.Namespace }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - namespace: {{ .Release.Namespace }} - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa ---- -{{- if .Values.global.cattle.psp.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa - namespace: {{ .Release.Namespace }} - labels: - app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa -spec: - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'MustRunAsNonRoot' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - - min: 1 - max: 65535 - readOnlyRootFilesystem: false - volumes: - - 'secret' -{{- end }} -{{- range $_, $ns := $namespaces }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: project-monitoring-policy - namespace: {{ $ns }} -spec: - podSelector: {} - ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} - egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} - policyTypes: - - Ingress - - Egress -{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml b/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml deleted file mode 100644 index b0dcf188..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml +++ /dev/null @@ -1,21 +0,0 @@ -#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} -# {{- $found := dict -}} -# {{- set $found "monitoring.coreos.com/v1alpha1/AlertmanagerConfig" false -}} -# {{- set $found "monitoring.coreos.com/v1/Alertmanager" false -}} -# {{- set $found "monitoring.coreos.com/v1/PodMonitor" false -}} -# {{- set $found "monitoring.coreos.com/v1/Probe" false -}} -# {{- set $found "monitoring.coreos.com/v1/Prometheus" false -}} -# {{- set $found "monitoring.coreos.com/v1/PrometheusRule" false -}} -# {{- set $found "monitoring.coreos.com/v1/ServiceMonitor" false -}} -# {{- set $found "monitoring.coreos.com/v1/ThanosRuler" false -}} -# {{- range .Capabilities.APIVersions -}} -# {{- if hasKey $found (toString .) -}} -# {{- set $found (toString .) true -}} -# {{- end -}} -# {{- end -}} -# {{- range $_, $exists := $found -}} -# {{- if (eq $exists false) -}} -# {{- required "Required Prometheus Operator CRDs are missing. Please install Prometheus Operator (e.g. rancher-monitoring) before installing this chart." "" -}} -# {{- end -}} -# {{- end -}} -#{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml b/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml deleted file mode 100644 index a30c59d3..00000000 --- a/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} -#{{- if .Values.global.cattle.psp.enabled }} -#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} -#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} -#{{- end }} -#{{- end }} -#{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/values.yaml b/charts/rancher-project-monitoring/0.3.0/values.yaml deleted file mode 100644 index ae4728e8..00000000 --- a/charts/rancher-project-monitoring/0.3.0/values.yaml +++ /dev/null @@ -1,1551 +0,0 @@ -# Default values for project-prometheus-stack. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# Rancher Project Monitoring Configuration - -## Provide a name in place of project-prometheus-stack for `app:` labels -## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url -## -nameOverride: "rancher-project-monitoring" - -## Override the deployment namespace -## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url -## -namespaceOverride: "" - -## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6 -## -kubeTargetVersionOverride: "" - -## Allow kubeVersion to be overridden while creating the ingress -## -kubeVersionOverride: "" - -## Provide a name to substitute for the full names of resources -## -fullnameOverride: "" - -## Labels to apply to all resources -## -commonLabels: {} -# scmhash: abc123 -# myLabel: aakkmd - -## Create default rules for monitoring the cluster -## -defaultRules: - create: true - rules: - general: true - prometheus: true - alertmanager: true - kubernetesApps: true - kubernetesStorage: true - - ## Reduce app namespace alert scope - appNamespacesTarget: ".*" - - ## Labels for default rules - labels: {} - ## Annotations for default rules - annotations: {} - - ## Additional labels for PrometheusRule alerts - additionalRuleLabels: {} - - ## Additional annotations for PrometheusRule alerts - additionalRuleAnnotations: {} - - ## Prefix for runbook URLs. Use this to override the first part of the runbookURLs that is common to all rules. - runbookUrl: "https://runbooks.prometheus-operator.dev/runbooks" - - ## Disabled PrometheusRule alerts - disabled: {} - -## -global: - cattle: - psp: - enabled: false - systemDefaultRegistry: "" - projectNamespaceSelector: {} - projectNamespaces: [] - kubectl: - repository: rancher/kubectl - tag: v1.20.2 - pullPolicy: IfNotPresent - securityContext: - runAsNonRoot: true - runAsUser: 1000 - networkPolicy: - # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. - # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, - # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs - # through the Rancher/Kubernetes API Proxy in the Rancher UI. - limitIngressToProject: false - # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. - ingress: null - # By default, all egress traffic is allowed. - egress: - - {} - rbac: - ## Create RBAC resources for ServiceAccounts and users - ## - create: true - - userRoles: - ## Create default user Roles that the Helm Project Operator will automatically create RoleBindings for - ## - ## How does this work? - ## - ## The operator will watch for all subjects bound to each Kubernetes default ClusterRole in the project registration namespace - ## where the ProjectHelmChart that deployed this chart belongs to; if it observes a subject bound to a particular role in - ## the project registration namespace (e.g. edit) and if a Role exists that is deployed by this chart with the label - ## 'helm.cattle.io/project-helm-chart-role-aggregate-from': '', it will automaticaly create a RoleBinding - ## in the release namespace binding all such subjects to that Role. - ## - ## Note: while the default behavior is to use the Kubernetes default ClusterRole, the operator deployment (prometheus-federator) - ## can be configured to use a different set of ClusterRoles as the source of truth for admin, edit, and view permissions. - ## - create: true - ## Add labels to Roles - aggregateToDefaultRoles: true - - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - # or - # - "image-pull-secret" - -federate: - ## enabled indicates whether to add federation to any Project Prometheus Stacks by default - ## If not enabled, no federation will be turned on - enabled: true - - # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from - # By default, this matches the default deployment of Rancher Monitoring - targets: - - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 - - ## Scrape interval - interval: "15s" - -## Configuration for alertmanager -## ref: https://prometheus.io/docs/alerting/alertmanager/ -## -alertmanager: - - ## Deploy alertmanager - ## - enabled: true - - ## Annotations for Alertmanager - ## - annotations: {} - - ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2 - ## - apiVersion: v2 - - ## Service account for Alertmanager to use. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - ## - serviceAccount: - create: true - name: "" - annotations: {} - - ## Configure pod disruption budgets for Alertmanager - ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget - ## This configuration is immutable once created and will require the PDB to be deleted to be changed - ## https://github.com/kubernetes/kubernetes/issues/45398 - ## - podDisruptionBudget: - enabled: false - minAvailable: 1 - maxUnavailable: "" - - ## Alertmanager configuration directives - ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file - ## https://prometheus.io/webtools/alerting/routing-tree-editor/ - ## - config: - global: - resolve_timeout: 5m - inhibit_rules: - - source_matchers: - - 'severity = critical' - target_matchers: - - 'severity =~ warning|info' - equal: - - 'namespace' - - 'alertname' - - source_matchers: - - 'severity = warning' - target_matchers: - - 'severity = info' - equal: - - 'namespace' - - 'alertname' - - source_matchers: - - 'alertname = InfoInhibitor' - target_matchers: - - 'severity = info' - equal: - - 'namespace' - route: - group_by: ['namespace'] - group_wait: 30s - group_interval: 5m - repeat_interval: 12h - receiver: 'null' - routes: - - receiver: 'null' - matchers: - - alertname =~ "InfoInhibitor|Watchdog" - receivers: - - name: 'null' - templates: - - '/etc/alertmanager/config/*.tmpl' - - ## Pass the Alertmanager configuration directives through Helm's templating - ## engine. If the Alertmanager configuration contains Alertmanager templates, - ## they'll need to be properly escaped so that they are not interpreted by - ## Helm - ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function - ## https://prometheus.io/docs/alerting/configuration/#tmpl_string - ## https://prometheus.io/docs/alerting/notifications/ - ## https://prometheus.io/docs/alerting/notification_examples/ - tplConfig: false - - ## Alertmanager template files to format alerts - ## By default, templateFiles are placed in /etc/alertmanager/config/ and if - ## they have a .tmpl file suffix will be loaded. See config.templates above - ## to change, add other suffixes. If adding other suffixes, be sure to update - ## config.templates above to include those suffixes. - ## ref: https://prometheus.io/docs/alerting/notifications/ - ## https://prometheus.io/docs/alerting/notification_examples/ - ## - - templateFiles: - rancher_defaults.tmpl: |- - {{- define "slack.rancher.text" -}} - {{ template "rancher.text_multiple" . }} - {{- end -}} - - {{- define "rancher.text_multiple" -}} - *[GROUP - Details]* - One or more alarms in this group have triggered a notification. - - {{- if gt (len .GroupLabels.Values) 0 }} - *Group Labels:* - {{- range .GroupLabels.SortedPairs }} - • *{{ .Name }}:* `{{ .Value }}` - {{- end }} - {{- end }} - {{- if .ExternalURL }} - *Link to AlertManager:* {{ .ExternalURL }} - {{- end }} - - {{- range .Alerts }} - {{ template "rancher.text_single" . }} - {{- end }} - {{- end -}} - - {{- define "rancher.text_single" -}} - {{- if .Labels.alertname }} - *[ALERT - {{ .Labels.alertname }}]* - {{- else }} - *[ALERT]* - {{- end }} - {{- if .Labels.severity }} - *Severity:* `{{ .Labels.severity }}` - {{- end }} - {{- if .Labels.cluster }} - *Cluster:* {{ .Labels.cluster }} - {{- end }} - {{- if .Annotations.summary }} - *Summary:* {{ .Annotations.summary }} - {{- end }} - {{- if .Annotations.message }} - *Message:* {{ .Annotations.message }} - {{- end }} - {{- if .Annotations.description }} - *Description:* {{ .Annotations.description }} - {{- end }} - {{- if .Annotations.runbook_url }} - *Runbook URL:* <{{ .Annotations.runbook_url }}|:spiral_note_pad:> - {{- end }} - {{- with .Labels }} - {{- with .Remove (stringSlice "alertname" "severity" "cluster") }} - {{- if gt (len .) 0 }} - *Additional Labels:* - {{- range .SortedPairs }} - • *{{ .Name }}:* `{{ .Value }}` - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- with .Annotations }} - {{- with .Remove (stringSlice "summary" "message" "description" "runbook_url") }} - {{- if gt (len .) 0 }} - *Additional Annotations:* - {{- range .SortedPairs }} - • *{{ .Name }}:* `{{ .Value }}` - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- end -}} - - ingress: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - - labels: {} - - ## Redirect ingress to an additional defined port on the service - # servicePort: 8081 - - ## Hosts must be provided if Ingress is enabled. - ## - hosts: [] - # - alertmanager.domain.com - - ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix - ## - paths: [] - # - / - - ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) - ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types - # pathType: ImplementationSpecific - - ## TLS configuration for Alertmanager Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: alertmanager-general-tls - # hosts: - # - alertmanager.example.com - - ## Configuration for Alertmanager secret - ## - secret: - annotations: {} - - ## Configuration for Alertmanager service - ## - service: - annotations: {} - labels: {} - clusterIP: "" - - ## Port for Alertmanager Service to listen on - ## - port: 9093 - ## To be used with a proxy extraContainer port - ## - targetPort: 9093 - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30903 - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - - ## Additional ports to open for Alertmanager service - additionalPorts: [] - # additionalPorts: - # - name: authenticated - # port: 8081 - # targetPort: 8081 - - externalIPs: [] - loadBalancerIP: "" - loadBalancerSourceRanges: [] - - ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints - ## - externalTrafficPolicy: Cluster - - ## Service type - ## - type: ClusterIP - - ## If true, create a serviceMonitor for alertmanager - ## - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - selfMonitor: true - - ## proxyUrl: URL of a proxy that should be used for scraping. - ## - proxyUrl: "" - - ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. - scheme: "" - - ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. - ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig - tlsConfig: {} - - bearerTokenFile: - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - ## RelabelConfigs to apply to samples before scraping - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - ## Settings affecting alertmanagerSpec - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerspec - ## - alertmanagerSpec: - ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata - ## Metadata Labels and Annotations gets propagated to the Alertmanager pods. - ## - podMetadata: {} - - ## Image of Alertmanager - ## - image: - repository: rancher/mirrored-prometheus-alertmanager - tag: v0.24.0 - sha: "" - - ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the - ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. - ## - secrets: [] - - ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. - ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/. - ## - configMaps: [] - - ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for - ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config. - ## - # configSecret: - - ## WebTLSConfig defines the TLS parameters for HTTPS - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerwebspec - web: {} - - ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. - ## - alertmanagerConfigSelector: - # default ignores resources created by Rancher Monitoring - matchExpressions: - - key: release - operator: NotIn - values: - - rancher-monitoring - - ## AlermanagerConfig to be used as top level configuration - ## - alertmanagerConfiguration: {} - ## Example with select a global alertmanagerconfig - # alertmanagerConfiguration: - # name: global-alertmanager-Configuration - - ## Define Log Format - # Use logfmt (default) or json logging - logFormat: logfmt - - ## Log level for Alertmanager to be configured with. - ## - logLevel: info - - ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the - ## running cluster equal to the expected size. - replicas: 1 - - ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression - ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours). - ## - retention: 120h - - ## Storage is the definition of how storage will be used by the Alertmanager instances. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md - ## - storage: {} - # volumeClaimTemplate: - # spec: - # storageClassName: gluster - # accessModes: ["ReadWriteOnce"] - # resources: - # requests: - # storage: 50Gi - # selector: {} - - - ## The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. string false - ## - externalUrl: - - ## The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, - ## but the server serves requests under a different route prefix. For example for use with kubectl proxy. - ## - routePrefix: / - - ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions. - ## - paused: false - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Define resources requests and limits for single Pods. - ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - limits: - memory: 500Mi - cpu: 1000m - requests: - memory: 100Mi - cpu: 100m - - ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. - ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. - ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. - ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. - ## - podAntiAffinity: "" - - ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. - ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone - ## - podAntiAffinityTopologyKey: kubernetes.io/hostname - - ## Assign custom affinity rules to the alertmanager instance - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - affinity: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/e2e-az-name - # operator: In - # values: - # - e2e-az1 - # - e2e-az2 - - ## If specified, the pod's tolerations. - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - ## If specified, the pod's topology spread constraints. - ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ - ## - topologySpreadConstraints: [] - # - maxSkew: 1 - # topologyKey: topology.kubernetes.io/zone - # whenUnsatisfiable: DoNotSchedule - # labelSelector: - # matchLabels: - # app: alertmanager - - ## SecurityContext holds pod-level security attributes and common container settings. - ## This defaults to non root user with uid 1000 and gid 2000. *v1.PodSecurityContext false - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - ## - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 2000 - - ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. - ## Note this is only for the Alertmanager UI, not the gossip communication. - ## - listenLocal: false - - ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. - ## - containers: [] - # containers: - # - name: oauth-proxy - # image: quay.io/oauth2-proxy/oauth2-proxy:v7.3.0 - # args: - # - --upstream=http://127.0.0.1:9093 - # - --http-address=0.0.0.0:8081 - # - ... - # ports: - # - containerPort: 8081 - # name: oauth-proxy - # protocol: TCP - # resources: {} - - # Additional volumes on the output StatefulSet definition. - volumes: [] - - # Additional VolumeMounts on the output StatefulSet definition. - volumeMounts: [] - - ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes - ## (permissions, dir tree) on mounted volumes before starting prometheus - initContainers: [] - - ## Priority class assigned to the Pods - ## - priorityClassName: "" - - ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster. - ## - additionalPeers: [] - - ## PortName to use for Alert Manager. - ## - portName: "http-web" - - ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918 - ## - clusterAdvertiseAddress: false - - ## ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. - ## Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. - forceEnableClusterMode: false - - ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to - ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). - minReadySeconds: 0 - - ## ExtraSecret can be used to store various data in an extra secret - ## (use it for example to store hashed basic auth credentials) - extraSecret: - ## if not set, name will be auto generated - # name: "" - annotations: {} - data: {} - # auth: | - # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 - # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. - -## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml -## -grafana: - enabled: true - namespaceOverride: "" - - ## Grafana's primary configuration - ## NOTE: values in map will be converted to ini format - ## ref: http://docs.grafana.org/installation/configuration/ - ## - grafana.ini: - users: - auto_assign_org_role: Viewer - auth: - disable_login_form: false - auth.anonymous: - enabled: true - org_role: Viewer - auth.basic: - enabled: false - security: - # Required to embed dashboards in Rancher Cluster Overview Dashboard on Cluster Explorer - allow_embedding: true - - deploymentStrategy: - type: Recreate - - ## ForceDeployDatasources Create datasource configmap even if grafana deployment has been disabled - ## - forceDeployDatasources: false - - ## ForceDeployDashboard Create dashboard configmap even if grafana deployment has been disabled - ## - forceDeployDashboards: false - - ## Deploy default dashboards - ## - defaultDashboardsEnabled: true - - ## Timezone for the default dashboards - ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg - ## - defaultDashboardsTimezone: utc - - adminPassword: prom-operator - - ingress: - ## If true, Grafana Ingress will be created - ## - enabled: false - - ## IngressClassName for Grafana Ingress. - ## Should be provided if Ingress is enable. - ## - # ingressClassName: nginx - - ## Annotations for Grafana Ingress - ## - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - - ## Labels to be added to the Ingress - ## - labels: {} - - ## Hostnames. - ## Must be provided if Ingress is enable. - ## - # hosts: - # - grafana.domain.com - hosts: [] - - ## Path for grafana ingress - path: / - - ## TLS configuration for grafana Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: grafana-general-tls - # hosts: - # - grafana.example.com - - sidecar: - dashboards: - enabled: true - label: grafana_dashboard - labelValue: "1" - - ## Annotations for Grafana dashboard configmaps - ## - annotations: {} - multicluster: - global: - enabled: false - provider: - allowUiUpdates: false - datasources: - enabled: true - defaultDatasourceEnabled: true - - uid: prometheus - - ## URL of prometheus datasource - ## - # url: http://prometheus-stack-prometheus:9090/ - - # If not defined, will use prometheus.prometheusSpec.scrapeInterval or its default - # defaultDatasourceScrapeInterval: 15s - - ## Annotations for Grafana datasource configmaps - ## - annotations: {} - - label: grafana_datasource - labelValue: "1" - - ## Field with internal link pointing to existing data source in Grafana. - ## Can be provisioned via additionalDataSources - exemplarTraceIdDestinations: {} - # datasourceUid: Jaeger - # traceIdLabelName: trace_id - - extraConfigmapMounts: [] - # - name: certs-configmap - # mountPath: /etc/grafana/ssl/ - # configMap: certs-configmap - # readOnly: true - - deleteDatasources: [] - # - name: example-datasource - # orgId: 1 - - ## Configure additional grafana datasources (passed through tpl) - ## ref: http://docs.grafana.org/administration/provisioning/#datasources - additionalDataSources: [] - # - name: prometheus-sample - # access: proxy - # basicAuth: true - # basicAuthPassword: pass - # basicAuthUser: daco - # editable: false - # jsonData: - # tlsSkipVerify: true - # orgId: 1 - # type: prometheus - # url: https://{{ printf "%s-prometheus.svc" .Release.Name }}:9090 - # version: 1 - - ## Passed to grafana subchart and used by servicemonitor below - ## - service: - portName: nginx-http - ## Port for Grafana Service to listen on - ## - port: 80 - ## To be used with a proxy extraContainer port - ## - targetPort: 8080 - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30950 - ## Service type - ## - type: ClusterIP - - proxy: - image: - repository: rancher/mirrored-library-nginx - tag: 1.24.0-alpine - - ## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod - extraContainers: | - - name: grafana-proxy - args: - - nginx - - -g - - daemon off; - - -c - - /nginx/nginx.conf - image: "{{ template "system_default_registry" . }}{{ .Values.proxy.image.repository }}:{{ .Values.proxy.image.tag }}" - ports: - - containerPort: 8080 - name: nginx-http - protocol: TCP - volumeMounts: - - mountPath: /nginx - name: grafana-nginx - - mountPath: /var/cache/nginx - name: nginx-home - securityContext: - runAsUser: 101 - runAsGroup: 101 - - ## Volumes that can be used in containers - extraContainerVolumes: - - name: nginx-home - emptyDir: {} - - name: grafana-nginx - configMap: - name: grafana-nginx-proxy-config - items: - - key: nginx.conf - mode: 438 - path: nginx.conf - - ## If true, create a serviceMonitor for grafana - ## - serviceMonitor: - # If true, a ServiceMonitor CRD is created for a prometheus operator - # https://github.com/coreos/prometheus-operator - # - enabled: true - - # Path to use for scraping metrics. Might be different if server.root_url is set - # in grafana.ini - path: "/metrics" - - # namespace: monitoring (defaults to use the namespace this chart is deployed to) - - # labels for the ServiceMonitor - labels: {} - - # Scrape interval. If not set, the Prometheus default scrape interval is used. - # - interval: "" - scheme: http - tlsConfig: {} - scrapeTimeout: 30s - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - ## RelabelConfigs to apply to samples before scraping - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - resources: - limits: - memory: 200Mi - cpu: 200m - requests: - memory: 100Mi - cpu: 100m - - testFramework: - enabled: false - -## Deploy a Prometheus instance -## -prometheus: - - enabled: true - - ## Annotations for Prometheus - ## - annotations: {} - - ## Service account for Prometheuses to use. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - ## - serviceAccount: - create: true - name: "" - annotations: {} - - ## Configuration for Prometheus service - ## - service: - annotations: {} - labels: {} - clusterIP: "" - - ## Port for Prometheus Service to listen on - ## - port: 9090 - - ## To be used with a proxy extraContainer port - targetPort: 8081 - - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30090 - - ## Loadbalancer IP - ## Only use if service.type is "LoadBalancer" - loadBalancerIP: "" - loadBalancerSourceRanges: [] - - ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints - ## - externalTrafficPolicy: Cluster - - ## Service type - ## - type: ClusterIP - - ## Additional port to define in the Service - additionalPorts: [] - # additionalPorts: - # - name: authenticated - # port: 8081 - # targetPort: 8081 - - ## Consider that all endpoints are considered "ready" even if the Pods themselves are not - ## Ref: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec - publishNotReadyAddresses: false - - sessionAffinity: "" - - ## Configure pod disruption budgets for Prometheus - ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget - ## This configuration is immutable once created and will require the PDB to be deleted to be changed - ## https://github.com/kubernetes/kubernetes/issues/45398 - ## - podDisruptionBudget: - enabled: false - minAvailable: 1 - maxUnavailable: "" - - ## ExtraSecret can be used to store various data in an extra secret - ## (use it for example to store hashed basic auth credentials) - extraSecret: - ## if not set, name will be auto generated - # name: "" - annotations: {} - data: {} - # auth: | - # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 - # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. - - ingress: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - labels: {} - - ## Redirect ingress to an additional defined port on the service - # servicePort: 8081 - - ## Hostnames. - ## Must be provided if Ingress is enabled. - ## - # hosts: - # - prometheus.domain.com - hosts: [] - - ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix - ## - paths: [] - # - / - - ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) - ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types - # pathType: ImplementationSpecific - - ## TLS configuration for Prometheus Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: prometheus-general-tls - # hosts: - # - prometheus.example.com - - ## Configure additional options for default pod security policy for Prometheus - ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ - podSecurityPolicy: - allowedCapabilities: [] - volumes: [] - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - selfMonitor: true - - ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. - scheme: "" - - ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. - ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig - tlsConfig: {} - - bearerTokenFile: - - ## Metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - ## Settings affecting prometheusSpec - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#prometheusspec - ## - prometheusSpec: - ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos - ## - disableCompaction: false - ## APIServerConfig - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#apiserverconfig - ## - apiserverConfig: {} - - ## Interval between consecutive scrapes. - ## Defaults to 30s. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 - ## - scrapeInterval: "30s" - - ## Number of seconds to wait for target to respond before erroring - ## - scrapeTimeout: "" - - ## Interval between consecutive evaluations. - ## - evaluationInterval: "1m" - - ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. - ## - listenLocal: false - - ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series. - ## This is disabled by default. - ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis - ## - enableAdminAPI: false - - ## WebTLSConfig defines the TLS parameters for HTTPS - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#webtlsconfig - web: {} - - ## Exemplars related settings that are runtime reloadable. - ## It requires to enable the exemplar storage feature to be effective. - exemplars: "" - ## Maximum number of exemplars stored in memory for all series. - ## If not set, Prometheus uses its default value. - ## A value of zero or less than zero disables the storage. - # maxSize: 100000 - - # EnableFeatures API enables access to Prometheus disabled features. - # ref: https://prometheus.io/docs/prometheus/latest/disabled_features/ - enableFeatures: [] - # - exemplar-storage - - ## Image of Prometheus. - ## - image: - repository: rancher/mirrored-prometheus-prometheus - tag: v2.38.0 - sha: "" - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - ## If specified, the pod's topology spread constraints. - ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ - ## - topologySpreadConstraints: [] - # - maxSkew: 1 - # topologyKey: topology.kubernetes.io/zone - # whenUnsatisfiable: DoNotSchedule - # labelSelector: - # matchLabels: - # app: prometheus - - ## Alertmanagers to which alerts will be sent - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerendpoints - ## - ## Default configuration will connect to the alertmanager deployed as part of this release - ## - alertingEndpoints: [] - # - name: "" - # namespace: "" - # port: http - # scheme: http - # pathPrefix: "" - # tlsConfig: {} - # bearerTokenFile: "" - # apiVersion: v2 - - ## External labels to add to any time series or alerts when communicating with external systems - ## - externalLabels: {} - - ## enable --web.enable-remote-write-receiver flag on prometheus-server - ## - enableRemoteWriteReceiver: false - - ## Name of the external label used to denote Prometheus instance name - ## - prometheusExternalLabelName: "" - - ## If true, the Operator won't add the external label used to denote Prometheus instance name - ## - prometheusExternalLabelNameClear: false - - ## External URL at which Prometheus will be reachable. - ## - externalUrl: "" - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. - ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not - ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated - ## with the new list of secrets. - ## - secrets: [] - - ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. - ## The ConfigMaps are mounted into /etc/prometheus/configmaps/. - ## - configMaps: [] - - ## QuerySpec defines the query command line flags when starting Prometheus. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#queryspec - ## - query: {} - - ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the PrometheusRule resources created - ## - ruleSelectorNilUsesHelmValues: false - - ## PrometheusRules to be selected for target discovery. - ## If {}, select all PrometheusRules - ## - ruleSelector: - # default ignores resources created by Rancher Monitoring - matchExpressions: - - key: release - operator: NotIn - values: - - rancher-monitoring - - ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the servicemonitors created - ## - serviceMonitorSelectorNilUsesHelmValues: false - - ## ServiceMonitors to be selected for target discovery. - ## If {}, select all ServiceMonitors - ## - serviceMonitorSelector: - # default ignores resources created by Rancher Monitoring - matchExpressions: - - key: release - operator: NotIn - values: - - rancher-monitoring - - ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the podmonitors created - ## - podMonitorSelectorNilUsesHelmValues: false - - ## PodMonitors to be selected for target discovery. - ## If {}, select all PodMonitors - ## - podMonitorSelector: - # default ignores resources created by Rancher Monitoring - matchExpressions: - - key: release - operator: NotIn - values: - - rancher-monitoring - - ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the probes created - ## - probeSelectorNilUsesHelmValues: true - - ## Probes to be selected for target discovery. - ## If {}, select all Probes - ## - probeSelector: - # default ignores resources created by Rancher Monitoring - matchExpressions: - - key: release - operator: NotIn - values: - - rancher-monitoring - - ## How long to retain metrics - ## - retention: 10d - - ## Maximum size of metrics - ## - retentionSize: "50GiB" - - ## Enable compression of the write-ahead log using Snappy. - ## - walCompression: true - - ## If true, the Operator won't process any Prometheus configuration changes - ## - paused: false - - ## Number of replicas of each shard to deploy for a Prometheus deployment. - ## Number of replicas multiplied by shards is the total number of Pods created. - ## - replicas: 1 - - ## EXPERIMENTAL: Number of shards to distribute targets onto. - ## Number of replicas multiplied by shards is the total number of Pods created. - ## Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved. - ## Increasing shards will not reshard data either but it will continue to be available from the same instances. - ## To query globally use Thanos sidecar and Thanos querier or remote write data to a central location. - ## Sharding is done on the content of the `__address__` target meta-label. - ## - shards: 1 - - ## Log level for Prometheus be configured in - ## - logLevel: info - - ## Log format for Prometheus be configured in - ## - logFormat: logfmt - - ## Prefix used to register routes, overriding externalUrl route. - ## Useful for proxies that rewrite URLs. - ## - routePrefix: / - - ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata - ## Metadata Labels and Annotations gets propagated to the prometheus pods. - ## - podMetadata: {} - # labels: - # app: prometheus - # k8s-app: prometheus - - ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. - ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. - ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. - ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. - podAntiAffinity: "" - - ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. - ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone - ## - podAntiAffinityTopologyKey: kubernetes.io/hostname - - ## Assign custom affinity rules to the prometheus instance - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - affinity: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/e2e-az-name - # operator: In - # values: - # - e2e-az1 - # - e2e-az2 - - ## The remote_write spec configuration for Prometheus. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec - remoteWrite: [] - # - url: http://remote1/push - ## additionalRemoteWrite is appended to remoteWrite - additionalRemoteWrite: [] - - ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature - remoteWriteDashboards: false - - ## Resource limits & requests - ## - resources: - limits: - memory: 3000Mi - cpu: 1000m - requests: - memory: 750Mi - cpu: 750m - - storage: - enabled: false - ## Prometheus StorageSpec for persistent data - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md - ## - storageSpec: {} - ## Using PersistentVolumeClaim - ## - # volumeClaimTemplate: - # spec: - # storageClassName: gluster - # accessModes: ["ReadWriteOnce"] - # resources: - # requests: - # storage: 50Gi - # selector: {} - - ## Using tmpfs volume - ## - # emptyDir: - # medium: Memory - - # Additional volumes on the output StatefulSet definition. - volumes: - - name: nginx-home - emptyDir: {} - - name: prometheus-nginx - configMap: - name: prometheus-nginx-proxy-config - defaultMode: 438 - - # Additional VolumeMounts on the output StatefulSet definition. - volumeMounts: [] - - ## SecurityContext holds pod-level security attributes and common container settings. - ## This defaults to non root user with uid 1000 and gid 2000. - ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md - ## - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 2000 - - ## Priority class assigned to the Pods - ## - priorityClassName: "" - - proxy: - image: - repository: rancher/mirrored-library-nginx - tag: 1.24.0-alpine - - ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. - ## if using proxy extraContainer update targetPort with proxy container port - containers: | - - name: prometheus-proxy - args: - - nginx - - -g - - daemon off; - - -c - - /nginx/nginx.conf - image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.proxy.image.repository }}:{{ .Values.prometheus.prometheusSpec.proxy.image.tag }}" - ports: - - containerPort: 8081 - name: nginx-http - protocol: TCP - volumeMounts: - - mountPath: /nginx - name: prometheus-nginx - - mountPath: /var/cache/nginx - name: nginx-home - securityContext: - runAsUser: 101 - runAsGroup: 101 - - ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes - ## (permissions, dir tree) on mounted volumes before starting prometheus - initContainers: [] - - ## PortName to use for Prometheus. - ## - portName: "http-web" - - ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files - ## on the file system of the Prometheus container e.g. bearer token files. - arbitraryFSAccessThroughSMs: false - - ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor - ## or PodMonitor to true, this overrides honor_labels to false. - overrideHonorLabels: false - - ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. - overrideHonorTimestamps: false - - ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. - ## The label value will always be the namespace of the object that is being created. - ## Disabled by default - enforcedNamespaceLabel: "" - - ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels. - ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair - ## Deprecated, use `excludedFromEnforcement` instead - prometheusRulesExcludedFromEnforce: [] - - ## ExcludedFromEnforcement - list of object references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects - ## to be excluded from enforcing a namespace label of origin. - ## Works only if enforcedNamespaceLabel set to true. - ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#objectreference - excludedFromEnforcement: [] - - ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable, - ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such - ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions - ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/) - queryLogFile: false - - ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit - ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall - ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead. - enforcedSampleLimit: false - - ## EnforcedTargetLimit defines a global limit on the number of scraped targets. This overrides any TargetLimit set - ## per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the TargetLimit to keep the overall - ## number of targets under the desired limit. Note that if TargetLimit is lower, that value will be taken instead, except - ## if either value is zero, in which case the non-zero value will be used. If both values are zero, no limit is enforced. - enforcedTargetLimit: false - - - ## Per-scrape limit on number of labels that will be accepted for a sample. If more than this number of labels are present - ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions - ## 2.27.0 and newer. - enforcedLabelLimit: false - - ## Per-scrape limit on length of labels name that will be accepted for a sample. If a label name is longer than this number - ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions - ## 2.27.0 and newer. - enforcedLabelNameLengthLimit: false - - ## Per-scrape limit on length of labels value that will be accepted for a sample. If a label value is longer than this - ## number post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus - ## versions 2.27.0 and newer. - enforcedLabelValueLengthLimit: false - - ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental - ## in Prometheus so it may change in any upcoming release. - allowOverlappingBlocks: false - - ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to - ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). - minReadySeconds: 0 - -## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. -## -cleanPrometheusOperatorObjectNames: false diff --git a/index.yaml b/index.yaml index e0678326..edbf9941 100755 --- a/index.yaml +++ b/index.yaml @@ -1,54 +1,6 @@ apiVersion: v1 entries: prometheus-federator: - - annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Prometheus Federator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-monitoring-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' - catalog.cattle.io/release-name: prometheus-federator - apiVersion: v2 - appVersion: 0.3.0 - created: "2023-05-23T13:32:09.229962-07:00" - dependencies: - - condition: helmProjectOperator.enabled - name: helmProjectOperator - repository: file://./charts/helmProjectOperator - description: Prometheus Federator - digest: 0becc4b9c61baf0498e97fcc4b073689d7337c0525b7c21a695b4f5266b49cc0 - icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg - name: prometheus-federator - urls: - - assets/prometheus-federator/prometheus-federator-0.3.0.tgz - version: 0.3.0 - - annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Prometheus Federator - catalog.cattle.io/kube-version: '>=1.16.0-0' - catalog.cattle.io/namespace: cattle-monitoring-system - catalog.cattle.io/os: linux,windows - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' - catalog.cattle.io/release-name: prometheus-federator - apiVersion: v2 - appVersion: 0.2.2 - created: "2023-04-11T12:38:12.222809-07:00" - dependencies: - - condition: helmProjectOperator.enabled - name: helmProjectOperator - repository: file://./charts/helmProjectOperator - description: Prometheus Federator - digest: 444ae559557178fce68e86322787013dd078c9365e636a8ae8a35c36ca462fe1 - icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg - name: prometheus-federator - urls: - - assets/prometheus-federator/prometheus-federator-0.2.3.tgz - version: 0.2.3 - annotations: catalog.cattle.io/certified: rancher catalog.cattle.io/display-name: Prometheus Federator @@ -276,44 +228,7 @@ entries: catalog.cattle.io/release-name: rancher-project-monitoring apiVersion: v2 appVersion: 0.59.1 - created: "2023-05-23T13:32:09.850018-07:00" - dependencies: - - condition: grafana.enabled - name: grafana - repository: file://./charts/grafana - description: Collects several related Helm charts, Grafana dashboards, and Prometheus - rules combined with documentation and scripts to provide easy to operate end-to-end - Kubernetes cluster monitoring with Prometheus. Depends on the existence of a - Cluster Prometheus deployed via Prometheus Operator - digest: dafa10c727a5fad99c20f6a5d6229b0b81139cac20e96d76540ea02222ebf2bf - home: https://github.com/prometheus-operator/kube-prometheus - icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png - keywords: - - prometheus - - monitoring - kubeVersion: '>=1.16.0-0' - maintainers: - - email: arvind.iyengar@suse.com - name: Arvind - - email: amangeet.samra@suse.com - name: Geet - url: https://github.com/geethub97 - name: rancher-project-monitoring - type: application - urls: - - assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz - version: 0.3.0 - - annotations: - catalog.cattle.io/certified: rancher - catalog.cattle.io/display-name: Project Monitoring - catalog.cattle.io/hidden: "true" - catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' - catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' - catalog.cattle.io/release-name: rancher-project-monitoring - apiVersion: v2 - appVersion: 0.59.1 - created: "2023-04-12T09:35:37.095436-07:00" + created: "2023-03-06T17:16:23.657697+01:00" dependencies: - condition: grafana.enabled name: grafana @@ -322,7 +237,7 @@ entries: rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster Prometheus deployed via Prometheus Operator - digest: 75e51f3ced73eb3e009b54d4ea93fa8f7bd09c678f6ed2a653a3822e880d0235 + digest: bce5481892fd21d7fd6eeb243f9e758728985b9eac035ca7a65e6af7ad3931de home: https://github.com/prometheus-operator/kube-prometheus icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png keywords: diff --git a/packages/prometheus-federator/charts/Chart.yaml b/packages/prometheus-federator/charts/Chart.yaml index ba842552..7790cb50 100755 --- a/packages/prometheus-federator/charts/Chart.yaml +++ b/packages/prometheus-federator/charts/Chart.yaml @@ -6,10 +6,10 @@ annotations: catalog.cattle.io/os: linux,windows catalog.cattle.io/permits-os: linux,windows catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.6.100-0' catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 -appVersion: 0.3.0 +appVersion: 0.2.1 dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator @@ -17,4 +17,4 @@ dependencies: description: Prometheus Federator icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg name: prometheus-federator -version: 0.3.0 +version: 0.2.2 diff --git a/packages/prometheus-federator/charts/values.yaml b/packages/prometheus-federator/charts/values.yaml index 4f22c1dd..8370727f 100755 --- a/packages/prometheus-federator/charts/values.yaml +++ b/packages/prometheus-federator/charts/values.yaml @@ -58,7 +58,7 @@ helmProjectOperator: image: repository: rancher/prometheus-federator - tag: v0.3.0 + tag: v0.2.1 pullPolicy: IfNotPresent # Additional arguments to be passed into the Prometheus Federator image diff --git a/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml b/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml index 8c67d60e..6533e374 100644 --- a/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml +++ b/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml @@ -1,4 +1,4 @@ workingDir: "" url: https://github.com/rancher/charts.git -subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2/charts/grafana -commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 +subdirectory: charts/rancher-monitoring/102.0.0+up40.1.2/charts/grafana +commit: 970470cf8b779b926e8ced60a10f270e401a44a4 diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/README.md b/packages/rancher-project-monitoring/generated-changes/exclude/README.md index dd2abe9c..6ef18acb 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/README.md +++ b/packages/rancher-project-monitoring/generated-changes/exclude/README.md @@ -469,7 +469,7 @@ The following table shows values exposed by Rancher Monitoring's additions to th | `namespaceOverride` | Override the deployment namespace | `"cattle-monitoring-system"` | | `global.rbac.userRoles.create` | Create default user ClusterRoles to allow users to interact with Prometheus CRs, ConfigMaps, and Secrets | `true` | | `global.rbac.userRoles.aggregateToDefaultRoles` | Aggregate default user ClusterRoles into default k8s ClusterRoles | `true` | -| `prometheus-adapter.enabled` | Whether to install [prometheus-adapter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-adapter) within the cluster | `true` | +| `prometheus-adapter.enabled` | Whether to install [prometheus-adapter](https://github.com/helm/charts/tree/master/stable/prometheus-adapter) within the cluster | `true` | | `prometheus-adapter.prometheus.url` | A URL pointing to the Prometheus deployment within your cluster. The default value is set based on the assumption that you plan to deploy the default Prometheus instance from this chart where `.Values.namespaceOverride=cattle-monitoring-system` and `.Values.nameOverride=rancher-monitoring` | `http://rancher-monitoring-prometheus.cattle-monitoring-system.svc` | | `prometheus-adapter.prometheus.port` | The port on the Prometheus deployment that Prometheus Adapter can make requests to | `9090` | | `prometheus.prometheusSpec.ignoreNamespaceSelectors` | Ignore NamespaceSelector settings from the PodMonitor and ServiceMonitor configs. If true, PodMonitors and ServiceMonitors can only discover Pods and Services within the namespace they are deployed into | `false` | diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md b/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md index 39208543..3d71158f 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md +++ b/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md @@ -8,9 +8,9 @@ The chart installs the following components: - [Prometheus Operator](https://github.com/coreos/prometheus-operator) - The operator provides easy monitoring definitions for Kubernetes services, manages [Prometheus](https://prometheus.io/) and [AlertManager](https://prometheus.io/docs/alerting/latest/alertmanager/) instances, and adds default scrape targets for some Kubernetes components. - [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) - A collection of community-curated Kubernetes manifests, Grafana Dashboards, and PrometheusRules that deploy a default end-to-end cluster monitoring configuration. -- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana) - Grafana allows a user to create / view dashboards based on the cluster metrics collected by Prometheus. -- [node-exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter) / [kube-state-metrics](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics) / [rancher-pushprox](https://github.com/rancher/charts/tree/dev-v2.7/packages/rancher-monitoring/rancher-pushprox/charts) - These charts monitor various Kubernetes components across different Kubernetes cluster types. -- [Prometheus Adapter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-adapter) - The adapter allows a user to expose custom metrics, resource metrics, and external metrics on the default [Prometheus](https://prometheus.io/) instance to the Kubernetes API Server. +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) - Grafana allows a user to create / view dashboards based on the cluster metrics collected by Prometheus. +- [node-exporter](https://github.com/helm/charts/tree/master/stable/prometheus-node-exporter) / [kube-state-metrics](https://github.com/helm/charts/tree/master/stable/kube-state-metrics) / [rancher-pushprox](https://github.com/rancher/charts/tree/dev-v2.5/packages/rancher-pushprox/charts) - These charts monitor various Kubernetes components across different Kubernetes cluster types. +- [Prometheus Adapter](https://github.com/helm/charts/tree/master/stable/prometheus-adapter) - The adapter allows a user to expose custom metrics, resource metrics, and external metrics on the default [Prometheus](https://prometheus.io/) instance to the Kubernetes API Server. For more information, review the Helm README of this chart. diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml index c3049e2a..13f5bc64 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml @@ -28,20 +28,22 @@ spec: proxyUrl: {{ .Values.coreDns.serviceMonitor.proxyUrl}} {{- end }} bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +{{- if .Values.coreDns.serviceMonitor.metricRelabelings }} metricRelabelings: - {{- if .Values.coreDns.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.coreDns.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.coreDns.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml index e73db372..46cdfc70 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml @@ -21,20 +21,22 @@ spec: {{- end }} port: https scheme: https - - metricRelabelings: - {{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }} +{{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }} + metricRelabelings: {{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.kubeApiServer.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.relabelings | indent 6) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml index 1c7e778e..9bcd9cb0 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml @@ -39,20 +39,22 @@ spec: serverName: {{ .Values.kubeControllerManager.serviceMonitor.serverName }} {{- end }} {{- end }} +{{- if .Values.kubeControllerManager.serviceMonitor.metricRelabelings }} metricRelabelings: - {{- if.Values.kubeControllerManager.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.kubeControllerManager.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml index ee930ce5..6c5365dc 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml @@ -28,20 +28,22 @@ spec: {{- if .Values.kubeDns.serviceMonitor.proxyUrl }} proxyUrl: {{ .Values.kubeDns.serviceMonitor.proxyUrl}} {{- end }} - - metricRelabelings: - {{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }} - {{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }} - {{- end }} +{{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }} + metricRelabelings: +{{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.kubeDns.serviceMonitor.dnsmasqRelabelings }} relabelings: {{ toYaml .Values.kubeDns.serviceMonitor.dnsmasqRelabelings | indent 4 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml index da4d2836..052b44da 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml @@ -50,14 +50,9 @@ spec: {{ tpl (toYaml .Values.kubeEtcd.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} {{- if .Values.kubeEtcd.serviceMonitor.relabelings }} relabelings: diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml index 762bb6a1..996aaf1e 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml @@ -33,20 +33,22 @@ spec: tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt {{- end}} - - metricRelabelings: - {{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }} + metricRelabelings: +{{ tpl (toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.kubeProxy.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeProxy.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml index d6a904bc..e07bb46a 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml @@ -39,20 +39,22 @@ spec: serverName: {{ .Values.kubeScheduler.serviceMonitor.serverName }} {{- end}} {{- end}} - - metricRelabelings: - {{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }} + metricRelabelings: +{{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end}} +{{- end }} {{- if .Values.kubeScheduler.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml index 12bdcc64..97df54a8 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml @@ -32,20 +32,24 @@ spec: insecureSkipVerify: true bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true - - metricRelabelings: - {{- if .Values.kubelet.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{- if .Values.kubelet.serviceMonitor.metricRelabelings }} + metricRelabelings: +{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - action: replace + sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - action: replace + sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.kubelet.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml index 058d6801..d6c8ae82 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml @@ -70,15 +70,15 @@ spec: {{- end }} - --localhost=127.0.0.1 {{- if .Values.prometheusOperator.prometheusDefaultBaseImage }} - - --prometheus-default-base-image={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusDefaultBaseImage }} + - --prometheus-default-base-image={{ .Values.prometheusOperator.prometheusDefaultBaseImage }} {{- end }} {{- if .Values.prometheusOperator.alertmanagerDefaultBaseImage }} - - --alertmanager-default-base-image={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.alertmanagerDefaultBaseImage }} + - --alertmanager-default-base-image={{ .Values.prometheusOperator.alertmanagerDefaultBaseImage }} {{- end }} {{- if .Values.prometheusOperator.prometheusConfigReloader.image.sha }} - - --prometheus-config-reloader={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloader.image.sha }} + - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloader.image.sha }} {{- else }} - - --prometheus-config-reloader={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }} + - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }} {{- end }} - --config-reloader-cpu-request={{ .Values.prometheusOperator.prometheusConfigReloader.resources.requests.cpu }} - --config-reloader-cpu-limit={{ .Values.prometheusOperator.prometheusConfigReloader.resources.limits.cpu }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml index 3af46529..531352a1 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml @@ -26,20 +26,22 @@ spec: {{- if .Values.prometheusOperator.serviceMonitor.interval }} interval: {{ .Values.prometheusOperator.serviceMonitor.interval }} {{- end }} +{{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }} metricRelabelings: - {{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} +{{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.prometheusOperator.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.prometheusOperator.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml index 9d410fd3..4181602b 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml @@ -30,20 +30,22 @@ spec: bearerTokenFile: {{ .Values.prometheus.thanosServiceMonitor.bearerTokenFile }} {{- end }} path: "/metrics" +{{- if .Values.prometheus.thanosServiceMonitor.metricRelabelings }} metricRelabelings: - {{- if .Values.prometheus.thanosServiceMonitor.metricRelabelings}} - {{ tpl (toYaml .Values.prometheus.thanosServiceMonitor.metricRelabelings | indent 6) . }} - {{- end }} +{{ tpl (toYaml .Values.prometheus.thanosServiceMonitor.metricRelabelings | indent 6) . }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} +{{- end }} {{- if .Values.prometheus.thanosServiceMonitor.relabelings }} relabelings: {{ toYaml .Values.prometheus.thanosServiceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml index b0f92e63..c9ebafe4 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml @@ -28,20 +28,22 @@ spec: proxyUrl: {{ .Values.ingressNginx.serviceMonitor.proxyUrl}} {{- end }} bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token +{{- if .Values.ingressNginx.serviceMonitor.metricRelabelings }} metricRelabelings: - {{- if .Values.ingressNginx.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.ingressNginx.serviceMonitor.metricRelabelings | indent 4) . }} - {{- end }} +{{ tpl (toYaml .Values.ingressNginx.serviceMonitor.metricRelabelings | indent 4) . }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} +{{ else }} + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} {{- end }} +{{- end }} {{- if .Values.ingressNginx.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.ingressNginx.serviceMonitor.relabelings | indent 4 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml index 1fba8f23..51df3c8c 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml @@ -14,18 +14,13 @@ spec: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecureSkipVerify: true serverName: rancher - metricRelabelings: - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} jobLabel: rancher + {{ if .Values.global.cattle.clusterId }} + metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} {{- if .Values.rancherMonitoring.namespaceSelector }} namespaceSelector: {{ .Values.rancherMonitoring.namespaceSelector | toYaml | nindent 4 }} {{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml index 1f2bd417..f2700a35 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml @@ -34,21 +34,20 @@ spec: tlsConfig: {{ toYaml .Values.thanosRuler.serviceMonitor.tlsConfig | nindent 6 }} {{- end }} path: "{{ trimSuffix "/" .Values.thanosRuler.thanosRulerSpec.routePrefix }}/metrics" - +{{- if .Values.thanosRuler.serviceMonitor.metricRelabelings }} metricRelabelings: - {{- if .Values.thanosRuler.serviceMonitor.metricRelabelings }} - {{ tpl (toYaml .Values.thanosRuler.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} - {{ if .Values.global.cattle.clusterId }} +{{ tpl (toYaml .Values.thanosRuler.serviceMonitor.metricRelabelings | indent 6) . }} + {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ if .Values.global.cattle.clusterName}} + {{- end }} + {{ else }} + metricRelabelings: - sourceLabels: [__address__] - targetLabel: cluster_name - replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} +{{- end }} {{- if .Values.thanosRuler.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.thanosRuler.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml b/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml index c15f36e7..0e9bc69d 100644 --- a/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml +++ b/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml @@ -30,7 +30,7 @@ questions: - variable: grafana.persistence.enabled type: boolean required: true - label: Enable Persistent Volume + label: Grafana Persistent Volume Enabled show_subquestion_if: true group: Grafana subquestions: @@ -101,7 +101,7 @@ questions: - variable: prometheus.prometheusSpec.storage.enabled type: boolean required: true - label: Enable Persistent Volume + label: Prometheus Persistent Volume Enabled show_subquestion_if: true group: Prometheus subquestions: diff --git a/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml b/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml index 535bc94e..b42c6626 100644 --- a/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml +++ b/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml @@ -17,10 +17,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -37,15 +35,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -59,7 +54,6 @@ rules: - update - patch - delete -{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -79,10 +73,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -99,15 +91,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -120,7 +109,6 @@ rules: - watch - update - patch -{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -140,10 +128,8 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" -{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" -{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -156,15 +142,12 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager -{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list -{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -176,4 +159,3 @@ rules: - list - watch {{- end }} -{{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch index 0480b685..1b856541 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch @@ -12,11 +12,10 @@ catalog.cattle.io/certified: rancher - catalog.cattle.io/deploys-on-os: windows - catalog.cattle.io/display-name: Monitoring -- catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' -- catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" -+ catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' +- catalog.cattle.io/namespace: cattle-monitoring-system catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: monitoring.coreos.com.prometheus/v1 - catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.8.0-0' @@ -72,5 +71,5 @@ -- https://github.com/prometheus-operator/kube-prometheus +name: rancher-project-monitoring type: application --version: 102.0.1+up40.1.2 +-version: 102.0.0+up40.1.2 +version: 0.1.0 diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch index e769efff..5b143a21 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch @@ -24,15 +24,16 @@ {{- if .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY value: "{{ .Values.sidecar.skipTlsVerify }}" -@@ -214,7 +210,7 @@ +@@ -214,8 +210,8 @@ {{- $root := . }} {{- range .Values.image.pullSecrets }} - name: {{ tpl . $root }} -{{- end}} -+{{- end }} {{- end }} ++{{- end }} {{- if not .Values.enableKubeBackwardCompatibility }} enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- end }} @@ -257,10 +253,8 @@ - name: UNIQUE_FILENAMES value: "{{ .Values.sidecar.enableUniqueFilenames }}" diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch index f1f423a7..cdb52683 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch @@ -9,22 +9,15 @@ location /api/dashboards { proxy_pass http://localhost:3000; -@@ -74,13 +74,12 @@ +@@ -75,7 +75,11 @@ proxy_pass http://localhost:3000/; sub_filter_once off; -- -- {{- if eq .Values.global.cattle.clusterId "local" -}} -- sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; -- {{- else -}} +{{- if not (empty .Values.global.cattle.clusterId) }} sub_filter '"appSubUrl":""' '"appSubUrl":"/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; -- {{- end -}} -- +{{- else }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- end }} -+ sub_filter '"url":"/' '"url":"./'; + sub_filter '"url":"/' '"url":"./'; sub_filter ':"/avatar/' ':"avatar/'; - if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch index 1858ea46..32f08393 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch @@ -360,27 +360,3 @@ {{- range .Values.global.imagePullSecrets }} {{- if eq (typeOf .) "map[string]interface {}" }} - {{ toYaml . | trim }} -@@ -382,3 +231,22 @@ - {{- end }} - {{- end }} - {{- end -}} -+ -+ -+{{/* Define ingress for all hardened namespaces */}} -+{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} -+{{- $root := index . 0 }} -+{{- $ns := index . 1 }} -+{{- if $root.Values.global.networkPolicy.ingress -}} -+{{ toYaml $root.Values.global.networkPolicy.ingress }} -+{{- end }} -+{{- if $root.Values.global.networkPolicy.limitIngressToProject }} -+- from: -+{{- if $root.Values.global.cattle.projectNamespaceSelector }} -+ - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} -+{{- end }} -+ - namespaceSelector: -+ matchLabels: -+ kubernetes.io/metadata.name: {{ $ns }} -+{{- end }} -+{{- end -}} -\ No newline at end of file diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch index e6f85e42..3993c276 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch @@ -31,10 +31,11 @@ {{- end }} access: proxy isDefault: true -@@ -39,23 +39,6 @@ +@@ -38,23 +38,6 @@ + exemplarTraceIdDestinations: - datasourceUid: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.datasourceUid }} name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} - {{- end }} +-{{- end }} -{{- if .Values.grafana.sidecar.datasources.createPrometheusReplicasDatasources }} -{{- range until (int .Values.prometheus.prometheusSpec.replicas) }} - - name: Prometheus-{{ . }} @@ -51,7 +52,6 @@ - name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} -{{- end }} -{{- end }} --{{- end }} + {{- end }} {{- end }} {{- if .Values.grafana.additionalDataSources }} - {{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch index 097cd631..7161e2a8 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch @@ -40,23 +40,25 @@ ], "spaceLength": 10, "span": 12, -@@ -90,15 +80,7 @@ +@@ -90,17 +80,9 @@ "steppedLine": false, "targets": [ { - "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", node=~\"$node\", resource=\"cpu\"})", -- "format": "time_series", -- "intervalFactor": 2, ++ "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, - "legendFormat": "max capacity", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", -+ "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, +- "format": "time_series", +- "intervalFactor": 2, "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 @@ -336,7 +318,7 @@ ], "targets": [ @@ -121,23 +123,25 @@ ], "spaceLength": 10, "span": 12, -@@ -485,15 +457,7 @@ +@@ -485,17 +457,9 @@ "steppedLine": false, "targets": [ { - "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", node=~\"$node\", resource=\"memory\"})", -- "format": "time_series", -- "intervalFactor": 2, ++ "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, - "legendFormat": "max capacity", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)", -+ "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, +- "format": "time_series", +- "intervalFactor": 2, "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 @@ -788,7 +752,7 @@ ], "targets": [ diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch index d9cebe4d..20149054 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch @@ -344,7 +344,7 @@ "tagValuesQuery": "", "tags": [ -@@ -2106,45 +2111,13 @@ +@@ -2106,42 +2111,10 @@ "options": [ ], @@ -353,9 +353,9 @@ "refresh": 2, "regex": "", "sort": 1, - "tagValuesQuery": "", - "tags": [ - +- "tagValuesQuery": "", +- "tags": [ +- - ], - "tagsQuery": "", - "type": "query", @@ -385,9 +385,6 @@ - "regex": "", - "skipUrlSync": false, - "sort": 0, -- "tagValuesQuery": "", -- "tags": [ -- - ], - "tagsQuery": "", - "type": "query", + "tagValuesQuery": "", + "tags": [ + diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch deleted file mode 100644 index 21943276..00000000 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- charts-original/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml -+++ charts/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml -@@ -8,16 +8,16 @@ - apiVersion: v1 - kind: ConfigMap - metadata: -- namespace: {{ .Values.grafana.defaultDashboards.namespace }} -- name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} -+ namespace: {{ template "project-prometheus-stack.namespace" . }} -+ name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} - annotations: - {{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} - {{- end }} -- app: {{ template "kube-prometheus-stack.name" $ }}-grafana --{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -+ app: {{ template "project-prometheus-stack.name" $ }}-grafana -+{{ include "project-prometheus-stack.labels" $ | indent 4 }} - data: - prometheus-remote-write.json: |- - { diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch index 4068cb02..bc0129ae 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch @@ -158,21 +158,23 @@ {{- end }} {{- end }} tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} -@@ -264,41 +230,12 @@ +@@ -264,42 +230,13 @@ {{- end }} {{- if .Values.global.imagePullSecrets }} imagePullSecrets: -{{ include "kube-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} --{{- end }} ++{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} + {{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigs }} -- additionalScrapeConfigs: ++{{- if .Values.federate.enabled }} + additionalScrapeConfigs: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-scrape-confg - key: additional-scrape-configs.yaml -+{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} ++ name: {{ template "project-prometheus-stack.fullname" . }}-federate ++ key: federate-scrape-config.yaml {{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.enabled }} -+{{- if .Values.federate.enabled }} - additionalScrapeConfigs: +- additionalScrapeConfigs: - name: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.name }} - key: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.key }} -{{- end }} @@ -199,11 +201,10 @@ - additionalAlertRelabelConfigs: - name: {{ .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigsSecret.name }} - key: {{ .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigsSecret.key }} -+ name: {{ template "project-prometheus-stack.fullname" . }}-federate -+ key: federate-scrape-config.yaml - {{- end }} +-{{- end }} {{- if .Values.prometheus.prometheusSpec.containers }} containers: + {{ tpl .Values.prometheus.prometheusSpec.containers $ | indent 4 }} @@ -311,10 +248,6 @@ {{- if .Values.prometheus.prometheusSpec.priorityClassName }} priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch index 0d333277..ba6ac1dd 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch @@ -18,12 +18,13 @@ spec: privileged: false # Allow core volume types. -@@ -49,8 +49,4 @@ +@@ -48,9 +48,5 @@ + {{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} allowedCapabilities: {{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} - {{- end }} +-{{- end }} -{{- if .Values.prometheus.podSecurityPolicy.allowedHostPaths }} - allowedHostPaths: -{{ toYaml .Values.prometheus.podSecurityPolicy.allowedHostPaths | indent 4 }} --{{- end }} + {{- end }} {{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch index cef1b08a..1d6bdede 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch @@ -110,7 +110,7 @@ spec: privileged: false hostNetwork: false -@@ -108,21 +111,19 @@ +@@ -108,6 +111,7 @@ readOnlyRootFilesystem: false volumes: - 'secret' @@ -118,22 +118,11 @@ {{- range $_, $ns := $namespaces }} --- apiVersion: networking.k8s.io/v1 - kind: NetworkPolicy - metadata: -- name: default-allow-all -+ name: project-monitoring-policy - namespace: {{ $ns }} - spec: - podSelector: {} -- ingress: -- - {} -- egress: -- - {} -+ ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} -+ egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} +@@ -124,5 +128,4 @@ policyTypes: - Ingress - Egress - {{- end }} +-{{- end }} -{{- end }} \ No newline at end of file ++{{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch index 16d3e9e3..2d8cee62 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch @@ -560,7 +560,7 @@ - ## Image to use to run the scripts - image: - repository: rancher/shell -- tag: v0.1.19 +- tag: v0.1.18 - -## Rancher Monitoring -## @@ -672,15 +672,15 @@ ## Reduce app namespace alert scope appNamespacesTarget: ".*" -@@ -696,28 +62,6 @@ +@@ -696,59 +62,43 @@ ## Disabled PrometheusRule alerts disabled: {} - # KubeAPIDown: true - # NodeRAIDDegraded: true -- + -## Deprecated way to provide custom recording or alerting rules to be deployed into the cluster. --## + ## -# additionalPrometheusRules: [] -# - name: my-rule-file -# groups: @@ -698,10 +698,10 @@ -# rules: -# - record: my_record -# expr: 100 * my_record - - ## +- +-## global: -@@ -725,30 +69,47 @@ + cattle: psp: enabled: false systemDefaultRegistry: "" @@ -725,17 +725,6 @@ + securityContext: + runAsNonRoot: true + runAsUser: 1000 -+ networkPolicy: -+ # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. -+ # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, -+ # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs -+ # through the Rancher/Kubernetes API Proxy in the Rancher UI. -+ limitIngressToProject: false -+ # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. -+ ingress: null -+ # By default, all egress traffic is allowed. -+ egress: -+ - {} rbac: ## Create RBAC resources for ServiceAccounts and users ## @@ -762,7 +751,7 @@ aggregateToDefaultRoles: true pspAnnotations: {} -@@ -769,6 +130,19 @@ +@@ -769,6 +119,19 @@ # or # - "image-pull-secret" @@ -782,7 +771,7 @@ ## Configuration for alertmanager ## ref: https://prometheus.io/docs/alerting/alertmanager/ ## -@@ -978,50 +352,6 @@ +@@ -978,50 +341,6 @@ secret: annotations: {} @@ -833,7 +822,7 @@ ## Configuration for Alertmanager service ## service: -@@ -1062,36 +392,6 @@ +@@ -1062,36 +381,6 @@ ## type: ClusterIP @@ -870,7 +859,7 @@ ## If true, create a serviceMonitor for alertmanager ## serviceMonitor: -@@ -1148,11 +448,6 @@ +@@ -1148,11 +437,6 @@ tag: v0.24.0 sha: "" @@ -882,7 +871,7 @@ ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. ## -@@ -1174,39 +469,13 @@ +@@ -1174,40 +458,14 @@ ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. ## @@ -901,7 +890,14 @@ - # alertmanagerConfigSelector: - # matchLabels: - # role: example-config -- ++ alertmanagerConfigSelector: ++ # default ignores resources created by Rancher Monitoring ++ matchExpressions: ++ - key: release ++ operator: NotIn ++ values: ++ - rancher-monitoring + - ## Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace. - ## - alertmanagerConfigNamespaceSelector: {} @@ -919,17 +915,11 @@ - # alertmanagerConfigNamespaceSelector: - # matchLabels: - # alertmanagerconfig: enabled -+ alertmanagerConfigSelector: -+ # default ignores resources created by Rancher Monitoring -+ matchExpressions: -+ - key: release -+ operator: NotIn -+ values: -+ - rancher-monitoring - +- ## AlermanagerConfig to be used as top level configuration ## -@@ -1417,9 +686,6 @@ + alertmanagerConfiguration: {} +@@ -1417,9 +675,6 @@ org_role: Viewer auth.basic: enabled: false @@ -939,7 +929,7 @@ security: # Required to embed dashboards in Rancher Cluster Overview Dashboard on Cluster Explorer allow_embedding: true -@@ -1439,18 +705,6 @@ +@@ -1439,18 +694,6 @@ ## defaultDashboardsEnabled: true @@ -958,7 +948,7 @@ ## Timezone for the default dashboards ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg ## -@@ -1500,7 +754,6 @@ +@@ -1500,17 +743,11 @@ dashboards: enabled: true label: grafana_dashboard @@ -966,16 +956,17 @@ labelValue: "1" ## Annotations for Grafana dashboard configmaps -@@ -1509,8 +762,6 @@ - multicluster: - global: - enabled: false + ## + annotations: {} +- multicluster: +- global: +- enabled: false - etcd: - enabled: false provider: allowUiUpdates: false datasources: -@@ -1530,11 +781,6 @@ +@@ -1530,11 +767,6 @@ ## annotations: {} @@ -987,7 +978,7 @@ label: grafana_datasource labelValue: "1" -@@ -1652,538 +898,8 @@ +@@ -1652,294 +884,10 @@ tlsConfig: {} scrapeTimeout: 30s @@ -1034,9 +1025,10 @@ - component: apiserver - provider: kubernetes - -- ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -- ## ++ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## - metricRelabelings: - # Drop excessively noisy apiserver buckets. - - action: drop @@ -1198,7 +1190,7 @@ - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## -- metricRelabelings: [] + metricRelabelings: [] - # - sourceLabels: [__name__, image] - # separator: ; - # regex: container_([a-z_]+); @@ -1279,21 +1271,13 @@ - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] -- # - action: keep -- # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' -- # sourceLabels: [__name__] -- -- ## RelabelConfigs to apply to samples before scraping -- ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -- ## -- relabelings: [] -- # - sourceLabels: [__meta_kubernetes_pod_node_name] -- # separator: ; -- # regex: ^(.*)$ -- # targetLabel: nodename -- # replacement: $1 -- # action: replace -- + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] +@@ -1955,735 +903,17 @@ + # replacement: $1 + # action: replace + - ## Additional labels - ## - additionalLabels: {} @@ -1521,16 +1505,25 @@ - ## Name of the server to use when validating TLS certificate - serverName: null - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. +- ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -+ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] - # - action: keep -@@ -2201,488 +917,16 @@ - # replacement: $1 - # action: replace - +- ## +- metricRelabelings: [] +- # - action: keep +- # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' +- # sourceLabels: [__name__] +- +- ## RelabelConfigs to apply to samples before scraping +- ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig +- ## +- relabelings: [] +- # - sourceLabels: [__meta_kubernetes_pod_node_name] +- # separator: ; +- # regex: ^(.*)$ +- # targetLabel: nodename +- # replacement: $1 +- # action: replace +- - ## Additional labels - ## - additionalLabels: {} @@ -1921,7 +1914,9 @@ - # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working - ## - hostNetwork: false -- ++ testFramework: ++ enabled: false + - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## @@ -2015,12 +2010,11 @@ - ## Set a Field Selector to filter watched secrets - ## - secretFieldSelector: "" -+ testFramework: -+ enabled: false - +- ## Deploy a Prometheus instance ## -@@ -2702,96 +946,6 @@ + prometheus: +@@ -2702,96 +932,6 @@ name: "" annotations: {} @@ -2117,7 +2111,7 @@ ## Configuration for Prometheus service ## service: -@@ -2842,36 +996,6 @@ +@@ -2842,36 +982,6 @@ sessionAffinity: "" @@ -2154,7 +2148,7 @@ ## Configure pod disruption budgets for Prometheus ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget ## This configuration is immutable once created and will require the PDB to be deleted to be changed -@@ -2882,46 +1006,6 @@ +@@ -2882,46 +992,6 @@ minAvailable: 1 maxUnavailable: "" @@ -2201,7 +2195,7 @@ ## ExtraSecret can be used to store various data in an extra secret ## (use it for example to store hashed basic auth credentials) extraSecret: -@@ -2970,55 +1054,10 @@ +@@ -2970,55 +1040,10 @@ # hosts: # - prometheus.example.com @@ -2257,7 +2251,7 @@ volumes: [] serviceMonitor: -@@ -3031,7 +1070,7 @@ +@@ -3031,7 +1056,7 @@ scheme: "" ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. @@ -2266,7 +2260,7 @@ tlsConfig: {} bearerTokenFile: -@@ -3069,7 +1108,7 @@ +@@ -3069,7 +1094,7 @@ ## Defaults to 30s. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 ## @@ -2275,7 +2269,7 @@ ## Number of seconds to wait for target to respond before erroring ## -@@ -3077,7 +1116,7 @@ +@@ -3077,7 +1102,7 @@ ## Interval between consecutive evaluations. ## @@ -2284,7 +2278,7 @@ ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. ## -@@ -3156,14 +1195,6 @@ +@@ -3156,14 +1181,6 @@ ## enableRemoteWriteReceiver: false @@ -2299,7 +2293,7 @@ ## Name of the external label used to denote Prometheus instance name ## prometheusExternalLabelName: "" -@@ -3198,12 +1229,6 @@ +@@ -3198,12 +1215,6 @@ ## query: {} @@ -2312,7 +2306,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, ## which will also match the PrometheusRule resources created -@@ -3213,21 +1238,13 @@ +@@ -3213,21 +1224,13 @@ ## PrometheusRules to be selected for target discovery. ## If {}, select all PrometheusRules ## @@ -2341,7 +2335,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3238,19 +1255,13 @@ +@@ -3238,20 +1241,14 @@ ## ServiceMonitors to be selected for target discovery. ## If {}, select all ServiceMonitors ## @@ -2350,14 +2344,6 @@ - # serviceMonitorSelector: - # matchLabels: - # prometheus: somelabel -- -- ## Namespaces to be selected for ServiceMonitor discovery. -- ## -- serviceMonitorNamespaceSelector: {} -- ## Example which selects ServiceMonitors in namespaces with label "prometheus" set to "somelabel" -- # serviceMonitorNamespaceSelector: -- # matchLabels: -- # prometheus: somelabel + serviceMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2366,9 +2352,18 @@ + values: + - rancher-monitoring +- ## Namespaces to be selected for ServiceMonitor discovery. +- ## +- serviceMonitorNamespaceSelector: {} +- ## Example which selects ServiceMonitors in namespaces with label "prometheus" set to "somelabel" +- # serviceMonitorNamespaceSelector: +- # matchLabels: +- # prometheus: somelabel +- ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3261,16 +1272,13 @@ + ## which will also match the podmonitors created +@@ -3261,17 +1258,14 @@ ## PodMonitors to be selected for target discovery. ## If {}, select all PodMonitors ## @@ -2377,11 +2372,6 @@ - # podMonitorSelector: - # matchLabels: - # prometheus: somelabel -- -- ## Namespaces to be selected for PodMonitor discovery. -- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage -- ## -- podMonitorNamespaceSelector: {} + podMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2390,9 +2380,15 @@ + values: + - rancher-monitoring +- ## Namespaces to be selected for PodMonitor discovery. +- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage +- ## +- podMonitorNamespaceSelector: {} +- ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3281,16 +1289,13 @@ + ## which will also match the probes created +@@ -3281,24 +1275,21 @@ ## Probes to be selected for target discovery. ## If {}, select all Probes ## @@ -2401,11 +2397,6 @@ - # probeSelector: - # matchLabels: - # prometheus: somelabel -- -- ## Namespaces to be selected for Probe discovery. -- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage -- ## -- probeNamespaceSelector: {} + probeSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2414,9 +2405,14 @@ + values: + - rancher-monitoring +- ## Namespaces to be selected for Probe discovery. +- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage +- ## +- probeNamespaceSelector: {} +- ## How long to retain metrics ## -@@ -3298,7 +1303,7 @@ + retention: 10d ## Maximum size of metrics ## @@ -2425,7 +2421,7 @@ ## Enable compression of the write-ahead log using Snappy. ## -@@ -3368,13 +1373,6 @@ +@@ -3368,13 +1359,6 @@ # - e2e-az1 # - e2e-az2 @@ -2439,7 +2435,7 @@ ## The remote_write spec configuration for Prometheus. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec remoteWrite: [] -@@ -3395,6 +1393,8 @@ +@@ -3395,6 +1379,8 @@ memory: 750Mi cpu: 750m @@ -2448,7 +2444,7 @@ ## Prometheus StorageSpec for persistent data ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md ## -@@ -3427,122 +1427,9 @@ +@@ -3427,122 +1413,9 @@ # Additional VolumeMounts on the output StatefulSet definition. volumeMounts: [] @@ -2572,7 +2568,7 @@ ## securityContext: runAsGroup: 2000 -@@ -3554,20 +1441,6 @@ +@@ -3554,20 +1427,6 @@ ## priorityClassName: "" @@ -2593,7 +2589,7 @@ proxy: image: repository: rancher/mirrored-library-nginx -@@ -3575,7 +1448,7 @@ +@@ -3575,7 +1434,7 @@ ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. ## if using proxy extraContainer update targetPort with proxy container port @@ -2602,7 +2598,16 @@ - name: prometheus-proxy args: - nginx -@@ -3616,10 +1489,6 @@ +@@ -3583,7 +1442,7 @@ + - daemon off; + - -c + - /nginx/nginx.conf +- image: rancher/mirrored-library-nginx:1.21.1-alpine ++ image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.proxy.image.repository }}:{{ .Values.prometheus.prometheusSpec.proxy.image.tag }}" + ports: + - containerPort: 8081 + name: nginx-http +@@ -3616,10 +1475,6 @@ ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. overrideHonorTimestamps: false @@ -2613,10 +2618,11 @@ ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. ## The label value will always be the namespace of the object that is being created. ## Disabled by default -@@ -3677,514 +1546,6 @@ +@@ -3676,514 +1531,6 @@ + ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). minReadySeconds: 0 - +- - additionalRulesForClusterRole: [] - # - apiGroups: [ "" ] - # resources: @@ -3124,7 +3130,6 @@ - # auth: | - # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 - # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. -- + ## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. ## - cleanPrometheusOperatorObjectNames: false diff --git a/packages/rancher-project-monitoring/package.yaml b/packages/rancher-project-monitoring/package.yaml index 75712fe0..06d1467f 100644 --- a/packages/rancher-project-monitoring/package.yaml +++ b/packages/rancher-project-monitoring/package.yaml @@ -1,8 +1,8 @@ workingDir: "" url: https://github.com/rancher/charts.git -subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2 -commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 -version: 0.3.0 +subdirectory: charts/rancher-monitoring/102.0.0+up40.1.2 +commit: 970470cf8b779b926e8ced60a10f270e401a44a4 +version: 0.2.2 ignoreDependencies: - hardenedKubelet - hardenedNodeExporter From afc21d3f5a6c1f03b32ebb942d8b287b5be07b52 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:50:51 -0700 Subject: [PATCH 02/21] Rebase rancher-project-monitoring to 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 --- .../patch/charts/grafana/Chart.yaml.patch | 10 ++ .../charts/grafana/templates/_pod.tpl.patch | 5 +- .../grafana/templates/nginx-config.yaml.patch | 10 +- .../templates/servicemonitor.yaml.patch | 29 ++++ .../alertmanager/servicemonitor.yaml.patch | 29 ++++ .../grafana/configmaps-datasources.yaml.patch | 8 +- .../k8s-resources-node.yaml.patch | 28 ++-- ...s-resources-workloads-namespace.yaml.patch | 17 ++- .../prometheus/prometheus.yaml.patch | 19 ++- .../patch/templates/prometheus/psp.yaml.patch | 7 +- .../prometheus/servicemonitor.yaml.patch | 29 ++++ .../rancher-monitoring/hardened.yaml.patch | 6 +- .../generated-changes/patch/values.yaml.patch | 126 +++++++++--------- 13 files changed, 213 insertions(+), 110 deletions(-) create mode 100644 packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch create mode 100644 packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch new file mode 100644 index 00000000..543859e3 --- /dev/null +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch @@ -0,0 +1,10 @@ +--- charts-original/charts/grafana/Chart.yaml ++++ charts/charts/grafana/Chart.yaml +@@ -1,6 +1,6 @@ + annotations: + catalog.cattle.io/hidden: "true" +- catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.25.0-0' ++ catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' + catalog.cattle.io/os: linux + catalog.rancher.io/certified: rancher + catalog.rancher.io/namespace: cattle-monitoring-system diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch index 5b143a21..e769efff 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/_pod.tpl.patch @@ -24,16 +24,15 @@ {{- if .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY value: "{{ .Values.sidecar.skipTlsVerify }}" -@@ -214,8 +210,8 @@ +@@ -214,7 +210,7 @@ {{- $root := . }} {{- range .Values.image.pullSecrets }} - name: {{ tpl . $root }} -{{- end}} - {{- end }} +{{- end }} + {{- end }} {{- if not .Values.enableKubeBackwardCompatibility }} enableServiceLinks: {{ .Values.enableServiceLinks }} - {{- end }} @@ -257,10 +253,8 @@ - name: UNIQUE_FILENAMES value: "{{ .Values.sidecar.enableUniqueFilenames }}" diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch index cdb52683..90ead7b8 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch @@ -9,7 +9,15 @@ location /api/dashboards { proxy_pass http://localhost:3000; -@@ -75,7 +75,11 @@ +@@ -52,7 +52,6 @@ + + sub_filter_types application/json; + sub_filter_once off; +- sub_filter '"url":"/d' '"url":"d'; + } + + location /api/live/ { +@@ -75,7 +74,11 @@ proxy_pass http://localhost:3000/; sub_filter_once off; diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch new file mode 100644 index 00000000..fdbcd204 --- /dev/null +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch @@ -0,0 +1,29 @@ +--- charts-original/charts/grafana/templates/servicemonitor.yaml ++++ charts/charts/grafana/templates/servicemonitor.yaml +@@ -30,21 +30,19 @@ + tlsConfig: + {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} +- {{- if .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: ++ {{- if .Values.serviceMonitor.metricRelabelings }} + {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 6 }} +- {{ if .Values.global.cattle.clusterId }} +- - sourceLabels: [__address__] +- targetLabel: cluster_id +- replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} +- {{ else }} + {{ if .Values.global.cattle.clusterId }} +- metricRelabelings: + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} ++ {{ if .Values.global.cattle.clusterName }} ++ - sourceLabels: [__address__] ++ targetLabel: cluster_name ++ replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} + {{- if .Values.serviceMonitor.relabelings }} + relabelings: diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch index af50cb4b..3ab1dc2c 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch @@ -27,3 +27,32 @@ endpoints: - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} {{- if .Values.alertmanager.serviceMonitor.interval }} +@@ -34,22 +34,20 @@ + tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" +-{{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} + metricRelabelings: +-{{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} ++ {{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} ++ {{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} ++ {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} +-{{ else }} +- {{ if .Values.global.cattle.clusterId }} +- metricRelabelings: ++ {{ if .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] +- targetLabel: cluster_id +- replacement: {{ .Values.global.cattle.clusterId }} ++ targetLabel: cluster_name ++ replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +-{{- end }} + {{- if .Values.alertmanager.serviceMonitor.relabelings }} + relabelings: + {{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch index 3993c276..e6f85e42 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/configmaps-datasources.yaml.patch @@ -31,11 +31,10 @@ {{- end }} access: proxy isDefault: true -@@ -38,23 +38,6 @@ - exemplarTraceIdDestinations: +@@ -39,23 +39,6 @@ - datasourceUid: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.datasourceUid }} name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} --{{- end }} + {{- end }} -{{- if .Values.grafana.sidecar.datasources.createPrometheusReplicasDatasources }} -{{- range until (int .Values.prometheus.prometheusSpec.replicas) }} - - name: Prometheus-{{ . }} @@ -52,6 +51,7 @@ - name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} -{{- end }} -{{- end }} - {{- end }} +-{{- end }} {{- end }} {{- if .Values.grafana.additionalDataSources }} + {{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch index 7161e2a8..097cd631 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-node.yaml.patch @@ -40,25 +40,23 @@ ], "spaceLength": 10, "span": 12, -@@ -90,17 +80,9 @@ +@@ -90,15 +80,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", node=~\"$node\", resource=\"cpu\"})", -+ "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, +- "format": "time_series", +- "intervalFactor": 2, - "legendFormat": "max capacity", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", -- "format": "time_series", -- "intervalFactor": 2, ++ "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 @@ -336,7 +318,7 @@ ], "targets": [ @@ -123,25 +121,23 @@ ], "spaceLength": 10, "span": 12, -@@ -485,17 +457,9 @@ +@@ -485,15 +457,7 @@ "steppedLine": false, "targets": [ { - "expr": "sum(kube_node_status_capacity{cluster=\"$cluster\", node=~\"$node\", resource=\"memory\"})", -+ "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, +- "format": "time_series", +- "intervalFactor": 2, - "legendFormat": "max capacity", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)", -- "format": "time_series", -- "intervalFactor": 2, ++ "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 @@ -788,7 +752,7 @@ ], "targets": [ diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch index 20149054..d9cebe4d 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml.patch @@ -344,7 +344,7 @@ "tagValuesQuery": "", "tags": [ -@@ -2106,42 +2111,10 @@ +@@ -2106,45 +2111,13 @@ "options": [ ], @@ -353,9 +353,9 @@ "refresh": 2, "regex": "", "sort": 1, -- "tagValuesQuery": "", -- "tags": [ -- + "tagValuesQuery": "", + "tags": [ + - ], - "tagsQuery": "", - "type": "query", @@ -385,6 +385,9 @@ - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - +- "tagValuesQuery": "", +- "tags": [ +- + ], + "tagsQuery": "", + "type": "query", diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch index bc0129ae..4068cb02 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/prometheus.yaml.patch @@ -158,23 +158,21 @@ {{- end }} {{- end }} tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} -@@ -264,42 +230,13 @@ +@@ -264,41 +230,12 @@ {{- end }} {{- if .Values.global.imagePullSecrets }} imagePullSecrets: -{{ include "kube-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} -+{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} - {{- end }} +-{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigs }} -+{{- if .Values.federate.enabled }} - additionalScrapeConfigs: +- additionalScrapeConfigs: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-scrape-confg - key: additional-scrape-configs.yaml -+ name: {{ template "project-prometheus-stack.fullname" . }}-federate -+ key: federate-scrape-config.yaml ++{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} {{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.enabled }} -- additionalScrapeConfigs: ++{{- if .Values.federate.enabled }} + additionalScrapeConfigs: - name: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.name }} - key: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.key }} -{{- end }} @@ -201,10 +199,11 @@ - additionalAlertRelabelConfigs: - name: {{ .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigsSecret.name }} - key: {{ .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigsSecret.key }} --{{- end }} ++ name: {{ template "project-prometheus-stack.fullname" . }}-federate ++ key: federate-scrape-config.yaml + {{- end }} {{- if .Values.prometheus.prometheusSpec.containers }} containers: - {{ tpl .Values.prometheus.prometheusSpec.containers $ | indent 4 }} @@ -311,10 +248,6 @@ {{- if .Values.prometheus.prometheusSpec.priorityClassName }} priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch index ba6ac1dd..0d333277 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/psp.yaml.patch @@ -18,13 +18,12 @@ spec: privileged: false # Allow core volume types. -@@ -48,9 +48,5 @@ - {{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} +@@ -49,8 +49,4 @@ allowedCapabilities: {{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} --{{- end }} + {{- end }} -{{- if .Values.prometheus.podSecurityPolicy.allowedHostPaths }} - allowedHostPaths: -{{ toYaml .Values.prometheus.podSecurityPolicy.allowedHostPaths | indent 4 }} - {{- end }} +-{{- end }} {{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch index 3a1c6380..783281c7 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch @@ -27,3 +27,32 @@ endpoints: - port: {{ .Values.prometheus.prometheusSpec.portName }} {{- if .Values.prometheus.serviceMonitor.interval }} +@@ -31,22 +31,20 @@ + bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} + {{- end }} + path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" +-{{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: +-{{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} ++ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} ++ {{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} ++ {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} +- {{ else }} +- {{ if .Values.global.cattle.clusterId }} +- metricRelabelings: ++ {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] +- targetLabel: cluster_id +- replacement: {{ .Values.global.cattle.clusterId }} ++ targetLabel: cluster_name ++ replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +-{{- end }} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch index 1d6bdede..686fd7f9 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch @@ -118,11 +118,9 @@ {{- range $_, $ns := $namespaces }} --- apiVersion: networking.k8s.io/v1 -@@ -124,5 +128,4 @@ - policyTypes: +@@ -125,4 +129,3 @@ - Ingress - Egress --{{- end }} + {{- end }} -{{- end }} \ No newline at end of file -+{{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch index 2d8cee62..2bb9f642 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch @@ -672,15 +672,15 @@ ## Reduce app namespace alert scope appNamespacesTarget: ".*" -@@ -696,59 +62,43 @@ +@@ -696,28 +62,6 @@ ## Disabled PrometheusRule alerts disabled: {} - # KubeAPIDown: true - # NodeRAIDDegraded: true - +- -## Deprecated way to provide custom recording or alerting rules to be deployed into the cluster. - ## +-## -# additionalPrometheusRules: [] -# - name: my-rule-file -# groups: @@ -698,10 +698,10 @@ -# rules: -# - record: my_record -# expr: 100 * my_record -- --## + + ## global: - cattle: +@@ -725,30 +69,36 @@ psp: enabled: false systemDefaultRegistry: "" @@ -871,7 +871,7 @@ ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. ## -@@ -1174,40 +458,14 @@ +@@ -1174,39 +458,13 @@ ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. ## @@ -890,14 +890,7 @@ - # alertmanagerConfigSelector: - # matchLabels: - # role: example-config -+ alertmanagerConfigSelector: -+ # default ignores resources created by Rancher Monitoring -+ matchExpressions: -+ - key: release -+ operator: NotIn -+ values: -+ - rancher-monitoring - +- - ## Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace. - ## - alertmanagerConfigNamespaceSelector: {} @@ -915,10 +908,16 @@ - # alertmanagerConfigNamespaceSelector: - # matchLabels: - # alertmanagerconfig: enabled -- ++ alertmanagerConfigSelector: ++ # default ignores resources created by Rancher Monitoring ++ matchExpressions: ++ - key: release ++ operator: NotIn ++ values: ++ - rancher-monitoring + ## AlermanagerConfig to be used as top level configuration ## - alertmanagerConfiguration: {} @@ -1417,9 +675,6 @@ org_role: Viewer auth.basic: @@ -978,7 +977,16 @@ label: grafana_datasource labelValue: "1" -@@ -1652,294 +884,10 @@ +@@ -1591,7 +823,7 @@ + proxy: + image: + repository: rancher/mirrored-library-nginx +- tag: 1.21.1-alpine ++ tag: 1.24.0-alpine + + ## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod + extraContainers: | +@@ -1652,292 +884,8 @@ tlsConfig: {} scrapeTimeout: 30s @@ -1027,8 +1035,7 @@ - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -+ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## +- ## - metricRelabelings: - # Drop excessively noisy apiserver buckets. - - action: drop @@ -1190,7 +1197,7 @@ - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] +- metricRelabelings: [] - # - sourceLabels: [__name__, image] - # separator: ; - # regex: container_([a-z_]+); @@ -1269,12 +1276,11 @@ - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -- ## -- metricRelabelings: [] ++ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] -@@ -1955,735 +903,17 @@ +@@ -1955,734 +903,16 @@ # replacement: $1 # action: replace @@ -1914,9 +1920,7 @@ - # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working - ## - hostNetwork: false -+ testFramework: -+ enabled: false - +- - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## @@ -2010,10 +2014,11 @@ - ## Set a Field Selector to filter watched secrets - ## - secretFieldSelector: "" -- ++ testFramework: ++ enabled: false + ## Deploy a Prometheus instance ## - prometheus: @@ -2702,96 +932,6 @@ name: "" annotations: {} @@ -2335,7 +2340,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3238,20 +1241,14 @@ +@@ -3238,19 +1241,13 @@ ## ServiceMonitors to be selected for target discovery. ## If {}, select all ServiceMonitors ## @@ -2344,6 +2349,14 @@ - # serviceMonitorSelector: - # matchLabels: - # prometheus: somelabel +- +- ## Namespaces to be selected for ServiceMonitor discovery. +- ## +- serviceMonitorNamespaceSelector: {} +- ## Example which selects ServiceMonitors in namespaces with label "prometheus" set to "somelabel" +- # serviceMonitorNamespaceSelector: +- # matchLabels: +- # prometheus: somelabel + serviceMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2352,18 +2365,9 @@ + values: + - rancher-monitoring -- ## Namespaces to be selected for ServiceMonitor discovery. -- ## -- serviceMonitorNamespaceSelector: {} -- ## Example which selects ServiceMonitors in namespaces with label "prometheus" set to "somelabel" -- # serviceMonitorNamespaceSelector: -- # matchLabels: -- # prometheus: somelabel -- ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the podmonitors created -@@ -3261,17 +1258,14 @@ +@@ -3261,16 +1258,13 @@ ## PodMonitors to be selected for target discovery. ## If {}, select all PodMonitors ## @@ -2372,6 +2376,11 @@ - # podMonitorSelector: - # matchLabels: - # prometheus: somelabel +- +- ## Namespaces to be selected for PodMonitor discovery. +- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage +- ## +- podMonitorNamespaceSelector: {} + podMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2380,15 +2389,9 @@ + values: + - rancher-monitoring -- ## Namespaces to be selected for PodMonitor discovery. -- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage -- ## -- podMonitorNamespaceSelector: {} -- ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the probes created -@@ -3281,24 +1275,21 @@ +@@ -3281,16 +1275,13 @@ ## Probes to be selected for target discovery. ## If {}, select all Probes ## @@ -2397,6 +2400,11 @@ - # probeSelector: - # matchLabels: - # prometheus: somelabel +- +- ## Namespaces to be selected for Probe discovery. +- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage +- ## +- probeNamespaceSelector: {} + probeSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: @@ -2405,14 +2413,9 @@ + values: + - rancher-monitoring -- ## Namespaces to be selected for Probe discovery. -- ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#namespaceselector for usage -- ## -- probeNamespaceSelector: {} -- ## How long to retain metrics ## - retention: 10d +@@ -3298,7 +1289,7 @@ ## Maximum size of metrics ## @@ -2568,7 +2571,7 @@ ## securityContext: runAsGroup: 2000 -@@ -3554,20 +1427,6 @@ +@@ -3554,28 +1427,14 @@ ## priorityClassName: "" @@ -2589,7 +2592,8 @@ proxy: image: repository: rancher/mirrored-library-nginx -@@ -3575,7 +1434,7 @@ +- tag: 1.21.1-alpine ++ tag: 1.24.0-alpine ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. ## if using proxy extraContainer update targetPort with proxy container port @@ -2618,11 +2622,10 @@ ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. ## The label value will always be the namespace of the object that is being created. ## Disabled by default -@@ -3676,514 +1531,6 @@ - ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to +@@ -3677,514 +1532,6 @@ ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). minReadySeconds: 0 -- + - additionalRulesForClusterRole: [] - # - apiGroups: [ "" ] - # resources: @@ -3130,6 +3133,7 @@ - # auth: | - # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 - # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. - +- ## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. ## + cleanPrometheusOperatorObjectNames: false From f1f1d6dacd2128160cb320b99194268c5ac38f99 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:50:52 -0700 Subject: [PATCH 03/21] Update rancher-project-monitoring to new base 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 --- .../generated-changes/exclude/README.md | 2 +- .../generated-changes/exclude/app-README.md | 6 ++-- .../exporters/core-dns/servicemonitor.yaml | 14 ++++----- .../kube-api-server/servicemonitor.yaml | 14 ++++----- .../servicemonitor.yaml | 22 +++++++------- .../exporters/kube-dns/servicemonitor.yaml | 24 +++++++-------- .../exporters/kube-etcd/servicemonitor.yaml | 11 +++++-- .../exporters/kube-proxy/servicemonitor.yaml | 24 +++++++-------- .../kube-scheduler/servicemonitor.yaml | 26 ++++++++--------- .../exporters/kubelet/servicemonitor.yaml | 26 +++++++---------- .../prometheus-operator/deployment.yaml | 8 ++--- .../prometheus-operator/servicemonitor.yaml | 22 +++++++------- .../servicemonitorThanosSidecar.yaml | 16 +++++----- .../ingress-nginx/servicemonitor.yaml | 22 +++++++------- .../exporters/rancher/servicemonitor.yaml | 17 +++++++---- .../thanos-ruler/servicemonitor.yaml | 19 ++++++------ .../generated-changes/patch/Chart.yaml.patch | 7 +++-- .../alertmanager/servicemonitor.yaml.patch | 29 ------------------- .../prometheus/servicemonitor.yaml.patch | 29 ------------------- .../generated-changes/patch/values.yaml.patch | 25 ++-------------- .../rancher-project-monitoring/package.yaml | 4 +-- 21 files changed, 140 insertions(+), 227 deletions(-) diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/README.md b/packages/rancher-project-monitoring/generated-changes/exclude/README.md index 6ef18acb..dd2abe9c 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/README.md +++ b/packages/rancher-project-monitoring/generated-changes/exclude/README.md @@ -469,7 +469,7 @@ The following table shows values exposed by Rancher Monitoring's additions to th | `namespaceOverride` | Override the deployment namespace | `"cattle-monitoring-system"` | | `global.rbac.userRoles.create` | Create default user ClusterRoles to allow users to interact with Prometheus CRs, ConfigMaps, and Secrets | `true` | | `global.rbac.userRoles.aggregateToDefaultRoles` | Aggregate default user ClusterRoles into default k8s ClusterRoles | `true` | -| `prometheus-adapter.enabled` | Whether to install [prometheus-adapter](https://github.com/helm/charts/tree/master/stable/prometheus-adapter) within the cluster | `true` | +| `prometheus-adapter.enabled` | Whether to install [prometheus-adapter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-adapter) within the cluster | `true` | | `prometheus-adapter.prometheus.url` | A URL pointing to the Prometheus deployment within your cluster. The default value is set based on the assumption that you plan to deploy the default Prometheus instance from this chart where `.Values.namespaceOverride=cattle-monitoring-system` and `.Values.nameOverride=rancher-monitoring` | `http://rancher-monitoring-prometheus.cattle-monitoring-system.svc` | | `prometheus-adapter.prometheus.port` | The port on the Prometheus deployment that Prometheus Adapter can make requests to | `9090` | | `prometheus.prometheusSpec.ignoreNamespaceSelectors` | Ignore NamespaceSelector settings from the PodMonitor and ServiceMonitor configs. If true, PodMonitors and ServiceMonitors can only discover Pods and Services within the namespace they are deployed into | `false` | diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md b/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md index 3d71158f..39208543 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md +++ b/packages/rancher-project-monitoring/generated-changes/exclude/app-README.md @@ -8,9 +8,9 @@ The chart installs the following components: - [Prometheus Operator](https://github.com/coreos/prometheus-operator) - The operator provides easy monitoring definitions for Kubernetes services, manages [Prometheus](https://prometheus.io/) and [AlertManager](https://prometheus.io/docs/alerting/latest/alertmanager/) instances, and adds default scrape targets for some Kubernetes components. - [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) - A collection of community-curated Kubernetes manifests, Grafana Dashboards, and PrometheusRules that deploy a default end-to-end cluster monitoring configuration. -- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) - Grafana allows a user to create / view dashboards based on the cluster metrics collected by Prometheus. -- [node-exporter](https://github.com/helm/charts/tree/master/stable/prometheus-node-exporter) / [kube-state-metrics](https://github.com/helm/charts/tree/master/stable/kube-state-metrics) / [rancher-pushprox](https://github.com/rancher/charts/tree/dev-v2.5/packages/rancher-pushprox/charts) - These charts monitor various Kubernetes components across different Kubernetes cluster types. -- [Prometheus Adapter](https://github.com/helm/charts/tree/master/stable/prometheus-adapter) - The adapter allows a user to expose custom metrics, resource metrics, and external metrics on the default [Prometheus](https://prometheus.io/) instance to the Kubernetes API Server. +- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana) - Grafana allows a user to create / view dashboards based on the cluster metrics collected by Prometheus. +- [node-exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter) / [kube-state-metrics](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics) / [rancher-pushprox](https://github.com/rancher/charts/tree/dev-v2.7/packages/rancher-monitoring/rancher-pushprox/charts) - These charts monitor various Kubernetes components across different Kubernetes cluster types. +- [Prometheus Adapter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-adapter) - The adapter allows a user to expose custom metrics, resource metrics, and external metrics on the default [Prometheus](https://prometheus.io/) instance to the Kubernetes API Server. For more information, review the Helm README of this chart. diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml index 13f5bc64..c3049e2a 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/core-dns/servicemonitor.yaml @@ -28,22 +28,20 @@ spec: proxyUrl: {{ .Values.coreDns.serviceMonitor.proxyUrl}} {{- end }} bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.coreDns.serviceMonitor.metricRelabelings }} metricRelabelings: -{{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }} + {{- if .Values.coreDns.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }} + {{- end }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} -{{ else }} - {{ if .Values.global.cattle.clusterId }} - metricRelabelings: + {{ if .Values.global.cattle.clusterName }} - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.coreDns.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.coreDns.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml index 46cdfc70..e73db372 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-api-server/servicemonitor.yaml @@ -21,22 +21,20 @@ spec: {{- end }} port: https scheme: https -{{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }} - metricRelabelings: + - metricRelabelings: + {{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }} {{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} -{{ else }} - {{ if .Values.global.cattle.clusterId }} - metricRelabelings: + {{ if .Values.global.cattle.clusterName}} - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.kubeApiServer.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.relabelings | indent 6) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml index 9bcd9cb0..1c7e778e 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-controller-manager/servicemonitor.yaml @@ -39,22 +39,20 @@ spec: serverName: {{ .Values.kubeControllerManager.serviceMonitor.serverName }} {{- end }} {{- end }} -{{- if .Values.kubeControllerManager.serviceMonitor.metricRelabelings }} metricRelabelings: -{{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + {{- if.Values.kubeControllerManager.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.kubeControllerManager.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml index 6c5365dc..ee930ce5 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-dns/servicemonitor.yaml @@ -28,22 +28,20 @@ spec: {{- if .Values.kubeDns.serviceMonitor.proxyUrl }} proxyUrl: {{ .Values.kubeDns.serviceMonitor.proxyUrl}} {{- end }} -{{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - metricRelabelings: + {{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }} + {{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.kubeDns.serviceMonitor.dnsmasqRelabelings }} relabelings: {{ toYaml .Values.kubeDns.serviceMonitor.dnsmasqRelabelings | indent 4 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml index 052b44da..da4d2836 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-etcd/servicemonitor.yaml @@ -50,9 +50,14 @@ spec: {{ tpl (toYaml .Values.kubeEtcd.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} {{- if .Values.kubeEtcd.serviceMonitor.relabelings }} relabelings: diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml index 996aaf1e..762bb6a1 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-proxy/servicemonitor.yaml @@ -33,22 +33,20 @@ spec: tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt {{- end}} -{{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - metricRelabelings: + {{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.kubeProxy.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeProxy.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml index e07bb46a..d6a904bc 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kube-scheduler/servicemonitor.yaml @@ -39,22 +39,20 @@ spec: serverName: {{ .Values.kubeScheduler.serviceMonitor.serverName }} {{- end}} {{- end}} -{{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - metricRelabelings: + {{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end}} -{{- end }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} {{- if .Values.kubeScheduler.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml index 97df54a8..12bdcc64 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/exporters/kubelet/servicemonitor.yaml @@ -32,24 +32,20 @@ spec: insecureSkipVerify: true bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true -{{- if .Values.kubelet.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - action: replace - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - metricRelabelings: + {{- if .Values.kubelet.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - action: replace - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.kubelet.serviceMonitor.relabelings }} relabelings: {{ tpl (toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4) . }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml index d6c8ae82..058d6801 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/deployment.yaml @@ -70,15 +70,15 @@ spec: {{- end }} - --localhost=127.0.0.1 {{- if .Values.prometheusOperator.prometheusDefaultBaseImage }} - - --prometheus-default-base-image={{ .Values.prometheusOperator.prometheusDefaultBaseImage }} + - --prometheus-default-base-image={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusDefaultBaseImage }} {{- end }} {{- if .Values.prometheusOperator.alertmanagerDefaultBaseImage }} - - --alertmanager-default-base-image={{ .Values.prometheusOperator.alertmanagerDefaultBaseImage }} + - --alertmanager-default-base-image={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.alertmanagerDefaultBaseImage }} {{- end }} {{- if .Values.prometheusOperator.prometheusConfigReloader.image.sha }} - - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloader.image.sha }} + - --prometheus-config-reloader={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloader.image.sha }} {{- else }} - - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }} + - --prometheus-config-reloader={{ template "system_default_registry" . }}{{ .Values.prometheusOperator.prometheusConfigReloader.image.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloader.image.tag }} {{- end }} - --config-reloader-cpu-request={{ .Values.prometheusOperator.prometheusConfigReloader.resources.requests.cpu }} - --config-reloader-cpu-limit={{ .Values.prometheusOperator.prometheusConfigReloader.resources.limits.cpu }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml index 531352a1..3af46529 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus-operator/servicemonitor.yaml @@ -26,22 +26,20 @@ spec: {{- if .Values.prometheusOperator.serviceMonitor.interval }} interval: {{ .Values.prometheusOperator.serviceMonitor.interval }} {{- end }} -{{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }} metricRelabelings: -{{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + {{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.prometheusOperator.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.prometheusOperator.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml index 4181602b..9d410fd3 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/prometheus/servicemonitorThanosSidecar.yaml @@ -30,22 +30,20 @@ spec: bearerTokenFile: {{ .Values.prometheus.thanosServiceMonitor.bearerTokenFile }} {{- end }} path: "/metrics" -{{- if .Values.prometheus.thanosServiceMonitor.metricRelabelings }} metricRelabelings: -{{ tpl (toYaml .Values.prometheus.thanosServiceMonitor.metricRelabelings | indent 6) . }} + {{- if .Values.prometheus.thanosServiceMonitor.metricRelabelings}} + {{ tpl (toYaml .Values.prometheus.thanosServiceMonitor.metricRelabelings | indent 6) . }} + {{- end }} {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} {{- end }} -{{ else }} - {{ if .Values.global.cattle.clusterId }} - metricRelabelings: + {{ if .Values.global.cattle.clusterName}} - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} -{{- end }} + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} {{- if .Values.prometheus.thanosServiceMonitor.relabelings }} relabelings: {{ toYaml .Values.prometheus.thanosServiceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml index c9ebafe4..b0f92e63 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/ingress-nginx/servicemonitor.yaml @@ -28,22 +28,20 @@ spec: proxyUrl: {{ .Values.ingressNginx.serviceMonitor.proxyUrl}} {{- end }} bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.ingressNginx.serviceMonitor.metricRelabelings }} metricRelabelings: -{{ tpl (toYaml .Values.ingressNginx.serviceMonitor.metricRelabelings | indent 4) . }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + {{- if .Values.ingressNginx.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.ingressNginx.serviceMonitor.metricRelabelings | indent 4) . }} {{- end }} -{{ else }} {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} {{- end }} -{{- end }} {{- if .Values.ingressNginx.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.ingressNginx.serviceMonitor.relabelings | indent 4 }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml index 51df3c8c..1fba8f23 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/rancher-monitoring/exporters/rancher/servicemonitor.yaml @@ -14,13 +14,18 @@ spec: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecureSkipVerify: true serverName: rancher + metricRelabelings: + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} jobLabel: rancher - {{ if .Values.global.cattle.clusterId }} - metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} {{- if .Values.rancherMonitoring.namespaceSelector }} namespaceSelector: {{ .Values.rancherMonitoring.namespaceSelector | toYaml | nindent 4 }} {{- end }} diff --git a/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml b/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml index f2700a35..1f2bd417 100644 --- a/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml +++ b/packages/rancher-project-monitoring/generated-changes/exclude/templates/thanos-ruler/servicemonitor.yaml @@ -34,20 +34,21 @@ spec: tlsConfig: {{ toYaml .Values.thanosRuler.serviceMonitor.tlsConfig | nindent 6 }} {{- end }} path: "{{ trimSuffix "/" .Values.thanosRuler.thanosRulerSpec.routePrefix }}/metrics" -{{- if .Values.thanosRuler.serviceMonitor.metricRelabelings }} + metricRelabelings: -{{ tpl (toYaml .Values.thanosRuler.serviceMonitor.metricRelabelings | indent 6) . }} - {{ if .Values.global.cattle.clusterId }} + {{- if .Values.thanosRuler.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.thanosRuler.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} - sourceLabels: [__address__] targetLabel: cluster_id replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} - {{ else }} - metricRelabelings: + {{- end }} + {{ if .Values.global.cattle.clusterName}} - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} -{{- end }} + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} {{- if .Values.thanosRuler.serviceMonitor.relabelings }} relabelings: {{ toYaml .Values.thanosRuler.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch index 1b856541..0480b685 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/Chart.yaml.patch @@ -12,10 +12,11 @@ catalog.cattle.io/certified: rancher - catalog.cattle.io/deploys-on-os: windows - catalog.cattle.io/display-name: Monitoring +- catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' +- catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" - catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' -- catalog.cattle.io/namespace: cattle-monitoring-system ++ catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' catalog.cattle.io/permits-os: linux,windows - catalog.cattle.io/provides-gvr: monitoring.coreos.com.prometheus/v1 - catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.8.0-0' @@ -71,5 +72,5 @@ -- https://github.com/prometheus-operator/kube-prometheus +name: rancher-project-monitoring type: application --version: 102.0.0+up40.1.2 +-version: 102.0.1+up40.1.2 +version: 0.1.0 diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch index 3ab1dc2c..af50cb4b 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/servicemonitor.yaml.patch @@ -27,32 +27,3 @@ endpoints: - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} {{- if .Values.alertmanager.serviceMonitor.interval }} -@@ -34,22 +34,20 @@ - tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" --{{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} - metricRelabelings: --{{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} -+ {{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} -+ {{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} -+ {{- end }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} --{{ else }} -- {{ if .Values.global.cattle.clusterId }} -- metricRelabelings: -+ {{ if .Values.global.cattle.clusterName }} - - sourceLabels: [__address__] -- targetLabel: cluster_id -- replacement: {{ .Values.global.cattle.clusterId }} -+ targetLabel: cluster_name -+ replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} --{{- end }} - {{- if .Values.alertmanager.serviceMonitor.relabelings }} - relabelings: - {{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch index 783281c7..3a1c6380 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/prometheus/servicemonitor.yaml.patch @@ -27,32 +27,3 @@ endpoints: - port: {{ .Values.prometheus.prometheusSpec.portName }} {{- if .Values.prometheus.serviceMonitor.interval }} -@@ -31,22 +31,20 @@ - bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} - {{- end }} - path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" --{{- if .Values.prometheus.serviceMonitor.metricRelabelings }} - metricRelabelings: --{{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} -+ {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} -+ {{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} -+ {{- end }} - {{ if .Values.global.cattle.clusterId }} - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} -- {{ else }} -- {{ if .Values.global.cattle.clusterId }} -- metricRelabelings: -+ {{ if .Values.global.cattle.clusterName}} - - sourceLabels: [__address__] -- targetLabel: cluster_id -- replacement: {{ .Values.global.cattle.clusterId }} -+ targetLabel: cluster_name -+ replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} --{{- end }} - {{- if .Values.prometheus.serviceMonitor.relabelings }} - relabelings: - {{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} diff --git a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch index 2bb9f642..61c4a015 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch @@ -560,7 +560,7 @@ - ## Image to use to run the scripts - image: - repository: rancher/shell -- tag: v0.1.18 +- tag: v0.1.19 - -## Rancher Monitoring -## @@ -977,15 +977,6 @@ label: grafana_datasource labelValue: "1" -@@ -1591,7 +823,7 @@ - proxy: - image: - repository: rancher/mirrored-library-nginx -- tag: 1.21.1-alpine -+ tag: 1.24.0-alpine - - ## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod - extraContainers: | @@ -1652,292 +884,8 @@ tlsConfig: {} scrapeTimeout: 30s @@ -2571,7 +2562,7 @@ ## securityContext: runAsGroup: 2000 -@@ -3554,28 +1427,14 @@ +@@ -3554,20 +1427,6 @@ ## priorityClassName: "" @@ -2592,8 +2583,7 @@ proxy: image: repository: rancher/mirrored-library-nginx -- tag: 1.21.1-alpine -+ tag: 1.24.0-alpine +@@ -3575,7 +1434,7 @@ ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. ## if using proxy extraContainer update targetPort with proxy container port @@ -2602,15 +2592,6 @@ - name: prometheus-proxy args: - nginx -@@ -3583,7 +1442,7 @@ - - daemon off; - - -c - - /nginx/nginx.conf -- image: rancher/mirrored-library-nginx:1.21.1-alpine -+ image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.proxy.image.repository }}:{{ .Values.prometheus.prometheusSpec.proxy.image.tag }}" - ports: - - containerPort: 8081 - name: nginx-http @@ -3616,10 +1475,6 @@ ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. overrideHonorTimestamps: false diff --git a/packages/rancher-project-monitoring/package.yaml b/packages/rancher-project-monitoring/package.yaml index 06d1467f..ba2179fe 100644 --- a/packages/rancher-project-monitoring/package.yaml +++ b/packages/rancher-project-monitoring/package.yaml @@ -1,7 +1,7 @@ workingDir: "" url: https://github.com/rancher/charts.git -subdirectory: charts/rancher-monitoring/102.0.0+up40.1.2 -commit: 970470cf8b779b926e8ced60a10f270e401a44a4 +subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2 +commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 version: 0.2.2 ignoreDependencies: - hardenedKubelet From fba6e73c0054cfc4077a82893b7b73360b1ab4f6 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:52:00 -0700 Subject: [PATCH 04/21] Update grafana dependency to new base 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 --- .../dependencies/grafana/dependency.yaml | 4 +-- .../patch/charts/grafana/Chart.yaml.patch | 10 ------- .../grafana/templates/nginx-config.yaml.patch | 19 ++++++------ .../templates/servicemonitor.yaml.patch | 29 ------------------- 4 files changed, 11 insertions(+), 51 deletions(-) delete mode 100644 packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch delete mode 100644 packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch diff --git a/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml b/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml index 6533e374..8c67d60e 100644 --- a/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml +++ b/packages/rancher-project-monitoring/generated-changes/dependencies/grafana/dependency.yaml @@ -1,4 +1,4 @@ workingDir: "" url: https://github.com/rancher/charts.git -subdirectory: charts/rancher-monitoring/102.0.0+up40.1.2/charts/grafana -commit: 970470cf8b779b926e8ced60a10f270e401a44a4 +subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2/charts/grafana +commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch deleted file mode 100644 index 543859e3..00000000 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/Chart.yaml.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- charts-original/charts/grafana/Chart.yaml -+++ charts/charts/grafana/Chart.yaml -@@ -1,6 +1,6 @@ - annotations: - catalog.cattle.io/hidden: "true" -- catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.25.0-0' -+ catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' - catalog.cattle.io/os: linux - catalog.rancher.io/certified: rancher - catalog.rancher.io/namespace: cattle-monitoring-system diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch index 90ead7b8..f1f423a7 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/nginx-config.yaml.patch @@ -9,23 +9,22 @@ location /api/dashboards { proxy_pass http://localhost:3000; -@@ -52,7 +52,6 @@ - - sub_filter_types application/json; - sub_filter_once off; -- sub_filter '"url":"/d' '"url":"d'; - } - - location /api/live/ { -@@ -75,7 +74,11 @@ +@@ -74,13 +74,12 @@ proxy_pass http://localhost:3000/; sub_filter_once off; +- +- {{- if eq .Values.global.cattle.clusterId "local" -}} +- sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +- {{- else -}} +{{- if not (empty .Values.global.cattle.clusterId) }} sub_filter '"appSubUrl":""' '"appSubUrl":"/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +- {{- end -}} +- +{{- else }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- end }} - sub_filter '"url":"/' '"url":"./'; ++ sub_filter '"url":"/' '"url":"./'; sub_filter ':"/avatar/' ':"avatar/'; + if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { diff --git a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch deleted file mode 100644 index fdbcd204..00000000 --- a/packages/rancher-project-monitoring/generated-changes/patch/charts/grafana/templates/servicemonitor.yaml.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- charts-original/charts/grafana/templates/servicemonitor.yaml -+++ charts/charts/grafana/templates/servicemonitor.yaml -@@ -30,21 +30,19 @@ - tlsConfig: - {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} -- {{- if .Values.serviceMonitor.metricRelabelings }} - metricRelabelings: -+ {{- if .Values.serviceMonitor.metricRelabelings }} - {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 6 }} -- {{ if .Values.global.cattle.clusterId }} -- - sourceLabels: [__address__] -- targetLabel: cluster_id -- replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} -- {{ else }} - {{ if .Values.global.cattle.clusterId }} -- metricRelabelings: - - sourceLabels: [__address__] - targetLabel: cluster_id - replacement: {{ .Values.global.cattle.clusterId }} - {{- end }} -+ {{ if .Values.global.cattle.clusterName }} -+ - sourceLabels: [__address__] -+ targetLabel: cluster_name -+ replacement: {{ .Values.global.cattle.clusterName }} - {{- end }} - {{- if .Values.serviceMonitor.relabelings }} - relabelings: From 4fd0796d2cd89d502cb11ca9ae8e1a8807af4a39 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 20:47:55 -0700 Subject: [PATCH 05/21] make charts --- .../prometheus-federator-0.3.0.tgz | Bin 0 -> 20567 bytes .../rancher-project-monitoring-0.3.0.tgz | Bin 0 -> 124765 bytes charts/prometheus-federator/0.3.0/Chart.yaml | 20 + charts/prometheus-federator/0.3.0/README.md | 120 + .../prometheus-federator/0.3.0/app-README.md | 27 + .../charts/helmProjectOperator/Chart.yaml | 15 + .../charts/helmProjectOperator/README.md | 77 + .../charts/helmProjectOperator/app-readme.md | 20 + .../charts/helmProjectOperator/questions.yaml | 43 + .../helmProjectOperator/templates/NOTES.txt | 2 + .../templates/_helpers.tpl | 66 + .../templates/cleanup.yaml | 82 + .../templates/clusterrole.yaml | 57 + .../templates/configmap.yaml | 14 + .../templates/deployment.yaml | 124 + .../helmProjectOperator/templates/psp.yaml | 68 + .../helmProjectOperator/templates/rbac.yaml | 32 + .../system-namespaces-configmap.yaml | 62 + .../templates/validate-psp-install.yaml | 7 + .../charts/helmProjectOperator/values.yaml | 226 ++ .../prometheus-federator/0.3.0/questions.yaml | 43 + .../0.3.0/templates/NOTES.txt | 3 + .../0.3.0/templates/_helpers.tpl | 66 + charts/prometheus-federator/0.3.0/values.yaml | 94 + .../0.3.0/Chart.yaml | 33 + .../0.3.0/README.md | 29 + .../0.3.0/app-README.md | 10 + .../0.3.0/charts/grafana/.helmignore | 23 + .../0.3.0/charts/grafana/Chart.yaml | 29 + .../0.3.0/charts/grafana/README.md | 571 ++++ .../grafana/dashboards/custom-dashboard.json | 1 + .../0.3.0/charts/grafana/templates/NOTES.txt | 54 + .../charts/grafana/templates/_helpers.tpl | 214 ++ .../0.3.0/charts/grafana/templates/_pod.tpl | 885 ++++++ .../charts/grafana/templates/clusterrole.yaml | 25 + .../grafana/templates/clusterrolebinding.yaml | 24 + .../configmap-dashboard-provider.yaml | 29 + .../charts/grafana/templates/configmap.yaml | 117 + .../templates/dashboards-json-configmap.yaml | 35 + .../charts/grafana/templates/deployment.yaml | 50 + .../grafana/templates/headless-service.yaml | 22 + .../0.3.0/charts/grafana/templates/hpa.yaml | 21 + .../templates/image-renderer-deployment.yaml | 123 + .../image-renderer-network-policy.yaml | 73 + .../templates/image-renderer-service.yaml | 33 + .../charts/grafana/templates/ingress.yaml | 78 + .../grafana/templates/networkpolicy.yaml | 52 + .../grafana/templates/nginx-config.yaml | 93 + .../templates/poddisruptionbudget.yaml | 22 + .../grafana/templates/podsecuritypolicy.yaml | 45 + .../0.3.0/charts/grafana/templates/pvc.yaml | 35 + .../0.3.0/charts/grafana/templates/role.yaml | 32 + .../charts/grafana/templates/rolebinding.yaml | 25 + .../charts/grafana/templates/secret-env.yaml | 14 + .../charts/grafana/templates/secret.yaml | 26 + .../charts/grafana/templates/service.yaml | 55 + .../grafana/templates/serviceaccount.yaml | 14 + .../grafana/templates/servicemonitor.yaml | 58 + .../charts/grafana/templates/statefulset.yaml | 56 + .../templates/tests/test-configmap.yaml | 17 + .../tests/test-podsecuritypolicy.yaml | 29 + .../grafana/templates/tests/test-role.yaml | 14 + .../templates/tests/test-rolebinding.yaml | 17 + .../templates/tests/test-serviceaccount.yaml | 9 + .../charts/grafana/templates/tests/test.yaml | 51 + .../0.3.0/charts/grafana/values.yaml | 1062 +++++++ .../federate/federate-scrape-config.yaml | 13 + .../rancher/pods/rancher-pod-containers.json | 636 ++++ .../0.3.0/files/rancher/pods/rancher-pod.json | 636 ++++ .../workloads/rancher-workload-pods.json | 652 ++++ .../rancher/workloads/rancher-workload.json | 652 ++++ .../0.3.0/questions.yaml | 128 + .../0.3.0/templates/NOTES.txt | 4 + .../0.3.0/templates/_helpers.tpl | 252 ++ .../templates/alertmanager/alertmanager.yaml | 165 + .../templates/alertmanager/extrasecret.yaml | 20 + .../0.3.0/templates/alertmanager/ingress.yaml | 77 + .../alertmanager/podDisruptionBudget.yaml | 21 + .../templates/alertmanager/psp-role.yaml | 21 + .../alertmanager/psp-rolebinding.yaml | 18 + .../0.3.0/templates/alertmanager/psp.yaml | 45 + .../0.3.0/templates/alertmanager/secret.yaml | 33 + .../0.3.0/templates/alertmanager/service.yaml | 53 + .../alertmanager/serviceaccount.yaml | 20 + .../alertmanager/servicemonitor.yaml | 55 + .../0.3.0/templates/dashboard-roles.yaml | 179 ++ .../templates/dashboard-values-configmap.yaml | 57 + .../dashboards/rancher/pods-dashboards.yaml | 17 + .../rancher/workload-dashboards.yaml | 17 + .../grafana/configmap-dashboards.yaml | 24 + .../grafana/configmaps-datasources.yaml | 46 + .../alertmanager-overview.yaml | 616 ++++ .../dashboards-1.14/cluster-total.yaml | 1646 ++++++++++ .../dashboards-1.14/grafana-overview.yaml | 635 ++++ .../k8s-resources-namespace.yaml | 2770 +++++++++++++++++ .../dashboards-1.14/k8s-resources-node.yaml | 963 ++++++ .../dashboards-1.14/k8s-resources-pod.yaml | 2442 +++++++++++++++ .../k8s-resources-project.yaml | 2480 +++++++++++++++ .../k8s-resources-workload.yaml | 1997 ++++++++++++ .../k8s-resources-workloads-namespace.yaml | 2162 +++++++++++++ .../dashboards-1.14/namespace-by-pod.yaml | 1438 +++++++++ .../namespace-by-workload.yaml | 1710 ++++++++++ .../persistentvolumesusage.yaml | 561 ++++ .../grafana/dashboards-1.14/pod-total.yaml | 1202 +++++++ .../prometheus-remote-write.yaml | 1674 ++++++++++ .../grafana/dashboards-1.14/prometheus.yaml | 1235 ++++++++ .../dashboards-1.14/workload-total.yaml | 1412 +++++++++ .../0.3.0/templates/prometheus/_rules.tpl | 8 + .../templates/prometheus/clusterrole.yaml | 25 + .../prometheus/clusterrolebinding.yaml | 18 + .../templates/prometheus/extrasecret.yaml | 20 + .../0.3.0/templates/prometheus/federate.yaml | 10 + .../0.3.0/templates/prometheus/ingress.yaml | 77 + .../templates/prometheus/nginx-config.yaml | 68 + .../prometheus/podDisruptionBudget.yaml | 21 + .../templates/prometheus/prometheus.yaml | 319 ++ .../templates/prometheus/psp-clusterrole.yaml | 20 + .../prometheus/psp-clusterrolebinding.yaml | 18 + .../0.3.0/templates/prometheus/psp.yaml | 52 + .../rules-1.14/alertmanager.rules.yaml | 217 ++ .../prometheus/rules-1.14/general.rules.yaml | 98 + .../rules-1.14/kubernetes-apps.yaml | 375 +++ .../rules-1.14/kubernetes-storage.yaml | 160 + .../prometheus/rules-1.14/prometheus.yaml | 448 +++ .../0.3.0/templates/prometheus/service.yaml | 56 + .../templates/prometheus/serviceaccount.yaml | 20 + .../templates/prometheus/servicemonitor.yaml | 52 + .../rancher-monitoring/hardened.yaml | 129 + .../0.3.0/templates/validate-install-crd.yaml | 21 + .../0.3.0/templates/validate-psp-install.yaml | 7 + .../0.3.0/values.yaml | 1551 +++++++++ index.yaml | 128 +- 132 files changed, 38172 insertions(+), 3 deletions(-) create mode 100644 assets/prometheus-federator/prometheus-federator-0.3.0.tgz create mode 100644 assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz create mode 100644 charts/prometheus-federator/0.3.0/Chart.yaml create mode 100644 charts/prometheus-federator/0.3.0/README.md create mode 100644 charts/prometheus-federator/0.3.0/app-README.md create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml create mode 100644 charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml create mode 100644 charts/prometheus-federator/0.3.0/questions.yaml create mode 100644 charts/prometheus-federator/0.3.0/templates/NOTES.txt create mode 100644 charts/prometheus-federator/0.3.0/templates/_helpers.tpl create mode 100644 charts/prometheus-federator/0.3.0/values.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/Chart.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/README.md create mode 100644 charts/rancher-project-monitoring/0.3.0/app-README.md create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json create mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json create mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json create mode 100644 charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json create mode 100644 charts/rancher-project-monitoring/0.3.0/questions.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml create mode 100644 charts/rancher-project-monitoring/0.3.0/values.yaml diff --git a/assets/prometheus-federator/prometheus-federator-0.3.0.tgz b/assets/prometheus-federator/prometheus-federator-0.3.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..5e2862423a900fba1f896d0bc7bc53119987c05f GIT binary patch literal 20567 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

NAfd}ssS(GpQ!LWjFf#||ayv`n?upgHo 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 W=i&Jh&;K6)0RR7V)jw?jY!?8ien?{g literal 0 HcmV?d00001 diff --git a/charts/prometheus-federator/0.3.0/Chart.yaml b/charts/prometheus-federator/0.3.0/Chart.yaml new file mode 100644 index 00000000..ba842552 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/Chart.yaml @@ -0,0 +1,20 @@ +annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Prometheus Federator + catalog.cattle.io/kube-version: '>=1.16.0-0' + catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' + catalog.cattle.io/release-name: prometheus-federator +apiVersion: v2 +appVersion: 0.3.0 +dependencies: +- condition: helmProjectOperator.enabled + name: helmProjectOperator + repository: file://./charts/helmProjectOperator +description: Prometheus Federator +icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg +name: prometheus-federator +version: 0.3.0 diff --git a/charts/prometheus-federator/0.3.0/README.md b/charts/prometheus-federator/0.3.0/README.md new file mode 100644 index 00000000..7da4edfc --- /dev/null +++ b/charts/prometheus-federator/0.3.0/README.md @@ -0,0 +1,120 @@ +# Prometheus Federator + +This chart is deploys a Helm Project Operator (based on the [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator)), an operator that manages deploying Helm charts each containing a Project Monitoring Stack, where each stack contains: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed resources + +> **Important Note: Prometheus Federator is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs.** + +By default, the chart is configured and intended to be deployed alongside [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that each Project Monitoring Stack is configured to federate namespace-scoped metrics from by default. + +## Pre-Installation: Using Prometheus Federator with Rancher and rancher-monitoring + +If you are running your cluster on [Rancher](https://rancher.com/) and already have [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) deployed onto your cluster, Prometheus Federator's default configuration should already be configured to work with your existing Cluster Monitoring Stack; however, here are some notes on how we recommend you configure rancher-monitoring to optimize the security and usability of Prometheus Federator in your cluster: + +### Ensure the cattle-monitoring-system namespace is placed into the System Project (or a similarly locked down Project that has access to other Projects in the cluster) + +Prometheus Operator's security model expects that the namespace it is deployed into (`cattle-monitoring-system`) has limited access for anyone except Cluster Admins to avoid privilege escalation via execing into Pods (such as the Jobs executing Helm operations). In addition, deploying Prometheus Federator and all Project Prometheus stacks into the System Project ensures that the each Project Prometheus is able to reach out to scrape workloads across all Projects (even if Network Policies are defined via Project Network Isolation) but has limited access for Project Owners, Project Members, and other users to be able to access data they shouldn't have access to (i.e. being allowed to exec into pods, set up the ability to scrape namespaces outside of a given Project, etc.). + +### Configure rancher-monitoring to only watch for resources created by the Helm chart itself + +Since each Project Monitoring Stack will watch the other namespaces and collect additional custom workload metrics or dashboards already, it's recommended to configure the following settings on all selectors to ensure that the Cluster Prometheus Stack only monitors resources created by the Helm Chart itself: + +``` +matchLabels: + release: "rancher-monitoring" +``` + +The following selector fields are recommended to have this value: +- `.Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector` +- `.Values.prometheus.prometheusSpec.serviceMonitorSelector` +- `.Values.prometheus.prometheusSpec.podMonitorSelector` +- `.Values.prometheus.prometheusSpec.ruleSelector` +- `.Values.prometheus.prometheusSpec.probeSelector` + +Once this setting is turned on, you can always create ServiceMonitors or PodMonitors that are picked up by the Cluster Prometheus by adding the label `release: "rancher-monitoring"` to them (in which case they will be ignored by Project Monitoring Stacks automatically by default, even if the namespace in which those ServiceMonitors or PodMonitors reside in are not system namespaces). + +> Note: If you don't want to allow users to be able to create ServiceMonitors and PodMonitors that aggregate into the Cluster Prometheus in Project namespaces, you can additionally set the namespaceSelectors on the chart to only target system namespaces (which must contain `cattle-monitoring-system` and `cattle-dashboards`, where resources are deployed into by default by rancher-monitoring; you will also need to monitor the `default` namespace to get apiserver metrics or create a custom ServiceMonitor to scrape apiserver metrics from the Service residing in the default namespace) to limit your Cluster Prometheus from picking up other Prometheus Operator CRs; in that case, it would be recommended to turn `.Values.prometheus.prometheusSpec.ignoreNamespaceSelectors=true` to allow you to define ServiceMonitors that can monitor non-system namespaces from within a system namespace. + +In addition, if you modified the default `.Values.grafana.sidecar.*.searchNamespace` values on the Grafana Helm subchart for Monitoring V2, it is also recommended to remove the overrides or ensure that your defaults are scoped to only system namespaces for the following values: +- `.Values.grafana.sidecar.dashboards.searchNamespace` (default `cattle-dashboards`) +- `.Values.grafana.sidecar.datasources.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) +- `.Values.grafana.sidecar.plugins.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) +- `.Values.grafana.sidecar.notifiers.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) + +### Increase the CPU / memory limits of the Cluster Prometheus + +Depending on a cluster's setup, it's generally recommended to give a large amount of dedicated memory to the Cluster Prometheus to avoid restarts due to out-of-memory errors (OOMKilled), usually caused by churn created in the cluster that causes a large number of high cardinality metrics to be generated and ingested by Prometheus within one block of time; this is one of the reasons why the default Rancher Monitoring stack expects around 4GB of RAM to be able to operate in a normal-sized cluster. However, when introducing Project Monitoring Stacks that are all sending `/federate` requests to the same Cluster Prometheus and are reliant on the Cluster Prometheus being "up" to federate that system data on their namespaces, it's even more important that the Cluster Prometheus has an ample amount of CPU / memory assigned to it to prevent an outage that can cause data gaps across all Project Prometheis in the cluster. + +> Note: There are no specific recommendations on how much memory the Cluster Prometheus should be configured with since it depends entirely on the user's setup (namely the likelihood of encountering a high churn rate and the scale of metrics that could be generated at that time); it generally varies per setup. + +## How does the operator work? + +1. On deploying this chart, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `monitoring.cattle.io/v1alpha1` (also known as "Project Monitors" in the Rancher UI) in a **Project Registration Namespace (`cattle-project-`)**. +2. On seeing each ProjectHelmChartCR, the operator will automatically deploy a Project Prometheus stack on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--monitoring`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. +3. RBAC will automatically be assigned in the Project Release Namespace to allow users to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack deployed; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). + +### What is a Project? + +In Prometheus Federator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. + +### Configuring the Helm release created by a ProjectHelmChart + +The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: +- View to the chart's definition located at [`rancher/prometheus-federator` under `charts/rancher-project-monitoring`](https://github.com/rancher/prometheus-federator/blob/main/charts/rancher-project-monitoring) (where the chart version will be tied to the version of this operator) +- Look for the ConfigMap named `monitoring.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `prometheus-federator` binary). + +### Namespaces + +As a Project Operator based on [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator), Prometheus Federator has three different classifications of namespaces that the operator looks out for: +1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-monitoring-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** +2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. +> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project +> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace +3. **Project Release Namespace (`cattle-project--monitoring`)**: this is the set of namespaces that the operator deploys Project Monitoring Stacks within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Project Monitoring Stack based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Prometheus Federator.** +> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace +> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) +> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace + +### Helm Resources (HelmChart, HelmRelease) + +On deploying a ProjectHelmChart, the Prometheus Federator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: +- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). +> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** +- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). +> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified + +Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. + +### RBAC + +As described in the section on namespaces above, Prometheus Federator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: +- ClusterRoleBindings +- RoleBindings in the Project Release Namespace + +On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). + +> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. + +If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: +- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` +- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` + +By default, the `rancher-project-monitoring` (the underlying chart deployed by Prometheus Federator) creates three default Roles per Project Release Namespace that provide `admin`, `edit`, and `view` users to permissions to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack to provide least privilege; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. + +### Advanced Helm Project Operator Configuration + +|Value|Configuration| +|---|---------------------------| +|`helmProjectOperator.valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | +|`helmProjectOperator.projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | +|`helmProjectOperator.otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `cattle-monitoring-system`, `cattle-dashboards`, and `kube-system` are explicitly marked as system namespaces as well, regardless of label or annotation. | +|`helmProjectOperator.releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces +|`helmProjectOperator.releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | +|`helmProjectOperator.hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | +|`helmProjectOperator.hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | +|`helmProjectOperator.helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2/K3s clusters before v1.23.14 / v1.24.8 / v1.25.4 since RKE2/K3s clusters already run Helm Controller at a cluster-wide level to manage internal Kubernetes components | +|`helmProjectOperator.helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.0/app-README.md b/charts/prometheus-federator/0.3.0/app-README.md new file mode 100644 index 00000000..99fa7ca1 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/app-README.md @@ -0,0 +1,27 @@ +# Prometheus Federator + +This chart deploys an operator that manages Project Monitoring Stacks composed of the following set of resources that are scoped to project namespaces: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed Prometheus, Grafana, and Alertmanager + +Since this Project Monitoring Stack deploys Prometheus Operator CRs, an existing Prometheus Operator instance must already be deployed in the cluster for Prometheus Federator to successfully be able to deploy Project Monitoring Stacks. It is recommended to use [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) for this. For more information on how the chart works or advanced configurations, please read the `README.md`. + +## Upgrading to Kubernetes v1.25+ + +Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. + +As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. +​ +> **Note:** +> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. + ​ +> **Note:** +> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** +> +> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. +Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. +​ +As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml new file mode 100644 index 00000000..421aabb1 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/Chart.yaml @@ -0,0 +1,15 @@ +annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Helm Project Operator + catalog.cattle.io/kube-version: '>=1.16.0-0' + catalog.cattle.io/namespace: cattle-helm-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.0-0' + catalog.cattle.io/release-name: helm-project-operator +apiVersion: v2 +appVersion: 0.1.0 +description: Helm Project Operator +name: helmProjectOperator +version: 0.1.1 diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md new file mode 100644 index 00000000..fc1d39e8 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/README.md @@ -0,0 +1,77 @@ +# Helm Project Operator + +## How does the operator work? + +1. On deploying a Helm Project Operator, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `dummy.cattle.io/v1alpha1` in a **Project Registration Namespace (`cattle-project-`)**. +2. On seeing each ProjectHelmChartCR, the operator will automatically deploy the embedded Helm chart on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--dummy`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. +3. RBAC will automatically be assigned in the Project Release Namespace to allow users to based on Role created in the Project Release Namespace with a given set of labels; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). + +### What is a Project? + +In Helm Project Operator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. + +### What is a ProjectHelmChart? + +A ProjectHelmChart is an instance of a (project-scoped) Helm chart deployed on behalf of a user who has permissions to create ProjectHelmChart resources in a Project Registration namespace. + +Generally, the best way to think about the ProjectHelmChart model is by comparing it to two other models: +1. Managed Kubernetes providers (EKS, GKE, AKS, etc.): in this model, a user has the ability to say "I want a Kubernetes cluster" but the underlying cloud provider is responsible for provisioning the infrastructure and offering **limited view and access** of the underlying resources created on their behalf; similarly, Helm Project Operator allows a Project Owner to say "I want this Helm chart deployed", but the underlying Operator is responsible for "provisioning" (deploying) the Helm chart and offering **limited view and access** of the underlying Kubernetes resources created on their behalf (based on configuring "least-privilege" Kubernetes RBAC for the Project Owners / Members in the newly created Project Release Namespace). +2. Dynamically-provisioned Persistent Volumes: in this model, a single resource (PersistentVolume) exists that allows you to specify a Storage Class that actually implements provisioning the underlying storage via a Storage Class Provisioner (e.g. Longhorn). Similarly, the ProjectHelmChart exists that allows you to specify a `spec.helmApiVersion` ("storage class") that actually implements deploying the underlying Helm chart via a Helm Project Operator (e.g. [`rancher/prometheus-federator`](https://github.com/rancher/prometheus-federator)). + +### Configuring the Helm release created by a ProjectHelmChart + +The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: +- View to the chart's definition located at [`rancher/helm-project-operator` under `charts/example-chart`](https://github.com/rancher/helm-project-operator/blob/main/charts/example-chart) (where the chart version will be tied to the version of this operator) +- Look for the ConfigMap named `dummy.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `helm-project-operator` binary). + +### Namespaces + +All Helm Project Operators have three different classifications of namespaces that the operator looks out for: +1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-helm-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** +2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. +> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project +> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace +3. **Project Release Namespace (`cattle-project--dummy`)**: this is the set of namespaces that the operator deploys Helm charts within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Helm charts based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Helm Project Operator.** +> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace +> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) +> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace + +### Helm Resources (HelmChart, HelmRelease) + +On deploying a ProjectHelmChart, the Helm Project Operator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: +- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). +> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** +- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). +> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified + +Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. + +### RBAC + +As described in the section on namespaces above, Helm Project Operator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: +- ClusterRoleBindings +- RoleBindings in the Project Release Namespace + +On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). + +> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. + +If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: +- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` +- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` + +By default, the `example-chart` (the underlying chart deployed by Helm Project Operator) does not create any default roles; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. + +### Advanced Helm Project Operator Configuration + +|Value|Configuration| +|---|---------------------------| +|`valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | +|`projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | +|`otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `kube-system` is explicitly marked as a system namespace as well, regardless of label or annotation. | +|`releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces +|`releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | +|`hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | +|`hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | +|`helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2 clusters since RKE2 clusters already run Helm Controller to manage internal Kubernetes components | +|`helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md new file mode 100644 index 00000000..fd551467 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/app-readme.md @@ -0,0 +1,20 @@ +# Helm Project Operator + +This chart installs the example [Helm Project Operator](https://github.com/rancher/helm-project-operator) onto your cluster. + +## Upgrading to Kubernetes v1.25+ + +Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. + +As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. +​ +> **Note:** +> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. + ​ +> **Note:** +> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** +> +> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. +Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. +​ +As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml new file mode 100644 index 00000000..054361a7 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/questions.yaml @@ -0,0 +1,43 @@ +questions: +- variable: global.cattle.psp.enabled + default: "false" + description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." + label: "Enable PodSecurityPolicies" + type: boolean + group: "Security Settings" +- variable: helmController.enabled + label: Enable Embedded Helm Controller + description: 'Note: If you are running this chart in an RKE2 cluster, this should be disabled.' + type: boolean + group: Helm Controller +- variable: helmLocker.enabled + label: Enable Embedded Helm Locker + type: boolean + group: Helm Locker +- variable: projectReleaseNamespaces.labelValue + label: Project Release Namespace Project ID + description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) + type: string + required: false + group: Namespaces +- variable: releaseRoleBindings.clusterRoleRefs.admin + label: Admin ClusterRole + description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: admin + required: false + group: RBAC +- variable: releaseRoleBindings.clusterRoleRefs.edit + label: Edit ClusterRole + description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: edit + required: false + group: RBAC +- variable: releaseRoleBindings.clusterRoleRefs.view + label: View ClusterRole + description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: view + required: false + group: RBAC diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt new file mode 100644 index 00000000..32baeebc --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/NOTES.txt @@ -0,0 +1,2 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "helm-project-operator.namespace" . }} get pods -l "release={{ $.Release.Name }}" diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl new file mode 100644 index 00000000..97dd6b36 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/_helpers.tpl @@ -0,0 +1,66 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Helm Project Operator + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "helm-project-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "helm-project-operator.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "helm-project-operator.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "helm-project-operator.labels" -}} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "helm-project-operator.name" . }} +chart: {{ template "helm-project-operator.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end -}} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml new file mode 100644 index 00000000..98675642 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/cleanup.yaml @@ -0,0 +1,82 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "helm-project-operator.name" . }}-cleanup + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed +spec: + template: + metadata: + name: {{ template "helm-project-operator.name" . }}-cleanup + labels: {{ include "helm-project-operator.labels" . | nindent 8 }} + app: {{ template "helm-project-operator.name" . }} + spec: + serviceAccountName: {{ template "helm-project-operator.name" . }} +{{- if .Values.cleanup.securityContext }} + securityContext: {{ toYaml .Values.cleanup.securityContext | nindent 8 }} +{{- end }} + initContainers: + - name: add-cleanup-annotations + image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + command: + - /bin/sh + - -c + - > + echo "Labeling all ProjectHelmCharts with helm.cattle.io/helm-project-operator-cleanup=true"; + EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; + IFS=$'\n'; + for namespace in $(kubectl get namespaces -l helm.cattle.io/helm-project-operated=true --no-headers -o=custom-columns=NAME:.metadata.name); do + for projectHelmChartAndHelmApiVersion in $(kubectl get projecthelmcharts -n ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name,HELMAPIVERSION:.spec.helmApiVersion); do + projectHelmChartAndHelmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | xargs); + projectHelmChart=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f1); + helmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f2); + if [[ ${helmApiVersion} != ${EXPECTED_HELM_API_VERSION} ]]; then + echo "Skipping marking ${namespace}/${projectHelmChart} with cleanup annotation since spec.helmApiVersion: ${helmApiVersion} is not ${EXPECTED_HELM_API_VERSION}"; + continue; + fi; + kubectl label projecthelmcharts -n ${namespace} ${projectHelmChart} helm.cattle.io/helm-project-operator-cleanup=true --overwrite; + done; + done; +{{- if .Values.cleanup.resources }} + resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} +{{- end }} +{{- if .Values.cleanup.containerSecurityContext }} + securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} +{{- end }} + containers: + - name: ensure-subresources-deleted + image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - > + SYSTEM_NAMESPACE={{ .Release.Namespace }} + EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; + HELM_API_VERSION_TRUNCATED=$(echo ${EXPECTED_HELM_API_VERSION} | cut -d'/' -f0); + echo "Ensuring HelmCharts and HelmReleases are deleted from ${SYSTEM_NAMESPACE}..."; + while [[ "$(kubectl get helmcharts,helmreleases -l helm.cattle.io/helm-api-version=${HELM_API_VERSION_TRUNCATED} -n ${SYSTEM_NAMESPACE} 2>&1)" != "No resources found in ${SYSTEM_NAMESPACE} namespace." ]]; do + echo "waiting for HelmCharts and HelmReleases to be deleted from ${SYSTEM_NAMESPACE}... sleeping 3 seconds"; + sleep 3; + done; + echo "Successfully deleted all HelmCharts and HelmReleases in ${SYSTEM_NAMESPACE}!"; +{{- if .Values.cleanup.resources }} + resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} +{{- end }} +{{- if .Values.cleanup.containerSecurityContext }} + securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} +{{- end }} + restartPolicy: OnFailure + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + {{- if .Values.cleanup.nodeSelector }} + {{- toYaml .Values.cleanup.nodeSelector | nindent 8 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + {{- if .Values.cleanup.tolerations }} + {{- toYaml .Values.cleanup.tolerations | nindent 8 }} + {{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml new file mode 100644 index 00000000..60ed263b --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/clusterrole.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-admin + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/finalizers + - projecthelmcharts/status + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-edit + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/status + verbs: + - 'get' + - 'list' + - 'watch' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-view + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/status + verbs: + - 'get' + - 'list' + - 'watch' +{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml new file mode 100644 index 00000000..d4def157 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/configmap.yaml @@ -0,0 +1,14 @@ +## Note: If you add another entry to this ConfigMap, make sure a corresponding env var is set +## in the deployment of the operator to ensure that a Helm upgrade will force the operator +## to reload the values in the ConfigMap and redeploy +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "helm-project-operator.name" . }}-config + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +data: + hardened.yaml: |- +{{ .Values.hardenedNamespaces.configuration | toYaml | indent 4 }} + values.yaml: |- +{{ .Values.valuesOverride | toYaml | indent 4 }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml new file mode 100644 index 00000000..c7309805 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/deployment.yaml @@ -0,0 +1,124 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ template "helm-project-operator.name" . }} + release: {{ $.Release.Name | quote }} + template: + metadata: + labels: {{ include "helm-project-operator.labels" . | nindent 8 }} + app: {{ template "helm-project-operator.name" . }} + spec: + containers: + - name: {{ template "helm-project-operator.name" . }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + args: + - {{ template "helm-project-operator.name" . }} + - --namespace={{ template "helm-project-operator.namespace" . }} + - --controller-name={{ template "helm-project-operator.name" . }} + - --values-override-file=/etc/helmprojectoperator/config/values.yaml +{{- if .Values.global.cattle.systemDefaultRegistry }} + - --system-default-registry={{ .Values.global.cattle.systemDefaultRegistry }} +{{- end }} +{{- if .Values.global.cattle.url }} + - --cattle-url={{ .Values.global.cattle.url }} +{{- end }} +{{- if .Values.global.cattle.projectLabel }} + - --project-label={{ .Values.global.cattle.projectLabel }} +{{- end }} +{{- if not .Values.projectReleaseNamespaces.enabled }} + - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} +{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} + - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} +{{- else if len .Values.otherSystemProjectLabelValues }} + - --system-project-label-values={{ join "," .Values.otherSystemProjectLabelValues }} +{{- end }} +{{- if .Values.projectReleaseNamespaces.enabled }} +{{- if .Values.projectReleaseNamespaces.labelValue }} + - --project-release-label-value={{ .Values.projectReleaseNamespaces.labelValue }} +{{- else if .Values.global.cattle.systemProjectId }} + - --project-release-label-value={{ .Values.global.cattle.systemProjectId }} +{{- end }} +{{- end }} +{{- if .Values.global.cattle.clusterId }} + - --cluster-id={{ .Values.global.cattle.clusterId }} +{{- end }} +{{- if .Values.releaseRoleBindings.aggregate }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.admin }} + - --admin-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.admin }} +{{- end }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.edit }} + - --edit-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.edit }} +{{- end }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.view }} + - --view-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.view }} +{{- end }} +{{- end }} +{{- end }} +{{- if .Values.hardenedNamespaces.enabled }} + - --hardening-options-file=/etc/helmprojectoperator/config/hardening.yaml +{{- else }} + - --disable-hardening +{{- end }} +{{- if .Values.debug }} + - --debug + - --debug-level={{ .Values.debugLevel }} +{{- end }} +{{- if not .Values.helmController.enabled }} + - --disable-embedded-helm-controller +{{- else }} + - --helm-job-image={{ template "system_default_registry" . }}{{ .Values.helmController.job.image.repository }}:{{ .Values.helmController.job.image.tag }} +{{- end }} +{{- if not .Values.helmLocker.enabled }} + - --disable-embedded-helm-locker +{{- end }} +{{- if .Values.additionalArgs }} +{{- toYaml .Values.additionalArgs | nindent 10 }} +{{- end }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + ## Note: The below two values only exist to force Helm to upgrade the deployment on + ## a change to the contents of the ConfigMap during an upgrade. Neither serve + ## any practical purpose and can be removed and replaced with a configmap reloader + ## in a future change if dynamic updates are required. + - name: HARDENING_OPTIONS_SHA_256_HASH + value: {{ .Values.hardenedNamespaces.configuration | toYaml | sha256sum }} + - name: VALUES_OVERRIDE_SHA_256_HASH + value: {{ .Values.valuesOverride | toYaml | sha256sum }} +{{- if .Values.resources }} + resources: {{ toYaml .Values.resources | nindent 12 }} +{{- end }} +{{- if .Values.containerSecurityContext }} + securityContext: {{ toYaml .Values.containerSecurityContext | nindent 12 }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/helmprojectoperator/config" + serviceAccountName: {{ template "helm-project-operator.name" . }} +{{- if .Values.securityContext }} + securityContext: {{ toYaml .Values.securityContext | nindent 8 }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} +{{- if .Values.nodeSelector }} +{{- toYaml .Values.nodeSelector | nindent 8 }} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} +{{- if .Values.tolerations }} +{{- toYaml .Values.tolerations | nindent 8 }} +{{- end }} + volumes: + - name: config + configMap: + name: {{ template "helm-project-operator.name" . }}-config diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml new file mode 100644 index 00000000..73dcc456 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/psp.yaml @@ -0,0 +1,68 @@ +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +{{- if .Values.global.rbac.pspAnnotations }} + annotations: {{ toYaml .Values.global.rbac.pspAnnotations | nindent 4 }} +{{- end }} +spec: + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +rules: +{{- if semverCompare "> 1.15.0-0" .Capabilities.KubeVersion.GitVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "helm-project-operator.name" . }}-psp +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "helm-project-operator.name" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml new file mode 100644 index 00000000..b1c40920 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/rbac.yaml @@ -0,0 +1,32 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "helm-project-operator.name" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "cluster-admin" # see note below +subjects: +- kind: ServiceAccount + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }} +{{- end }} +# --- +# NOTE: +# As of now, due to the fact that the k3s-io/helm-controller can only deploy jobs that are cluster-bound to the cluster-admin +# ClusterRole, the only way for this operator to be able to perform that binding is if it is also bound to the cluster-admin ClusterRole. +# +# As a result, this ClusterRoleBinding will be left as a work-in-progress until changes are made in k3s-io/helm-controller to allow us to grant +# only scoped down permissions to the Job that is deployed. diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml new file mode 100644 index 00000000..f4c85254 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml @@ -0,0 +1,62 @@ +{{- if .Values.systemNamespacesConfigMap.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +data: + system-namespaces.json: |- + { +{{- if .Values.projectReleaseNamespaces.enabled }} +{{- if .Values.projectReleaseNamespaces.labelValue }} + "projectReleaseLabelValue": {{ .Values.projectReleaseNamespaces.labelValue | quote }}, +{{- else if .Values.global.cattle.systemProjectId }} + "projectReleaseLabelValue": {{ .Values.global.cattle.systemProjectId | quote }}, +{{- else }} + "projectReleaseLabelValue": "", +{{- end }} +{{- else }} + "projectReleaseLabelValue": "", +{{- end }} +{{- if not .Values.projectReleaseNamespaces.enabled }} + "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} +{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} + "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} +{{- else if len .Values.otherSystemProjectLabelValues }} + "systemProjectLabelValues": {{ .Values.otherSystemProjectLabelValues | toJson }} +{{- else }} + "systemProjectLabelValues": [] +{{- end }} + } +--- +{{- if (and .Values.systemNamespacesConfigMap.rbac.enabled .Values.systemNamespacesConfigMap.rbac.subjects) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + resourceNames: + - "{{ template "helm-project-operator.name" . }}-system-namespaces" + verbs: + - 'get' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "helm-project-operator.name" . }}-system-namespaces +subjects: {{ .Values.systemNamespacesConfigMap.rbac.subjects | toYaml | nindent 2 }} +{{- end }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml new file mode 100644 index 00000000..a30c59d3 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/templates/validate-psp-install.yaml @@ -0,0 +1,7 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +#{{- if .Values.global.cattle.psp.enabled }} +#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} +#{{- end }} +#{{- end }} +#{{- end }} diff --git a/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml new file mode 100644 index 00000000..4905bf1a --- /dev/null +++ b/charts/prometheus-federator/0.3.0/charts/helmProjectOperator/values.yaml @@ -0,0 +1,226 @@ +# Default values for helm-project-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Helm Project Operator Configuration + +global: + cattle: + clusterId: "" + psp: + enabled: false + projectLabel: field.cattle.io/projectId + systemDefaultRegistry: "" + systemProjectId: "" + url: "" + rbac: + ## Create RBAC resources for ServiceAccounts and users + ## + create: true + + userRoles: + ## Create default user ClusterRoles to allow users to interact with ProjectHelmCharts + create: true + ## Aggregate default user ClusterRoles into default k8s ClusterRoles + aggregateToDefaultRoles: true + + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + +helmApiVersion: dummy.cattle.io/v1alpha1 + +## valuesOverride overrides values that are set on each ProjectHelmChart deployment on an operator-level +## User-provided values will be overwritten based on the values provided here +valuesOverride: {} + +## projectReleaseNamespaces are auto-generated namespaces that are created to host Helm Releases +## managed by this operator on behalf of a ProjectHelmChart +projectReleaseNamespaces: + ## Enabled determines whether Project Release Namespaces should be created. If false, the underlying + ## Helm release will be deployed in the Project Registration Namespace + enabled: true + ## labelValue is the value of the Project that the projectReleaseNamespace should be created within + ## If empty, this will be set to the value of global.cattle.systemProjectId + ## If global.cattle.systemProjectId is also empty, project release namespaces will be disabled + labelValue: "" + +## otherSystemProjectLabelValues are project labels that identify namespaces as those that should be treated as system projects +## i.e. they will be entirely ignored by the operator +## By default, the global.cattle.systemProjectId will be in this list +otherSystemProjectLabelValues: [] + +## releaseRoleBindings configures RoleBindings automatically created by the Helm Project Operator +## in Project Release Namespaces where underlying Helm charts are deployed +releaseRoleBindings: + ## aggregate enables creating these RoleBindings off aggregating RoleBindings in the + ## Project Registration Namespace or ClusterRoleBindings that bind users to the ClusterRoles + ## specified under clusterRoleRefs + aggregate: true + + ## clusterRoleRefs are the ClusterRoles whose RoleBinding or ClusterRoleBindings should determine + ## the RoleBindings created in the Project Release Namespace + ## + ## By default, these are set to create RoleBindings based on the RoleBindings / ClusterRoleBindings + ## attached to the default K8s user-facing ClusterRoles of admin, edit, and view. + ## ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + ## + clusterRoleRefs: + admin: admin + edit: edit + view: view + +hardenedNamespaces: + # Whether to automatically manage the configuration of the default ServiceAccount and + # auto-create a NetworkPolicy for each namespace created by this operator + enabled: true + + configuration: + # Values to be applied to each default ServiceAccount created in a managed namespace + serviceAccountSpec: + secrets: [] + imagePullSecrets: [] + automountServiceAccountToken: false + # Values to be applied to each default generated NetworkPolicy created in a managed namespace + networkPolicySpec: + podSelector: {} + egress: [] + ingress: [] + policyTypes: ["Ingress", "Egress"] + +## systemNamespacesConfigMap is a ConfigMap created to allow users to see valid entries +## for registering a ProjectHelmChart for a given Project on the Rancher Dashboard UI. +## It does not need to be enabled for a non-Rancher use case. +systemNamespacesConfigMap: + ## Create indicates whether the system namespaces configmap should be created + ## This is a required value for integration with Rancher Dashboard + create: true + + ## RBAC provides options around the RBAC created to allow users to be able to view + ## the systemNamespacesConfigMap; if not specified, only users with the ability to + ## view ConfigMaps in the namespace where this chart is deployed will be able to + ## properly view the system namespaces on the Rancher Dashboard UI + rbac: + ## enabled indicates that we should deploy a RoleBinding and Role to view this ConfigMap + enabled: true + ## subjects are the subjects that should be bound to this default RoleBinding + ## By default, we allow anyone who is authenticated to the system to be able to view + ## this ConfigMap in the deployment namespace + subjects: + - kind: Group + name: system:authenticated + +nameOverride: "" + +namespaceOverride: "" + +image: + repository: rancher/helm-project-operator + tag: v0.1.0 + pullPolicy: IfNotPresent + +helmController: + # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components + enabled: true + + job: + image: + repository: rancher/klipper-helm + tag: v0.7.0-build20220315 + +helmLocker: + enabled: true + +# Additional arguments to be passed into the Helm Project Operator image +additionalArgs: [] + +## Define which Nodes the Pods are scheduled on. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for use with node taints +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +# - key: "key" +# operator: "Equal" +# value: "value" +# effect: "NoSchedule" + +resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m + +containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + +securityContext: {} + # runAsGroup: 1000 + # runAsUser: 1000 + # supplementalGroups: + # - 1000 + +debug: false +debugLevel: 0 + +cleanup: + image: + repository: rancher/shell + tag: v0.1.19 + pullPolicy: IfNotPresent + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + + securityContext: + runAsNonRoot: false + runAsUser: 0 + + resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m diff --git a/charts/prometheus-federator/0.3.0/questions.yaml b/charts/prometheus-federator/0.3.0/questions.yaml new file mode 100644 index 00000000..87cf1339 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/questions.yaml @@ -0,0 +1,43 @@ +questions: +- variable: global.cattle.psp.enabled + default: "false" + description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." + label: "Enable PodSecurityPolicies" + type: boolean + group: "Security Settings" +- variable: helmProjectOperator.helmController.enabled + label: Enable Embedded Helm Controller + description: 'Note: If you are running Prometheus Federator in an RKE2 / K3s cluster before v1.23.14 / v1.24.8 / v1.25.4, this should be disabled.' + type: boolean + group: Helm Controller +- variable: helmProjectOperator.helmLocker.enabled + label: Enable Embedded Helm Locker + type: boolean + group: Helm Locker +- variable: helmProjectOperator.projectReleaseNamespaces.labelValue + label: Project Release Namespace Project ID + description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) + type: string + required: false + group: Namespaces +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin + label: Admin ClusterRole + description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: admin + required: false + group: RBAC +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit + label: Edit ClusterRole + description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: edit + required: false + group: RBAC +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view + label: View ClusterRole + description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: view + required: false + group: RBAC \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.0/templates/NOTES.txt b/charts/prometheus-federator/0.3.0/templates/NOTES.txt new file mode 100644 index 00000000..f551f366 --- /dev/null +++ b/charts/prometheus-federator/0.3.0/templates/NOTES.txt @@ -0,0 +1,3 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "prometheus-federator.namespace" . }} get pods -l "release={{ $.Release.Name }}" + diff --git a/charts/prometheus-federator/0.3.0/templates/_helpers.tpl b/charts/prometheus-federator/0.3.0/templates/_helpers.tpl new file mode 100644 index 00000000..15ea4e5c --- /dev/null +++ b/charts/prometheus-federator/0.3.0/templates/_helpers.tpl @@ -0,0 +1,66 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Helm Project Operator + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "prometheus-federator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "prometheus-federator.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "prometheus-federator.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "prometheus-federator.labels" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "prometheus-federator.name" . }} +chart: {{ template "prometheus-federator.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.0/values.yaml b/charts/prometheus-federator/0.3.0/values.yaml new file mode 100644 index 00000000..4f22c1dd --- /dev/null +++ b/charts/prometheus-federator/0.3.0/values.yaml @@ -0,0 +1,94 @@ +# Default values for helm-project-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Prometheus Federator Configuration + +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectLabel: field.cattle.io/projectId + clusterId: "" + systemProjectId: "" + url: "" + rbac: + pspEnabled: true + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + +helmProjectOperator: + enabled: true + + # ensures that all resources created by subchart show up as prometheus-federator + helmApiVersion: monitoring.cattle.io/v1alpha1 + + nameOverride: prometheus-federator + + helmController: + # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components + enabled: true + + helmLocker: + enabled: true + + ## valuesOverride overrides values that are set on each Project Prometheus Stack Helm Chart deployment on an operator level + ## all values provided here will override any user-provided values automatically + valuesOverride: + + federate: + # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from + # By default, this matches the default deployment of Rancher Monitoring + targets: + - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 + + image: + repository: rancher/prometheus-federator + tag: v0.3.0 + pullPolicy: IfNotPresent + + # Additional arguments to be passed into the Prometheus Federator image + additionalArgs: [] + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m + + securityContext: {} + # allowPrivilegeEscalation: false + # readOnlyRootFilesystem: true + + debug: false + debugLevel: 0 \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/Chart.yaml b/charts/rancher-project-monitoring/0.3.0/Chart.yaml new file mode 100644 index 00000000..8d20806d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/Chart.yaml @@ -0,0 +1,33 @@ +annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' + catalog.cattle.io/release-name: rancher-project-monitoring +apiVersion: v2 +appVersion: 0.59.1 +dependencies: +- condition: grafana.enabled + name: grafana + repository: file://./charts/grafana +description: Collects several related Helm charts, Grafana dashboards, and Prometheus + rules combined with documentation and scripts to provide easy to operate end-to-end + Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster + Prometheus deployed via Prometheus Operator +home: https://github.com/prometheus-operator/kube-prometheus +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +keywords: +- prometheus +- monitoring +kubeVersion: '>=1.16.0-0' +maintainers: +- email: arvind.iyengar@suse.com + name: Arvind +- email: amangeet.samra@suse.com + name: Geet + url: https://github.com/geethub97 +name: rancher-project-monitoring +type: application +version: 0.3.0 diff --git a/charts/rancher-project-monitoring/0.3.0/README.md b/charts/rancher-project-monitoring/0.3.0/README.md new file mode 100644 index 00000000..eab333c3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/README.md @@ -0,0 +1,29 @@ +# rancher-project-monitoring + +This chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting), a Helm chart based off of [`kube-prometheus stack`](https://github.com/prometheus-operator/kube-prometheus). It deploys a collection of Kubernetes manifests, [Grafana](http://grafana.com/) dashboards, and [Prometheus rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) combined with documentation and scripts to provide easy to operate end-to-end Kubernetes project monitoring with [Prometheus](https://prometheus.io/) using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator). See the [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus) README for details about components, dashboards, and alerts. + +## Prerequisites + +- Kubernetes 1.16+ +- Helm 3+ + +## Install Chart + +This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). For a Prometheus Stack intended to be deployed standalone, please use [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) or the upstream [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) project. + +## Dependencies + +This chart is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs. Specifically, the chart is configured and intended to be deployed alongside [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that `rancher-project-monitoring` is configured to federate namespace-scoped metrics from by default. + +### Configuration + +Since this chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), a Helm chart based off of [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack), most of the options that apply to either of those charts will apply to this chart (e.g. support for configuring persistent volumes, ingresses, etc.) and can be passed in as part of the `spec.values` of the ProjectHelmChart that deploys this chart; however, certain advanced functionality (such as Thanos support) and options that pose security risks in Project environments (e.g. ability to `ignoreNamespaceSelectors` or modify the existing namepaceSelectors of the Cluster Prometheus, ability to mount additional scrape configs, etc.) have been removed from the `values.yaml` of the chart. For more information on how to configure values and what they mean, please see the comments and options provided on the `values.yaml` packaged with this chart. + +## Further Information + +For more in-depth documentation of configuration options meanings, please see + +- [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) +- [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) +- [Prometheus](https://prometheus.io/docs/introduction/overview/) +- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana#grafana-helm-chart) \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/app-README.md b/charts/rancher-project-monitoring/0.3.0/app-README.md new file mode 100644 index 00000000..6b833291 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/app-README.md @@ -0,0 +1,10 @@ +# Rancher Project Monitoring and Alerting + +The chart installs a Project Monitoring Stack, which contains: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed resources + +Note: This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore b/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore new file mode 100644 index 00000000..8cade131 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.vscode +.project +.idea/ +*.tmproj +OWNERS diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml new file mode 100644 index 00000000..9b0ca179 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/Chart.yaml @@ -0,0 +1,29 @@ +annotations: + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' + catalog.cattle.io/os: linux + catalog.rancher.io/certified: rancher + catalog.rancher.io/namespace: cattle-monitoring-system + catalog.rancher.io/release-name: rancher-grafana +apiVersion: v2 +appVersion: 9.1.5 +description: The leading tool for querying and visualizing time series and metrics. +home: https://grafana.net +icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png +kubeVersion: ^1.8.0-0 +maintainers: +- email: zanhsieh@gmail.com + name: zanhsieh +- email: rluckie@cisco.com + name: rtluckie +- email: maor.friedman@redhat.com + name: maorfr +- email: miroslav.hadzhiev@gmail.com + name: Xtigyro +- email: mail@torstenwalter.de + name: torstenwalter +name: grafana +sources: +- https://github.com/grafana/grafana +type: application +version: 6.38.6 diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md b/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md new file mode 100644 index 00000000..f3d31768 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/README.md @@ -0,0 +1,571 @@ +# Grafana Helm Chart + +* Installs the web dashboarding system [Grafana](http://grafana.org/) + +## Get Repo Info + +```console +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release grafana/grafana +``` + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Upgrading an existing Release to a new major version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an +incompatible breaking change needing manual actions. + +### To 4.0.0 (And 3.12.1) + +This version requires Helm >= 2.12.0. + +### To 5.0.0 + +You have to add --force to your helm upgrade command as the labels of the chart have changed. + +### To 6.0.0 + +This version requires Helm >= 3.1.0. + +## Configuration + +| Parameter | Description | Default | +|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| +| `replicas` | Number of nodes | `1` | +| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | +| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | +| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | +| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | +| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| +| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | +| `priorityClassName` | Name of Priority Class to assign pods | `nil` | +| `image.repository` | Image repository | `grafana/grafana` | +| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` | +| `image.sha` | Image sha (optional) | `` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` | +| `service.enabled` | Enable grafana service | `true` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Kubernetes port where service is exposed | `80` | +| `service.portName` | Name of the port on the service | `service` | +| `service.appProtocol` | Adds the appProtocol field to the service | `` | +| `service.targetPort` | Internal service is port | `3000` | +| `service.nodePort` | Kubernetes service nodePort | `nil` | +| `service.annotations` | Service annotations (can be templated) | `{}` | +| `service.labels` | Custom labels | `{}` | +| `service.clusterIP` | internal cluster service IP | `nil` | +| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | +| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | +| `service.externalIPs` | service external IP addresses | `[]` | +| `headlessService` | Create a headless service | `false` | +| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | +| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | +| `ingress.labels` | Custom labels | `{}` | +| `ingress.path` | Ingress accepted path | `/` | +| `ingress.pathType` | Ingress type of path | `Prefix` | +| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | +| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | +| `ingress.tls` | Ingress TLS configuration | `[]` | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Toleration labels for pod assignment | `[]` | +| `affinity` | Affinity settings for pod assignment | `{}` | +| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | +| `extraContainers` | Sidecar containers to add to the grafana pod | `""` | +| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | +| `extraLabels` | Custom labels for all manifests | `{}` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `persistence.enabled` | Use persistent volume to store data | `false` | +| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | +| `persistence.size` | Size of persistent volume claim | `10Gi` | +| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` | +| `persistence.storageClassName` | Type of persistent volume claim | `nil` | +| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | +| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | +| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | +| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` | +| `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` | +| `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` | +| `initChownData.enabled` | If false, don't reset data ownership at startup | true | +| `initChownData.image.repository` | init-chown-data container image repository | `busybox` | +| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | +| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | +| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | +| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | +| `schedulerName` | Alternate scheduler name | `nil` | +| `env` | Extra environment variables passed to pods | `{}` | +| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | +| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret | `{}` | +| `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` | +| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | +| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | +| `createConfigmap` | Enable creating the grafana configmap | `true` | +| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` | +| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | +| `plugins` | Plugins to be loaded along with Grafana | `[]` | +| `datasources` | Configure grafana datasources (passed through tpl) | `{}` | +| `alerting` | Configure grafana alerting (passed through tpl) | `{}` | +| `notifiers` | Configure grafana notifiers | `{}` | +| `dashboardProviders` | Configure grafana dashboard providers | `{}` | +| `dashboards` | Dashboards to import | `{}` | +| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | +| `grafana.ini` | Grafana's primary configuration | `{}` | +| `ldap.enabled` | Enable LDAP authentication | `false` | +| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | +| `ldap.config` | Grafana's LDAP configuration | `""` | +| `annotations` | Deployment annotations | `{}` | +| `labels` | Deployment labels | `{}` | +| `podAnnotations` | Pod annotations | `{}` | +| `podLabels` | Pod labels | `{}` | +| `podPortName` | Name of the grafana port on the pod | `grafana` | +| `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` | +| `sidecar.image.repository` | Sidecar image repository | `quay.io/kiwigrid/k8s-sidecar` | +| `sidecar.image.tag` | Sidecar image tag | `1.19.2` | +| `sidecar.image.sha` | Sidecar image sha (optional) | `""` | +| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | +| `sidecar.resources` | Sidecar resources | `{}` | +| `sidecar.securityContext` | Sidecar securityContext | `{}` | +| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` | +| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | +| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | +| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | +| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | +| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | +| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | +| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | +| `sidecar.dashboards.provider.type` | Provider type | `file` | +| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | +| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | +| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | +| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` | +| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | +| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | +| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | +| `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` | +| `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` | +| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | +| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | +| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` | +| `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` | +| `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` | +| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | +| `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | +| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | +| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | +| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` | +| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | +| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | +| `serviceAccount.autoMount` | Automount the service account token in the pod| `true` | +| `serviceAccount.annotations` | ServiceAccount annotations | | +| `serviceAccount.create` | Create service account | `true` | +| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | +| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | +| `rbac.create` | Create and use RBAC resources | `true` | +| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | +| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | +| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `true` | +| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `true` | +| `rbac.extraRoleRules` | Additional rules to add to the Role | [] | +| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | +| `command` | Define command to be executed by grafana container at startup | `nil` | +| `testFramework.enabled` | Whether to create test-related resources | `true` | +| `testFramework.image` | `test-framework` image repository. | `bats/bats` | +| `testFramework.tag` | `test-framework` image tag. | `v1.4.1` | +| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | +| `testFramework.securityContext` | `test-framework` securityContext | `{}` | +| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | +| `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | +| `downloadDashboardsImage.repository` | Curl docker image repo | `curlimages/curl` | +| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | +| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | +| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | +| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | +| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | +| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | +| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | +| `serviceMonitor.path` | Path to scrape | `/metrics` | +| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` | +| `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` | +| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | +| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | +| `serviceMonitor.relabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | +| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | +| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | +| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | +| `imageRenderer.image.tag` | image-renderer Image tag | `latest` | +| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | +| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | +| `imageRenderer.env` | extra env-vars for image-renderer | `{}` | +| `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | +| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | +| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | +| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | +| `imageRenderer.service.enabled` | Enable the image-renderer service | `true` | +| `imageRenderer.service.portName` | image-renderer service port name | `http` | +| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` | +| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` | +| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` | +| `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` | +| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | +| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | +| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | +| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | +| `imageRenderer.resources` | Set resource limits for image-renderer pdos | `{}` | +| `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` | +| `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` | +| `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` | +| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` | +| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` | +| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` | +| `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` | + + + +### Example ingress with path + +With grafana 6.3 and above +```yaml +grafana.ini: + server: + domain: monitoring.example.com + root_url: "%(protocol)s://%(domain)s/grafana" + serve_from_sub_path: true +ingress: + enabled: true + hosts: + - "monitoring.example.com" + path: "/grafana" +``` + +### Example of extraVolumeMounts + +Volume can be type persistentVolumeClaim or hostPath but not both at same time. +If neither existingClaim or hostPath argument is given then type is emptyDir. + +```yaml +- extraVolumeMounts: + - name: plugins + mountPath: /var/lib/grafana/plugins + subPath: configs/grafana/plugins + existingClaim: existing-grafana-claim + readOnly: false + - name: dashboards + mountPath: /var/lib/grafana/dashboards + hostPath: /usr/shared/grafana/dashboards + readOnly: false +``` + +## Import dashboards + +There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: + +```yaml +dashboards: + default: + some-dashboard: + json: | + { + "annotations": + + ... + # Complete json file here + ... + + "title": "Some Dashboard", + "uid": "abcd1234", + "version": 1 + } + custom-dashboard: + # This is a path to a file inside the dashboards directory inside the chart directory + file: dashboards/custom-dashboard.json + prometheus-stats: + # Ref: https://grafana.com/dashboards/2 + gnetId: 2 + revision: 2 + datasource: Prometheus + local-dashboard: + url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json +``` + +## BASE64 dashboards + +Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) +A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. +If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. + +### Gerrit use case + +Gerrit API for download files has the following schema: where {project-name} and +{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard +the url value is + +## Sidecar for dashboards + +If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana +pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with +a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written +to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported +dashboards are deleted/updated. + +A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside +one configmap is currently not properly mirrored in grafana. + +Example dashboard config: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-dashboard + labels: + grafana_dashboard: "1" +data: + k8s-dashboard.json: |- + [...] +``` + +## Sidecar for datasources + +If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the data sources in grafana can be imported. + +Secrets are recommended over configmaps for this usecase because datasources usually contain private +data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): + +```yaml +datasources: + datasources.yaml: + apiVersion: 1 + datasources: + # name of the datasource. Required + - name: Graphite + # datasource type. Required + type: graphite + # access mode. proxy or direct (Server or Browser in the UI). Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://localhost:8080 + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: + # basic auth username + basicAuthUser: + # basic auth password + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: + # fields that will be converted to json and stored in json_data + jsonData: + graphiteVersion: "1.1" + tlsAuth: true + tlsAuthWithCACert: true + # json object of data that will be encrypted. + secureJsonData: + tlsCACert: "..." + tlsClientCert: "..." + tlsClientKey: "..." + version: 1 + # allow users to edit datasources from the UI. + editable: false +``` + +## Sidecar for notifiers + +If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the notification channels in grafana can be imported. The secrets must be created before +`helm install` so that the notifiers init container can list the secrets. + +Secrets are recommended over configmaps for this usecase because alert notification channels usually contain +private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): + +```yaml +notifiers: + - name: notification-channel-1 + type: slack + uid: notifier1 + # either + org_id: 2 + # or + org_name: Main Org. + is_default: true + send_reminder: true + frequency: 1h + disable_resolve_message: false + # See `Supported Settings` section for settings supporter for each + # alert notification type. + settings: + recipient: 'XXX' + token: 'xoxb' + uploadImage: true + url: https://slack.com + +delete_notifiers: + - name: notification-channel-1 + uid: notifier1 + org_id: 2 + - name: notification-channel-2 + # default org_id: 1 +``` + +## How to serve Grafana with a path prefix (/grafana) + +In order to serve Grafana with a prefix (e.g., ), add the following to your values.yaml. + +```yaml +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: /$1 + nginx.ingress.kubernetes.io/use-regex: "true" + + path: /grafana/?(.*) + hosts: + - k8s.example.dev + +grafana.ini: + server: + root_url: http://localhost:3000/grafana # this host can be localhost +``` + +## How to securely reference secrets in grafana.ini + +This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. + +In grafana.ini: + +```yaml +grafana.ini: + [auth.generic_oauth] + enabled = true + client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} + client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} +``` + +Existing secret, or created along with helm: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: auth-generic-oauth-secret +type: Opaque +stringData: + client_id: + client_secret: +``` + +Include in the `extraSecretMounts` configuration flag: + +```yaml +- extraSecretMounts: + - name: auth-generic-oauth-secret-mount + secretName: auth-generic-oauth-secret + defaultMode: 0440 + mountPath: /etc/secrets/auth_generic_oauth + readOnly: true +``` + +### extraSecretMounts using a Container Storage Interface (CSI) provider + +This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure) + +```yaml +- extraSecretMounts: + - name: secrets-store-inline + mountPath: /run/secrets + readOnly: true + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: "my-provider" + nodePublishSecretRef: + name: akv-creds +``` + +## Image Renderer Plug-In + +This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker) + +```yaml +imageRenderer: + enabled: true +``` + +### Image Renderer NetworkPolicy + +By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance + +### High Availability for unified alerting + +If you want to run Grafana in a high availability cluster you need to enable +the headless service by setting `headlessService: true` in your `values.yaml` +file. + +As next step you have to setup the `grafana.ini` in your `values.yaml` in a way +that it will make use of the headless service to obtain all the IPs of the +cluster. You should replace ``{{ Name }}`` with the name of your helm deployment. + +```yaml +grafana.ini: + ... + unified_alerting: + enabled: true + ha_peers: {{ Name }}-headless:9094 + alerting: + enabled: false +``` diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json b/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/dashboards/custom-dashboard.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt new file mode 100644 index 00000000..1fc8436d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/NOTES.txt @@ -0,0 +1,54 @@ +1. Get your '{{ .Values.adminUser }}' user password by running: + + kubectl get secret --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo + +2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: + + {{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}.svc.cluster.local +{{ if .Values.ingress.enabled }} + If you bind grafana to 80, please update values in values.yaml and reinstall: + ``` + securityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + + command: + - "setcap" + - "'cap_net_bind_service=+ep'" + - "/usr/sbin/grafana-server &&" + - "sh" + - "/run.sh" + ``` + Details refer to https://grafana.com/docs/installation/configuration/#http-port. + Or grafana would always crash. + + From outside the cluster, the server URL(s) are: +{{- range .Values.ingress.hosts }} + http://{{ . }} +{{- end }} +{{ else }} + Get the Grafana URL to visit by running these commands in the same shell: +{{ if contains "NodePort" .Values.service.type -}} + export NODE_PORT=$(kubectl get --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{ else if contains "LoadBalancer" .Values.service.type -}} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ template "grafana.namespace" . }} -w {{ template "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + http://$SERVICE_IP:{{ .Values.service.port -}} +{{ else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "grafana.namespace" . }} -l "app.kubernetes.io/name={{ template "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ template "grafana.namespace" . }} port-forward $POD_NAME 3000 +{{- end }} +{{- end }} + +3. Login with the password from step 1 and the username: {{ .Values.adminUser }} + +{{- if not .Values.persistence.enabled }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Grafana pod is terminated. ##### +################################################################################# +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl new file mode 100644 index 00000000..e5e3b287 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,214 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "grafana.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "grafana.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "grafana.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "grafana.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{- define "grafana.serviceAccountNameTest" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} +{{- else -}} + {{ default "default" .Values.serviceAccount.nameTest }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "grafana.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "grafana.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.imageRenderer.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.imageRenderer.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels ImageRenderer +*/}} +{{- define "grafana.imageRenderer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Looks if there's an existing secret and reuse its password. If not it generates +new password and use it. +*/}} +{{- define "grafana.password" -}} +{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) -}} + {{- if $secret -}} + {{- index $secret "data" "admin-password" -}} + {{- else -}} + {{- (randAlphaNum 40) | b64enc | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for rbac. +*/}} +{{- define "grafana.rbac.apiVersion" -}} + {{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} + {{- print "rbac.authorization.k8s.io/v1" -}} + {{- else -}} + {{- print "rbac.authorization.k8s.io/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for HorizontalPodAutoscaler. +*/}} +{{- define "grafana.hpa.apiVersion" -}} + {{- if .Capabilities.APIVersions.Has "autoscaling/v2" }} + {{- print "autoscaling/v2" -}} + {{- else if .Capabilities.APIVersions.Has "autoscaling/v1" }} + {{- print "autoscaling/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "grafana.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "grafana.podDisruptionBudget.apiVersion" -}} + {{- if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return if ingress is stable. +*/}} +{{- define "grafana.ingress.isStable" -}} + {{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "grafana.ingress.supportsIngressClassName" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} + +{{/* +Return if ingress supports pathType. +*/}} +{{- define "grafana.ingress.supportsPathType" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl new file mode 100644 index 00000000..ae36c28a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/_pod.tpl @@ -0,0 +1,885 @@ +{{- define "grafana.pod" -}} +{{- if .Values.schedulerName }} +schedulerName: "{{ .Values.schedulerName }}" +{{- end }} +serviceAccountName: {{ template "grafana.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} +{{- with .Values.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.hostAliases }} +hostAliases: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- if .Values.priorityClassName }} +priorityClassName: {{ .Values.priorityClassName }} +{{- end }} +{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.notifiers.enabled .Values.extraInitContainers (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources)) }} +initContainers: +{{- end }} +{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} + - name: init-chown-data + {{- if .Values.initChownData.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} + securityContext: + runAsNonRoot: false + runAsUser: 0 + command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] + {{- with .Values.initChownData.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- end }} +{{- if .Values.dashboards }} + - name: download-dashboards + {{- if .Values.downloadDashboardsImage.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} + command: ["/bin/sh"] + args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] + {{- with .Values.downloadDashboards.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + env: +{{- range $key, $value := .Values.downloadDashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" +{{- end }} + {{- with .Values.downloadDashboards.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if .Values.downloadDashboards.envFromSecret }} + envFrom: + - secretRef: + name: {{ tpl .Values.downloadDashboards.envFromSecret . }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/download_dashboards.sh" + subPath: download_dashboards.sh + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} + - name: {{ template "grafana.name" . }}-init-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end }} +{{- if .Values.sidecar.notifiers.enabled }} + - name: {{ template "grafana.name" . }}-sc-notifiers + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: LIST + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + {{- if .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.notifiers.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/notifiers" + - name: RESOURCE + value: {{ quote .Values.sidecar.notifiers.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} +{{- if .Values.extraInitContainers }} +{{ tpl (toYaml .Values.extraInitContainers) . | indent 2 }} +{{- end }} +{{- if .Values.image.pullSecrets }} +imagePullSecrets: +{{- $root := . }} +{{- range .Values.image.pullSecrets }} + - name: {{ tpl . $root }} +{{- end }} +{{- end }} +{{- if not .Values.enableKubeBackwardCompatibility }} +enableServiceLinks: {{ .Values.enableServiceLinks }} +{{- end }} +containers: +{{- if .Values.sidecar.dashboards.enabled }} + - name: {{ template "grafana.name" . }}-sc-dashboard + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.dashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.dashboards.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.dashboards.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.dashboards.label }}" + {{- if .Values.sidecar.dashboards.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.dashboards.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.dashboards.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.dashboards.folderAnnotation }} + - name: FOLDER_ANNOTATION + value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" + {{- end }} + {{- if .Values.sidecar.dashboards.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.dashboards.script }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchServerTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchServerTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchClientTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchClientTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + {{- if .Values.sidecar.dashboards.extraMounts }} + {{- toYaml .Values.sidecar.dashboards.extraMounts | trim | nindent 6}} + {{- end }} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: {{ template "grafana.name" . }}-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.datasources.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.datasources.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.datasources.script }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.datasources.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.datasources.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.datasources.watchServerTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchServerTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.datasources.watchClientTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchClientTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: {{ template "grafana.name" . }}-sc-plugins + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.plugins.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.plugins.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.plugins.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.plugins.label }}" + {{- if .Values.sidecar.plugins.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.plugins.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/plugins" + - name: RESOURCE + value: {{ quote .Values.sidecar.plugins.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.plugins.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.plugins.script }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.plugins.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.plugins.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.plugins.watchServerTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchServerTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.plugins.watchClientTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchClientTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} + - name: {{ .Chart.Name }} + {{- if .Values.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.command }} + command: + {{- range .Values.command }} + - {{ . }} + {{- end }} + {{- end}} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/grafana.ini" + subPath: grafana.ini + {{- if .Values.ldap.enabled }} + - name: ldap + mountPath: "/etc/grafana/ldap.toml" + subPath: ldap.toml + {{- end }} + {{- $root := . }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ (tpl .subPath $root) | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- if .Values.dashboards }} +{{- range $provider, $dashboards := .Values.dashboards }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} + - name: dashboards-{{ $provider }} + mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" + subPath: "{{ $key }}.json" +{{- end }} +{{- end }} +{{- end }} +{{- end -}} +{{- if .Values.dashboardsConfigMaps }} +{{- range (keys .Values.dashboardsConfigMaps | sortAlpha) }} + - name: dashboards-{{ . }} + mountPath: "/var/lib/grafana/dashboards/{{ . }}" +{{- end }} +{{- end }} +{{- if .Values.datasources }} +{{- range (keys .Values.datasources | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.notifiers }} +{{- range (keys .Values.notifiers | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.alerting }} +{{- range (keys .Values.alerting | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.dashboardProviders }} +{{- range (keys .Values.dashboardProviders | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} +{{ if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" + subPath: provider.yaml +{{- end}} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + ports: + - name: {{ .Values.podPortName }} + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + env: + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if .Values.plugins }} + - name: GF_INSTALL_PLUGINS + valueFrom: + configMapKeyRef: + name: {{ template "grafana.fullname" . }} + key: plugins + {{- end }} + {{- if .Values.smtp.existingSecret }} + - name: GF_SMTP_USER + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.userKey | default "user" }} + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.passwordKey | default "password" }} + {{- end }} + {{- if .Values.imageRenderer.enabled }} + - name: GF_RENDERING_SERVER_URL + value: http://{{ template "grafana.fullname" . }}-image-renderer.{{ template "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render + - name: GF_RENDERING_CALLBACK_URL + value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} + {{- end }} + - name: GF_PATHS_DATA + value: {{ (get .Values "grafana.ini").paths.data }} + - name: GF_PATHS_LOGS + value: {{ (get .Values "grafana.ini").paths.logs }} + - name: GF_PATHS_PLUGINS + value: {{ (get .Values "grafana.ini").paths.plugins }} + - name: GF_PATHS_PROVISIONING + value: {{ (get .Values "grafana.ini").paths.provisioning }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: +{{ tpl (toYaml $value) $ | indent 10 }} + {{- end }} +{{- range $key, $value := .Values.env }} + - name: "{{ tpl $key $ }}" + value: "{{ tpl (print $value) $ }}" +{{- end }} + {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} + envFrom: + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ tpl .Values.envFromSecret . }} + {{- end }} + {{- if .Values.envRenderSecret }} + - secretRef: + name: {{ template "grafana.fullname" . }}-env + {{- end }} + {{- range .Values.envFromSecrets }} + - secretRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- range .Values.envFromConfigMaps }} + - configMapRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- end }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if .Values.lifecycleHooks }} + lifecycle: {{ tpl (.Values.lifecycleHooks | toYaml) . | nindent 6 }} +{{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- with .Values.extraContainers }} +{{ tpl . $ | indent 2 }} +{{- end }} +nodeSelector: {{ include "linux-node-selector" . | nindent 2 }} +{{- if .Values.nodeSelector }} +{{ toYaml .Values.nodeSelector | indent 2 }} +{{- end }} +{{- $root := . }} +{{- with .Values.affinity }} +affinity: +{{ tpl (toYaml .) $root | indent 2 }} +{{- end }} +{{- with .Values.topologySpreadConstraints }} +topologySpreadConstraints: + {{- toYaml . | nindent 2 }} +{{- end }} +tolerations: {{ include "linux-node-tolerations" . | nindent 2 }} +{{- if .Values.tolerations }} +{{ toYaml .Values.tolerations | indent 2 }} +{{- end }} +volumes: + - name: config + configMap: + name: {{ template "grafana.fullname" . }} +{{- $root := . }} +{{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} + {{- if .items }} + items: {{ toYaml .items | nindent 6 }} + {{- end }} +{{- end }} + {{- if .Values.dashboards }} + {{- range (keys .Values.dashboards | sortAlpha) }} + - name: dashboards-{{ . }} + configMap: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsConfigMaps }} + {{ $root := . }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} + - name: dashboards-{{ $provider }} + configMap: + name: {{ tpl $name $root }} + {{- end }} + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + secret: + {{- if .Values.ldap.existingSecret }} + secretName: {{ .Values.ldap.existingSecret }} + {{- else }} + secretName: {{ template "grafana.fullname" . }} + {{- end }} + items: + - key: ldap-toml + path: ldap.toml + {{- end }} +{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} + - name: storage + persistentVolumeClaim: + claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} +{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} +# nothing +{{- else }} + - name: storage +{{- if .Values.persistence.inMemory.enabled }} + emptyDir: + medium: Memory +{{- if .Values.persistence.inMemory.sizeLimit }} + sizeLimit: {{ .Values.persistence.inMemory.sizeLimit }} +{{- end -}} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume +{{- if .Values.sidecar.dashboards.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.dashboards.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + configMap: + name: {{ template "grafana.fullname" . }}-config-dashboards +{{- end }} +{{- end }} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume +{{- if .Values.sidecar.datasources.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.datasources.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume +{{- if .Values.sidecar.plugins.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.plugins.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume +{{- if .Values.sidecar.notifiers.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.notifiers.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- range .Values.extraSecretMounts }} +{{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- if .items }} + items: {{ toYaml .items | nindent 6 }} + {{- end }} +{{- else if .projected }} + - name: {{ .name }} + projected: {{- toYaml .projected | nindent 6 }} +{{- else if .csi }} + - name: {{ .name }} + csi: {{- toYaml .csi | nindent 6 }} +{{- end }} +{{- end }} +{{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + path: {{ .hostPath }} + {{- else if .csi }} + csi: + data: + {{ toYaml .data | nindent 6 }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} +{{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + emptyDir: {} +{{- end -}} +{{- if .Values.extraContainerVolumes }} +{{ tpl (toYaml .Values.extraContainerVolumes) . | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml new file mode 100644 index 00000000..154658b5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled (or .Values.rbac.extraClusterRoleRules (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} +rules: +{{- if or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled) }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end}} +{{- with .Values.rbac.extraClusterRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end}} +{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..4accbfac --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/clusterrolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "grafana.fullname" . }}-clusterrolebinding + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +roleRef: + kind: ClusterRole +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml new file mode 100644 index 00000000..65d73858 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap-dashboard-provider.yaml @@ -0,0 +1,29 @@ +{{- if .Values.sidecar.dashboards.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-config-dashboards + namespace: {{ template "grafana.namespace" . }} +data: + provider.yaml: |- + apiVersion: 1 + providers: + - name: '{{ .Values.sidecar.dashboards.provider.name }}' + orgId: {{ .Values.sidecar.dashboards.provider.orgid }} + {{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + folder: '{{ .Values.sidecar.dashboards.provider.folder }}' + {{- end}} + type: {{ .Values.sidecar.dashboards.provider.type }} + disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} + allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} + updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }} + options: + foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} +{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml new file mode 100644 index 00000000..2461d175 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/configmap.yaml @@ -0,0 +1,117 @@ +{{- if .Values.createConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +data: +{{- if .Values.plugins }} + plugins: {{ join "," .Values.plugins }} +{{- end }} + grafana.ini: | +{{- range $elem, $elemVal := index .Values "grafana.ini" }} + {{- if not (kindIs "map" $elemVal) }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} +{{- end }} +{{- range $key, $value := index .Values "grafana.ini" }} + {{- if kindIs "map" $value }} + [{{ $key }}] + {{- range $elem, $elemVal := $value }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{- if .Values.datasources }} +{{ $root := . }} + {{- range $key, $value := .Values.datasources }} + {{ $key }}: | +{{ tpl (toYaml $value | indent 4) $root }} + {{- end -}} +{{- end -}} + +{{- if .Values.notifiers }} + {{- range $key, $value := .Values.notifiers }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.alerting }} +{{ $root := . }} + {{- range $key, $value := .Values.alerting }} + {{ $key }}: | +{{ tpl (toYaml $value | indent 4) $root }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboards }} + download_dashboards.sh: | + #!/usr/bin/env sh + set -euf + {{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{- range $value.providers }} + mkdir -p {{ .options.path }} + {{- end }} + {{- end }} + {{- end }} + {{ $dashboardProviders := .Values.dashboardProviders }} + {{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} + curl -skf \ + --connect-timeout 60 \ + --max-time 60 \ + {{- if not $value.b64content }} + -H "Accept: application/json" \ + {{- if $value.token }} + -H "Authorization: token {{ $value.token }}" \ + {{- end }} + {{- if $value.bearerToken }} + -H "Authorization: Bearer {{ $value.bearerToken }}" \ + {{- end }} + {{- if $value.gitlabToken }} + -H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \ + {{- end }} + -H "Content-Type: application/json;charset=UTF-8" \ + {{ end }} + {{- $dpPath := "" -}} + {{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers }} + {{- if eq $kd.name $provider -}} + {{- $dpPath = $kd.options.path -}} + {{- end -}} + {{- end -}} + {{- if $value.url -}}"{{ $value.url }}"{{- else -}}"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download"{{- end -}}{{ if $value.datasource }} | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g'{{ end }}{{- if $value.b64content -}} | base64 -d {{- end -}} \ + > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" + {{- end }} + {{- end -}} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml new file mode 100644 index 00000000..59e0be64 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/dashboards-json-configmap.yaml @@ -0,0 +1,35 @@ +{{- if .Values.dashboards }} +{{ $files := .Files }} +{{- range $provider, $dashboards := .Values.dashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} + namespace: {{ template "grafana.namespace" $ }} + labels: + {{- include "grafana.labels" $ | nindent 4 }} + dashboard-provider: {{ $provider }} +{{- if $dashboards }} +data: +{{- $dashboardFound := false }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} +{{- $dashboardFound = true }} +{{ print $key | indent 2 }}.json: +{{- if hasKey $value "json" }} + |- +{{ $value.json | indent 6 }} +{{- end }} +{{- if hasKey $value "file" }} +{{ toYaml ( $files.Get $value.file ) | indent 4}} +{{- end }} +{{- end }} +{{- end }} +{{- if not $dashboardFound }} + {} +{{- end }} +{{- end }} +--- +{{- end }} + +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml new file mode 100644 index 00000000..fee9c335 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/deployment.yaml @@ -0,0 +1,50 @@ +{{ if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} + replicas: {{ .Values.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- with .Values.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} +{{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- if .Values.envRenderSecret }} + checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | indent 6 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml new file mode 100644 index 00000000..b5faddcf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/headless-service.yaml @@ -0,0 +1,22 @@ +{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset"))}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-headless + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + clusterIP: None + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} + type: ClusterIP + ports: + - protocol: TCP + port: 3000 + targetPort: {{ .Values.service.targetPort }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml new file mode 100644 index 00000000..236a06d6 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/hpa.yaml @@ -0,0 +1,21 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: {{ template "grafana.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "grafana.name" . }} + helm.sh/chart: {{ template "grafana.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "grafana.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: +{{ toYaml .Values.autoscaling.metrics | indent 4 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml new file mode 100644 index 00000000..97a8675b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-deployment.yaml @@ -0,0 +1,123 @@ +{{ if .Values.imageRenderer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.labels }} +{{ toYaml .Values.imageRenderer.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.imageRenderer.replicas }} + revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} +{{- with .Values.imageRenderer.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} +{{- with .Values.imageRenderer.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- with .Values.imageRenderer.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + + {{- if .Values.imageRenderer.schedulerName }} + schedulerName: "{{ .Values.imageRenderer.schedulerName }}" + {{- end }} + {{- if .Values.imageRenderer.serviceAccountName }} + serviceAccountName: "{{ .Values.imageRenderer.serviceAccountName }}" + {{- else }} + serviceAccountName: {{ template "grafana.serviceAccountName" . }} + {{- end }} + {{- if .Values.imageRenderer.securityContext }} + securityContext: + {{- toYaml .Values.imageRenderer.securityContext | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.hostAliases }} + hostAliases: + {{- toYaml .Values.imageRenderer.hostAliases | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.priorityClassName }} + priorityClassName: {{ .Values.imageRenderer.priorityClassName }} + {{- end }} + {{- if .Values.imageRenderer.image.pullSecrets }} + imagePullSecrets: + {{- $root := . }} + {{- range .Values.imageRenderer.image.pullSecrets }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + containers: + - name: {{ .Chart.Name }}-image-renderer + {{- if .Values.imageRenderer.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} + {{- if .Values.imageRenderer.command }} + command: + {{- range .Values.imageRenderer.command }} + - {{ . }} + {{- end }} + {{- end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + containerPort: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: {{ .Values.imageRenderer.service.portName }} + env: + - name: HTTP_PORT + value: {{ .Values.imageRenderer.service.targetPort | quote }} + {{- range $key, $value := .Values.imageRenderer.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + securityContext: + capabilities: + drop: ['all'] + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /tmp + name: image-renderer-tmpfs + {{- with .Values.imageRenderer.resources }} + resources: +{{ toYaml . | indent 12 }} + {{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + {{- if .Values.imageRenderer.nodeSelector }} +{{ toYaml . | indent 8 }} + {{- end }} + {{- $root := . }} + {{- with .Values.imageRenderer.affinity }} + affinity: +{{ tpl (toYaml .) $root | indent 8 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + {{- if .Values.imageRenderer.tolerations }} +{{ toYaml . | indent 8 }} + {{- end }} + volumes: + - name: image-renderer-tmpfs + emptyDir: {} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml new file mode 100644 index 00000000..0d9bdfe4 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-network-policy.yaml @@ -0,0 +1,73 @@ +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-ingress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer ingress traffic from grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Ingress + ingress: + - ports: + - port: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + from: + - namespaceSelector: + matchLabels: + name: {{ template "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} + +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-egress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer egress traffic to grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Egress + egress: + # allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # talk only to grafana + - ports: + - port: {{ .Values.service.port }} + protocol: TCP + to: + - podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml new file mode 100644 index 00000000..fcf707a3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/image-renderer-service.yaml @@ -0,0 +1,33 @@ +{{ if .Values.imageRenderer.enabled }} +{{ if .Values.imageRenderer.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.service.labels }} +{{ toYaml .Values.imageRenderer.service.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + type: ClusterIP + {{- if .Values.imageRenderer.service.clusterIP }} + clusterIP: {{ .Values.imageRenderer.service.clusterIP }} + {{end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + port: {{ .Values.imageRenderer.service.port }} + protocol: TCP + targetPort: {{ .Values.imageRenderer.service.targetPort }} + {{- if .Values.imageRenderer.appProtocol }} + appProtocol: {{ .Values.imageRenderer.appProtocol }} + {{- end }} + selector: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} +{{ end }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml new file mode 100644 index 00000000..7699ceca --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/ingress.yaml @@ -0,0 +1,78 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +{{- $ingressPathType := .Values.ingress.pathType -}} +{{- $extraPaths := .Values.ingress.extraPaths -}} +apiVersion: {{ include "grafana.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels | indent 4 }} +{{- end }} + {{- if .Values.ingress.annotations }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end -}} +{{- if .Values.ingress.tls }} + tls: +{{ tpl (toYaml .Values.ingress.tls) $ | indent 4 }} +{{- end }} + rules: + {{- if .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} + - host: {{ tpl . $}} + http: + paths: +{{- if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + - backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- if $ingressPath }} + path: {{ $ingressPath }} + {{- end }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + {{- end -}} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml new file mode 100644 index 00000000..b751d943 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/networkpolicy.yaml @@ -0,0 +1,52 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + policyTypes: + {{- if .Values.networkPolicy.ingress }} + - Ingress + {{- end }} + {{- if .Values.networkPolicy.egress.enabled }} + - Egress + {{- end }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + + {{- if .Values.networkPolicy.egress.enabled }} + egress: + - ports: + {{ .Values.networkPolicy.egress.ports | toJson }} + {{- end }} + {{- if .Values.networkPolicy.ingress }} + ingress: + - ports: + - port: {{ .Values.service.targetPort }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "grafana.fullname" . }}-client: "true" + {{- with .Values.networkPolicy.explicitNamespacesSelector }} + - namespaceSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "grafana.labels" . | nindent 14 }} + role: read + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml new file mode 100644 index 00000000..6b1e8ede --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/nginx-config.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-nginx-proxy-config + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +data: + nginx.conf: |- + worker_processes auto; + error_log /dev/stdout warn; + pid /var/cache/nginx/nginx.pid; + + events { + worker_connections 1024; + } + + http { + include /etc/nginx/mime.types; + log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; + + proxy_connect_timeout 10; + proxy_read_timeout 180; + proxy_send_timeout 5; + proxy_buffering off; + proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + server { + listen 8080; + access_log off; + + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + proxy_set_header Host $http_host; + + location /api/dashboards { + proxy_pass http://localhost:3000; + } + + location /api/search { + proxy_pass http://localhost:3000; + + sub_filter_types application/json; + sub_filter_once off; + } + + location /api/live/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $http_host; + proxy_pass http://localhost:3000; + } + + location / { + proxy_cache my_zone; + proxy_cache_valid 200 302 1d; + proxy_cache_valid 301 30d; + proxy_cache_valid any 5m; + proxy_cache_bypass $http_cache_control; + add_header X-Proxy-Cache $upstream_cache_status; + add_header Cache-Control "public"; + + proxy_pass http://localhost:3000/; + + sub_filter_once off; +{{- if not (empty .Values.global.cattle.clusterId) }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- else }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- end }} + sub_filter '"url":"/' '"url":"./'; + sub_filter ':"/avatar/' ':"avatar/'; + + if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { + expires 90d; + } + + rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; + + } + } + } diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml new file mode 100644 index 00000000..70901b70 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +spec: +{{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml new file mode 100644 index 00000000..82d295ad --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/podsecuritypolicy.yaml @@ -0,0 +1,45 @@ +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.rbac.pspAnnotations }} + annotations: {{ toYaml .Values.rbac.pspAnnotations | nindent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + # Default set from Docker, with DAC_OVERRIDE and CHOWN + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'csi' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml new file mode 100644 index 00000000..8a3ee122 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/pvc.yaml @@ -0,0 +1,35 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.persistence.annotations }} + annotations: +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .Values.persistence.finalizers }} + finalizers: +{{ toYaml . | indent 4 }} + {{- end }} +spec: + accessModes: +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClassName }} + storageClassName: {{ .Values.persistence.storageClassName }} + {{- end -}} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 6 }} + {{- end }} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml new file mode 100644 index 00000000..80e2c596 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/role.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +{{- if or .Values.global.cattle.psp.enabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled (or .Values.sidecar.plugins.enabled .Values.rbac.extraRoleRules)))) }} +rules: +{{- if .Values.global.cattle.psp.enabled }} +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}] +{{- end }} +{{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end }} +{{- with .Values.rbac.extraRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml new file mode 100644 index 00000000..e0107255 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/rolebinding.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }} +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml new file mode 100644 index 00000000..5c09313e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret-env.yaml @@ -0,0 +1,14 @@ +{{- if .Values.envRenderSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }}-env + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +type: Opaque +data: +{{- range $key, $val := .Values.envRenderSecret }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end -}} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml new file mode 100644 index 00000000..c8aa750a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/secret.yaml @@ -0,0 +1,26 @@ +{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +type: Opaque +data: + {{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} + admin-user: {{ .Values.adminUser | b64enc | quote }} + {{- if .Values.adminPassword }} + admin-password: {{ .Values.adminPassword | b64enc | quote }} + {{- else }} + admin-password: {{ template "grafana.password" . }} + {{- end }} + {{- end }} + {{- if not .Values.ldap.existingSecret }} + ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml new file mode 100644 index 00000000..d0a1756c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/service.yaml @@ -0,0 +1,55 @@ +{{ if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- $root := . }} +{{- with .Values.service.annotations }} + annotations: +{{ tpl (toYaml . | indent 4) $root }} +{{- end }} +spec: +{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{end}} +{{- else if eq .Values.service.type "LoadBalancer" }} + type: {{ .Values.service.type }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} + {{- end -}} +{{- else }} + type: {{ .Values.service.type }} +{{- end }} +{{- if .Values.service.externalIPs }} + externalIPs: +{{ toYaml .Values.service.externalIPs | indent 4 }} +{{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.service.targetPort }} + {{- if .Values.service.appProtocol }} + appProtocol: {{ .Values.service.appProtocol }} + {{- end }} + {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{.Values.service.nodePort}} + {{ end }} + {{- if .Values.extraExposePorts }} + {{- tpl (toYaml .Values.extraExposePorts) . | nindent 4 }} + {{- end }} + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 00000000..4ccee15e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- $root := . }} +{{- with .Values.serviceAccount.annotations }} + annotations: +{{ tpl (toYaml . | indent 4) $root }} +{{- end }} + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml new file mode 100644 index 00000000..31ab6b88 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/servicemonitor.yaml @@ -0,0 +1,58 @@ +{{- if .Values.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "grafana.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ tpl .Values.serviceMonitor.namespace . }} + {{- else }} + namespace: {{ template "grafana.namespace" . }} + {{- end }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.serviceMonitor.path }} + scheme: {{ .Values.serviceMonitor.scheme }} + {{- if .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + metricRelabelings: + {{- if .Values.serviceMonitor.metricRelabelings }} + {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} + {{- if .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} + {{- end }} + jobLabel: "{{ .Release.Name }}" + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 8 }} + namespaceSelector: + matchNames: + - {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml new file mode 100644 index 00000000..aa6f305e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/statefulset.yaml @@ -0,0 +1,56 @@ +{{- if (or (.Values.useStatefulSet) (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")))}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + serviceName: {{ template "grafana.fullname" . }}-headless + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} + {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} + {{- if .Values.persistence.enabled}} + volumeClaimTemplates: + - metadata: + name: storage + spec: +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} + accessModes: {{ .Values.persistence.accessModes }} + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size }} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml new file mode 100644 index 00000000..ff53aaf1 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-configmap.yaml @@ -0,0 +1,17 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +data: + run.sh: |- + @test "Test Health" { + url="http://{{ template "grafana.fullname" . }}/api/health" + + code=$(wget --server-response --spider --timeout 10 --tries 1 ${url} 2>&1 | awk '/^ HTTP/{print $2}') + [ "$code" == "200" ] + } +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml new file mode 100644 index 00000000..5dd736ef --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-podsecuritypolicy.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }}-test + labels: + {{- include "grafana.labels" . | nindent 4 }} +spec: + allowPrivilegeEscalation: true + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + fsGroup: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + volumes: + - configMap + - downwardAPI + - emptyDir + - projected + - csi + - secret +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml new file mode 100644 index 00000000..ea2f8c6b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-role.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}-test] +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml new file mode 100644 index 00000000..7eda2651 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "grafana.fullname" . }}-test +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountNameTest" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml new file mode 100644 index 00000000..5c335073 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test-serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + name: {{ template "grafana.serviceAccountNameTest" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml new file mode 100644 index 00000000..3a84fbe0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/templates/tests/test.yaml @@ -0,0 +1,51 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ template "grafana.fullname" . }}-test + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + namespace: {{ template "grafana.namespace" . }} +spec: + serviceAccountName: {{ template "grafana.serviceAccountNameTest" . }} + {{- if .Values.testFramework.securityContext }} + securityContext: {{ toYaml .Values.testFramework.securityContext | nindent 4 }} + {{- end }} + {{- $root := . }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} + {{- if .Values.nodeSelector }} +{{ toYaml .Values.nodeSelector | indent 4 }} + {{- end }} + {{- $root := . }} + {{- with .Values.affinity }} + affinity: +{{ tpl (toYaml .) $root | indent 4 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.tolerations }} +{{ toYaml .Values.tolerations | indent 4 }} +{{- end }} + containers: + - name: {{ .Release.Name }}-test + image: "{{ template "system_default_registry" . }}{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" + imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" + command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] + volumeMounts: + - mountPath: /tests + name: tests + readOnly: true + volumes: + - name: tests + configMap: + name: {{ template "grafana.fullname" . }}-test + restartPolicy: Never +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml b/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml new file mode 100644 index 00000000..196a07bf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/charts/grafana/values.yaml @@ -0,0 +1,1062 @@ +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectNamespaces: [] + +rbac: + create: true + ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) + # useExistingRole: name-of-some-(cluster)role + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + namespaced: false + extraRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] + extraClusterRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] +serviceAccount: + create: true + name: + nameTest: +## Service account annotations. Can be templated. +# annotations: +# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + autoMount: true + +replicas: 1 + +## Create a headless service for the deployment +headlessService: false + +## Create HorizontalPodAutoscaler object for deployment type +# +autoscaling: + enabled: false +# minReplicas: 1 +# maxReplicas: 10 +# metrics: +# - type: Resource +# resource: +# name: cpu +# targetAverageUtilization: 60 +# - type: Resource +# resource: +# name: memory +# targetAverageUtilization: 60 + +## See `kubectl explain poddisruptionbudget.spec` for more +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} +# minAvailable: 1 +# maxUnavailable: 1 + +## See `kubectl explain deployment.spec.strategy` for more +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +deploymentStrategy: + type: RollingUpdate + +readinessProbe: + httpGet: + path: /api/health + port: 3000 + +livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 30 + failureThreshold: 10 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: "default-scheduler" + +image: + repository: rancher/mirrored-grafana-grafana + # Overrides the Grafana image tag whose default is the chart appVersion + tag: 9.1.5 + sha: "" + pullPolicy: IfNotPresent + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Can be templated. + ## + # pullSecrets: + # - myRegistrKeySecretName + +testFramework: + enabled: false + image: "rancher/mirrored-bats-bats" + tag: "v1.4.1" + imagePullPolicy: IfNotPresent + securityContext: + runAsNonRoot: true + runAsUser: 1000 + +securityContext: + runAsNonRoot: true + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 + +containerSecurityContext: + {} + +# Enable creating the grafana configmap +createConfigmap: true + +# Extra configmaps to mount in grafana pods +# Values are templated. +extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # subPath: certificates.crt # (optional) + # configMap: certs-configmap + # readOnly: true + + +extraEmptyDirMounts: [] + # - name: provisioning-notifiers + # mountPath: /etc/grafana/provisioning/notifiers + + +# Apply extra labels to common labels. +extraLabels: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: + +downloadDashboardsImage: + repository: rancher/mirrored-curlimages-curl + tag: 7.85.0 + sha: "" + pullPolicy: IfNotPresent + +downloadDashboards: + env: {} + envFromSecret: "" + resources: {} + securityContext: {} + +## Pod Annotations +# podAnnotations: {} + +## Pod Labels +# podLabels: {} + +podPortName: grafana + +## Deployment annotations +# annotations: {} + +## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + enabled: true + type: ClusterIP + port: 80 + targetPort: 3000 + # targetPort: 4181 To be used with a proxy extraContainer + ## Service annotations. Can be templated. + annotations: {} + labels: {} + portName: service + # Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + +serviceMonitor: + ## If true, a ServiceMonitor CRD is created for a prometheus operator + ## https://github.com/coreos/prometheus-operator + ## + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 1m + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + relabelings: [] + +extraExposePorts: [] + # - name: keycloak + # port: 8080 + # targetPort: 8080 + # type: ClusterIP + +# overrides pod.spec.hostAliases in the grafana deployment's pods +hostAliases: [] + # - ip: "1.2.3.4" + # hostnames: + # - "my.host.com" + +ingress: + enabled: false + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + # Values can be templated + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + hosts: + - chart-example.local + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## Or for k8s > 1.19 + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + +## Node labels for pod assignment +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +# +nodeSelector: {} + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Topology Spread Constraints +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] + +## Additional init containers (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +## +extraInitContainers: [] + +## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod +extraContainers: "" +# extraContainers: | +# - name: proxy +# image: quay.io/gambol99/keycloak-proxy:latest +# args: +# - -provider=github +# - -client-id= +# - -client-secret= +# - -github-org= +# - -email-domain=* +# - -cookie-secret= +# - -http-address=http://0.0.0.0:4181 +# - -upstream-url=http://127.0.0.1:3000 +# ports: +# - name: proxy-web +# containerPort: 4181 + +## Volumes that can be used in init containers that will not be mounted to deployment pods +extraContainerVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + type: pvc + enabled: false + # storageClassName: default + accessModes: + - ReadWriteOnce + size: 10Gi + # annotations: {} + finalizers: + - kubernetes.io/pvc-protection + # selectorLabels: {} + ## Sub-directory of the PV to mount. Can be templated. + # subPath: "" + ## Name of an existing PVC. Can be templated. + # existingClaim: + + ## If persistence is not enabled, this allows to mount the + ## local storage in-memory to improve performance + ## + inMemory: + enabled: false + ## The maximum usage on memory medium EmptyDir would be + ## the minimum value between the SizeLimit specified + ## here and the sum of memory limits of all containers in a pod + ## + # sizeLimit: 300Mi + +initChownData: + ## If false, data ownership will not be reset at startup + ## This allows the prometheus-server to be run with an arbitrary user + ## + enabled: true + + ## initChownData container image + ## + image: + repository: rancher/mirrored-library-busybox + tag: "1.31.1" + sha: "" + pullPolicy: IfNotPresent + + ## initChownData resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + +# Administrator credentials when not using an existing secret (see below) +adminUser: admin +# adminPassword: strongpassword + +# Use an existing secret for the admin user. +admin: + ## Name of the secret. Can be templated. + existingSecret: "" + userKey: admin-user + passwordKey: admin-password + +## Define command to be executed at startup by grafana container +## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) +## Default is "run.sh" as defined in grafana's Dockerfile +# command: +# - "sh" +# - "/run.sh" + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Extra environment variables that will be pass onto deployment pods +## +## to provide grafana with access to CloudWatch on AWS EKS: +## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) +## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the +## same oidc eks provider as noted before (same as the existing line) +## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name +## +## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", +## +## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess +## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) +## +## env: +## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here +## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token +## AWS_REGION: us-east-1 +## +## 5. uncomment the EKS section in extraSecretMounts: below +## 6. uncomment the annotation section in the serviceAccount: above +## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn + +env: {} + +## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core +## Renders in container spec as: +## env: +## ... +## - name: +## valueFrom: +## +envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + +## The name of a secret in the same kubernetes namespace which contain values to be added to the environment +## This can be useful for auth tokens, etc. Value is templated. +envFromSecret: "" + +## Sensible environment variables that will be rendered as new secret object +## This can be useful for auth tokens, etc +envRenderSecret: {} + +## The names of secrets in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. +## Name is templated. +envFromSecrets: [] +## - name: secret-name +## optional: true + +## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. +## Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core +envFromConfigMaps: [] +## - name: configmap-name +## optional: true + +# Inject Kubernetes services as environment variables. +# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables +enableServiceLinks: true + +## Additional grafana server secret mounts +# Defines additional mounts with secrets. Secrets must be manually created in the namespace. +extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # secretName: grafana-secret-files + # readOnly: true + # subPath: "" + # + # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) + # - name: aws-iam-token + # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount + # readOnly: true + # projected: + # defaultMode: 420 + # sources: + # - serviceAccountToken: + # audience: sts.amazonaws.com + # expirationSeconds: 86400 + # path: token + # + # for CSI e.g. Azure Key Vault use the following + # - name: secrets-store-inline + # mountPath: /run/secrets + # readOnly: true + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "akv-grafana-spc" + # nodePublishSecretRef: # Only required when using service principal mode + # name: grafana-akv-creds # Only required when using service principal mode + +## Additional grafana server volume mounts +# Defines additional volume mounts. +extraVolumeMounts: [] + # - name: extra-volume-0 + # mountPath: /mnt/volume0 + # readOnly: true + # existingClaim: volume-claim + # - name: extra-volume-1 + # mountPath: /mnt/volume1 + # readOnly: true + # hostPath: /usr/shared/ + # - name: grafana-secrets + # csi: true + # data: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "grafana-env-spc" + +## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request +lifecycleHooks: {} + # postStart: + # exec: + # command: [] + +## Pass the plugins you want installed as a list. +## +plugins: [] + # - digrich-bubblechart-panel + # - grafana-clock-panel + +## Configure grafana datasources +## ref: http://docs.grafana.org/administration/provisioning/#datasources +## +datasources: {} +# datasources.yaml: +# apiVersion: 1 +# datasources: +# - name: Prometheus +# type: prometheus +# url: http://prometheus-prometheus-server +# access: proxy +# isDefault: true +# - name: CloudWatch +# type: cloudwatch +# access: proxy +# uid: cloudwatch +# editable: false +# jsonData: +# authType: default +# defaultRegion: us-east-1 + +## Configure grafana alerting (can be templated) +## ref: http://docs.grafana.org/administration/provisioning/#alerting +## +alerting: {} + # rules.yaml: + # apiVersion: 1 + # groups: + # - orgId: 1 + # name: '{{ .Chart.Name }}_my_rule_group' + # folder: my_first_folder + # interval: 60s + # rules: + # - uid: my_id_1 + # title: my_first_rule + # condition: A + # data: + # - refId: A + # datasourceUid: '-100' + # model: + # conditions: + # - evaluator: + # params: + # - 3 + # type: gt + # operator: + # type: and + # query: + # params: + # - A + # reducer: + # type: last + # type: query + # datasource: + # type: __expr__ + # uid: '-100' + # expression: 1==0 + # intervalMs: 1000 + # maxDataPoints: 43200 + # refId: A + # type: math + # dashboardUid: my_dashboard + # panelId: 123 + # noDataState: Alerting + # for: 60s + # annotations: + # some_key: some_value + # labels: + # team: sre_team_1 + # contactpoints.yaml: + # apiVersion: 1 + # contactPoints: + # - orgId: 1 + # name: cp_1 + # receivers: + # - uid: first_uid + # type: pagerduty + # settings: + # integrationKey: XXX + # severity: critical + # class: ping failure + # component: Grafana + # group: app-stack + # summary: | + # {{ `{{ template "default.message" . }}` }} + +## Configure notifiers +## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels +## +notifiers: {} +# notifiers.yaml: +# notifiers: +# - name: email-notifier +# type: email +# uid: email1 +# # either: +# org_id: 1 +# # or +# org_name: Main Org. +# is_default: true +# settings: +# addresses: an_email_address@example.com +# delete_notifiers: + +## Configure grafana dashboard providers +## ref: http://docs.grafana.org/administration/provisioning/#dashboards +## +## `path` must be /var/lib/grafana/dashboards/ +## +dashboardProviders: {} +# dashboardproviders.yaml: +# apiVersion: 1 +# providers: +# - name: 'default' +# orgId: 1 +# folder: '' +# type: file +# disableDeletion: false +# editable: true +# options: +# path: /var/lib/grafana/dashboards/default + +## Configure grafana dashboard to import +## NOTE: To use dashboards you must also enable/configure dashboardProviders +## ref: https://grafana.com/dashboards +## +## dashboards per provider, use provider name as key. +## +dashboards: {} + # default: + # some-dashboard: + # json: | + # $RAW_JSON + # custom-dashboard: + # file: dashboards/custom-dashboard.json + # prometheus-stats: + # gnetId: 2 + # revision: 2 + # datasource: Prometheus + # local-dashboard: + # url: https://example.com/repository/test.json + # token: '' + # local-dashboard-base64: + # url: https://example.com/repository/test-b64.json + # token: '' + # b64content: true + # local-dashboard-gitlab: + # url: https://example.com/repository/test-gitlab.json + # gitlabToken: '' + # local-dashboard-bitbucket: + # url: https://example.com/repository/test-bitbucket.json + # bearerToken: '' + +## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. +## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. +## ConfigMap data example: +## +## data: +## example-dashboard.json: | +## RAW_JSON +## +dashboardsConfigMaps: {} +# default: "" + +## Grafana's primary configuration +## NOTE: values in map will be converted to ini format +## ref: http://docs.grafana.org/installation/configuration/ +## +grafana.ini: + paths: + data: /var/lib/grafana/ + logs: /var/log/grafana + plugins: /var/lib/grafana/plugins + provisioning: /etc/grafana/provisioning + analytics: + check_for_updates: true + log: + mode: console + grafana_net: + url: https://grafana.net + server: + domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ end }}" +## grafana Authentication can be enabled with the following values on grafana.ini + # server: + # The full public facing url you use in browser, used for redirects and emails + # root_url: + # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana + # auth.github: + # enabled: false + # allow_sign_up: false + # scopes: user:email,read:org + # auth_url: https://github.com/login/oauth/authorize + # token_url: https://github.com/login/oauth/access_token + # api_url: https://api.github.com/user + # team_ids: + # allowed_organizations: + # client_id: + # client_secret: +## LDAP Authentication can be enabled with the following values on grafana.ini +## NOTE: Grafana will fail to start if the value for ldap.toml is invalid + # auth.ldap: + # enabled: true + # allow_sign_up: true + # config_file: /etc/grafana/ldap.toml + +## Grafana's LDAP configuration +## Templated by the template in _helpers.tpl +## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled +## ref: http://docs.grafana.org/installation/configuration/#auth-ldap +## ref: http://docs.grafana.org/installation/ldap/#configuration +ldap: + enabled: false + # `existingSecret` is a reference to an existing secret containing the ldap configuration + # for Grafana in a key `ldap-toml`. + existingSecret: "" + # `config` is the content of `ldap.toml` that will be stored in the created secret + config: "" + # config: |- + # verbose_logging = true + + # [[servers]] + # host = "my-ldap-server" + # port = 636 + # use_ssl = true + # start_tls = false + # ssl_skip_verify = false + # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" + +## Grafana's SMTP configuration +## NOTE: To enable, grafana.ini must be configured with smtp.enabled +## ref: http://docs.grafana.org/installation/configuration/#smtp +smtp: + # `existingSecret` is a reference to an existing secret containing the smtp configuration + # for Grafana. + existingSecret: "" + userKey: "user" + passwordKey: "password" + +## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders +## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards +sidecar: + image: + repository: rancher/mirrored-kiwigrid-k8s-sidecar + tag: 1.19.2 + sha: "" + imagePullPolicy: IfNotPresent + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + securityContext: {} + # skipTlsVerify Set to true to skip tls verification for kube api calls + # skipTlsVerify: true + enableUniqueFilenames: false + readinessProbe: {} + livenessProbe: {} + # Log level default for all sidecars. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. Defaults to INFO + # logLevel: INFO + dashboards: + enabled: false + # Additional environment variables for the dashboards sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + SCProvider: true + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # value of label that the configmaps with dashboards are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) + folder: /tmp/dashboards + # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead + defaultFolderName: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # If specified, the sidecar will look for annotation with this name to create folder and put graph here. + # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. + folderAnnotation: null + # Absolute path to shell script to execute after a configmap got reloaded + script: null + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # provider configuration that lets grafana manage the dashboards + provider: + # name of the provider, should be unique + name: sidecarProvider + # orgid as configured in grafana + orgid: 1 + # folder in which the dashboards should be imported in grafana + folder: '' + # type of the provider + type: file + # disableDelete to activate a import-only behaviour + disableDelete: false + # allow updating provisioned dashboards from the UI + allowUiUpdates: false + # allow Grafana to replicate dashboard structure from filesystem + foldersFromFilesStructure: false + # Additional dashboard sidecar volume mounts + extraMounts: [] + # Sets the size limit of the dashboard sidecar emptyDir volume + sizeLimit: {} + datasources: + enabled: false + # Additional environment variables for the datasourcessidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with datasources are marked with + label: grafana_datasource + # value of label that the configmaps with datasources are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # Endpoint to send request to reload datasources + reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" + # Absolute path to shell script to execute after a datasource got reloaded + script: null + skipReload: true + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any datasources defined at startup time. + initDatasources: true + # Sets the size limit of the datasource sidecar emptyDir volume + sizeLimit: {} + plugins: + enabled: false + # Additional environment variables for the plugins sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with plugins are marked with + label: grafana_plugin + # value of label that the configmaps with plugins are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # Endpoint to send request to reload plugins + reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" + # Absolute path to shell script to execute after a plugin got reloaded + script: null + skipReload: false + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any plugins defined at startup time. + initPlugins: false + # Sets the size limit of the plugin sidecar emptyDir volume + sizeLimit: {} + notifiers: + enabled: false + # Additional environment variables for the notifierssidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with notifiers are marked with + label: grafana_notifier + # value of label that the configmaps with notifiers are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # search in configmap, secret or both + resource: both + # Sets the size limit of the notifier sidecar emptyDir volume + sizeLimit: {} + +## Override the deployment namespace +## +namespaceOverride: "" + +## Number of old ReplicaSets to retain +## +revisionHistoryLimit: 10 + +## Add a seperate remote image renderer deployment/service +imageRenderer: + # Enable the image-renderer deployment & service + enabled: false + replicas: 1 + image: + # image-renderer Image repository + repository: rancher/mirrored-grafana-grafana-image-renderer + # image-renderer Image tag + tag: 3.0.1 + # image-renderer Image sha (optional) + sha: "" + # image-renderer ImagePullPolicy + pullPolicy: Always + # extra environment variables + env: + HTTP_HOST: "0.0.0.0" + # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 + # RENDERING_MODE: clustered + # IGNORE_HTTPS_ERRORS: true + # image-renderer deployment serviceAccount + serviceAccountName: "" + # image-renderer deployment securityContext + securityContext: {} + # image-renderer deployment Host Aliases + hostAliases: [] + # image-renderer deployment priority class + priorityClassName: '' + service: + # Enable the image-renderer service + enabled: true + # image-renderer service port name + portName: 'http' + # image-renderer service port used by both service and deployment + port: 8081 + targetPort: 8081 + # Adds the appProtocol field to the image-renderer service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + # If https is enabled in Grafana, this needs to be set as 'https' to correctly configure the callback used in Grafana + grafanaProtocol: http + # In case a sub_path is used this needs to be added to the image renderer callback + grafanaSubPath: "" + # name of the image-renderer port on the pod + podPortName: http + # number of image-renderer replica sets to keep + revisionHistoryLimit: 10 + networkPolicy: + # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods + limitIngress: true + # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods + limitEgress: false + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + ## Affinity for pod assignment (evaluated as template) + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to grafana port defined. + ## When true, grafana will accept connections from any source + ## (with the correct destination port). + ## + ingress: true + ## @param networkPolicy.ingress When true enables the creation + ## an ingress network policy + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed + ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the grafana. + ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + ## + ## + ## + ## + ## + ## + egress: + ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be + ## created allowing grafana to connect to external data sources from kubernetes cluster. + enabled: false + ## + ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress + ports: [] + ## Add ports to the egress by specifying - port: + ## E.X. + ## ports: + ## - port: 80 + ## - port: 443 + ## + ## + ## + ## + ## + ## + +# Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option +enableKubeBackwardCompatibility: false +useStatefulSet: false diff --git a/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml b/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml new file mode 100644 index 00000000..b5ceb698 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/files/federate/federate-scrape-config.yaml @@ -0,0 +1,13 @@ +- job_name: 'federate' + scrape_interval: {{ .Values.federate.interval }} + honor_labels: true + metrics_path: '/federate' + + params: + 'match[]': + - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=~"kube-state-metrics|kubelet|k3s-server"}' + - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=""}' + + static_configs: + - targets: {{ .Values.federate.targets | toYaml | nindent 6 }} + diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json new file mode 100644 index 00000000..9e53081a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod-containers.json @@ -0,0 +1,636 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "CFS throttled ({{container}})", + "refId": "A" + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "System ({{container}})", + "refId": "B" + }, + { + "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Total ({{container}})", + "refId": "C" + }, + { + "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "User ({{container}})", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}) by (container)", + "interval": "", + "legendFormat": "({{container}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Total ({{container}})", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Total ({{container}})", + "refId": "B" + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Dropped ({{container}})", + "refId": "C" + }, + { + "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Errors ({{container}})", + "refId": "D" + }, + { + "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Errors ({{container}})", + "refId": "E" + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Dropped ({{container}})", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Total ({{container}})", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Total ({{container}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Write ({{container}})", + "refId": "A" + }, + { + "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Read ({{container}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Pod (Containers)", + "uid": "rancher-pod-containers-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json new file mode 100644 index 00000000..65c6bf18 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/files/rancher/pods/rancher-pod.json @@ -0,0 +1,636 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "CFS throttled", + "refId": "A" + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "System", + "refId": "B" + }, + { + "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Total", + "refId": "C" + }, + { + "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "User", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"})", + "interval": "", + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Dropped", + "refId": "C" + }, + { + "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Errors", + "refId": "D" + }, + { + "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Errors", + "refId": "E" + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Dropped", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Write", + "refId": "A" + }, + { + "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Read", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace!=\"\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace=\"$namespace\", pod!=\"\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Pod", + "uid": "rancher-pod-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json new file mode 100644 index 00000000..f6b5078a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload-pods.json @@ -0,0 +1,652 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "CFS throttled ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "System ({{pod}})", + "refId": "B" + }, + { + "expr": "(sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Total ({{pod}})", + "refId": "C" + }, + { + "expr": "(sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "User ({{pod}})", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "({{pod}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Total ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Total ({{pod}})", + "refId": "B" + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Dropped ({{pod}})", + "refId": "C" + }, + { + "expr": "(sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Errors ({{pod}})", + "refId": "D" + }, + { + "expr": "(sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Errors ({{pod}})", + "refId": "E" + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Dropped ({{pod}})", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Total ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Total ({{pod}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Write ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Read ({{pod}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*namespace=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "kind", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_kind=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_name=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Workload (Pods)", + "uid": "rancher-workload-pods-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json new file mode 100644 index 00000000..9f5317c2 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/files/rancher/workloads/rancher-workload.json @@ -0,0 +1,652 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "CFS throttled", + "refId": "A" + }, + { + "expr": "sum((sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "System", + "refId": "B" + }, + { + "expr": "sum((sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Total", + "refId": "C" + }, + { + "expr": "sum((sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "User", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum((sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + }, + { + "expr": "sum((sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Dropped", + "refId": "C" + }, + { + "expr": "sum((sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Errors", + "refId": "D" + }, + { + "expr": "sum((sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Errors", + "refId": "E" + }, + { + "expr": "sum((sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Dropped", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum((sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Write", + "refId": "A" + }, + { + "expr": "sum((sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Read", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*namespace=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "kind", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_kind=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_name=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Workload", + "uid": "rancher-workload-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.0/questions.yaml b/charts/rancher-project-monitoring/0.3.0/questions.yaml new file mode 100644 index 00000000..c15f36e7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/questions.yaml @@ -0,0 +1,128 @@ +questions: +- variable: alertmanager.enabled + label: Enable Alertmanager + default: true + type: boolean + group: Alertmanager +- variable: grafana.enabled + label: Enable Grafana + default: true + type: boolean + group: Grafana + show_subquestion_if: true + subquestions: + - variable: grafana.adminUser + label: Grafana Admin User + type: string + default: admin + group: Grafana + - variable: grafana.adminPassword + label: Grafana Admin Password + type: string + default: prom-operator + group: Grafana + - variable: grafana.sidecar.dashboards.label + label: Default Grafana Dashboard Label + default: grafana_dashboard + description: All ConfigMaps with this label are parsed as Grafana Dashboards + type: string + group: Grafana +- variable: grafana.persistence.enabled + type: boolean + required: true + label: Enable Persistent Volume + show_subquestion_if: true + group: Grafana + subquestions: + - variable: grafana.persistence.size + type: string + default: 1Gi + label: Size + - variable: grafana.persistence.storageClass + type: storageclass + label: Storage Class Name + - variable: grafana.persistence.accessModes + type: enum + default: + - ReadWriteOnce + options: + - [ReadWriteOnce] + - [ReadWriteMany] + - [ReadOnlyMany] + label: Access Mode +- variable: prometheus.prometheusSpec.scrapeInterval + type: string + required: true + label: Scrape Interval + default: 30s + group: Prometheus +- variable: prometheus.prometheusSpec.evaluationInterval + type: string + required: true + label: Evaluation Interval + default: 1m + group: Prometheus +- variable: prometheus.prometheusSpec.retention + type: string + required: true + label: Retention + default: 10d + group: Prometheus +- variable: prometheus.prometheusSpec.retentionSize + type: string + required: false + label: Retention Size + default: 50GB + group: Prometheus +- variable: prometheus.prometheusSpec.resources.requests.cpu + type: string + required: true + label: Requested CPU + default: 750m + group: Prometheus +- variable: prometheus.prometheusSpec.resources.requests.memory + type: string + required: true + label: Requested Memory + default: 750Mi + group: Prometheus +- variable: prometheus.prometheusSpec.resources.limits.cpu + type: string + required: true + label: CPU Limit + default: 1000m + group: Prometheus +- variable: prometheus.prometheusSpec.resources.limits.memory + type: string + required: true + label: Memory Limit + default: 3000Mi + group: Prometheus +- variable: prometheus.prometheusSpec.storage.enabled + type: boolean + required: true + label: Enable Persistent Volume + show_subquestion_if: true + group: Prometheus + subquestions: + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage + type: string + default: 50Gi + label: Size + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName + type: storageclass + label: Storage Class Name + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.accessModes + type: enum + default: + - ReadWriteOnce + options: + - [ReadWriteOnce] + - [ReadWriteMany] + - [ReadOnlyMany] + label: Access Mode +- variable: federate.enabled + label: Enable Federated Metrics From Cluster Prometheus + default: true + type: boolean + group: Federation diff --git a/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt new file mode 100644 index 00000000..9e4d6d87 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/NOTES.txt @@ -0,0 +1,4 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "project-prometheus-stack.namespace" . }} get pods -l "release={{ $.Release.Name }}" + +Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator. diff --git a/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl new file mode 100644 index 00000000..5333d28b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/_helpers.tpl @@ -0,0 +1,252 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +{{/* +https://github.com/helm/helm/issues/4535#issuecomment-477778391 +Usage: {{ include "call-nested" (list . "SUBCHART_NAME" "TEMPLATE") }} +e.g. {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +*/}} +{{- define "call-nested" }} +{{- $dot := index . 0 }} +{{- $subchart := index . 1 | splitList "." }} +{{- $template := index . 2 }} +{{- $values := $dot.Values }} +{{- range $subchart }} +{{- $values = index $values . }} +{{- end }} +{{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }} +{{- end }} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Prometheus Operator + +{{/* Comma-delimited list of namespaces that need to be watched to configure Project Prometheus Stack components */}} +{{- define "project-prometheus-stack.projectNamespaceList" -}} +{{ append .Values.global.cattle.projectNamespaces .Release.Namespace | uniq | join "," }} +{{- end }} + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "project-prometheus-stack.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +The components in this chart create additional resources that expand the longest created name strings. +The longest name that gets created adds and extra 37 characters, so truncation should be 63-35=26. +*/}} +{{- define "project-prometheus-stack.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 26 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Prometheus custom resource instance name */}} +{{- define "project-prometheus-stack.prometheus.crname" -}} +{{- if .Values.cleanPrometheusOperatorObjectNames }} +{{- include "project-prometheus-stack.fullname" . }} +{{- else }} +{{- print (include "project-prometheus-stack.fullname" .) "-prometheus" }} +{{- end }} +{{- end }} + +{{/* Alertmanager custom resource instance name */}} +{{- define "project-prometheus-stack.alertmanager.crname" -}} +{{- if .Values.cleanPrometheusOperatorObjectNames }} +{{- include "project-prometheus-stack.fullname" . }} +{{- else }} +{{- print (include "project-prometheus-stack.fullname" .) "-alertmanager" -}} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "project-prometheus-stack.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "project-prometheus-stack.labels" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "project-prometheus-stack.name" . }} +chart: {{ template "project-prometheus-stack.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} + +{{/* Create the name of prometheus service account to use */}} +{{- define "project-prometheus-stack.prometheus.serviceAccountName" -}} +{{- if .Values.prometheus.serviceAccount.create -}} + {{ default (print (include "project-prometheus-stack.fullname" .) "-prometheus") .Values.prometheus.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.prometheus.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* Create the name of alertmanager service account to use */}} +{{- define "project-prometheus-stack.alertmanager.serviceAccountName" -}} +{{- if .Values.alertmanager.serviceAccount.create -}} + {{ default (print (include "project-prometheus-stack.fullname" .) "-alertmanager") .Values.alertmanager.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.alertmanager.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "project-prometheus-stack.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Use the grafana namespace override for multi-namespace deployments in combined charts +*/}} +{{- define "project-prometheus-stack-grafana.namespace" -}} + {{- if .Values.grafana.namespaceOverride -}} + {{- .Values.grafana.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Allow KubeVersion to be overridden. */}} +{{- define "project-prometheus-stack.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} +{{- end -}} + +{{/* Get Ingress API Version */}} +{{- define "project-prometheus-stack.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "project-prometheus-stack.kubeVersion" .)) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* Check Ingress stability */}} +{{- define "project-prometheus-stack.ingress.isStable" -}} + {{- eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* Check Ingress supports pathType */}} +{{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}} +{{- define "project-prometheus-stack.ingress.supportsPathType" -}} + {{- or (eq (include "project-prometheus-stack.ingress.isStable" .) "true") (and (eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "project-prometheus-stack.kubeVersion" .))) -}} +{{- end -}} + +{{/* Get Policy API Version */}} +{{- define "project-prometheus-stack.pdb.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">= 1.21-0" (include "project-prometheus-stack.kubeVersion" .)) -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} + {{- end -}} + +{{/* Get value based on current Kubernetes version */}} +{{- define "project-prometheus-stack.kubeVersionDefaultValue" -}} + {{- $values := index . 0 }} + {{- $kubeVersion := index . 1 }} + {{- $old := index . 2 }} + {{- $new := index . 3 }} + {{- $default := index . 4 }} + {{- if kindIs "invalid" $default -}} + {{- if semverCompare $kubeVersion (include "project-prometheus-stack.kubeVersion" $values) -}} + {{- print $new -}} + {{- else -}} + {{- print $old -}} + {{- end -}} + {{- else -}} + {{- print $default }} + {{- end -}} +{{- end -}} + +{{/* +To help compatibility with other charts which use global.imagePullSecrets. +Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). +global: + imagePullSecrets: + - name: pullSecret1 + - name: pullSecret2 + +or + +global: + imagePullSecrets: + - pullSecret1 + - pullSecret2 +*/}} +{{- define "project-prometheus-stack.imagePullSecrets" -}} +{{- range .Values.global.imagePullSecrets }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} + + +{{/* Define ingress for all hardened namespaces */}} +{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} +{{- $root := index . 0 }} +{{- $ns := index . 1 }} +{{- if $root.Values.global.networkPolicy.ingress -}} +{{ toYaml $root.Values.global.networkPolicy.ingress }} +{{- end }} +{{- if $root.Values.global.networkPolicy.limitIngressToProject }} +- from: +{{- if $root.Values.global.cattle.projectNamespaceSelector }} + - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} +{{- end }} + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ $ns }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml new file mode 100644 index 00000000..f8b3db0c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/alertmanager.yaml @@ -0,0 +1,165 @@ +{{- if .Values.alertmanager.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: Alertmanager +metadata: + name: {{ template "project-prometheus-stack.alertmanager.crname" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.annotations }} + annotations: +{{ toYaml .Values.alertmanager.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.alertmanager.alertmanagerSpec.image }} + {{- if and .Values.alertmanager.alertmanagerSpec.image.tag .Values.alertmanager.alertmanagerSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" + {{- else if .Values.alertmanager.alertmanagerSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" + {{- else if .Values.alertmanager.alertmanagerSpec.image.tag }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}" + {{- end }} + version: {{ .Values.alertmanager.alertmanagerSpec.image.tag }} + {{- if .Values.alertmanager.alertmanagerSpec.image.sha }} + sha: {{ .Values.alertmanager.alertmanagerSpec.image.sha }} + {{- end }} +{{- end }} + replicas: {{ .Values.alertmanager.alertmanagerSpec.replicas }} + listenLocal: {{ .Values.alertmanager.alertmanagerSpec.listenLocal }} + serviceAccountName: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} +{{- if .Values.alertmanager.alertmanagerSpec.externalUrl }} + externalUrl: "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}" +{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} + externalUrl: "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy" +{{- else }} + externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.nodeSelector }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.nodeSelector | indent 4 }} +{{- end }} + paused: {{ .Values.alertmanager.alertmanagerSpec.paused }} + logFormat: {{ .Values.alertmanager.alertmanagerSpec.logFormat | quote }} + logLevel: {{ .Values.alertmanager.alertmanagerSpec.logLevel | quote }} + retention: {{ .Values.alertmanager.alertmanagerSpec.retention | quote }} +{{- if .Values.alertmanager.alertmanagerSpec.secrets }} + secrets: +{{ toYaml .Values.alertmanager.alertmanagerSpec.secrets | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.configSecret }} + configSecret: {{ .Values.alertmanager.alertmanagerSpec.configSecret }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.configMaps }} + configMaps: +{{ toYaml .Values.alertmanager.alertmanagerSpec.configMaps | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector }} + alertmanagerConfigSelector: +{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector | indent 4}} +{{ else }} + alertmanagerConfigSelector: {} +{{- end }} + alertmanagerConfigNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.web }} + web: +{{ toYaml .Values.alertmanager.alertmanagerSpec.web | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration }} + alertmanagerConfiguration: +{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.resources }} + resources: +{{ toYaml .Values.alertmanager.alertmanagerSpec.resources | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} + routePrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.alertmanagerSpec.securityContext | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.storage }} + storage: +{{ tpl (toYaml .Values.alertmanager.alertmanagerSpec.storage | indent 4) . }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.podMetadata }} + podMetadata: +{{ toYaml .Values.alertmanager.alertmanagerSpec.podMetadata | indent 4 }} +{{- end }} +{{- if or .Values.alertmanager.alertmanagerSpec.podAntiAffinity .Values.alertmanager.alertmanagerSpec.affinity }} + affinity: +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.affinity }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.affinity | indent 4 }} +{{- end }} +{{- if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} + - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} +{{- else if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} + - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.tolerations }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.tolerations | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} + imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.containers }} + containers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.containers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.initContainers }} + initContainers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.initContainers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.priorityClassName }} + priorityClassName: {{.Values.alertmanager.alertmanagerSpec.priorityClassName }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.additionalPeers }} + additionalPeers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.additionalPeers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.volumes }} + volumes: +{{ toYaml .Values.alertmanager.alertmanagerSpec.volumes | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.volumeMounts }} + volumeMounts: +{{ toYaml .Values.alertmanager.alertmanagerSpec.volumeMounts | indent 4 }} +{{- end }} + portName: {{ .Values.alertmanager.alertmanagerSpec.portName }} +{{- if .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} + clusterAdvertiseAddress: {{ .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} + forceEnableClusterMode: {{ .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.minReadySeconds }} + minReadySeconds: {{ .Values.alertmanager.alertmanagerSpec.minReadySeconds }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml new file mode 100644 index 00000000..af469be7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/extrasecret.yaml @@ -0,0 +1,20 @@ +{{- if .Values.alertmanager.extraSecret.data -}} +{{- $secretName := printf "alertmanager-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ default $secretName .Values.alertmanager.extraSecret.name }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.alertmanager.extraSecret.annotations }} + annotations: +{{ toYaml .Values.alertmanager.extraSecret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/component: alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- range $key, $val := .Values.alertmanager.extraSecret.data }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml new file mode 100644 index 00000000..022922b0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/ingress.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }} +{{- $pathType := .Values.alertmanager.ingress.pathType | default "ImplementationSpecific" }} +{{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} +{{- $servicePort := .Values.alertmanager.ingress.servicePort | default .Values.alertmanager.service.port -}} +{{- $routePrefix := list .Values.alertmanager.alertmanagerSpec.routePrefix }} +{{- $paths := .Values.alertmanager.ingress.paths | default $routePrefix -}} +{{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} +apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $serviceName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.alertmanager.ingress.annotations }} + annotations: +{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{- if .Values.alertmanager.ingress.labels }} +{{ toYaml .Values.alertmanager.ingress.labels | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if $apiIsStable }} + {{- if .Values.alertmanager.ingress.ingressClassName }} + ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }} + {{- end }} + {{- end }} + rules: + {{- if .Values.alertmanager.ingress.hosts }} + {{- range $host := .Values.alertmanager.ingress.hosts }} + - host: {{ tpl $host $ }} + http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- else }} + - http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- if .Values.alertmanager.ingress.tls }} + tls: +{{ tpl (toYaml .Values.alertmanager.ingress.tls | indent 4) . }} + {{- end -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml new file mode 100644 index 00000000..a8d7feaf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/podDisruptionBudget.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.podDisruptionBudget.enabled }} +apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if .Values.alertmanager.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.alertmanager.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: alertmanager + alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml new file mode 100644 index 00000000..b959bf00 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-role.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml new file mode 100644 index 00000000..d027f8e5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp-rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml new file mode 100644 index 00000000..138f1180 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/psp.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{- if .Values.global.rbac.pspAnnotations }} + annotations: +{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + privileged: false + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml new file mode 100644 index 00000000..848d085f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/secret.yaml @@ -0,0 +1,33 @@ +{{- if .Values.alertmanager.enabled }} +{{/* This file is applied when the operation is helm install and the target secret does not exist. */}} +{{- $secretName := (printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .)) }} +{{- if (not (lookup "v1" "Secret" (include "project-prometheus-stack.namespace" .) $secretName)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + annotations: + "helm.sh/hook": pre-install, pre-upgrade + "helm.sh/hook-weight": "3" + "helm.sh/resource-policy": keep +{{- if .Values.alertmanager.secret.annotations }} +{{ toYaml .Values.alertmanager.secret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- if .Values.alertmanager.tplConfig }} +{{- if eq (typeOf .Values.alertmanager.config) "string" }} + alertmanager.yaml: {{ tpl (.Values.alertmanager.config) . | b64enc | quote }} +{{- else }} + alertmanager.yaml: {{ tpl (toYaml .Values.alertmanager.config) . | b64enc | quote }} +{{- end }} +{{- else }} + alertmanager.yaml: {{ toYaml .Values.alertmanager.config | b64enc | quote }} +{{- end}} +{{- range $key, $val := .Values.alertmanager.templateFiles }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }}{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml new file mode 100644 index 00000000..3fb5cb3c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/service.yaml @@ -0,0 +1,53 @@ +{{- if .Values.alertmanager.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + self-monitor: {{ .Values.alertmanager.serviceMonitor.selfMonitor | quote }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.service.labels }} +{{ toYaml .Values.alertmanager.service.labels | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.service.annotations }} + annotations: +{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.alertmanager.service.clusterIP }} + clusterIP: {{ .Values.alertmanager.service.clusterIP }} +{{- end }} +{{- if .Values.alertmanager.service.externalIPs }} + externalIPs: +{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if ne .Values.alertmanager.service.type "ClusterIP" }} + externalTrafficPolicy: {{ .Values.alertmanager.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if eq .Values.alertmanager.service.type "NodePort" }} + nodePort: {{ .Values.alertmanager.service.nodePort }} + {{- end }} + port: {{ .Values.alertmanager.service.port }} + targetPort: {{ .Values.alertmanager.service.targetPort }} + protocol: TCP +{{- if .Values.alertmanager.service.additionalPorts }} +{{ toYaml .Values.alertmanager.service.additionalPorts | indent 2 }} +{{- end }} + selector: + app.kubernetes.io/name: alertmanager + alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} + type: "{{ .Values.alertmanager.service.type }}" +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml new file mode 100644 index 00000000..00b4b177 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/component: alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.alertmanager.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2}} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml new file mode 100644 index 00000000..1cc9c6f7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/alertmanager/servicemonitor.yaml @@ -0,0 +1,55 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + release: {{ $.Release.Name | quote }} + self-monitor: "true" + namespaceSelector: + matchNames: + - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} + endpoints: + - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if .Values.alertmanager.serviceMonitor.interval }} + interval: {{ .Values.alertmanager.serviceMonitor.interval }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.proxyUrl }} + proxyUrl: {{ .Values.alertmanager.serviceMonitor.proxyUrl}} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.scheme }} + scheme: {{ .Values.alertmanager.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.alertmanager.serviceMonitor.bearerTokenFile }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" + metricRelabelings: + {{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +{{- if .Values.alertmanager.serviceMonitor.relabelings }} + relabelings: +{{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml new file mode 100644 index 00000000..535bc94e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-roles.yaml @@ -0,0 +1,179 @@ +{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-admin + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: admin + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' + - 'create' + - 'update' + - 'patch' + - 'delete' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +{{- if .Values.alertmanager.enabled }} +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch + - update + - patch + - delete +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-edit + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: edit + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' + - 'create' + - 'update' + - 'patch' + - 'delete' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +{{- if .Values.alertmanager.enabled }} +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch + - update + - patch +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-view + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: view + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +{{- if .Values.alertmanager.enabled }} +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml new file mode 100644 index 00000000..16acc46d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/dashboard-values-configmap.yaml @@ -0,0 +1,57 @@ +{{- $rancherDashboards := dict }} +{{- range $glob := tuple "files/rancher/workloads/*" "files/rancher/pods/*" -}} +{{- range $dashboard, $_ := ($.Files.Glob $glob) }} +{{- $dashboardMap := ($.Files.Get $dashboard | fromJson) }} +{{- $_ := set $rancherDashboards (get $dashboardMap "uid") (get $dashboardMap "title") -}} +{{- end }} +{{- end }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-dashboard-values + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/dashboard-values-configmap: {{ .Release.Name }} +data: + values.json: |- + { +{{- if not .Values.prometheus.enabled }} + "prometheusURL": "", +{{- else if .Values.prometheus.prometheusSpec.externalUrl }} + "prometheusURL": "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}", +{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} + "prometheusURL": "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "prometheusURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy", +{{- else }} + "prometheusURL": "http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}", +{{- end }} + +{{- if not .Values.grafana.enabled }} + "grafanaURL": "", +{{- else if and .Values.grafana.ingress.enabled .Values.grafana.ingress.hosts }} + "grafanaURL": "http://{{ tpl (index .Values.grafana.ingress.hosts 0) . }}{{ .Values.grafana.grafanaSpec.ingress.path }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "grafanaURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}/proxy", +{{- else }} + "grafanaURL": "http://{{ include "call-nested" (list . "grafana" "grafana.fullname") }}.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.grafana.service.port }}", +{{- end }} + +{{- if not .Values.alertmanager.enabled }} + "alertmanagerURL": "", +{{- else if .Values.alertmanager.alertmanagerSpec.externalUrl }} + "alertmanagerURL": "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}", +{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} + "alertmanagerURL": "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "alertmanagerURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy", +{{- else }} + "alertmanagerURL": "http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }}", +{{- end }} + +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} + "rancherDashboards": {{- $rancherDashboards | toPrettyJson | nindent 8 }} +{{- else }} + "rancherDashboards": [] +{{- end }} + } \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml new file mode 100644 index 00000000..6214dc5c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/pods-dashboards.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: rancher-default-dashboards-pods + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: +{{ (.Files.Glob "files/rancher/pods/*").AsConfig | indent 2 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml new file mode 100644 index 00000000..7934818f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/dashboards/rancher/workload-dashboards.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: rancher-default-dashboards-workloads + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: +{{ (.Files.Glob "files/rancher/workloads/*").AsConfig | indent 2 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml new file mode 100644 index 00000000..c2763573 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmap-dashboards.yaml @@ -0,0 +1,24 @@ +{{- if or (and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled) .Values.grafana.forceDeployDashboards }} +{{- $files := .Files.Glob "dashboards-1.14/*.json" }} +{{- if $files }} +apiVersion: v1 +kind: ConfigMapList +items: +{{- range $path, $fileContents := $files }} +{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} +- apiVersion: v1 + kind: ConfigMap + metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) $dashboardName | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 6 }} + data: + {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml new file mode 100644 index 00000000..7f2c5b55 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/configmaps-datasources.yaml @@ -0,0 +1,46 @@ +{{- if or (and .Values.grafana.enabled .Values.grafana.sidecar.datasources.enabled) .Values.grafana.forceDeployDatasources }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-grafana-datasource + namespace: {{ include "project-prometheus-stack.namespace" . }} +{{- if .Values.grafana.sidecar.datasources.annotations }} + annotations: +{{ toYaml .Values.grafana.sidecar.datasources.annotations | indent 4 }} +{{- end }} + labels: + {{ $.Values.grafana.sidecar.datasources.label }}: "1" + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + datasource.yaml: |- + apiVersion: 1 +{{- if .Values.grafana.deleteDatasources }} + deleteDatasources: +{{ tpl (toYaml .Values.grafana.deleteDatasources | indent 6) . }} +{{- end }} + datasources: +{{- $scrapeInterval := .Values.grafana.sidecar.datasources.defaultDatasourceScrapeInterval | default .Values.prometheus.prometheusSpec.scrapeInterval | default "30s" }} +{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }} + - name: Prometheus + type: prometheus + uid: {{ .Values.grafana.sidecar.datasources.uid }} + {{- if .Values.grafana.sidecar.datasources.url }} + url: {{ .Values.grafana.sidecar.datasources.url }} + {{- else }} + url: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}/{{ trimPrefix "/" .Values.prometheus.prometheusSpec.routePrefix }} + {{- end }} + access: proxy + isDefault: true + jsonData: + timeInterval: {{ $scrapeInterval }} +{{- if .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations }} + exemplarTraceIdDestinations: + - datasourceUid: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.datasourceUid }} + name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} +{{- end }} +{{- end }} +{{- if .Values.grafana.additionalDataSources }} +{{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml new file mode 100644 index 00000000..8f8e6ffe --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/alertmanager-overview.yaml @@ -0,0 +1,616 @@ +{{- /* +Generated from 'alertmanager-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "alertmanager-overview" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + alertmanager-overview.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 1, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "30s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "current set of alerts stored in the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(alertmanager_alerts{namespace=~\"$namespace\",service=~\"$service\"}) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "rate of successful and invalid alerts received by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(alertmanager_alerts_received_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Received", + "refId": "A" + }, + { + "expr": "sum(rate(alertmanager_alerts_invalid_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Invalid", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts receive rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Alerts", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "rate of successful and invalid notifications sent by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "integration", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(alertmanager_notifications_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Total", + "refId": "A" + }, + { + "expr": "sum(rate(alertmanager_notifications_failed_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Failed", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "$integration: Notifications Send Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "latency of notifications sent by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 5, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "integration", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} 99th Percentile", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.50,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Median", + "refId": "B" + }, + { + "expr": "sum(rate(alertmanager_notification_latency_seconds_sum{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n/\nsum(rate(alertmanager_notification_latency_seconds_count{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Average", + "refId": "C" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "$integration: Notification Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Notifications", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "alertmanager-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(alertmanager_alerts, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "service", + "multi": false, + "name": "service", + "options": [ + + ], + "query": "label_values(alertmanager_alerts, service)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "all", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": true, + "label": null, + "multi": false, + "name": "integration", + "options": [ + + ], + "query": "label_values(alertmanager_notifications_total{integration=~\".*\"}, integration)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Alertmanager / Overview", + "uid": "alertmanager-overview", + "version": 0 + } +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml new file mode 100644 index 00000000..70764069 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/cluster-total.yaml @@ -0,0 +1,1646 @@ +{{- /* +Generated from 'cluster-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "cluster-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + cluster-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "Value #G", + "value": "Value #G" + }, + { + "text": "Value #H", + "value": "Value #H" + }, + { + "text": "namespace", + "value": "namespace" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "90%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Current Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?orgId=1&refresh=30s&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 6, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 9, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth History", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 13, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 15, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Project", + "uid": "ff635a025bcfea7bc3dd4f508990a3e9", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml new file mode 100644 index 00000000..ef663df7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/grafana-overview.yaml @@ -0,0 +1,635 @@ +{{- /* +Generated from 'grafana-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack-grafana.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "grafana-overview" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + grafana-overview.json: |- + { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [ + + ], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 3085, + "iteration": 1631554945276, + "links": [ + + ], + "panels": [ + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "mappings": [ + + ], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": { + + }, + "textMode": "auto" + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "grafana_alerting_result_total{job=~\"$job\", instance=~\"$instance\", state=\"alerting\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Firing Alerts", + "type": "stat" + }, + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "mappings": [ + + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": { + + }, + "textMode": "auto" + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "sum(grafana_stat_totals_dashboard{job=~\"$job\", instance=~\"$instance\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Dashboards", + "type": "stat" + }, + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "auto" + }, + "mappings": [ + + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 10, + "options": { + "showHeader": true + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "grafana_build_info{job=~\"$job\", instance=~\"$instance\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Build Info", + "transformations": [ + { + "id": "labelsToFields", + "options": { + + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true, + "branch": true, + "container": true, + "goversion": true, + "namespace": true, + "pod": true, + "revision": true + }, + "indexByName": { + "Time": 7, + "Value": 11, + "branch": 4, + "container": 8, + "edition": 2, + "goversion": 6, + "instance": 1, + "job": 0, + "namespace": 9, + "pod": 10, + "revision": 5, + "version": 3 + }, + "renameByName": { + + } + } + } + ], + "type": "table" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "links": [ + + ] + }, + "overrides": [ + + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status_code) (irate(grafana_http_request_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[1m])) ", + "interval": "", + "legendFormat": "{{`{{`}}status_code{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeRegions": [ + + ], + "timeShift": null, + "title": "RPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "$$hashKey": "object:157", + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:158", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "links": [ + + ] + }, + "overrides": [ + + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", + "interval": "", + "legendFormat": "99th Percentile", + "refId": "A" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", + "interval": "", + "legendFormat": "50th Percentile", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(irate(grafana_http_request_duration_seconds_sum{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) * 1 / sum(irate(grafana_http_request_duration_seconds_count{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Average", + "refId": "C" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeRegions": [ + + ], + "timeShift": null, + "title": "Request Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "$$hashKey": "object:210", + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:211", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "schemaVersion": 30, + "style": "dark", + "tags": [ + + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": [ + "default/grafana" + ], + "value": [ + "default/grafana" + ] + }, + "datasource": "$datasource", + "definition": "label_values(grafana_build_info, job)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "job", + "options": [ + + ], + "query": { + "query": "label_values(grafana_build_info, job)", + "refId": "Billing Admin-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "definition": "label_values(grafana_build_info, instance)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "instance", + "options": [ + + ], + "query": { + "query": "label_values(grafana_build_info, instance)", + "refId": "Billing Admin-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Grafana Overview", + "uid": "6be0s85Mk", + "version": 2 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml new file mode 100644 index 00000000..c87b4188 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml @@ -0,0 +1,2770 @@ +{{- /* +Generated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-namespace" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-namespace.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "100px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "CPU Utilisation (from requests)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "CPU Utilisation (from limits)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Memory Utilisation (from requests)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Memory Utilisation (from limits)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Headlines", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_cache{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(container_memory_swap{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 14, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 16, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 17, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 18, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Namespace (Pods)", + "uid": "85a562078cdf77779eaa1add43ccec1e", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml new file mode 100644 index 00000000..e2e8d2aa --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-node.yaml @@ -0,0 +1,963 @@ +{{- /* +Generated from 'k8s-resources-node' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-node" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-node.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_rss{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_cache{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_swap{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": true, + "name": "node", + "options": [ + + ], + "query": "label_values(kube_pod_info, node)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Node (Pods)", + "uid": "200ac8fdbfbb74b39aff88118e4d1c2c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml new file mode 100644 index 00000000..c8d57cfd --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml @@ -0,0 +1,2442 @@ +{{- /* +Generated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-pod" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-pod.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "requests", + "color": "#F2495C", + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "limits", + "color": "#FF9830", + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container) /sum(increase(container_cpu_cfs_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.25, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Throttling", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Throttling", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (WSS)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage (WSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_cache{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(container_memory_swap{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Reads", + "legendLink": null, + "step": 10 + }, + { + "expr": "ceil(sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Writes", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Reads", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Writes", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution(Pod - Read & Writes)", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 14, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(container) (rate(container_fs_reads_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution(Containers)", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 16, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "options": [ + + ], + "query": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Pod", + "uid": "6581e46e4e5c7ba40a07646395ef7b23", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml new file mode 100644 index 00000000..56d9c77f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-project.yaml @@ -0,0 +1,2480 @@ +{{- /* +Generated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-cluster" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-cluster.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workloads", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to workloads", + "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(kube_pod_owner{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workloads", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to workloads", + "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(kube_pod_owner{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Requests by Namespace", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Requests", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 11, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Namespace: Received", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Namespace: Transmitted", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Namespace", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 17, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 18, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 19, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 20, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 21, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 22, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_writes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Project", + "uid": "efa86fd1d0c121a26444b636a3f509a8", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml new file mode 100644 index 00000000..4e72d70a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml @@ -0,0 +1,1997 @@ +{{- /* +Generated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workload" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-workload.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Pod: Received", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Pod: Transmitted", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Pod", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\"}, workload)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\"}, workload_type)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Workload", + "uid": "a164a7f0339f99e89cea5cb47e9be617", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml new file mode 100644 index 00000000..c6548c43 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml @@ -0,0 +1,2162 @@ +{{- /* +Generated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workloads-namespace" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-workloads-namespace.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Running Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Running Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$type", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Workload: Received", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Workload: Transmitted", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Workload", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Namespace (Workloads)", + "uid": "a87fb0d919ec0ea5f6543124e16c42a5", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml new file mode 100644 index 00000000..0d4fdc0f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-pod.yaml @@ -0,0 +1,1438 @@ +{{- /* +Generated from 'namespace-by-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-pod" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + namespace-by-pod.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "height": 9, + "id": 3, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "height": 9, + "id": 4, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "pod", + "value": "pod" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?orgId=1&refresh=30s&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 6, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 9, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Namespace (Pods)", + "uid": "8b7a8b326d7a6f1f04244066368c67af", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml new file mode 100644 index 00000000..aa2a3573 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/namespace-by-workload.yaml @@ -0,0 +1,1710 @@ +{{- /* +Generated from 'namespace-by-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-workload" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + namespace-by-workload.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "Value #G", + "value": "Value #G" + }, + { + "text": "Value #H", + "value": "Value #H" + }, + { + "text": "workload", + "value": "workload" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "90%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Current Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?orgId=1&refresh=30s&var-namespace=$namespace&var-type=$type&var-workload=$__cell", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 6, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 9, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth HIstory", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 15, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 17, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Namespace (Workload)", + "uid": "bbb2a765a623ae38130206c7d94a160f", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml new file mode 100644 index 00000000..cd599c62 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml @@ -0,0 +1,561 @@ +{{- /* +Generated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "persistentvolumesusage" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + persistentvolumesusage.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 9, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used Space", + "refId": "A" + }, + { + "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Free Space", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Volume Space Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$datasource", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + + }, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "rightSide": true + }, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "max without(instance,node) (\n(\n topk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n topk(1, kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n/\ntopk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "80, 90", + "title": "Volume Space Usage", + "tooltip": { + "shared": false + }, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 9, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used inodes", + "refId": "A" + }, + { + "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " Free inodes", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Volume inodes Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$datasource", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + + }, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "rightSide": true + }, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "max without(instance,node) (\ntopk(1, kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n/\ntopk(1, kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "80, 90", + "title": "Volume inodes Usage", + "tooltip": { + "shared": false + }, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "PersistentVolumeClaim", + "multi": false, + "name": "volume", + "options": [ + + ], + "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\"}, persistentvolumeclaim)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-7d", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Persistent Volumes", + "uid": "919b92a8e8041bd567af9edab12c840c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml new file mode 100644 index 00000000..48b0db9b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/pod-total.yaml @@ -0,0 +1,1202 @@ +{{- /* +Generated from 'pod-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "pod-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + pod-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "height": 9, + "id": 3, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace: $pod", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "height": 9, + "id": 4, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace: $pod", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 8, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Pod", + "uid": "7a18067ce943a40ae25454675c19ff5c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml new file mode 100644 index 00000000..2f0a6bfa --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml @@ -0,0 +1,1674 @@ +{{- /* +Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + prometheus-remote-write.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "60s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(\n prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} \n- \n ignoring(remote_name, url) group_right(instance) (prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} != 0)\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Highest Timestamp In vs. Highest Timestamp Sent", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "clamp_min(\n rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) \n- \n ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n, 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate[5m]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Timestamps", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(\n prometheus_remote_storage_samples_in_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n- \n ignoring(remote_name, url) group_right(instance) (rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n- \n (rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate, in vs. succeeded or dropped [5m]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Samples", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 5, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 6, + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_max{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Max Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_min{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Min Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_desired{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Desired Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Shards", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shard_capacity{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Shard Capacity", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_pending_samples{cluster=~\"$cluster\", instance=~\"$instance\"} or prometheus_remote_storage_samples_pending{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Pending Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Shard Details", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_wal_segment_current{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "TSDB Current Segment", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_wal_watcher_current_segment{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}consumer{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Remote Write Current Segment", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Segments", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Dropped Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_failed_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Failed Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_retried_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_retried_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Retried Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Enqueue Retries", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Misc. Rates", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "prometheus-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "value": { + "selected": true, + "text": "All", + "value": "$__all" + } + }, + "datasource": "$datasource", + "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster.global.enabled }}0{{ else }}2{{ end }}, + "includeAll": true, + "label": null, + "multi": false, + "name": "cluster", + "options": [ + + ], + "query": "label_values(kube_pod_container_info{image=~\".*prometheus.*\"}, cluster)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "value": { + "selected": true, + "text": "All", + "value": "$__all" + } + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "instance", + "options": [ + + ], + "query": "label_values(prometheus_build_info{cluster=~\"$cluster\"}, instance)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "url", + "options": [ + + ], + "query": "label_values(prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}, url)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Prometheus / Remote Write", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml new file mode 100644 index 00000000..c94ce252 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/prometheus.yaml @@ -0,0 +1,1235 @@ +{{- /* +Generated from 'prometheus' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + prometheus.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "60s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Count", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Uptime", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Instance", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "instance", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Job", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "job", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Version", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "version", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count by (job, instance, version) (prometheus_build_info{job=~\"$job\", instance=~\"$instance\"})", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "max by (job, instance) (time() - process_start_time_seconds{job=~\"$job\", instance=~\"$instance\"})", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Prometheus Stats", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Prometheus Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(prometheus_target_sync_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m])) by (scrape_job) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}scrape_job{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Target Sync", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(prometheus_sd_discovered_targets{job=~\"$job\",instance=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Targets", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Targets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Discovery", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_target_interval_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{job=~\"$job\",instance=~\"$instance\"}[5m]) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}interval{{`}}`}} configured", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Scrape Interval Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_body_size_limit_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "exceeded body size limit: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_sample_limit_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "exceeded sample limit: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "duplicate timestamp: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_bounds_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "out of bounds: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_order_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "out of order: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Scrape failures", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_head_samples_appended_total{job=~\"$job\",instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Appended Samples", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Retrieval", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_series{job=~\"$job\",instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head series", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Head Series", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_chunks{job=~\"$job\",instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head chunks", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Head Chunks", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_engine_query_duration_seconds_count{job=~\"$job\",instance=~\"$instance\",slice=\"inner_eval\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "max by (slice) (prometheus_engine_query_duration_seconds{quantile=\"0.9\",job=~\"$job\",instance=~\"$instance\"}) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}slice{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Stage Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Query", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "prometheus-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "job", + "multi": true, + "name": "job", + "options": [ + + ], + "query": "label_values(prometheus_build_info{job=\"prometheus-k8s\",namespace=\"monitoring\"}, job)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "instance", + "multi": true, + "name": "instance", + "options": [ + + ], + "query": "label_values(prometheus_build_info{job=~\"$job\"}, instance)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Prometheus / Overview", + "uid": "", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml new file mode 100644 index 00000000..0dfd208c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/grafana/dashboards-1.14/workload-total.yaml @@ -0,0 +1,1412 @@ +{{- /* +Generated from 'workload-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "workload-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + workload-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 8, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth HIstory", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 14, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Workload", + "uid": "728bf77cc1166d2f3133bf25846876cc", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl new file mode 100644 index 00000000..d82cc2d3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/_rules.tpl @@ -0,0 +1,8 @@ +{{- define "rules.names" }} +rules: + - "alertmanager.rules" + - "general.rules" + - "kubernetes-storage" + - "prometheus" + - "kubernetes-apps" +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml new file mode 100644 index 00000000..b5d97aec --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +# This permission are not in the kube-prometheus repo +# they're grabbed from https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml +- apiGroups: [""] + resources: + - nodes + - nodes/metrics + - services + - endpoints + - pods + verbs: ["get", "list", "watch"] +- apiGroups: + - "networking.k8s.io" + resources: + - ingresses + verbs: ["get", "list", "watch"] +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml new file mode 100644 index 00000000..18249a0c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} + diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml new file mode 100644 index 00000000..61664d01 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/extrasecret.yaml @@ -0,0 +1,20 @@ +{{- if .Values.prometheus.extraSecret.data -}} +{{- $secretName := printf "prometheus-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ default $secretName .Values.prometheus.extraSecret.name }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.prometheus.extraSecret.annotations }} + annotations: +{{ toYaml .Values.prometheus.extraSecret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/component: prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- range $key, $val := .Values.prometheus.extraSecret.data }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml new file mode 100644 index 00000000..29d4ba20 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/federate.yaml @@ -0,0 +1,10 @@ +{{- if and .Values.prometheus.enabled .Values.federate.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-federate + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} +data: + federate-scrape-config.yaml: {{ tpl (.Files.Get "files/federate/federate-scrape-config.yaml" ) $ | b64enc | quote }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml new file mode 100644 index 00000000..387e2b5d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/ingress.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.ingress.enabled -}} + {{- $pathType := .Values.prometheus.ingress.pathType | default "ImplementationSpecific" -}} + {{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" -}} + {{- $servicePort := .Values.prometheus.ingress.servicePort | default .Values.prometheus.service.port -}} + {{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix -}} + {{- $paths := .Values.prometheus.ingress.paths | default $routePrefix -}} + {{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} + {{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} +apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.prometheus.ingress.annotations }} + annotations: +{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }} +{{- end }} + name: {{ $serviceName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.ingress.labels }} +{{ toYaml .Values.prometheus.ingress.labels | indent 4 }} +{{- end }} +spec: + {{- if $apiIsStable }} + {{- if .Values.prometheus.ingress.ingressClassName }} + ingressClassName: {{ .Values.prometheus.ingress.ingressClassName }} + {{- end }} + {{- end }} + rules: + {{- if .Values.prometheus.ingress.hosts }} + {{- range $host := .Values.prometheus.ingress.hosts }} + - host: {{ tpl $host $ }} + http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- else }} + - http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- if .Values.prometheus.ingress.tls }} + tls: +{{ tpl (toYaml .Values.prometheus.ingress.tls | indent 4) . }} + {{- end -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml new file mode 100644 index 00000000..c28edc07 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/nginx-config.yaml @@ -0,0 +1,68 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-nginx-proxy-config + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.annotations }} + annotations: +{{ toYaml .Values.prometheus.annotations | indent 4 }} +{{- end }} +data: + nginx.conf: |- + worker_processes auto; + error_log /dev/stdout warn; + pid /var/cache/nginx/nginx.pid; + + events { + worker_connections 1024; + } + + http { + include /etc/nginx/mime.types; + log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; + + proxy_connect_timeout 10; + proxy_read_timeout 180; + proxy_send_timeout 5; + proxy_buffering off; + proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; + + server { + listen 8081; + access_log off; + + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + proxy_set_header Host $host; + + location / { + proxy_cache my_zone; + proxy_cache_valid 200 302 1d; + proxy_cache_valid 301 30d; + proxy_cache_valid any 5m; + proxy_cache_bypass $http_cache_control; + add_header X-Proxy-Cache $upstream_cache_status; + add_header Cache-Control "public"; + + proxy_pass http://localhost:9090/; + + sub_filter_once off; + sub_filter 'var PATH_PREFIX = "";' 'var PATH_PREFIX = ".";'; + + if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { + expires 90d; + } + + rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; + + } + } + } diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml new file mode 100644 index 00000000..24e4c6a7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/podDisruptionBudget.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.podDisruptionBudget.enabled }} +apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if .Values.prometheus.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.prometheus.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.prometheus.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.prometheus.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: prometheus + prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml new file mode 100644 index 00000000..2e4cfe52 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/prometheus.yaml @@ -0,0 +1,319 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: Prometheus +metadata: + name: {{ template "project-prometheus-stack.prometheus.crname" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.annotations }} + annotations: +{{ toYaml .Values.prometheus.annotations | indent 4 }} +{{- end }} +spec: + alerting: + alertmanagers: +{{- if .Values.prometheus.prometheusSpec.alertingEndpoints }} +{{ toYaml .Values.prometheus.prometheusSpec.alertingEndpoints | indent 6 }} +{{- else if .Values.alertmanager.enabled }} + - namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + port: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} + pathPrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" + {{- end }} + apiVersion: {{ .Values.alertmanager.apiVersion }} +{{- else }} + [] +{{- end }} +{{- if .Values.prometheus.prometheusSpec.apiserverConfig }} + apiserverConfig: +{{ toYaml .Values.prometheus.prometheusSpec.apiserverConfig | indent 4}} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.image }} + {{- if and .Values.prometheus.prometheusSpec.image.tag .Values.prometheus.prometheusSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" + {{- else if .Values.prometheus.prometheusSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" + {{- else if .Values.prometheus.prometheusSpec.image.tag }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}" + {{- end }} + version: {{ .Values.prometheus.prometheusSpec.image.tag }} + {{- if .Values.prometheus.prometheusSpec.image.sha }} + sha: {{ .Values.prometheus.prometheusSpec.image.sha }} + {{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.externalLabels }} + externalLabels: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.externalLabels | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.prometheusExternalLabelNameClear }} + prometheusExternalLabelName: "" +{{- else if .Values.prometheus.prometheusSpec.prometheusExternalLabelName }} + prometheusExternalLabelName: "{{ .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} + enableRemoteWriteReceiver: {{ .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.externalUrl }} + externalUrl: "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}" +{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} + externalUrl: "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}" +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy" +{{- else }} + externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.nodeSelector }} +{{ toYaml .Values.prometheus.prometheusSpec.nodeSelector | indent 4 }} +{{- end }} + paused: {{ .Values.prometheus.prometheusSpec.paused }} + replicas: {{ .Values.prometheus.prometheusSpec.replicas }} + shards: {{ .Values.prometheus.prometheusSpec.shards }} + logLevel: {{ .Values.prometheus.prometheusSpec.logLevel }} + logFormat: {{ .Values.prometheus.prometheusSpec.logFormat }} + listenLocal: {{ .Values.prometheus.prometheusSpec.listenLocal }} + enableAdminAPI: {{ .Values.prometheus.prometheusSpec.enableAdminAPI }} +{{- if .Values.prometheus.prometheusSpec.web }} + web: +{{ toYaml .Values.prometheus.prometheusSpec.web | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.exemplars }} + exemplars: + {{ toYaml .Values.prometheus.prometheusSpec.exemplars | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enableFeatures }} + enableFeatures: +{{- range $enableFeatures := .Values.prometheus.prometheusSpec.enableFeatures }} + - {{ tpl $enableFeatures $ }} +{{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.scrapeInterval }} + scrapeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.prometheusSpec.scrapeTimeout }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.evaluationInterval }} + evaluationInterval: {{ .Values.prometheus.prometheusSpec.evaluationInterval }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.resources }} + resources: +{{ toYaml .Values.prometheus.prometheusSpec.resources | indent 4 }} +{{- end }} + retention: {{ .Values.prometheus.prometheusSpec.retention | quote }} +{{- if .Values.prometheus.prometheusSpec.retentionSize }} + retentionSize: {{ .Values.prometheus.prometheusSpec.retentionSize | quote }} +{{- end }} +{{- if eq .Values.prometheus.prometheusSpec.walCompression false }} + walCompression: false +{{ else }} + walCompression: true +{{- end }} +{{- if .Values.prometheus.prometheusSpec.routePrefix }} + routePrefix: {{ .Values.prometheus.prometheusSpec.routePrefix | quote }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.secrets }} + secrets: +{{ toYaml .Values.prometheus.prometheusSpec.secrets | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.configMaps }} + configMaps: +{{ toYaml .Values.prometheus.prometheusSpec.configMaps | indent 4 }} +{{- end }} + serviceAccountName: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} +{{- if .Values.prometheus.prometheusSpec.serviceMonitorSelector }} + serviceMonitorSelector: +{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues }} + serviceMonitorSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + serviceMonitorSelector: {} +{{- end }} + serviceMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.podMonitorSelector }} + podMonitorSelector: +{{ toYaml .Values.prometheus.prometheusSpec.podMonitorSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues }} + podMonitorSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + podMonitorSelector: {} +{{- end }} + podMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.probeSelector }} + probeSelector: +{{ toYaml .Values.prometheus.prometheusSpec.probeSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.probeSelectorNilUsesHelmValues }} + probeSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + probeSelector: {} +{{- end }} +{{- if (or .Values.prometheus.prometheusSpec.remoteWrite .Values.prometheus.prometheusSpec.additionalRemoteWrite) }} + remoteWrite: +{{- if .Values.prometheus.prometheusSpec.remoteWrite }} +{{ tpl (toYaml .Values.prometheus.prometheusSpec.remoteWrite | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.additionalRemoteWrite }} +{{ toYaml .Values.prometheus.prometheusSpec.additionalRemoteWrite | indent 4 }} +{{- end }} +{{- end }} + probeNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.securityContext }} + securityContext: +{{ toYaml .Values.prometheus.prometheusSpec.securityContext | indent 4 }} +{{- end }} + ruleNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.ruleSelector }} + ruleSelector: +{{ toYaml .Values.prometheus.prometheusSpec.ruleSelector | indent 4}} +{{- else if .Values.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues }} + ruleSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + ruleSelector: {} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.storage.enabled }} + storage: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.storageSpec | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.podMetadata }} + podMetadata: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.podMetadata | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.query }} + query: +{{ toYaml .Values.prometheus.prometheusSpec.query | indent 4}} +{{- end }} +{{- if or .Values.prometheus.prometheusSpec.podAntiAffinity .Values.prometheus.prometheusSpec.affinity }} + affinity: +{{- if .Values.prometheus.prometheusSpec.affinity }} +{{ toYaml .Values.prometheus.prometheusSpec.affinity | indent 4 }} +{{- end }} +{{- if eq .Values.prometheus.prometheusSpec.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} + - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} +{{- else if eq .Values.prometheus.prometheusSpec.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} + - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} +{{- end }} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.tolerations }} +{{ toYaml .Values.prometheus.prometheusSpec.tolerations | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.prometheus.prometheusSpec.topologySpreadConstraints | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} + imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} +{{- end }} +{{- if .Values.federate.enabled }} + additionalScrapeConfigs: + name: {{ template "project-prometheus-stack.fullname" . }}-federate + key: federate-scrape-config.yaml +{{- end }} +{{- if .Values.prometheus.prometheusSpec.containers }} + containers: +{{ tpl .Values.prometheus.prometheusSpec.containers $ | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.initContainers }} + initContainers: +{{ toYaml .Values.prometheus.prometheusSpec.initContainers | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.priorityClassName }} + priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.disableCompaction }} + disableCompaction: {{ .Values.prometheus.prometheusSpec.disableCompaction }} +{{- end }} + portName: {{ .Values.prometheus.prometheusSpec.portName }} +{{- if .Values.prometheus.prometheusSpec.volumes }} + volumes: +{{ toYaml .Values.prometheus.prometheusSpec.volumes | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.volumeMounts }} + volumeMounts: +{{ toYaml .Values.prometheus.prometheusSpec.volumeMounts | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs }} + arbitraryFSAccessThroughSMs: +{{ toYaml .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.overrideHonorLabels }} + overrideHonorLabels: {{ .Values.prometheus.prometheusSpec.overrideHonorLabels }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} + overrideHonorTimestamps: {{ .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} +{{- end }} + ignoreNamespaceSelectors: true # always hard-coded to true for security reasons +{{- if .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} + enforcedNamespaceLabel: {{ .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} +{{- $prometheusDefaultRulesExcludedFromEnforce := (include "rules.names" .) | fromYaml }} + prometheusRulesExcludedFromEnforce: +{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} + - ruleNamespace: "{{ template "project-prometheus-stack.namespace" $ }}" + ruleName: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce }} +{{ toYaml .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce | indent 4 }} +{{- end }} + excludedFromEnforcement: +{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} + - resource: prometheusrules + namespace: "{{ template "project-prometheus-stack.namespace" $ }}" + name: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.excludedFromEnforcement }} +{{ tpl (toYaml .Values.prometheus.prometheusSpec.excludedFromEnforcement | indent 4) . }} +{{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.queryLogFile }} + queryLogFile: {{ .Values.prometheus.prometheusSpec.queryLogFile }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedSampleLimit }} + enforcedSampleLimit: {{ .Values.prometheus.prometheusSpec.enforcedSampleLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedTargetLimit }} + enforcedTargetLimit: {{ .Values.prometheus.prometheusSpec.enforcedTargetLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelLimit }} + enforcedLabelLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} + enforcedLabelNameLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit}} + enforcedLabelValueLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} + allowOverlappingBlocks: {{ .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.minReadySeconds }} + minReadySeconds: {{ .Values.prometheus.prometheusSpec.minReadySeconds }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml new file mode 100644 index 00000000..8a3cbea5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml new file mode 100644 index 00000000..736525c9 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp-clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} + diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml new file mode 100644 index 00000000..b0130af7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/psp.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{- if .Values.global.rbac.pspAnnotations }} + annotations: +{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + privileged: false + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' +{{- if .Values.prometheus.podSecurityPolicy.volumes }} +{{ toYaml .Values.prometheus.podSecurityPolicy.volumes | indent 4 }} +{{- end }} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +{{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} + allowedCapabilities: +{{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml new file mode 100644 index 00000000..0cca1fb3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/alertmanager.rules.yaml @@ -0,0 +1,217 @@ +{{- /* +Generated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/alertmanager-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }} +{{- $alertmanagerJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} +{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager.rules" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: alertmanager.rules + rules: +{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedReload | default false) }} + - alert: AlertmanagerFailedReload + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Configuration has failed to load for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedreload + summary: Reloading an Alertmanager configuration has failed. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(alertmanager_config_last_reload_successful{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) == 0 + for: 10m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerMembersInconsistent | default false) }} + - alert: AlertmanagerMembersInconsistent + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} has only found {{`{{`}} $value {{`}}`}} members of the {{`{{`}}$labels.job{{`}}`}} cluster. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagermembersinconsistent + summary: A member of an Alertmanager cluster has not found all other cluster members. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + < on (namespace,service) group_left + count by (namespace,service) (max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m])) + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedToSendAlerts | default false) }} + - alert: AlertmanagerFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} failed to send {{`{{`}} $value | humanizePercentage {{`}}`}} of notifications to {{`{{`}} $labels.integration {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedtosendalerts + summary: An Alertmanager instance failed to send notifications. + expr: |- + ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} + - alert: AlertmanagerClusterFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts + summary: All Alertmanager instances in a cluster failed to send notifications to a critical integration. + expr: |- + min by (namespace,service, integration) ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} + - alert: AlertmanagerClusterFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts + summary: All Alertmanager instances in a cluster failed to send notifications to a non-critical integration. + expr: |- + min by (namespace,service, integration) ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerConfigInconsistent | default false) }} + - alert: AlertmanagerConfigInconsistent + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have different configurations. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerconfiginconsistent + summary: Alertmanager instances within the same cluster have different configurations. + expr: |- + count by (namespace,service) ( + count_values by (namespace,service) ("config_hash", alertmanager_config_hash{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) + ) + != 1 + for: 20m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterDown | default false) }} + - alert: AlertmanagerClusterDown + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have been up for less than half of the last 5m.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterdown + summary: Half or more of the Alertmanager instances within the same cluster are down. + expr: |- + ( + count by (namespace,service) ( + avg_over_time(up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) < 0.5 + ) + / + count by (namespace,service) ( + up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} + ) + ) + >= 0.5 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterCrashlooping | default false) }} + - alert: AlertmanagerClusterCrashlooping + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have restarted at least 5 times in the last 10m.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclustercrashlooping + summary: Half or more of the Alertmanager instances within the same cluster are crashlooping. + expr: |- + ( + count by (namespace,service) ( + changes(process_start_time_seconds{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[10m]) > 4 + ) + / + count by (namespace,service) ( + up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} + ) + ) + >= 0.5 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml new file mode 100644 index 00000000..13c158c0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/general.rules.yaml @@ -0,0 +1,98 @@ +{{- /* +Generated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubePrometheus-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "general.rules" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: general.rules + rules: +{{- if not (.Values.defaultRules.disabled.TargetDown | default false) }} + - alert: TargetDown + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.4g" $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.service {{`}}`}} targets in {{`{{`}} $labels.namespace {{`}}`}} namespace are down.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/targetdown + summary: One or more targets are unreachable. + expr: 100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) > 10 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.Watchdog | default false) }} + - alert: Watchdog + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'This is an alert meant to ensure that the entire alerting pipeline is functional. + + This alert is always firing, therefore it should always be firing in Alertmanager + + and always fire against a receiver. There are integrations with various notification + + mechanisms that send a notification when this alert is not firing. For example the + + "DeadMansSnitch" integration in PagerDuty. + + ' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/watchdog + summary: An alert that should always be firing to certify that Alertmanager is working properly. + expr: vector(1) + labels: + severity: none +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.InfoInhibitor | default false) }} + - alert: InfoInhibitor + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'This is an alert that is used to inhibit info alerts. + + By themselves, the info-level alerts are sometimes very noisy, but they are relevant when combined with + + other alerts. + + This alert fires whenever there''s a severity="info" alert, and stops firing when another alert with a + + severity of ''warning'' or ''critical'' starts firing on the same namespace. + + This alert should be routed to a null receiver and configured to inhibit alerts with severity="info". + + ' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/infoinhibitor + summary: Info-level alert inhibition. + expr: ALERTS{severity = "info"} == 1 unless on(namespace) ALERTS{alertname != "InfoInhibitor", severity =~ "warning|critical", alertstate="firing"} == 1 + labels: + severity: none +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml new file mode 100644 index 00000000..c956157e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-apps.yaml @@ -0,0 +1,375 @@ +{{- /* +Generated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }} +{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-apps" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: kubernetes-apps + rules: +{{- if not (.Values.defaultRules.disabled.KubePodCrashLooping | default false) }} + - alert: KubePodCrashLooping + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is in waiting state (reason: "CrashLoopBackOff").' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodcrashlooping + summary: Pod is crash looping. + expr: max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) >= 1 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePodNotReady | default false) }} + - alert: KubePodNotReady + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodnotready + summary: Pod has been in a non-ready state for more than 15 minutes. + expr: |- + sum by (namespace, pod, cluster) ( + max by(namespace, pod, cluster) ( + kube_pod_status_phase{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}", phase=~"Pending|Unknown"} + ) * on(namespace, pod, cluster) group_left(owner_kind) topk by(namespace, pod, cluster) ( + 1, max by(namespace, pod, owner_kind, cluster) (kube_pod_owner{owner_kind!="Job"}) + ) + ) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDeploymentGenerationMismatch | default false) }} + - alert: KubeDeploymentGenerationMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentgenerationmismatch + summary: Deployment generation mismatch due to possible roll-back + expr: |- + kube_deployment_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_deployment_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDeploymentReplicasMismatch | default false) }} + - alert: KubeDeploymentReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentreplicasmismatch + summary: Deployment has not matched the expected number of replicas. + expr: |- + ( + kube_deployment_spec_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + > + kube_deployment_status_replicas_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) and ( + changes(kube_deployment_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetReplicasMismatch | default false) }} + - alert: KubeStatefulSetReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetreplicasmismatch + summary: Deployment has not matched the expected number of replicas. + expr: |- + ( + kube_statefulset_status_replicas_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_status_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) and ( + changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetGenerationMismatch | default false) }} + - alert: KubeStatefulSetGenerationMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetgenerationmismatch + summary: StatefulSet generation mismatch due to possible roll-back + expr: |- + kube_statefulset_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetUpdateNotRolledOut | default false) }} + - alert: KubeStatefulSetUpdateNotRolledOut + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetupdatenotrolledout + summary: StatefulSet update has not been rolled out. + expr: |- + ( + max without (revision) ( + kube_statefulset_status_current_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + unless + kube_statefulset_status_update_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + * + ( + kube_statefulset_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + ) and ( + changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetRolloutStuck | default false) }} + - alert: KubeDaemonSetRolloutStuck + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} has not finished or progressed for at least 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetrolloutstuck + summary: DaemonSet rollout is stuck. + expr: |- + ( + ( + kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) or ( + kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + 0 + ) or ( + kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) or ( + kube_daemonset_status_number_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + ) and ( + changes(kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeContainerWaiting | default false) }} + - alert: KubeContainerWaiting + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: pod/{{`{{`}} $labels.pod {{`}}`}} in namespace {{`{{`}} $labels.namespace {{`}}`}} on container {{`{{`}} $labels.container{{`}}`}} has been in waiting state for longer than 1 hour. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubecontainerwaiting + summary: Pod container waiting longer than 1 hour + expr: sum by (namespace, pod, container, cluster) (kube_pod_container_status_waiting_reason{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) > 0 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetNotScheduled | default false) }} + - alert: KubeDaemonSetNotScheduled + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetnotscheduled + summary: DaemonSet pods are not scheduled. + expr: |- + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + - + kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetMisScheduled | default false) }} + - alert: KubeDaemonSetMisScheduled + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetmisscheduled + summary: DaemonSet pods are misscheduled. + expr: kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeJobNotCompleted | default false) }} + - alert: KubeJobNotCompleted + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than {{`{{`}} "43200" | humanizeDuration {{`}}`}} to complete. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobnotcompleted + summary: Job did not complete in time + expr: |- + time() - max by(namespace, job_name, cluster) (kube_job_status_start_time{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + and + kube_job_status_active{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0) > 43200 + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeJobFailed | default false) }} + - alert: KubeJobFailed + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. Removing failed job after investigation should clear this alert. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobfailed + summary: Job failed to complete. + expr: kube_job_failed{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeHpaReplicasMismatch | default false) }} + - alert: KubeHpaReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has not matched the desired number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpareplicasmismatch + summary: HPA has not matched desired number of replicas. + expr: |- + (kube_horizontalpodautoscaler_status_desired_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + > + kube_horizontalpodautoscaler_spec_min_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + < + kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + changes(kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[15m]) == 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeHpaMaxedOut | default false) }} + - alert: KubeHpaMaxedOut + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has been running at max replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpamaxedout + summary: HPA is running at max replicas + expr: |- + kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + == + kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml new file mode 100644 index 00000000..b6fe43fb --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/kubernetes-storage.yaml @@ -0,0 +1,160 @@ +{{- /* +Generated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }} +{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-storage" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: kubernetes-storage + rules: +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} + - alert: KubePersistentVolumeFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} $value | humanizePercentage {{`}}`}} free. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup + summary: PersistentVolume is filling up. + expr: |- + kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + < 0.03 + and + kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} + - alert: KubePersistentVolumeFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} is available. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup + summary: PersistentVolume is filling up. + expr: |- + ( + kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.15 + and + kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + and + predict_linear(kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} + - alert: KubePersistentVolumeInodesFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} only has {{`{{`}} $value | humanizePercentage {{`}}`}} free inodes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup + summary: PersistentVolumeInodes are filling up. + expr: |- + ( + kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.03 + and + kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} + - alert: KubePersistentVolumeInodesFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to run out of inodes within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} of its inodes are free. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup + summary: PersistentVolumeInodes are filling up. + expr: |- + ( + kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.15 + and + kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + and + predict_linear(kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeErrors | default false) }} + - alert: KubePersistentVolumeErrors + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeerrors + summary: PersistentVolume is having issues with provisioning. + expr: kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml new file mode 100644 index 00000000..d3aa167d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/rules-1.14/prometheus.yaml @@ -0,0 +1,448 @@ +{{- /* +Generated from 'prometheus' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }} +{{- $prometheusJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" }} +{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: prometheus + rules: +{{- if not (.Values.defaultRules.disabled.PrometheusBadConfig | default false) }} + - alert: PrometheusBadConfig + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to reload its configuration. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusbadconfig + summary: Failed Prometheus configuration reload. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(prometheus_config_last_reload_successful{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) == 0 + for: 10m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotificationQueueRunningFull | default false) }} + - alert: PrometheusNotificationQueueRunningFull + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alert notification queue of Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is running full. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotificationqueuerunningfull + summary: Prometheus alert notification queue predicted to run full in less than 30m. + expr: |- + # Without min_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + predict_linear(prometheus_notifications_queue_length{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m], 60 * 30) + > + min_over_time(prometheus_notifications_queue_capacity{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToSomeAlertmanagers | default false) }} + - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.alertmanager{{`}}`}}.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstosomealertmanagers + summary: Prometheus has encountered more than 1% errors sending alerts to a specific Alertmanager. + expr: |- + ( + rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + / + rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + * 100 + > 1 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotConnectedToAlertmanagers | default false) }} + - alert: PrometheusNotConnectedToAlertmanagers + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not connected to any Alertmanagers. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotconnectedtoalertmanagers + summary: Prometheus is not connected to any Alertmanagers. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(prometheus_notifications_alertmanagers_discovered{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) < 1 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTSDBReloadsFailing | default false) }} + - alert: PrometheusTSDBReloadsFailing + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} reload failures over the last 3h. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbreloadsfailing + summary: Prometheus has issues reloading blocks from disk. + expr: increase(prometheus_tsdb_reloads_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 + for: 4h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTSDBCompactionsFailing | default false) }} + - alert: PrometheusTSDBCompactionsFailing + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last 3h. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbcompactionsfailing + summary: Prometheus has issues compacting blocks. + expr: increase(prometheus_tsdb_compactions_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 + for: 4h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotIngestingSamples | default false) }} + - alert: PrometheusNotIngestingSamples + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not ingesting samples. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotingestingsamples + summary: Prometheus is not ingesting samples. + expr: |- + ( + rate(prometheus_tsdb_head_samples_appended_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) <= 0 + and + ( + sum without(scrape_job) (prometheus_target_metadata_cache_entries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 + or + sum without(rule_group) (prometheus_rule_group_rules{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 + ) + ) + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusDuplicateTimestamps | default false) }} + - alert: PrometheusDuplicateTimestamps + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with different values but duplicated timestamp. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusduplicatetimestamps + summary: Prometheus is dropping samples with duplicate timestamps. + expr: rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusOutOfOrderTimestamps | default false) }} + - alert: PrometheusOutOfOrderTimestamps + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with timestamps arriving out of order. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusoutofordertimestamps + summary: Prometheus drops samples with out-of-order timestamps. + expr: rate(prometheus_target_scrapes_sample_out_of_order_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteStorageFailures | default false) }} + - alert: PrometheusRemoteStorageFailures + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} failed to send {{`{{`}} printf "%.1f" $value {{`}}`}}% of the samples to {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}} + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotestoragefailures + summary: Prometheus fails to send samples to remote storage. + expr: |- + ( + (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + / + ( + (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + + + (rate(prometheus_remote_storage_succeeded_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + ) + ) + * 100 + > 1 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteBehind | default false) }} + - alert: PrometheusRemoteWriteBehind + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write is {{`{{`}} printf "%.1f" $value {{`}}`}}s behind for {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritebehind + summary: Prometheus remote write is behind. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + - ignoring(remote_name, url) group_right + max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + > 120 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteDesiredShards | default false) }} + - alert: PrometheusRemoteWriteDesiredShards + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write desired shards calculation wants to run {{`{{`}} $value {{`}}`}} shards for queue {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}, which is more than the max of {{`{{`}} printf `prometheus_remote_storage_shards_max{instance="%s",job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}` $labels.instance | query | first | value {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritedesiredshards + summary: Prometheus remote write desired shards calculation wants to run more than configured max shards. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + max_over_time(prometheus_remote_storage_shards_desired{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + > + max_over_time(prometheus_remote_storage_shards_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRuleFailures | default false) }} + - alert: PrometheusRuleFailures + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to evaluate {{`{{`}} printf "%.0f" $value {{`}}`}} rules in the last 5m. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusrulefailures + summary: Prometheus is failing rule evaluations. + expr: increase(prometheus_rule_evaluation_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusMissingRuleEvaluations | default false) }} + - alert: PrometheusMissingRuleEvaluations + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has missed {{`{{`}} printf "%.0f" $value {{`}}`}} rule group evaluations in the last 5m. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusmissingruleevaluations + summary: Prometheus is missing rule evaluations due to slow rule group evaluation. + expr: increase(prometheus_rule_group_iterations_missed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTargetLimitHit | default false) }} + - alert: PrometheusTargetLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because the number of targets exceeded the configured target_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetlimithit + summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit. + expr: increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusLabelLimitHit | default false) }} + - alert: PrometheusLabelLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because some samples exceeded the configured label_limit, label_name_length_limit or label_value_length_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuslabellimithit + summary: Prometheus has dropped targets because some scrape configs have exceeded the labels limit. + expr: increase(prometheus_target_scrape_pool_exceeded_label_limits_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusScrapeBodySizeLimitHit | default false) }} + - alert: PrometheusScrapeBodySizeLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured body_size_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapebodysizelimithit + summary: Prometheus has dropped some targets that exceeded body size limit. + expr: increase(prometheus_target_scrapes_exceeded_body_size_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusScrapeSampleLimitHit | default false) }} + - alert: PrometheusScrapeSampleLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured sample_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapesamplelimithit + summary: Prometheus has failed scrapes that have exceeded the configured sample limit. + expr: increase(prometheus_target_scrapes_exceeded_sample_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTargetSyncFailure | default false) }} + - alert: PrometheusTargetSyncFailure + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.0f" $value {{`}}`}} targets in Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} have failed to sync because invalid configuration was supplied.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetsyncfailure + summary: Prometheus has failed to sync targets. + expr: increase(prometheus_target_sync_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[30m]) > 0 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusHighQueryLoad | default false) }} + - alert: PrometheusHighQueryLoad + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} query API has less than 20% available capacity in its query engine for the last 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheushighqueryload + summary: Prometheus is reaching its maximum capacity serving concurrent requests. + expr: avg_over_time(prometheus_engine_queries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) / max_over_time(prometheus_engine_queries_concurrent_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0.8 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToAnyAlertmanager | default false) }} + - alert: PrometheusErrorSendingAlertsToAnyAlertmanager + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% minimum errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to any Alertmanager.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstoanyalertmanager + summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager. + expr: |- + min without (alertmanager) ( + rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) + / + rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) + ) + * 100 + > 3 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml new file mode 100644 index 00000000..411ec5fa --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/service.yaml @@ -0,0 +1,56 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + self-monitor: {{ .Values.prometheus.serviceMonitor.selfMonitor | quote }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.service.labels }} +{{ toYaml .Values.prometheus.service.labels | indent 4 }} +{{- end }} +{{- if .Values.prometheus.service.annotations }} + annotations: +{{ toYaml .Values.prometheus.service.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.prometheus.service.clusterIP }} + clusterIP: {{ .Values.prometheus.service.clusterIP }} +{{- end }} +{{- if .Values.prometheus.service.externalIPs }} + externalIPs: +{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if ne .Values.prometheus.service.type "ClusterIP" }} + externalTrafficPolicy: {{ .Values.prometheus.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.prometheus.prometheusSpec.portName }} + {{- if eq .Values.prometheus.service.type "NodePort" }} + nodePort: {{ .Values.prometheus.service.nodePort }} + {{- end }} + port: {{ .Values.prometheus.service.port }} + targetPort: {{ .Values.prometheus.service.targetPort }} +{{- if .Values.prometheus.service.additionalPorts }} +{{ toYaml .Values.prometheus.service.additionalPorts | indent 2 }} +{{- end }} + publishNotReadyAddresses: {{ .Values.prometheus.service.publishNotReadyAddresses }} + selector: + app.kubernetes.io/name: prometheus + prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} +{{- if .Values.prometheus.service.sessionAffinity }} + sessionAffinity: {{ .Values.prometheus.service.sessionAffinity }} +{{- end }} + type: "{{ .Values.prometheus.service.type }}" +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml new file mode 100644 index 00000000..b4d44164 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/component: prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml new file mode 100644 index 00000000..2d995511 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/prometheus/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + release: {{ $.Release.Name | quote }} + self-monitor: "true" + namespaceSelector: + matchNames: + - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} + endpoints: + - port: {{ .Values.prometheus.prometheusSpec.portName }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.scheme }} + scheme: {{ .Values.prometheus.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} + {{- end }} + path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" + metricRelabelings: + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +{{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: +{{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml new file mode 100644 index 00000000..42f13a0f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/rancher-monitoring/hardened.yaml @@ -0,0 +1,129 @@ +{{- $namespaces := dict "_0" .Release.Namespace -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + annotations: + "helm.sh/hook": post-install, post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded, before-hook-creation +spec: + template: + metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + spec: + serviceAccountName: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +{{- if .Values.global.kubectl.securityContext }} + securityContext: {{ toYaml .Values.global.kubectl.securityContext | nindent 8 }} +{{- end }} + restartPolicy: Never + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + containers: + {{- range $_, $ns := $namespaces }} + - name: patch-sa-{{ $ns }} + image: {{ template "system_default_registry" $ }}{{ $.Values.global.kubectl.repository }}:{{ $.Values.global.kubectl.tag }} + imagePullPolicy: {{ $.Values.global.kubectl.pullPolicy }} + command: ["kubectl", "patch", "serviceaccount", "default", "-p", "{\"automountServiceAccountToken\": false}"] + args: ["-n", "{{ $ns }}"] +{{- if $.Values.global.kubectl.resources }} + resources: {{ toYaml $.Values.global.kubectl.resources | nindent 10 }} +{{- end }} +{{- if $.Values.global.kubectl.containerSecurityContext }} + securityContext: {{ toYaml $.Values.global.kubectl.containerSecurityContext | nindent 10 }} +{{- end }} + {{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: ['get', 'patch'] +{{- if .Values.global.cattle.psp.enabled }} +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-patch-sa +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +subjects: +- kind: ServiceAccount + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +--- +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +spec: + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false + volumes: + - 'secret' +{{- end }} +{{- range $_, $ns := $namespaces }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: project-monitoring-policy + namespace: {{ $ns }} +spec: + podSelector: {} + ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} + egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} + policyTypes: + - Ingress + - Egress +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml b/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml new file mode 100644 index 00000000..b0dcf188 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/validate-install-crd.yaml @@ -0,0 +1,21 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +# {{- $found := dict -}} +# {{- set $found "monitoring.coreos.com/v1alpha1/AlertmanagerConfig" false -}} +# {{- set $found "monitoring.coreos.com/v1/Alertmanager" false -}} +# {{- set $found "monitoring.coreos.com/v1/PodMonitor" false -}} +# {{- set $found "monitoring.coreos.com/v1/Probe" false -}} +# {{- set $found "monitoring.coreos.com/v1/Prometheus" false -}} +# {{- set $found "monitoring.coreos.com/v1/PrometheusRule" false -}} +# {{- set $found "monitoring.coreos.com/v1/ServiceMonitor" false -}} +# {{- set $found "monitoring.coreos.com/v1/ThanosRuler" false -}} +# {{- range .Capabilities.APIVersions -}} +# {{- if hasKey $found (toString .) -}} +# {{- set $found (toString .) true -}} +# {{- end -}} +# {{- end -}} +# {{- range $_, $exists := $found -}} +# {{- if (eq $exists false) -}} +# {{- required "Required Prometheus Operator CRDs are missing. Please install Prometheus Operator (e.g. rancher-monitoring) before installing this chart." "" -}} +# {{- end -}} +# {{- end -}} +#{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml b/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml new file mode 100644 index 00000000..a30c59d3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/templates/validate-psp-install.yaml @@ -0,0 +1,7 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +#{{- if .Values.global.cattle.psp.enabled }} +#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} +#{{- end }} +#{{- end }} +#{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.0/values.yaml b/charts/rancher-project-monitoring/0.3.0/values.yaml new file mode 100644 index 00000000..1f0f1654 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.0/values.yaml @@ -0,0 +1,1551 @@ +# Default values for project-prometheus-stack. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Rancher Project Monitoring Configuration + +## Provide a name in place of project-prometheus-stack for `app:` labels +## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url +## +nameOverride: "rancher-project-monitoring" + +## Override the deployment namespace +## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url +## +namespaceOverride: "" + +## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6 +## +kubeTargetVersionOverride: "" + +## Allow kubeVersion to be overridden while creating the ingress +## +kubeVersionOverride: "" + +## Provide a name to substitute for the full names of resources +## +fullnameOverride: "" + +## Labels to apply to all resources +## +commonLabels: {} +# scmhash: abc123 +# myLabel: aakkmd + +## Create default rules for monitoring the cluster +## +defaultRules: + create: true + rules: + general: true + prometheus: true + alertmanager: true + kubernetesApps: true + kubernetesStorage: true + + ## Reduce app namespace alert scope + appNamespacesTarget: ".*" + + ## Labels for default rules + labels: {} + ## Annotations for default rules + annotations: {} + + ## Additional labels for PrometheusRule alerts + additionalRuleLabels: {} + + ## Additional annotations for PrometheusRule alerts + additionalRuleAnnotations: {} + + ## Prefix for runbook URLs. Use this to override the first part of the runbookURLs that is common to all rules. + runbookUrl: "https://runbooks.prometheus-operator.dev/runbooks" + + ## Disabled PrometheusRule alerts + disabled: {} + +## +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectNamespaceSelector: {} + projectNamespaces: [] + kubectl: + repository: rancher/kubectl + tag: v1.20.2 + pullPolicy: IfNotPresent + securityContext: + runAsNonRoot: true + runAsUser: 1000 + networkPolicy: + # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. + # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, + # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs + # through the Rancher/Kubernetes API Proxy in the Rancher UI. + limitIngressToProject: false + # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. + ingress: null + # By default, all egress traffic is allowed. + egress: + - {} + rbac: + ## Create RBAC resources for ServiceAccounts and users + ## + create: true + + userRoles: + ## Create default user Roles that the Helm Project Operator will automatically create RoleBindings for + ## + ## How does this work? + ## + ## The operator will watch for all subjects bound to each Kubernetes default ClusterRole in the project registration namespace + ## where the ProjectHelmChart that deployed this chart belongs to; if it observes a subject bound to a particular role in + ## the project registration namespace (e.g. edit) and if a Role exists that is deployed by this chart with the label + ## 'helm.cattle.io/project-helm-chart-role-aggregate-from': '', it will automaticaly create a RoleBinding + ## in the release namespace binding all such subjects to that Role. + ## + ## Note: while the default behavior is to use the Kubernetes default ClusterRole, the operator deployment (prometheus-federator) + ## can be configured to use a different set of ClusterRoles as the source of truth for admin, edit, and view permissions. + ## + create: true + ## Add labels to Roles + aggregateToDefaultRoles: true + + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + # or + # - "image-pull-secret" + +federate: + ## enabled indicates whether to add federation to any Project Prometheus Stacks by default + ## If not enabled, no federation will be turned on + enabled: true + + # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from + # By default, this matches the default deployment of Rancher Monitoring + targets: + - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 + + ## Scrape interval + interval: "15s" + +## Configuration for alertmanager +## ref: https://prometheus.io/docs/alerting/alertmanager/ +## +alertmanager: + + ## Deploy alertmanager + ## + enabled: true + + ## Annotations for Alertmanager + ## + annotations: {} + + ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2 + ## + apiVersion: v2 + + ## Service account for Alertmanager to use. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## + serviceAccount: + create: true + name: "" + annotations: {} + + ## Configure pod disruption budgets for Alertmanager + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + ## This configuration is immutable once created and will require the PDB to be deleted to be changed + ## https://github.com/kubernetes/kubernetes/issues/45398 + ## + podDisruptionBudget: + enabled: false + minAvailable: 1 + maxUnavailable: "" + + ## Alertmanager configuration directives + ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file + ## https://prometheus.io/webtools/alerting/routing-tree-editor/ + ## + config: + global: + resolve_timeout: 5m + inhibit_rules: + - source_matchers: + - 'severity = critical' + target_matchers: + - 'severity =~ warning|info' + equal: + - 'namespace' + - 'alertname' + - source_matchers: + - 'severity = warning' + target_matchers: + - 'severity = info' + equal: + - 'namespace' + - 'alertname' + - source_matchers: + - 'alertname = InfoInhibitor' + target_matchers: + - 'severity = info' + equal: + - 'namespace' + route: + group_by: ['namespace'] + group_wait: 30s + group_interval: 5m + repeat_interval: 12h + receiver: 'null' + routes: + - receiver: 'null' + matchers: + - alertname =~ "InfoInhibitor|Watchdog" + receivers: + - name: 'null' + templates: + - '/etc/alertmanager/config/*.tmpl' + + ## Pass the Alertmanager configuration directives through Helm's templating + ## engine. If the Alertmanager configuration contains Alertmanager templates, + ## they'll need to be properly escaped so that they are not interpreted by + ## Helm + ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function + ## https://prometheus.io/docs/alerting/configuration/#tmpl_string + ## https://prometheus.io/docs/alerting/notifications/ + ## https://prometheus.io/docs/alerting/notification_examples/ + tplConfig: false + + ## Alertmanager template files to format alerts + ## By default, templateFiles are placed in /etc/alertmanager/config/ and if + ## they have a .tmpl file suffix will be loaded. See config.templates above + ## to change, add other suffixes. If adding other suffixes, be sure to update + ## config.templates above to include those suffixes. + ## ref: https://prometheus.io/docs/alerting/notifications/ + ## https://prometheus.io/docs/alerting/notification_examples/ + ## + + templateFiles: + rancher_defaults.tmpl: |- + {{- define "slack.rancher.text" -}} + {{ template "rancher.text_multiple" . }} + {{- end -}} + + {{- define "rancher.text_multiple" -}} + *[GROUP - Details]* + One or more alarms in this group have triggered a notification. + + {{- if gt (len .GroupLabels.Values) 0 }} + *Group Labels:* + {{- range .GroupLabels.SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- if .ExternalURL }} + *Link to AlertManager:* {{ .ExternalURL }} + {{- end }} + + {{- range .Alerts }} + {{ template "rancher.text_single" . }} + {{- end }} + {{- end -}} + + {{- define "rancher.text_single" -}} + {{- if .Labels.alertname }} + *[ALERT - {{ .Labels.alertname }}]* + {{- else }} + *[ALERT]* + {{- end }} + {{- if .Labels.severity }} + *Severity:* `{{ .Labels.severity }}` + {{- end }} + {{- if .Labels.cluster }} + *Cluster:* {{ .Labels.cluster }} + {{- end }} + {{- if .Annotations.summary }} + *Summary:* {{ .Annotations.summary }} + {{- end }} + {{- if .Annotations.message }} + *Message:* {{ .Annotations.message }} + {{- end }} + {{- if .Annotations.description }} + *Description:* {{ .Annotations.description }} + {{- end }} + {{- if .Annotations.runbook_url }} + *Runbook URL:* <{{ .Annotations.runbook_url }}|:spiral_note_pad:> + {{- end }} + {{- with .Labels }} + {{- with .Remove (stringSlice "alertname" "severity" "cluster") }} + {{- if gt (len .) 0 }} + *Additional Labels:* + {{- range .SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Annotations }} + {{- with .Remove (stringSlice "summary" "message" "description" "runbook_url") }} + {{- if gt (len .) 0 }} + *Additional Annotations:* + {{- range .SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end -}} + + ingress: + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + annotations: {} + + labels: {} + + ## Redirect ingress to an additional defined port on the service + # servicePort: 8081 + + ## Hosts must be provided if Ingress is enabled. + ## + hosts: [] + # - alertmanager.domain.com + + ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix + ## + paths: [] + # - / + + ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) + ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types + # pathType: ImplementationSpecific + + ## TLS configuration for Alertmanager Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: alertmanager-general-tls + # hosts: + # - alertmanager.example.com + + ## Configuration for Alertmanager secret + ## + secret: + annotations: {} + + ## Configuration for Alertmanager service + ## + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Port for Alertmanager Service to listen on + ## + port: 9093 + ## To be used with a proxy extraContainer port + ## + targetPort: 9093 + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30903 + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + + ## Additional ports to open for Alertmanager service + additionalPorts: [] + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + + externalIPs: [] + loadBalancerIP: "" + loadBalancerSourceRanges: [] + + ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + ## + externalTrafficPolicy: Cluster + + ## Service type + ## + type: ClusterIP + + ## If true, create a serviceMonitor for alertmanager + ## + serviceMonitor: + ## Scrape interval. If not set, the Prometheus default scrape interval is used. + ## + interval: "" + selfMonitor: true + + ## proxyUrl: URL of a proxy that should be used for scraping. + ## + proxyUrl: "" + + ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. + scheme: "" + + ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. + ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + + bearerTokenFile: + + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + ## RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + ## Settings affecting alertmanagerSpec + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerspec + ## + alertmanagerSpec: + ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata + ## Metadata Labels and Annotations gets propagated to the Alertmanager pods. + ## + podMetadata: {} + + ## Image of Alertmanager + ## + image: + repository: rancher/mirrored-prometheus-alertmanager + tag: v0.24.0 + sha: "" + + ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the + ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. + ## + secrets: [] + + ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. + ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/. + ## + configMaps: [] + + ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for + ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config. + ## + # configSecret: + + ## WebTLSConfig defines the TLS parameters for HTTPS + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerwebspec + web: {} + + ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. + ## + alertmanagerConfigSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## AlermanagerConfig to be used as top level configuration + ## + alertmanagerConfiguration: {} + ## Example with select a global alertmanagerconfig + # alertmanagerConfiguration: + # name: global-alertmanager-Configuration + + ## Define Log Format + # Use logfmt (default) or json logging + logFormat: logfmt + + ## Log level for Alertmanager to be configured with. + ## + logLevel: info + + ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the + ## running cluster equal to the expected size. + replicas: 1 + + ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression + ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours). + ## + retention: 120h + + ## Storage is the definition of how storage will be used by the Alertmanager instances. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md + ## + storage: {} + # volumeClaimTemplate: + # spec: + # storageClassName: gluster + # accessModes: ["ReadWriteOnce"] + # resources: + # requests: + # storage: 50Gi + # selector: {} + + + ## The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. string false + ## + externalUrl: + + ## The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, + ## but the server serves requests under a different route prefix. For example for use with kubectl proxy. + ## + routePrefix: / + + ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions. + ## + paused: false + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Define resources requests and limits for single Pods. + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + memory: 500Mi + cpu: 1000m + requests: + memory: 100Mi + cpu: 100m + + ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. + ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. + ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. + ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. + ## + podAntiAffinity: "" + + ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. + ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone + ## + podAntiAffinityTopologyKey: kubernetes.io/hostname + + ## Assign custom affinity rules to the alertmanager instance + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/e2e-az-name + # operator: In + # values: + # - e2e-az1 + # - e2e-az2 + + ## If specified, the pod's tolerations. + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + ## If specified, the pod's topology spread constraints. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app: alertmanager + + ## SecurityContext holds pod-level security attributes and common container settings. + ## This defaults to non root user with uid 1000 and gid 2000. *v1.PodSecurityContext false + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + + ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. + ## Note this is only for the Alertmanager UI, not the gossip communication. + ## + listenLocal: false + + ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. + ## + containers: [] + # containers: + # - name: oauth-proxy + # image: quay.io/oauth2-proxy/oauth2-proxy:v7.3.0 + # args: + # - --upstream=http://127.0.0.1:9093 + # - --http-address=0.0.0.0:8081 + # - ... + # ports: + # - containerPort: 8081 + # name: oauth-proxy + # protocol: TCP + # resources: {} + + # Additional volumes on the output StatefulSet definition. + volumes: [] + + # Additional VolumeMounts on the output StatefulSet definition. + volumeMounts: [] + + ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes + ## (permissions, dir tree) on mounted volumes before starting prometheus + initContainers: [] + + ## Priority class assigned to the Pods + ## + priorityClassName: "" + + ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster. + ## + additionalPeers: [] + + ## PortName to use for Alert Manager. + ## + portName: "http-web" + + ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918 + ## + clusterAdvertiseAddress: false + + ## ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. + ## Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. + forceEnableClusterMode: false + + ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to + ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). + minReadySeconds: 0 + + ## ExtraSecret can be used to store various data in an extra secret + ## (use it for example to store hashed basic auth credentials) + extraSecret: + ## if not set, name will be auto generated + # name: "" + annotations: {} + data: {} + # auth: | + # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 + # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. + +## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml +## +grafana: + enabled: true + namespaceOverride: "" + + ## Grafana's primary configuration + ## NOTE: values in map will be converted to ini format + ## ref: http://docs.grafana.org/installation/configuration/ + ## + grafana.ini: + users: + auto_assign_org_role: Viewer + auth: + disable_login_form: false + auth.anonymous: + enabled: true + org_role: Viewer + auth.basic: + enabled: false + security: + # Required to embed dashboards in Rancher Cluster Overview Dashboard on Cluster Explorer + allow_embedding: true + + deploymentStrategy: + type: Recreate + + ## ForceDeployDatasources Create datasource configmap even if grafana deployment has been disabled + ## + forceDeployDatasources: false + + ## ForceDeployDashboard Create dashboard configmap even if grafana deployment has been disabled + ## + forceDeployDashboards: false + + ## Deploy default dashboards + ## + defaultDashboardsEnabled: true + + ## Timezone for the default dashboards + ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg + ## + defaultDashboardsTimezone: utc + + adminPassword: prom-operator + + ingress: + ## If true, Grafana Ingress will be created + ## + enabled: false + + ## IngressClassName for Grafana Ingress. + ## Should be provided if Ingress is enable. + ## + # ingressClassName: nginx + + ## Annotations for Grafana Ingress + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + ## Labels to be added to the Ingress + ## + labels: {} + + ## Hostnames. + ## Must be provided if Ingress is enable. + ## + # hosts: + # - grafana.domain.com + hosts: [] + + ## Path for grafana ingress + path: / + + ## TLS configuration for grafana Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: grafana-general-tls + # hosts: + # - grafana.example.com + + sidecar: + dashboards: + enabled: true + label: grafana_dashboard + labelValue: "1" + + ## Annotations for Grafana dashboard configmaps + ## + annotations: {} + multicluster: + global: + enabled: false + provider: + allowUiUpdates: false + datasources: + enabled: true + defaultDatasourceEnabled: true + + uid: prometheus + + ## URL of prometheus datasource + ## + # url: http://prometheus-stack-prometheus:9090/ + + # If not defined, will use prometheus.prometheusSpec.scrapeInterval or its default + # defaultDatasourceScrapeInterval: 15s + + ## Annotations for Grafana datasource configmaps + ## + annotations: {} + + label: grafana_datasource + labelValue: "1" + + ## Field with internal link pointing to existing data source in Grafana. + ## Can be provisioned via additionalDataSources + exemplarTraceIdDestinations: {} + # datasourceUid: Jaeger + # traceIdLabelName: trace_id + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # configMap: certs-configmap + # readOnly: true + + deleteDatasources: [] + # - name: example-datasource + # orgId: 1 + + ## Configure additional grafana datasources (passed through tpl) + ## ref: http://docs.grafana.org/administration/provisioning/#datasources + additionalDataSources: [] + # - name: prometheus-sample + # access: proxy + # basicAuth: true + # basicAuthPassword: pass + # basicAuthUser: daco + # editable: false + # jsonData: + # tlsSkipVerify: true + # orgId: 1 + # type: prometheus + # url: https://{{ printf "%s-prometheus.svc" .Release.Name }}:9090 + # version: 1 + + ## Passed to grafana subchart and used by servicemonitor below + ## + service: + portName: nginx-http + ## Port for Grafana Service to listen on + ## + port: 80 + ## To be used with a proxy extraContainer port + ## + targetPort: 8080 + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30950 + ## Service type + ## + type: ClusterIP + + proxy: + image: + repository: rancher/mirrored-library-nginx + tag: 1.24.0-alpine + + ## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod + extraContainers: | + - name: grafana-proxy + args: + - nginx + - -g + - daemon off; + - -c + - /nginx/nginx.conf + image: "{{ template "system_default_registry" . }}{{ .Values.proxy.image.repository }}:{{ .Values.proxy.image.tag }}" + ports: + - containerPort: 8080 + name: nginx-http + protocol: TCP + volumeMounts: + - mountPath: /nginx + name: grafana-nginx + - mountPath: /var/cache/nginx + name: nginx-home + securityContext: + runAsUser: 101 + runAsGroup: 101 + + ## Volumes that can be used in containers + extraContainerVolumes: + - name: nginx-home + emptyDir: {} + - name: grafana-nginx + configMap: + name: grafana-nginx-proxy-config + items: + - key: nginx.conf + mode: 438 + path: nginx.conf + + ## If true, create a serviceMonitor for grafana + ## + serviceMonitor: + # If true, a ServiceMonitor CRD is created for a prometheus operator + # https://github.com/coreos/prometheus-operator + # + enabled: true + + # Path to use for scraping metrics. Might be different if server.root_url is set + # in grafana.ini + path: "/metrics" + + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + + # labels for the ServiceMonitor + labels: {} + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + # + interval: "" + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + ## RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + resources: + limits: + memory: 200Mi + cpu: 200m + requests: + memory: 100Mi + cpu: 100m + + testFramework: + enabled: false + +## Deploy a Prometheus instance +## +prometheus: + + enabled: true + + ## Annotations for Prometheus + ## + annotations: {} + + ## Service account for Prometheuses to use. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## + serviceAccount: + create: true + name: "" + annotations: {} + + ## Configuration for Prometheus service + ## + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Port for Prometheus Service to listen on + ## + port: 9090 + + ## To be used with a proxy extraContainer port + targetPort: 8081 + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30090 + + ## Loadbalancer IP + ## Only use if service.type is "LoadBalancer" + loadBalancerIP: "" + loadBalancerSourceRanges: [] + + ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + ## + externalTrafficPolicy: Cluster + + ## Service type + ## + type: ClusterIP + + ## Additional port to define in the Service + additionalPorts: [] + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + + ## Consider that all endpoints are considered "ready" even if the Pods themselves are not + ## Ref: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec + publishNotReadyAddresses: false + + sessionAffinity: "" + + ## Configure pod disruption budgets for Prometheus + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + ## This configuration is immutable once created and will require the PDB to be deleted to be changed + ## https://github.com/kubernetes/kubernetes/issues/45398 + ## + podDisruptionBudget: + enabled: false + minAvailable: 1 + maxUnavailable: "" + + ## ExtraSecret can be used to store various data in an extra secret + ## (use it for example to store hashed basic auth credentials) + extraSecret: + ## if not set, name will be auto generated + # name: "" + annotations: {} + data: {} + # auth: | + # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 + # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. + + ingress: + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + annotations: {} + labels: {} + + ## Redirect ingress to an additional defined port on the service + # servicePort: 8081 + + ## Hostnames. + ## Must be provided if Ingress is enabled. + ## + # hosts: + # - prometheus.domain.com + hosts: [] + + ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix + ## + paths: [] + # - / + + ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) + ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types + # pathType: ImplementationSpecific + + ## TLS configuration for Prometheus Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-general-tls + # hosts: + # - prometheus.example.com + + ## Configure additional options for default pod security policy for Prometheus + ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + podSecurityPolicy: + allowedCapabilities: [] + volumes: [] + + serviceMonitor: + ## Scrape interval. If not set, the Prometheus default scrape interval is used. + ## + interval: "" + selfMonitor: true + + ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. + scheme: "" + + ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. + ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + + bearerTokenFile: + + ## Metric relabel configs to apply to samples before ingestion. + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + ## Settings affecting prometheusSpec + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#prometheusspec + ## + prometheusSpec: + ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos + ## + disableCompaction: false + ## APIServerConfig + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#apiserverconfig + ## + apiserverConfig: {} + + ## Interval between consecutive scrapes. + ## Defaults to 30s. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 + ## + scrapeInterval: "30s" + + ## Number of seconds to wait for target to respond before erroring + ## + scrapeTimeout: "" + + ## Interval between consecutive evaluations. + ## + evaluationInterval: "1m" + + ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. + ## + listenLocal: false + + ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series. + ## This is disabled by default. + ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis + ## + enableAdminAPI: false + + ## WebTLSConfig defines the TLS parameters for HTTPS + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#webtlsconfig + web: {} + + ## Exemplars related settings that are runtime reloadable. + ## It requires to enable the exemplar storage feature to be effective. + exemplars: "" + ## Maximum number of exemplars stored in memory for all series. + ## If not set, Prometheus uses its default value. + ## A value of zero or less than zero disables the storage. + # maxSize: 100000 + + # EnableFeatures API enables access to Prometheus disabled features. + # ref: https://prometheus.io/docs/prometheus/latest/disabled_features/ + enableFeatures: [] + # - exemplar-storage + + ## Image of Prometheus. + ## + image: + repository: rancher/mirrored-prometheus-prometheus + tag: v2.38.0 + sha: "" + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + ## If specified, the pod's topology spread constraints. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app: prometheus + + ## Alertmanagers to which alerts will be sent + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerendpoints + ## + ## Default configuration will connect to the alertmanager deployed as part of this release + ## + alertingEndpoints: [] + # - name: "" + # namespace: "" + # port: http + # scheme: http + # pathPrefix: "" + # tlsConfig: {} + # bearerTokenFile: "" + # apiVersion: v2 + + ## External labels to add to any time series or alerts when communicating with external systems + ## + externalLabels: {} + + ## enable --web.enable-remote-write-receiver flag on prometheus-server + ## + enableRemoteWriteReceiver: false + + ## Name of the external label used to denote Prometheus instance name + ## + prometheusExternalLabelName: "" + + ## If true, the Operator won't add the external label used to denote Prometheus instance name + ## + prometheusExternalLabelNameClear: false + + ## External URL at which Prometheus will be reachable. + ## + externalUrl: "" + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. + ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not + ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated + ## with the new list of secrets. + ## + secrets: [] + + ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. + ## The ConfigMaps are mounted into /etc/prometheus/configmaps/. + ## + configMaps: [] + + ## QuerySpec defines the query command line flags when starting Prometheus. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#queryspec + ## + query: {} + + ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the PrometheusRule resources created + ## + ruleSelectorNilUsesHelmValues: false + + ## PrometheusRules to be selected for target discovery. + ## If {}, select all PrometheusRules + ## + ruleSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the servicemonitors created + ## + serviceMonitorSelectorNilUsesHelmValues: false + + ## ServiceMonitors to be selected for target discovery. + ## If {}, select all ServiceMonitors + ## + serviceMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the podmonitors created + ## + podMonitorSelectorNilUsesHelmValues: false + + ## PodMonitors to be selected for target discovery. + ## If {}, select all PodMonitors + ## + podMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the probes created + ## + probeSelectorNilUsesHelmValues: true + + ## Probes to be selected for target discovery. + ## If {}, select all Probes + ## + probeSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## How long to retain metrics + ## + retention: 10d + + ## Maximum size of metrics + ## + retentionSize: "50GiB" + + ## Enable compression of the write-ahead log using Snappy. + ## + walCompression: true + + ## If true, the Operator won't process any Prometheus configuration changes + ## + paused: false + + ## Number of replicas of each shard to deploy for a Prometheus deployment. + ## Number of replicas multiplied by shards is the total number of Pods created. + ## + replicas: 1 + + ## EXPERIMENTAL: Number of shards to distribute targets onto. + ## Number of replicas multiplied by shards is the total number of Pods created. + ## Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved. + ## Increasing shards will not reshard data either but it will continue to be available from the same instances. + ## To query globally use Thanos sidecar and Thanos querier or remote write data to a central location. + ## Sharding is done on the content of the `__address__` target meta-label. + ## + shards: 1 + + ## Log level for Prometheus be configured in + ## + logLevel: info + + ## Log format for Prometheus be configured in + ## + logFormat: logfmt + + ## Prefix used to register routes, overriding externalUrl route. + ## Useful for proxies that rewrite URLs. + ## + routePrefix: / + + ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata + ## Metadata Labels and Annotations gets propagated to the prometheus pods. + ## + podMetadata: {} + # labels: + # app: prometheus + # k8s-app: prometheus + + ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. + ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. + ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. + ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. + podAntiAffinity: "" + + ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. + ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone + ## + podAntiAffinityTopologyKey: kubernetes.io/hostname + + ## Assign custom affinity rules to the prometheus instance + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/e2e-az-name + # operator: In + # values: + # - e2e-az1 + # - e2e-az2 + + ## The remote_write spec configuration for Prometheus. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec + remoteWrite: [] + # - url: http://remote1/push + ## additionalRemoteWrite is appended to remoteWrite + additionalRemoteWrite: [] + + ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature + remoteWriteDashboards: false + + ## Resource limits & requests + ## + resources: + limits: + memory: 3000Mi + cpu: 1000m + requests: + memory: 750Mi + cpu: 750m + + storage: + enabled: false + ## Prometheus StorageSpec for persistent data + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md + ## + storageSpec: {} + ## Using PersistentVolumeClaim + ## + # volumeClaimTemplate: + # spec: + # storageClassName: gluster + # accessModes: ["ReadWriteOnce"] + # resources: + # requests: + # storage: 50Gi + # selector: {} + + ## Using tmpfs volume + ## + # emptyDir: + # medium: Memory + + # Additional volumes on the output StatefulSet definition. + volumes: + - name: nginx-home + emptyDir: {} + - name: prometheus-nginx + configMap: + name: prometheus-nginx-proxy-config + defaultMode: 438 + + # Additional VolumeMounts on the output StatefulSet definition. + volumeMounts: [] + + ## SecurityContext holds pod-level security attributes and common container settings. + ## This defaults to non root user with uid 1000 and gid 2000. + ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md + ## + securityContext: + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + + ## Priority class assigned to the Pods + ## + priorityClassName: "" + + proxy: + image: + repository: rancher/mirrored-library-nginx + tag: 1.24.0-alpine + + ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. + ## if using proxy extraContainer update targetPort with proxy container port + containers: | + - name: prometheus-proxy + args: + - nginx + - -g + - daemon off; + - -c + - /nginx/nginx.conf + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.proxy.image.repository }}:{{ .Values.prometheus.prometheusSpec.proxy.image.tag }}" + ports: + - containerPort: 8081 + name: nginx-http + protocol: TCP + volumeMounts: + - mountPath: /nginx + name: prometheus-nginx + - mountPath: /var/cache/nginx + name: nginx-home + securityContext: + runAsUser: 101 + runAsGroup: 101 + + ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes + ## (permissions, dir tree) on mounted volumes before starting prometheus + initContainers: [] + + ## PortName to use for Prometheus. + ## + portName: "http-web" + + ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files + ## on the file system of the Prometheus container e.g. bearer token files. + arbitraryFSAccessThroughSMs: false + + ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor + ## or PodMonitor to true, this overrides honor_labels to false. + overrideHonorLabels: false + + ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. + overrideHonorTimestamps: false + + ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. + ## The label value will always be the namespace of the object that is being created. + ## Disabled by default + enforcedNamespaceLabel: "" + + ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels. + ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair + ## Deprecated, use `excludedFromEnforcement` instead + prometheusRulesExcludedFromEnforce: [] + + ## ExcludedFromEnforcement - list of object references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects + ## to be excluded from enforcing a namespace label of origin. + ## Works only if enforcedNamespaceLabel set to true. + ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#objectreference + excludedFromEnforcement: [] + + ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable, + ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such + ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions + ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/) + queryLogFile: false + + ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit + ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall + ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead. + enforcedSampleLimit: false + + ## EnforcedTargetLimit defines a global limit on the number of scraped targets. This overrides any TargetLimit set + ## per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the TargetLimit to keep the overall + ## number of targets under the desired limit. Note that if TargetLimit is lower, that value will be taken instead, except + ## if either value is zero, in which case the non-zero value will be used. If both values are zero, no limit is enforced. + enforcedTargetLimit: false + + + ## Per-scrape limit on number of labels that will be accepted for a sample. If more than this number of labels are present + ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions + ## 2.27.0 and newer. + enforcedLabelLimit: false + + ## Per-scrape limit on length of labels name that will be accepted for a sample. If a label name is longer than this number + ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions + ## 2.27.0 and newer. + enforcedLabelNameLengthLimit: false + + ## Per-scrape limit on length of labels value that will be accepted for a sample. If a label value is longer than this + ## number post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus + ## versions 2.27.0 and newer. + enforcedLabelValueLengthLimit: false + + ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental + ## in Prometheus so it may change in any upcoming release. + allowOverlappingBlocks: false + + ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to + ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). + minReadySeconds: 0 + +## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. +## +cleanPrometheusOperatorObjectNames: false \ No newline at end of file diff --git a/index.yaml b/index.yaml index edbf9941..d4b93dbf 100755 --- a/index.yaml +++ b/index.yaml @@ -1,6 +1,54 @@ apiVersion: v1 entries: prometheus-federator: + - annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Prometheus Federator + catalog.cattle.io/kube-version: '>=1.16.0-0' + catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' + catalog.cattle.io/release-name: prometheus-federator + apiVersion: v2 + appVersion: 0.3.1 + created: "2023-05-24T21:18:24.966511-07:00" + dependencies: + - condition: helmProjectOperator.enabled + name: helmProjectOperator + repository: file://./charts/helmProjectOperator + description: Prometheus Federator + digest: 6d73736f0f4507f08c792eb888ee2b22821e2f4cabc90cca39d401f3f39dc4b4 + icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg + name: prometheus-federator + urls: + - assets/prometheus-federator/prometheus-federator-0.3.1.tgz + version: 0.3.1 + - annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Prometheus Federator + catalog.cattle.io/kube-version: '>=1.16.0-0' + catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' + catalog.cattle.io/release-name: prometheus-federator + apiVersion: v2 + appVersion: 0.3.0 + created: "2023-05-24T21:18:24.965565-07:00" + dependencies: + - condition: helmProjectOperator.enabled + name: helmProjectOperator + repository: file://./charts/helmProjectOperator + description: Prometheus Federator + digest: 04f6943cce0d15fa57a12c5eba64ade11a0264318bcf0fc07ab16b1370d1e0d9 + icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg + name: prometheus-federator + urls: + - assets/prometheus-federator/prometheus-federator-0.3.0.tgz + version: 0.3.0 - annotations: catalog.cattle.io/certified: rancher catalog.cattle.io/display-name: Prometheus Federator @@ -228,7 +276,81 @@ entries: catalog.cattle.io/release-name: rancher-project-monitoring apiVersion: v2 appVersion: 0.59.1 - created: "2023-03-06T17:16:23.657697+01:00" + created: "2023-05-24T21:18:25.019667-07:00" + dependencies: + - condition: grafana.enabled + name: grafana + repository: file://./charts/grafana + description: Collects several related Helm charts, Grafana dashboards, and Prometheus + rules combined with documentation and scripts to provide easy to operate end-to-end + Kubernetes cluster monitoring with Prometheus. Depends on the existence of a + Cluster Prometheus deployed via Prometheus Operator + digest: 4c3c45ed36f38d3302e9023984240384b6404194faac49ccf462e0bd09d6987f + home: https://github.com/prometheus-operator/kube-prometheus + icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png + keywords: + - prometheus + - monitoring + kubeVersion: '>=1.16.0-0' + maintainers: + - email: arvind.iyengar@suse.com + name: Arvind + - email: amangeet.samra@suse.com + name: Geet + url: https://github.com/geethub97 + name: rancher-project-monitoring + type: application + urls: + - assets/rancher-project-monitoring/rancher-project-monitoring-0.3.1.tgz + version: 0.3.1 + - annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' + catalog.cattle.io/release-name: rancher-project-monitoring + apiVersion: v2 + appVersion: 0.59.1 + created: "2023-05-24T21:18:25.014272-07:00" + dependencies: + - condition: grafana.enabled + name: grafana + repository: file://./charts/grafana + description: Collects several related Helm charts, Grafana dashboards, and Prometheus + rules combined with documentation and scripts to provide easy to operate end-to-end + Kubernetes cluster monitoring with Prometheus. Depends on the existence of a + Cluster Prometheus deployed via Prometheus Operator + digest: de5faa33a81aa92afcf05f187a35d6a8d4a16235c7f85215c762f1a98b8b6deb + home: https://github.com/prometheus-operator/kube-prometheus + icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png + keywords: + - prometheus + - monitoring + kubeVersion: '>=1.16.0-0' + maintainers: + - email: arvind.iyengar@suse.com + name: Arvind + - email: amangeet.samra@suse.com + name: Geet + url: https://github.com/geethub97 + name: rancher-project-monitoring + type: application + urls: + - assets/rancher-project-monitoring/rancher-project-monitoring-0.3.0.tgz + version: 0.3.0 + - annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' + catalog.cattle.io/release-name: rancher-project-monitoring + apiVersion: v2 + appVersion: 0.59.1 + created: "2023-05-24T21:18:25.008457-07:00" dependencies: - condition: grafana.enabled name: grafana @@ -237,7 +359,7 @@ entries: rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster Prometheus deployed via Prometheus Operator - digest: bce5481892fd21d7fd6eeb243f9e758728985b9eac035ca7a65e6af7ad3931de + digest: 75e51f3ced73eb3e009b54d4ea93fa8f7bd09c678f6ed2a653a3822e880d0235 home: https://github.com/prometheus-operator/kube-prometheus icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png keywords: @@ -508,4 +630,4 @@ entries: urls: - assets/rancher-project-monitoring/rancher-project-monitoring-0.0.1.tgz version: 0.0.1 -generated: "2022-04-18T09:31:51.970932-07:00" +generated: "2022-04-18T09:31:51.970932-07:00" \ No newline at end of file From 768c90305cb1ec91dc2e11a87e0c086280ec3ac9 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:55:08 -0700 Subject: [PATCH 06/21] Bumping federator and monitoring versions --- packages/prometheus-federator/charts/Chart.yaml | 4 ++-- packages/prometheus-federator/charts/values.yaml | 2 +- packages/rancher-project-monitoring/package.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/prometheus-federator/charts/Chart.yaml b/packages/prometheus-federator/charts/Chart.yaml index 7790cb50..3e4b2cd6 100755 --- a/packages/prometheus-federator/charts/Chart.yaml +++ b/packages/prometheus-federator/charts/Chart.yaml @@ -9,7 +9,7 @@ annotations: catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.6.100-0' catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 -appVersion: 0.2.1 +appVersion: 0.3.0 dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator @@ -17,4 +17,4 @@ dependencies: description: Prometheus Federator icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg name: prometheus-federator -version: 0.2.2 +version: 0.3.0 diff --git a/packages/prometheus-federator/charts/values.yaml b/packages/prometheus-federator/charts/values.yaml index 8370727f..4f22c1dd 100755 --- a/packages/prometheus-federator/charts/values.yaml +++ b/packages/prometheus-federator/charts/values.yaml @@ -58,7 +58,7 @@ helmProjectOperator: image: repository: rancher/prometheus-federator - tag: v0.2.1 + tag: v0.3.0 pullPolicy: IfNotPresent # Additional arguments to be passed into the Prometheus Federator image diff --git a/packages/rancher-project-monitoring/package.yaml b/packages/rancher-project-monitoring/package.yaml index ba2179fe..75712fe0 100644 --- a/packages/rancher-project-monitoring/package.yaml +++ b/packages/rancher-project-monitoring/package.yaml @@ -2,7 +2,7 @@ workingDir: "" url: https://github.com/rancher/charts.git subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2 commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 -version: 0.2.2 +version: 0.3.0 ignoreDependencies: - hardenedKubelet - hardenedNodeExporter From e5400c85d3340039c710124e1bd9e4223e458121 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 19:55:20 -0700 Subject: [PATCH 07/21] make charts --- .../prometheus-federator-0.3.1.tgz | Bin 0 -> 20568 bytes .../rancher-project-monitoring-0.3.1.tgz | Bin 0 -> 124333 bytes charts/prometheus-federator/0.3.1/Chart.yaml | 20 + charts/prometheus-federator/0.3.1/README.md | 120 + .../prometheus-federator/0.3.1/app-README.md | 27 + .../charts/helmProjectOperator/Chart.yaml | 15 + .../charts/helmProjectOperator/README.md | 77 + .../charts/helmProjectOperator/app-readme.md | 20 + .../charts/helmProjectOperator/questions.yaml | 43 + .../helmProjectOperator/templates/NOTES.txt | 2 + .../templates/_helpers.tpl | 66 + .../templates/cleanup.yaml | 82 + .../templates/clusterrole.yaml | 57 + .../templates/configmap.yaml | 14 + .../templates/deployment.yaml | 124 + .../helmProjectOperator/templates/psp.yaml | 68 + .../helmProjectOperator/templates/rbac.yaml | 32 + .../system-namespaces-configmap.yaml | 62 + .../templates/validate-psp-install.yaml | 7 + .../charts/helmProjectOperator/values.yaml | 226 ++ .../prometheus-federator/0.3.1/questions.yaml | 43 + .../0.3.1/templates/NOTES.txt | 3 + .../0.3.1/templates/_helpers.tpl | 66 + charts/prometheus-federator/0.3.1/values.yaml | 94 + .../0.3.1/Chart.yaml | 33 + .../0.3.1/README.md | 29 + .../0.3.1/app-README.md | 10 + .../0.3.1/charts/grafana/.helmignore | 23 + .../0.3.1/charts/grafana/Chart.yaml | 29 + .../0.3.1/charts/grafana/README.md | 571 ++++ .../grafana/dashboards/custom-dashboard.json | 1 + .../0.3.1/charts/grafana/templates/NOTES.txt | 54 + .../charts/grafana/templates/_helpers.tpl | 214 ++ .../0.3.1/charts/grafana/templates/_pod.tpl | 885 ++++++ .../charts/grafana/templates/clusterrole.yaml | 25 + .../grafana/templates/clusterrolebinding.yaml | 24 + .../configmap-dashboard-provider.yaml | 29 + .../charts/grafana/templates/configmap.yaml | 117 + .../templates/dashboards-json-configmap.yaml | 35 + .../charts/grafana/templates/deployment.yaml | 50 + .../grafana/templates/headless-service.yaml | 22 + .../0.3.1/charts/grafana/templates/hpa.yaml | 21 + .../templates/image-renderer-deployment.yaml | 123 + .../image-renderer-network-policy.yaml | 73 + .../templates/image-renderer-service.yaml | 33 + .../charts/grafana/templates/ingress.yaml | 78 + .../grafana/templates/networkpolicy.yaml | 52 + .../grafana/templates/nginx-config.yaml | 93 + .../templates/poddisruptionbudget.yaml | 22 + .../grafana/templates/podsecuritypolicy.yaml | 45 + .../0.3.1/charts/grafana/templates/pvc.yaml | 35 + .../0.3.1/charts/grafana/templates/role.yaml | 32 + .../charts/grafana/templates/rolebinding.yaml | 25 + .../charts/grafana/templates/secret-env.yaml | 14 + .../charts/grafana/templates/secret.yaml | 26 + .../charts/grafana/templates/service.yaml | 55 + .../grafana/templates/serviceaccount.yaml | 14 + .../grafana/templates/servicemonitor.yaml | 58 + .../charts/grafana/templates/statefulset.yaml | 56 + .../templates/tests/test-configmap.yaml | 17 + .../tests/test-podsecuritypolicy.yaml | 29 + .../grafana/templates/tests/test-role.yaml | 14 + .../templates/tests/test-rolebinding.yaml | 17 + .../templates/tests/test-serviceaccount.yaml | 9 + .../charts/grafana/templates/tests/test.yaml | 51 + .../0.3.1/charts/grafana/values.yaml | 1062 +++++++ .../federate/federate-scrape-config.yaml | 13 + .../rancher/pods/rancher-pod-containers.json | 636 ++++ .../0.3.1/files/rancher/pods/rancher-pod.json | 636 ++++ .../workloads/rancher-workload-pods.json | 652 ++++ .../rancher/workloads/rancher-workload.json | 652 ++++ .../0.3.1/questions.yaml | 128 + .../0.3.1/templates/NOTES.txt | 4 + .../0.3.1/templates/_helpers.tpl | 233 ++ .../templates/alertmanager/alertmanager.yaml | 165 + .../templates/alertmanager/extrasecret.yaml | 20 + .../0.3.1/templates/alertmanager/ingress.yaml | 77 + .../alertmanager/podDisruptionBudget.yaml | 21 + .../templates/alertmanager/psp-role.yaml | 21 + .../alertmanager/psp-rolebinding.yaml | 18 + .../0.3.1/templates/alertmanager/psp.yaml | 45 + .../0.3.1/templates/alertmanager/secret.yaml | 33 + .../0.3.1/templates/alertmanager/service.yaml | 53 + .../alertmanager/serviceaccount.yaml | 20 + .../alertmanager/servicemonitor.yaml | 55 + .../0.3.1/templates/dashboard-roles.yaml | 161 + .../templates/dashboard-values-configmap.yaml | 57 + .../dashboards/rancher/pods-dashboards.yaml | 17 + .../rancher/workload-dashboards.yaml | 17 + .../grafana/configmap-dashboards.yaml | 24 + .../grafana/configmaps-datasources.yaml | 46 + .../alertmanager-overview.yaml | 616 ++++ .../dashboards-1.14/cluster-total.yaml | 1646 ++++++++++ .../dashboards-1.14/grafana-overview.yaml | 635 ++++ .../k8s-resources-namespace.yaml | 2770 +++++++++++++++++ .../dashboards-1.14/k8s-resources-node.yaml | 963 ++++++ .../dashboards-1.14/k8s-resources-pod.yaml | 2442 +++++++++++++++ .../k8s-resources-project.yaml | 2480 +++++++++++++++ .../k8s-resources-workload.yaml | 1997 ++++++++++++ .../k8s-resources-workloads-namespace.yaml | 2162 +++++++++++++ .../dashboards-1.14/namespace-by-pod.yaml | 1438 +++++++++ .../namespace-by-workload.yaml | 1710 ++++++++++ .../persistentvolumesusage.yaml | 561 ++++ .../grafana/dashboards-1.14/pod-total.yaml | 1202 +++++++ .../prometheus-remote-write.yaml | 1674 ++++++++++ .../grafana/dashboards-1.14/prometheus.yaml | 1235 ++++++++ .../dashboards-1.14/workload-total.yaml | 1412 +++++++++ .../0.3.1/templates/prometheus/_rules.tpl | 8 + .../templates/prometheus/clusterrole.yaml | 25 + .../prometheus/clusterrolebinding.yaml | 18 + .../templates/prometheus/extrasecret.yaml | 20 + .../0.3.1/templates/prometheus/federate.yaml | 10 + .../0.3.1/templates/prometheus/ingress.yaml | 77 + .../templates/prometheus/nginx-config.yaml | 68 + .../prometheus/podDisruptionBudget.yaml | 21 + .../templates/prometheus/prometheus.yaml | 319 ++ .../templates/prometheus/psp-clusterrole.yaml | 20 + .../prometheus/psp-clusterrolebinding.yaml | 18 + .../0.3.1/templates/prometheus/psp.yaml | 52 + .../rules-1.14/alertmanager.rules.yaml | 217 ++ .../prometheus/rules-1.14/general.rules.yaml | 98 + .../rules-1.14/kubernetes-apps.yaml | 375 +++ .../rules-1.14/kubernetes-storage.yaml | 160 + .../prometheus/rules-1.14/prometheus.yaml | 448 +++ .../0.3.1/templates/prometheus/service.yaml | 56 + .../templates/prometheus/serviceaccount.yaml | 20 + .../templates/prometheus/servicemonitor.yaml | 52 + .../rancher-monitoring/hardened.yaml | 131 + .../0.3.1/templates/validate-install-crd.yaml | 21 + .../0.3.1/templates/validate-psp-install.yaml | 7 + .../0.3.1/values.yaml | 1537 +++++++++ 131 files changed, 37998 insertions(+) create mode 100644 assets/prometheus-federator/prometheus-federator-0.3.1.tgz create mode 100644 assets/rancher-project-monitoring/rancher-project-monitoring-0.3.1.tgz create mode 100644 charts/prometheus-federator/0.3.1/Chart.yaml create mode 100644 charts/prometheus-federator/0.3.1/README.md create mode 100644 charts/prometheus-federator/0.3.1/app-README.md create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/README.md create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/app-readme.md create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/questions.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/NOTES.txt create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/_helpers.tpl create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/cleanup.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/clusterrole.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/configmap.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/psp.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/rbac.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/validate-psp-install.yaml create mode 100644 charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml create mode 100644 charts/prometheus-federator/0.3.1/questions.yaml create mode 100644 charts/prometheus-federator/0.3.1/templates/NOTES.txt create mode 100644 charts/prometheus-federator/0.3.1/templates/_helpers.tpl create mode 100644 charts/prometheus-federator/0.3.1/values.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/Chart.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/README.md create mode 100644 charts/rancher-project-monitoring/0.3.1/app-README.md create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/.helmignore create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/Chart.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/README.md create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/dashboards/custom-dashboard.json create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/NOTES.txt create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_helpers.tpl create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_pod.tpl create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap-dashboard-provider.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/dashboards-json-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/deployment.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/headless-service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/hpa.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-deployment.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-network-policy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/networkpolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/nginx-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/poddisruptionbudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/podsecuritypolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/pvc.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret-env.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/statefulset.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-podsecuritypolicy.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/charts/grafana/values.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/files/federate/federate-scrape-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod-containers.json create mode 100644 charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod.json create mode 100644 charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload-pods.json create mode 100644 charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload.json create mode 100644 charts/rancher-project-monitoring/0.3.1/questions.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/NOTES.txt create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/alertmanager.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/extrasecret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/podDisruptionBudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-role.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-rolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/secret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/alertmanager/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/dashboard-values-configmap.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/pods-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/workload-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/configmap-dashboards.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/configmaps-datasources.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/alertmanager-overview.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/cluster-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/grafana-overview.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-node.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-project.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-pod.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-workload.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/pod-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/workload-total.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/_rules.tpl create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/extrasecret.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/federate.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/ingress.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/nginx-config.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/podDisruptionBudget.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrole.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrolebinding.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/alertmanager.rules.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/general.rules.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-apps.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-storage.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/prometheus.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/service.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/serviceaccount.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/prometheus/servicemonitor.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/validate-install-crd.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/templates/validate-psp-install.yaml create mode 100644 charts/rancher-project-monitoring/0.3.1/values.yaml diff --git a/assets/prometheus-federator/prometheus-federator-0.3.1.tgz b/assets/prometheus-federator/prometheus-federator-0.3.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..f8cef683d78f9f5a34497a7949f1b86347eaec5f GIT binary patch literal 20568 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 z⋙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 z zdEwDnjB3SHXvAbJYot5;(PRZnf{R${S_YaXwNcHcqefXgQcjs?iw4z6Z(~D#WXWuA zMQ+xxez1@80Qz>+ zp|E7!dB*NAhfiHmF*I4PlGLLC8hmw>_cl&C9lFyEWY`7rl>? z{EfWaPob4QiA0s>7?H`9xzNw>t~P96$35kI;2o6wFbxHc{x7I3`h>_|ctm29bL$ORpks-R=6`>2o8+(H;p|Rg3DgVV?StNCwK>*|``!7fF4`jR zz$!J^&y7nwx-aB|s|o$-&xUnou-&tPg}NbF$vvl6w*ymFv_Uu|Qu<%$lZ-^_Ee(<8QVb%mQt zKi!`~SEru@hYzgQ5I{G{R9ZgGEsW>FMMP2Zcf>+Fk0h@_8Bx8`$q7a#euBfD5&MKh zYOQM>ufUOU*_9b~LXa6FH?qJ|l=P|2fvrx%T8eKt9mJn|QP#wq(PT+-CPmNZCkEC7 z_D==8&3|7{Zru%3252Pk@Df#5AIGx#b%Ye(xC^ ze@BR?lqEcYsSt&+Z$RQDrzi>nM(Q{T?9|&v+z8~Yv47X$I=l# zdeiYOZ%Ts^dhq4Kr$1c-Y39OPrEU%L%5mwI+2g(%8z$s=1_`6(L?=ajzlaV_-aZlYCFLh0UnNLIu z-};NMfi{5{T}UK;8)9C!G*+)|yqs!GZ(awsFO@>!t(!%>0tkoxiZKfT_L%>C`b zJqx^j0%lx&z5%MdO8Y<7c&~?i!246Y+jkfIx8L7>fUCmRAmqz{V{Om|zL&k1K}Rjd ziY?@;JO>LW1$7hsMNz zt@$6LzH(sw!V{f5fqq%T><_#gw1EvOY1$O zb^a9C8G)LotANebB@GVJcioG#?+DfJ5N~+)aOyV#C@~oX$z4shV=7h z_5o<~7zPn=0XnANq%4F;Cc-OtMKlb%P1re%(9xNudoYLC`0})&tmsltcgFa zMujUql}F}xfu6G*9HIb*!f6WNjS7NA>_9uBcJ2I!$ch)|d+*ikdMG%)ebPA$6@dy1 z5c09_;s`G;6(iumHNh9!s4G^CdGmhtmF3JT+MCXSSAaSl} z!;UfUI^;4TgDidMWGMYct8=%Oazcl?IyJFyUw-cp=Flpo&%~N3q3i|MmY~Yv;5F0l zo4S~)!@qnv#aeiue(ylby138;R@ZaOX?t=3i%2PKZ(4%_8j~W{;|ZFdo=4_%*FM*=(BU8;-}i>!>E-0*dCMStA!S1JTj=-) zFNt}H;F#iN#;${FuFfaw=NXX!{%&o1wD5G#S7u>$fxs?f>!m|gH8xq2PQ7t5c<3=n z7OFb{NYx`+8IWKa1m)NOyj<$r-Ds=8_avst&=-b)W)R9erp#lsU+Mq3!b3Q5l$2etrFG zrTuyB?O9rkdf2zDdwZAS@X=6IG9sHx z^RR{@$|%!Eit~t*ZtW*S^w5N24ZS1Y58ft-lInq^UdJJ&?p-Jgwguex2`QEd&G8&wORR~x_;9zUuPx{ zc3n4O!x(~%b1%hUf8+v#y2&JlMi~tzG6Itt5tIjt?;q-$G-!XGm(b%-Gk>j`%_wXo` zi@PbyruKUZ>AfzKf#RaCaG)t#xI30mDC4Z4-8AeQDWVyP)yY2^F-vc-S90{Ft~WHp z$uA!y9@C5xL|FPBIiQiF1F#f2>89e)wV2-!MDIHbn0|hrJ&eb@ID|gz~ z#{K+Ax(yB#=IQl}dvX+O0g^F&0JR#wtM8SO|IePqu|OwIHN2f>q*e zBm`tQz5cPO^xe4|D8P4e;V?Po!SM5^!P<#%Gv>R5_X2htD@MWdYy{)oC&74SFF|OY zKr*)=b#7|oD1b-DfNQ%5j2S`xX;`~NOx>05thFH_v+&9~e(JY_F0wL&DcsdOyvv8* z`AYJwMQED+#I{SYPam~cbIDBEvwiz~jxMklFG^furfJlf?x)gbF4`mFbCR^MUByc`o(OA+IZ^9q_>z<3Fh_;mSf{zcS^K+I#>xs zqAoRD>y8OLDZETTf*4T7?6D(kC?)iML0 z6(Xh4b1*BI*v7&Rf3`(}z1O{Vk(8-b`UtysrUPBio*G3%^hSeBuIc98jyr%@t=2tD zSa@10r&tmpo&jK*KtwBR57__0!||O(bB{m`t-^bg2(Hq6SlhmSc3qfE{@|k3vnt?# zrlC_S_X0${V5$jNq;NAWazI*`%Ra0d#>u3P7-t-Y4$5YhsW_nb8JG&bEYs7h9j}?H zkuNgBL>X>fAV5Us&~Kz3!^SPD${j82LLI;7x3>pSehN6#PA_@#iWw98()Zdj;ia=84=c5dL%9H6gkvO-I+{i`t?p9xj zj6{fE_vPa1!fTFh%j=en%fT5@g8wD}(;J7bx6Q%^ z-6`A}m89poTlYPgDyIzT+m{Lh_U3_Rna@u6D4mt{^r82ItTwPyY-Xz@vcy`vjbWZ@C z(X&f$fXmHgN}vl=fA&O>+aVf;$J0h2P00!rVBUOTf7co8)Ae?sC(Y2w7(jm^3z?k- zssh_*)>OK=wdPZp`FK_gBozWAI8q5Cl!70(#Sw|do)ZPE2~55nJ_fW;A+iH{G)Ctj zJ{*|F*@&ixGAMJYg(A|H>PQMwXa|R6V)`8;k^;{H@9H02&q!Urs_;)PwQmM1zenUM zQTj|=vzXTrSu@vGU|D~1FAypUp$WQv0_1Szhh#<0zdB8u%@FR%Fl?X;doztQ=D8&)KeqJVReBqSO(TVE_+ z&fi}xAvyUsb2Znd?36l5^cifiNCCZ>HzG z!u2K9>E3SyjlMPL8p9NfC`>8}R>3B^k7UJQcjUX!%ALk4}EhV|Fgh8hq?TL-hqcY1FNXKK9zX0D$r{nyvu zx|H8metvePF@TQf*`(K6Z(BRw>&Z&RQBR%;^;#SSjX1UMQ@gI(`UdMPmG6#pmx0gU z4P8O)nlHo^Y&Qnl>3rKjT)(FO#0oKm;mde2D?T(%sQ8p9(Lj2>NIgmxLQ`H zW|@^8_NkXC*d?%Fvf;L7a~yy(y$Kt#;GZn|fg2tHxZz<0y_!##|;^ z9ph;Uq6wsTiv72p-JhH=Tm{#gwfJ6Yc}HchuJO@?%OA@Il7SGbW+bCcevr*0?)t_| zch|Rw6ZoeNcuZ89W{lD?HdO2p>|VhpGENuyNFxM}V9q@X9?C18QD~Sk-p*Yh9Ixwm-InUC}O1G^GfenS&&)%#;&7s6JnUg?~bsT102DiX;fJ^Add#z4_NB(aUR`LaC!pte>4NF^rsi1V6~ z_8zHAebwa5X13J8qGabxuTPk3%R_hnjZ~(QT=+x5b3Pa`FB{V{S;FPt`Arcqp{E6_|2ZXVTRE%k`8qJt>-#f2EH< zddai#3;dY=xl}vG=;MhKzRKrBQwB`~$Oxvz3^W=DPm|&59VrxJs&HXXS|N9>;9^0q z!lgzc(!riH6?o_eRvqAmkLQvUUA(Vw2s2eP*m9b!4WV>X(gyy)4z&xJ1RnNv6PJkY ze|9Ju@3}nB{24??{h~@h)ZZCRf7S$LdLI_-;tXzDEI4jF6u4YjnFVtay}R*jmgh43 zQIvgLsbuZ5gpCz&d$qqL5^Gda$_FE$e(T*|PAluxUWlMG@F_*-LazzJ1LqAR z^&8B#%nwQks<&}-Vu`#SCEf1bPkS*%Zyi-(k0hLaMZK^q0IP<(joGQe+cOaH3?$_V z>tfGM3x+cbYDxMvIAbBoAYNEZz_G$3kKmVGa- zX;Qc+nD;2`o%yg$ad&%!*B!y)Vq0U+_xnSJvxOoJ@;u}ZIzhGq0hOrDQZ?!-d$5%@ zOjtL$qPoJ?MXCz;b6FX5Ta+~DJ-&tNs1c_?I?o^(v z67*sYorna~A))VHp2M+%J!*31Jt|&-)^idUpAb#r$2=-Dz2_PN%B22r%BjR6c+M%y z>`o%RGDfr$vDNQtnVrz_?C9b2d}baT?}B#RqDfOOEVNJ zme#Z`y~;S3E@8Kcpj?gTgX9Cc5kUy*;)C5ngU}GZMO~NiWj>3M1o>bp#t@8!*Kl48 zrprEyic?J{F|cqowX)^BB^KG;@oytDYcNu@D%A|&AQ>up_{Nt6EB}Hi9mQXcd;}Vw z&v-{vMxWXX7u~~JO?W1NWreJ`)u9oGYKFsOW}&X%E>EIMiZn%3@x{W6ony^q-pa85 zLb*tSGj1+ieSEvS9&j7s7LEB_-!yh%8X)QlwP0KmozBIza!iet2-*M=`?;m~A7G}W zhYG~kgmp7EoAs$Ic@2mbQct$DP7Q^F;!QI>#EV<34ZX{wvl{r{n1oV6PCXfWJ|)wY z(=4Dr=`9+8wS!c9jS)Ma=kPsu4gY@EksAQ`MNqfOC>kEfzf5?-gfraMojyAkWJ!W8 z7|?R-xErY_i5x|`03R2i1*z^n75bbJiJ~h``W{a?O~#aX8zdQUmK`+=KrQ5OKu(M3 z*F~;-j30M!w=*mmvsc2?>J-=@#(Y z4Uo;Mt+$6~Y$b{bl6ns;n$6>q+#PKW`_a>zXWQdLn=+(ET2_I771EGzsl`4EJcXT* zJL+l6i3UdUv5mLU>iN(;tdR@4N*Pu7{&8L-WUD@mFR)!=%*t(=&MFu1LfKP6#X0+O zHhW3YMZ4kXdMyWRIYhJE+Yxl2X@-r6HSPbJS5&UV_V5r-7#+eQM0XVz7KSkTw=?eYD((U!my@r) z;3w<5ukA0AnJ;djc82AH7vq)iEo&R8^_#$jy(2YbP1FFYC zUfwB8#U8@R`1rjmU%mGjwsi*6I`1U90eoR}Q#!xt3HVZ9(JbxvV8dtssPHt7>Rvnt zW@F#`2Zo!Zdon(eR@nqO%cN$Wb#m5W)@yye5xTK-K!X#`zq+KPI}j<71(FB~C_93X zINZZD@SuUey5pcYk1YXj5nfY)D!8>$l0&aNqc9>LXjHtySh|=3 z8Es*Mg>H2%4^u&%8-V1U)=2I7KhrQ}2`%UbLKBdeqh^A>W=C=QsZVHxo_zf$28O3Yk@%GTTIT`#O0lbH@I zkIi&ED*4OORM0N(Hh)vxD-1amq_PPN_pyYmlM9k^UaR{Rc{~=peC<9Kl zW!j_PL)L%EPnt8(OxD1^#M`5H%Rjxyep zcfn?Wzn{OjQm#QtR(49VtY^zOCR3p6LVB*%u6h6$<7KZWLG^4IPNE=yI5rUI+1|AL zAc%5lS>@6#eC&8accrl-N}lXbt_SYK(McQz3h{cLXch_V5 ziCM{!VEawe;R(@;!Q;W_ePK&3u-0s?LsyZi1FX8si>z}@2vx6-713} z{%$0UPt1F@W6eHq0pC1$I`Iz$anaN5#kcuqt^$n}NZxow!&FJlDhp}Z<5*d!k+rWB z00D}Ha~J;WpfXNN!(zZ%qD?*o#=io4x;KY}#QZ`N-$5GZ*X8P1Z!O-27+wM~o$|tx z$#cKTfy2=!FV6*adSS#+rLA`4gL77DR-%~6dua_bpBv4}q_~rtGalO`FD()-Y|&yz04*&u4f5UI|ZfhrP3t6yP3 zz$VJkxQiiSYWaBu(IA#jR96MZXi|doM|L|IzDu2|wbx%K8Si}XeNYU!nD!yxy^X!C zdh>u>+)JLyC&0$5_jGMcmI0`AX@^iJ;-y17^f6X=mKM4$?!WJNW7b(lgdCGZ|3N{4F*fvkR{g;joLGXjOv<}+ z7TGnB$hErn)3PT01gu@_zI~sVK|p-40(zro8$Np{mg-kc+Q~ygbAta^P?}!WM9^aW zVpQ!v_33Z!MQ#s?BS7k(&%2(zGJ2?l3oSWWaP)%eiLELZmdxP&mLoG*hBF~(jbta* zJ195?5f2W5DxF%JZ>;+FW_?z9=FcQD#2KS4^5P{MYtZgFo|A(Oi}_a^zWa@}cA-K3 zsRO7?d_5{O+u{ZFKU{-}Lmj=1w?8mk$yan$3(LfamL~^APYH|KORx?L z6K1(Lw{s!Oh!#4B%8?|z=I%<1oJ?|#pA8PGKh_9jDzG8HxTu|xQGpKvznnx6+evQG zSPFB4Yt>o1$#8-SwGD_G?dV$Fj=nd9r0t!iP^kCObG1#%vwNojSLOgakV)s{>*^nO zpJ*J(0C0qW*z@sgztb-d4Y}fEAw)o8~a>1x9rI3pPEAFUgP}`Mz>J{A;ic@v} zDc2;ZhT%aMq(?bw1>ui-plgk~r)dd|u|pD1%ulBH?l_X=FoMANXxIdZ(e;iligqz6 zZ9s7-r7;mTl)tbUd1;-_!g2)7QgC;V*b1zjnF~N>K7umzN2_L-aHd2K@nDlIqZo@9 zBOj2xGrvE>Nl%}1B9iPWO64;KX89<=P;qDZ?@>e(*%i8KE|E|lw<6whjAV>|%{PH( zYL!6^F6%}9A%2g*&HP@MeB7z+Wpk)-uYy74+1Ka&T))hy+q9e3CLA&>OCC0j5`ckk zo!;4O$c>>Wv_m%~@;a@3uGAXCn4WQMMsU@{UYp=b7Y${Ga@aF9WRhL^Do5 zJ;;kzV%-n?wspM9>ITa7B-^n@>|=~o#du9(o{)tJ?5~i=J&2L7Ww2Se0&3@fyIkAVw$^Ze@kav{w0_g<;P0=qk&NK z7tw52aL>dt_PAH;_VAc})Z*C`F<%plCOn*Zlg*{LoO2!$8jX&=^`=R4T(=@R<%}MS z3s#k7N5pa{=S6nuAJ(|r>nv0oh7h~aJwXtjfIl*ms3O;PI;YbF#7VkT?RXzvra3jk z+kU@jrcx&bF@;&f-u%4Feb~W;S>tkS7Vrt-H0v{Ewu~lQm!aTeH|ru0A0J*HaKXRk z?L*O6$sytS>dmVlo>N4JDEv7kXFQTjwSZ}x=nN)Zx~r_Ti<45y)6&QDtvUKTuDWD& zs#N`~_9*r--fxCLnmlb=_*uY>xw>^DlHkDOWu^Obgx>=4ix(XBi`M=qLG<)8>eIoTtfR+|6;*Q?+wy5KGzuK%^Rs2*xHKf1EnH;$K&JO|4{m;+A zpF6cLezr$WDEEFym5$YMXZlzNc7R|~OZ4iQnc(iV%_&VBeXRUrixm15o8rPa6sJ}m zl4}KGCW{uqd&CoyiMCpqHvbse7;AKfQ4!oI888G$DAq|^bj*{#H*P!t=2O7y^xg%6 z-MT}YHNM&$puh1;@$+P+|JfE7;6a_s%Hjjgf>ruP)M~9q^jBK~^ENp6bQ6(sAM|lD zRRZmB(hmDN1?K}d739?vOQf|-V zOkg);yU=H?IPbxkugkM3P(>e0Kp(iBUu-U@+*vn9%ZBeA_9mG=tXBeIE}!U41>5JA zLYst9A1)6~W&9<-5;d}c!-WDl?R4}nbNNv7jK(;d z38$VwH6UbEQ;-bN2q&I_lq7xQ3$JiVPnE}ciqIL#;HIP__@ad})8A4k3M&bytXum} zn|QUAUzVj?=IRfGGYqL{Oi4nX9$EX4qjUkN+v+)M9GN0i;DN+XsUemXj5|h2bg7M* zNMSQjA`X`n@@y!rA;w33?X`p$xe-z~QP?O1T)8%2KPyyto-lJLO>|k_vSJ7}fU+E_ zbmEX%g~h?j16Z`HvzbJ8hed`*-b3W~r*1~s}>dRq>nIu%H{_R(S? z8`KXpFt73Kde`Z*-I46^XV7~e()qwIJ2In3~8 zb(%a|h8>ME0kUru?M5p9CrV;*gCLU@)v0__=Z>3kv`4?jK0%lu3sQyHYi%@Ks*{bh zBTpd-<9^PHn}|tf*Sq~V!&Z}3fD~(3(PF>;172%Jt+p2#t%=>B93t(EG)KQJLL4PS zIKp-Z2AZBjoinJ3~(6d`Mw7P>P{G^6)uAjwONftv# z_Ey~oqQAp!-Igr1>!;Ht8BHW_8NlyPZ=Hx{DBBt2(VXv)NmS``r}M1ySwHNk>AO5u zO4g&jO;-UN5}MR^z}ha~fL;AgYrqX3U)j}9EL@du)Cj@^bw}8G!&3RDNx2qHovFM- zc@ZSB@63`-9)ZaFxB-=YicKf&XeDAqvsII`7ua?024=>X6Z57~we3e2&=Qa{e8AFq zj_Q$_GJsod&qox~X;Tm#=usvU-6khUJMK6v@AkZI8by1Jk40#{cYCQ{D#=96=yM`b zLeK(2+bNzF285N~Lv_)8FsQTH&_p#4uG$aDKUEjkKX2}R80q}ar@2o}2EhCZ@D~+! z&3a4pvA~q6HhGLg%L1(Ves^^N9xnAeX8?}Wx#;g0H!sp%3mut;;nd7(zA8C-u1Aui z$zoX!{~G(<>iW0s$(2oJar|{|4t-eST8iwgg?g6vI9};{t55cfFZ3R!+5i?aE|%Lp zV>D?m%2ZC5{W+P!)74~_-~WO)J3Mdc0ib)I9X&*}FxU9+3c`!{W?l`X5ggIgzqoe{e2{6kb;-Gy762*7 zA799H3Bc@6=SSz!gWqh<&C;VEc5W?PaK^Skt0{&LYuE}=H-G0ThMO%>)VcMu5>~le z)tbm3t+xe4YU^P0#;A;H)e`(BO_|!XwGSJt?_D1Je|7tma2#I4#B|P?hO4948(QXW zW@a!~*Ee?g*)qKr;agV)CAm1?ewg5@??;Oq0gmbW^G!EXnDIMUkUk5;nIuIOU^Y%; z;hq?5o#Dj_#yOB#e`Ws<0GU8$zd4T-O`2V_4G*aS!P5xn^NHKW9D-}JE7_MZRcdAOeq%8k6) z$50m{ld^{z3Gd-{OAXz2;W?=)?$7d{y`Nc;0VPpr!}SV~TK{MfeuSDqDix2LHe|L0 zH9}2o;tLuQgQbaK4QLcOyk`%76gZ@Wsltn)py3fO;ZKkIx!2o8vx{DMzc2kJ5NeL~ z?+GAAGzH`Pjh6njVNr(stQ+P-wFqTB=kTM(o zp=&;G@3i;5s=8G@#i=Zy)}(uxXijLoToB+QgNUoVAqg|~sj$NGmmsJshyz6WL@!d2 zBq8B@$|eV71+vFbQIQD9Wdh*IG~R$a1v0Ac1xeZq2C}C{f-4n~uqR2tS?F##$V&d{ z<*&`7Pp^OVZxr~?ugyF{{@3PK!b5nL@bK5>7An;JwfXIrKlggN`%LlsZF5tbvNsLWDDbUPqk;^8$2Jd}RUBav#MyJEE5q0|5QaV- zqYSzW%0hkt_uhC=rVA-KjkRB+oggKP)|`MQlBYDZL9IuREKk z8rC@{^VJF_lZb~kmm1;+M4X=`5p&MwYi~B~w_F;kksxx!qp&0;6^+ST0ScVciL>X& zWN595QiYQd9jM6~3Y6{UtE128v!aoWJk72b z%+M%863`e&lYnUzIa?h;l9rYa?vtphPQ-^lU`dK*U#5yq6gRr)#A9!mS8|RVN;%SV zdFOCW(8PFhIpBy6tF&-<{+^s?Ko^Woi-OwRyAS5xixrrA&uVk8HuvT;_i|k$CNUS| zo;|SKlSK9UV@2djO+2mdOsYAyYoqA|JdWv2^t~#bW^wEBF4dV2fZJN5L95efcBZH^ zuw?IEQK%J~TA|6_-@QV!bFc!9=6S8r)Edov8VxP^d2AAvo*)6C=cJcl5HQx=Gp9DO zh%bjuapv3_AlFrFjtyXF5g*)wPV#A!qXcGBt9^GqJ2wx>wOykYvW4bnL5KIe#1jgx zsrCL4(TxGLEHS+{fZdEs`>N?GTu6S8kn+ad*S@%8coi(>z9A)}>xHoL=7t#Wom2Mh zLA3OQEk@gK?}(?%fw1>ot|Nf>kS6 zk6*!R*k&~eYU=V^Xu>_>I2S;>2j;OFNA~osI0Ni76&`vAU~SrQ%7*itMb71WVHOm* zggNjoPAFgs)@P|erRHRhCHutaCb9V%D~wKxx|??lxk9tks#xOAS^v_=p8n<)_;*Ug z7<|`NuzRT9DLfsL%Mvs7&N*j*l!>vh2BLphtdvN+0tYtV!C_RT{#38>W}HTfRup&m z$}jS-!Ui^UwC{ugz~;dA`QYYW(e9g}(|$tnkpJ zTKK;Xu4eJ=loxg;%xJt9sU)Xn^;fEj_i1_(9a{0meAk~RBT(>4nNbXe5u*o&)GtAXWRR+=l|G=^Y8oK z_Z|Po-nRe7QyX@@?>jb4LUE+Ob5PZrmXkXb$R!o)pd%iljaON&5Hr2a6b!m%bv}{S zjwy7W$&MF|yU&#WI6v3U|8iB*7w>aL{+I3TgNggU_V()hFSqik^S?aw{4ce`vQGI@ zJ1ifW!}6|EzN{q2%j3%Fa(|P!ESI(AQDtelmuXp+%ER)Q@~+(1L@Uc=R;e?oJgF^- zI+M!1-<8;^4X67Q=}{+7sST$(dCE$Xr`&`hS?5T3w7N>2Bc)bVYE{MluG6B_y2@Sa zDz}&x<<9b;tmMGc!%K8>cbQFAbByW1rY^bjTqP??PV&H#k*p^B$V1CEvZC}N4>z62 z-RBQkRl<-uK}c;2*9k&uOSra#>zp8{HiYk&A-uAT4|kLVtm($vC>)>G%sphuuj!c>w*tm7rgaU9ZTirc$m33mPx*G&lRIO*+#7uJqfL-PPS1e z+qjct8((`pUAouPLMInm?eG4WH1gZu6*4?nkyPj6xQkpIOUzp-GY2H*$mX(6((xFR zbWF|5Q77Yg%%8dQe_U{J7IEw)0dY_CDv`6&fn1UQ--ErA>iZ`84sixwQ88uTbgv@{ z1i^}gz5cj&Mp>wB1pRO6m9C;+Iql%r=C_q36G0o6(XAjI@-$3W<`uanikHb3@~CIk zWF5J3Iv0pMpEjLUsXlINHlF}_X4jw0oW}(M*r(6qM5dD4n#L>x$)ldh&yt8MC$i3H zlK1qO_I>J%Cii~pXR9^^?|~^;CpM`~!P_(i=g4d_T`O5MPs#L_9-1<+PoKFYSr4%_=qI!X3 zIg1IYTV-N5)B6LP@p;);otx)rxozs)JhjuNcG{piMNjRsxraWRxy~xD*3?@;mk&cV zx?_LMEl%w!`+OL4yM(XiJ}ABQQTzI+eXa1C7q!A$=OL;U-p8WwE|-YtF{mbx;pnCh z+ANmr=rN%6nBc3OoA*V}tMe(IH2yOiG|9)-$_TA>M&CdNu z0(2i2j-JA6ubGKFO{KN*IM&pp!d9=WIaZd_TyJc3&Cr}5-NLixz`a{|@Nb>hY)W3U zpDhWXjUygPGyCNnXN5FYPcGZp3i5x=O8o_&tMY&C?LI5z|Jr}Hw^!%?x{Xhr|Etdb zRc}I=-*x`4dK1FEyraty9&HY=YhOW7NCLL}j>Ie^*Xh4*V?s^-ujNlB&6>$N^ViMJ z;jA0e7QC^#PWp9MllWN@F~>P3`>oFP^$7MP>s(*=ep_;@Hv8^@*;nWKs?EOJHv67< zzONfmM(bo>k5-qdlYP~yOs&e)$-Zh`<{s)Yb;7SZR*DKINLT1KuXBCf`P3E-wKS4V-l;hp;wxj7PYB7S>|Rr_yg*K`#RXEG*X!0Ndp6&y z(|J8D$4s5ht9HxOZW&ak^Qyfv_tYy>r}TP^9+^6u*S+$_+y_;+&hJp?cc|4|^P*OB z>m**an){g4+{cs1>)KigWb(SX(=rb?hu0G7JD%pqyf4~aow}=5?Vf~cSEuf(Q+L&= zyXw?kb?UDBzNYHbU3KcNyIy#8>aK^Jy2})pmb2@rrR!SxXGZ?7f2Tx(&e$H~I9j5Q z+4;Y=4-R(riuu2Go z^adW7%v!ck10n0A&g?+V54)((c|$NM3-e*NKIBdhctU>!) z27-c#s#i#a%r3|WoJe#*)d;B(m8L(01wjcGl7tA$$xdZ8B1)sJ8f&7Zh*X3H#9M^r z#U;qUQz}T9Euhk@9Jy8$`Uj8FnAr6jUa<}*7j0=_R!@)*w4}c~?P6m5-W2ToNbMsF z`iZM|We182JS49oEM=)9coBFnT-)Xif;#9Uj_2zM2LX}t0}n~DBf`?SJf2L`YN2C- zL-2inVu3@2^?Y=_V!ss1{Z{$r17_oiH=kHE_FvdR9s;yTgIicxxhtiee?3V^(3XL~ z33+D~w8q4QOPdgy_}L zXCJQT``gP+*92T93Bh$h``~K&(0!mQ0WYF4T@-1rjy|LJx?XW%ZLbJp7NkY-WpfKm z0JgWiy&SSEQ@@5R%)44v9C|=sB@wS22z);WAYMh7#;3;PPugRm*G22!zeGFjorCsvYa9I)?X-8F>#ysTRk`eNEWZL%Dam%E2t*$6YM6e_+-9Xky%P#o_PUt_}u+DcI zI7zafe`)Wu_ZtPX^>jo~L~uyi5Gl?hG~fb(Ggv>tEJWv2rZ}R%LkSuaWMZh`U2Hf? zyD{P#l#x=2>~(x+ zL*rp5;zMqNwG%7|Q@v-~+n4Qx4I6qcvqAp9o%Rboca0cR>!Alf5s5L4y6AVzMv{`z ze-HI<-E{*YgGu))FD#-oIHTmh11bYvC@YkCm6we%7wv(dB#bfpZ$ZKlR)s3Mz(9Bv zsNgcf=j{;=e;-kDUIEfS6&;QR_j{qye=9Dua&mzqMMOI!S@FV)hI!`Jg;f+ZDzbTk znW#d4!*G6_BoPe^r_X5RpuP8^eQ=i!>-qV=39Y$~0GP@DcebDHJliev|AXy=n*ZO% zXBhE5jx6g}5ixpKA`_>8SzXBAyD|*bdi{>ckV+-SUDP!DJa#30bSzmyFjhnKaRA-G z#$2Wrt*xQYk|4|wxujBQ&S=%CV;+%?{)09`k`M-bl{2IpYG({TG;novbDO$7luGi( zHl=HKfu37@(2_hRt&PC6zA1R5`%h%zT^C^ksn^z!)_3V(j1nFqPez)T$7GQ6Va+iG zBZ^2ZP(mKaPQY0}5+yqck7zLNBs^?M5~PBvamzki!%2cg48GV^H7Q9D@Hkmzi(?t6 z2pRirt2)B#P<0#@6Bs>y)KqCSRp^Mf-9-I-;v3l{ANSPLa?)Uoq&D$DY z^IcSK-ZbY>oVV8}YCdQy!JDhSYVao7vx3Gf;+(q3r4m@L+v7B{q@#OoA)L@3waJh_ z)8@C6MESFGBKqz(H0F`h@@+~Y&S^jn1K8THpl1-2_TN(?Rkxvu$<#vFRPza{jb34f z`UKhVI})}VYX}w8(ly{iXR?iB{5xm(LV}#t6x_msb&>vqFJzbExZB;?-Fvow@chMJ zwzs#tx=e@SxCMoQ6O4$^fZ|l~4=@M=dP5Kp(6Wnm8XD+VFffGCh~O~N2BRH3=yhsD zP)L%9k7L4A!OM}anHAau^R2u|mGj9=&oF)_`Y4*ef;~$WxC z81lJyt{#CE8IBhlL&nqd+q$%2Ab1oJAv<{|oi*1%BY${eA9XW##W9cc+WVY@SOJM> z>xM{qBzPalT*LAsQC4ffYScv?oY2mQ;7EIa#7ULX=TOarBx*czj~g z^~2ggU{CQ>We@lC!vUsID#)pe!3TP1s9ma?060^EVo4o?IDGS=wieralR@$RbXRBr{2i6+ttwvG&9@^Ghoiu+he_|tTA(mda3KWpza zU9F>OGlGy)T3&Ic$fcz@k+MVik+WmYl^4Mek3UNy%>G8BQBk?Fs#o#Z^IiAgN8{`? zPX_+aMm7T{lRbR>)@ZCb=PS%Ucuq#dS>njdW{i`DSsbt2Zzt8)&>O7;g@NDp`%b7mh{tU`c@F}pOUJ(Q9T8N%pDP!5a1ZFT4d z^duoVK$57&8cNDVx{XH2FPIj4c`(SkxmahAiU`O@!dFLJ&)YBd+uL(;yve=|ZJ%4C zlCbl)g2#pv*w#E{8_JZa%;DvThsZNi_2_w6wp(36gHuz+$8W;JBQDg(f-6f`dY$W? zxX=l%=;6&}qD6*JgibG3T=Pe>7o-hy!DGZzC245NTd{~X-g6xOfFsNTB3$iF5Vc&` z`iLsizy(z!%kZ=M)}(oNlvhS4L_whpm~leDv8o?x9YTYrUlK%BQLI;si&PTP8m2TP z9owc6+4e_)aToS@GUyskd3gZ}3h1^+zBZ!?%zylB=fw^>1uUi-gAn)@1 zha?jKJ(Y@bJpxl(l86Kvj5d06*+or_{-&PwrV0{G5nfk7BM#jkj9;>A#{F(!4*ntR zP+;GqSI4il8sk(2tvq9IcN2LLaBFK--rIl+!eu9~(kfJ`64zF5wKkSvo8FE@?ovf) z!=2>USV}D&Wo1p2n^C{0v^D|J*xoG9m<#Q;(KT@B&2Ag$wH8SuuN+^2sG(D%BD+W- zL7+v-hSo)ALLl8h!@)ZA(Bw)fi4npSk_l7L*NlxelB8IPeqJ=3L>;*2Ck7u|-eXO~=lPYcJsnbf9 zzohMezq5YoUo8aT;%bsqT6Lm9rtr zA2>fxC3KdDc)wlo5~vNs(sGYvOKVEjpz0Rqv85uXx#qLI=E6d%ro2(q!qyNnfmqg8 z6(lJbL9zL1JXT$_v-{!$)sI}X&^*Pp+VPQx#A(GE_prkNdM|hq=P+bF&4lrgv@)UE zX{fBCMQiti0cBK;D?mUS zHvZHEbvqujxddpYaj^0=PC9GYb`RiUrfADO(Ez*e9?lXT@!=SqB-*G#uQ-!R=<&*H zy5h9-f^8OMn{G*HTFVR9v_+nIZ+iAR&QTeL)L4e#5<{64Emwlc63n`b+*M*=1djEN zQI)BrIds-y$1K}M%PMQ}Uesh|&O2j*8R+StNg^DECUOGdRE-Ez)+uWhVqMNR;2WiO zL4RB;_tr&!GzymQrEx!7pUb~fJl6Oa;<(SFzx<`+l%5t8?P^>~1vRi3W)AfhSi>O^ zFO4ec9tRO6OtonEvh>98uk5L*)#76K@~@wcf9!oc{P5;`_Y&e2S|N`yWiP+W8shwn zl5#_Oc3U_Mwa9&GjhpQ@{MXgyg)5gPQVD|NRw^P_ZfEy7l-%iped3fn$JvTVYh93j z=C{wLH@9P8A()6yZA4(@^arqPD4STfQ09V05n|l<{dme0Xutl>2&jO?IkmmO@>|Qn zG|`GJZADrv8Fm0yZqst>XotjjR(vS$gEC(Ua5qYY7x9;jJMndHa}t~TH@;P9y#TB)=VB8%Zl=+BA+PX5 zMzpUxZS_+*?sH=%88`n8vn=X1+>6BUf^wfX7J+n#u zA&Fl65x>}MWXC<-nawp+IE)FW05}^a?&xJ>GK$GI>tY3}(eO_8#;95uCm8^T~hZ!c$EqSp`$G@y}|(srC((E6Hk)HGi@wvl_i9c(@B zN?=6TIThR(OYX>muQc@uOg!SOLSNENuNhYcsHxe!8h&Ry?uw&VdR~6UDi~=Qa`^KJ zdh_=a2;tdjTc4`N6U8wSJTeP+oDkIfne-6_YE$E;Y1L`Oh|@4=lQY@=4s9^5h-1R$ zttJq?$_32wZX1!18c%-nRHRaYn-a8(5lv*%(TeVVOIrvCqew4j%Cdci6F8#t=HIEN z{2;=qbV`_(#%pUx0@2YhK;%s3pkNT_M9aqk7X)oUIc%gxM%cPHfE7oQZ)tuW;ea5m zv7a0rzIp>ZwZeVeD&XATs&HXZxgS_Jp?}$lL(L3_scaD}Rcogd3`N7vKd<<7W!i`Q za1g%PwY}TUyBYl58L&6EEJS;4gq6YpY)^praa#grV#YiLeP5#Gxzv_YuT+)51VNl4H7hr5M&dcC>%u|8zh0GD1#(h2CEHuj) zvenp;={^AGdinQ`KfQm`J3Rh)ofxyMk)PlE(0lj#&BxPsr~lJC{q*-YAA4`#y?@h1 zopUTSAL>}n*O?4*E6!3!@iW3a@ZS9R?$gIE%2tIP#C{v4Ofx=WR8UREnjwSr>@092 zO5Bz(h(2BSpj_8;TzXA-3)n>iBHZWaFzy(iX{}Jeo}inrg)!*O9!wJ!tkG~As=6DK zP7ktZR`N&9s)^9bdWlowFsw8z+eRK!SqMkGn&oHxbcTePBVt~$7EWmAe5bwhm(Cht z=jT`$1*vtu(+X^4*D>VT1syrpA+^?xu(azjUzrHC+imyN8K{3fBjfMgLxeKabn|Bj z{naS>Hmfgqi2mpB!~5?wTK|#N$n>^1AO8Wah+GMC@dtk=W34OZzEv9q;ldGM7W21f zS{E_dM9;|B_}A>t7Z?goU2+RcKhF{9amI@g4Mq+{rbX#Cp53GZyUv$G!`T4217eVx z(>XZRtXR{O+(JYJZL`-=S^$$f_a=;wNvapw9Fp0`HzOBrv?lg*0r)g1W~De_oU_tx zBWi3q&FiL+`9|}7!ju@hO)%F4HZyug##_K$^@#Xn5ZJ{?%NOA(y;-oA)90Ka=4$IU zVaZnzXkmV=8z^`2S)Yy-r`ZWp9AzOwCG-WH(SZpSdJq`QXl^Mau8hm=?se8OkO(_3 z@j5$Md48Aje3e*8^^~D^U^4i7vu-<0(^w@*wi~ndT8j>F*I3KmYy#(@IAhvO@xp_R z2Z06z7`yATm37%L9s?Vr@Sd_W>8(1?iSLKfKunAw3XshWXR=A~h}#)A;art>^unjL|>9K%bbDip3;b+MXsY%Ct3Qdi1gGVcdCxCh-|anvFgb^qh!N z^X)*=_Sp+f-mYBbyx5(BL!|`mr>cN;)8LUc5nq`Yh9*8c&%&)`61aF1#CS-K(tbqc z$dDBH)2csfNCT3k&@e74W2QR8FcFjmGy!T4$;76*gFr(Q2olOwbTXSU8BEP&Oobwr zznC45Df|UW*zJtgb_ET_Om)ob?OEhi^x3=ZpFsbb-rvs5{&r^dH{#OONTukQwECSw zS4HmU7@uCaenX*ibE8F;@|3kaYcWq*%??V!&dq9uV@sJ8@}3SzFb*Pue&YO0w$U5o zE7V%M*%k;;AInkZQRKoHfS945PEU`VE4LB3hM=9y%1F3WCkp40Amow+In>U7=Qfv* zu(W=BxamZKui*kiJhxQFvw$VIg(L)eHf%v};e~W4XfSH^(|$i9CMYDq406@!_YNaL z#Dg>Y#v;Xd@bd7qEXVo8PM+2%+V1>57sJdYXaf`q0n}^7h8o^a7nR~Yf>YRb2h&ed zV77PtlD3drkY0)syC&>j;l%S)MA=9@kI=;Ci7RiMi2jZ`LWs)Og)}GySaSDI5tdxS z&ulxTVO3cYQf1S*WQXJsLjRK7ZYQnfqS6I5x$V#FRhXY`)@aS$E7gktvSot$QI3(@ zTy9agh9N-3e$VJeq*1mK46ziKf_XMH2Ryw1NG^u&!n{B(Pu9PFMQxMj1q_65-+J-5 zr@QGvE9+j30gpn>rQ&gKK!sF2^S~>SN2nfbOYb>=T~u3IW-{Y(kA}USk^%y`fxV7& z{ZbLFzEGPxvh=FRTk{U#@|MZsMe6yip;~Y4Y;Uhul+)renryoOkgR^MA+TXOHm13v z2m4k#lmrw`T? z0bnc3rE+?&RjU4dkZ2hp}u@s*165c5zq%|4`Edmit(jpYj9VX z?4oCTyHg6zSnzI8F@__TMe?zSSw33=_0zT%%>+gwU@N=j)yTMp@I=8e@k7Vaie&~| zl=+1Il(G{Q0hc@mZ(`Sc1LsSrkc}UnsHzB#yGRPs)88!10T)c5%tdHd@>N^fB7PqB z8YBhYW^ce1)x6N~x|EjjY{fMm5)r1Vyoe=H3gY=EMywap(8w6r7yjoz|2c_Ja!v$< zKn8*;YQv!mMQjjvqJ^D3Tsv8Y#|dYIDL<1YH6V!eL- zioSgPnhDwL%xpU*QsNW?F;($tt7AWQ)r%2r~w!uGSh^FHUjG z9{6foUaF`SnP5Nnwx}7wyMq1$Pj=j+HAJWyX(nkOa53!BFw+Zl2`>DXrq2(UGW1Cd z+qvG>3nvvfe|_azl!-OeYAR+ufTw4l{kMy=4!Dhm4oO55>3L(Hrd7KP(r$BhY3(}8 z4sCYGz9d+UzGRLv@bg5ppPg>ZD|G(qU;u1=Z?tp!)|pbCl5XE*fM21jXXQ%kU_Hwe zl26w=e=3~@w!U6mBsS~;J|UG_7k;hL4xJWs;#^hs=QvBim`!n#yTYcR$SKfQ&87)< z;{u%EA3vSG>7r9}4k~X9>^Ybh@Z%W|Y92d*CUHOEyLQVW;BjYS=DnU0A~O7M0T@{< z0JB^F)?=Q}cy6~k3UQuG9+Os9Ea$-5@+k7LKOZ0d-22q zQe^yzuy!k(Z}qVx2hSGorPV)pHoGT;`UlT!w!DJpqzuB4stEV50fMPmgu*;Ky=v4{ zncESsGjLb8*m0j=K}6oM*=x4@IB=rr5@MdbjQa($XhUpN6%;H941f+#-9P@k(&JLfkV1c(f^IO=B94mQ7WE13gAMdE?; z00vhXSr+Ks->I@Z-ib!L6Z~Tqc$NsN)t2Jfu$)Z`~{Tv5uvO%A8oOb9CAWRjnoD;@Yyx_5lo$#aPyl)2F+YT7rAOrBY} zJ0oKN93I5cSV2}IT`?Gu;H)>`qL)It8JQ=Q=0j5?hHa97Gij2yxw|Bo%OF#r7C&_+ zvJPyE060p~Ma{2Y5gniny^`DJlw;c+SG2Ld6VKsH*(Un-?d#X-cjynJyqh9~h3MP2 zrk+eE4iAfmS****^_NA5<(pb|+3+mHQO{`uqUQ54X@Wo1)zT+$v2d8Re&s2BT%)s0U z7s~SdG;833vq?<5w!?CayV098DteL*Sx?&y{wo>qM6Z=p643?Fw*cWzd(};_uIWeHpcL{&@va}U=*1`k(+~0~C^)KaLNZNg5yW$b zIB6>$M~G@}ca9@#$HIK;x0$QIltE!_a23G%Yy2el@&@v6x#a+0uX6eM2VCZYQwU%yeu~u{q7mnc& z;P78@GU!V&%>0X$5JJEFVpy;I?Kf{T5WPgrcnq^-H%HvYFytS3i4OJ-?1NO2o|KVm)>;snntCdd z=%qI&2uT_Bm+_d3q5fjB9TbS; z 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.16.0-0' + catalog.cattle.io/namespace: cattle-monitoring-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.6.100-0' + catalog.cattle.io/release-name: prometheus-federator +apiVersion: v2 +appVersion: 0.3.1 +dependencies: +- condition: helmProjectOperator.enabled + name: helmProjectOperator + repository: file://./charts/helmProjectOperator +description: Prometheus Federator +icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg +name: prometheus-federator +version: 0.3.1 diff --git a/charts/prometheus-federator/0.3.1/README.md b/charts/prometheus-federator/0.3.1/README.md new file mode 100644 index 00000000..7da4edfc --- /dev/null +++ b/charts/prometheus-federator/0.3.1/README.md @@ -0,0 +1,120 @@ +# Prometheus Federator + +This chart is deploys a Helm Project Operator (based on the [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator)), an operator that manages deploying Helm charts each containing a Project Monitoring Stack, where each stack contains: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed resources + +> **Important Note: Prometheus Federator is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs.** + +By default, the chart is configured and intended to be deployed alongside [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that each Project Monitoring Stack is configured to federate namespace-scoped metrics from by default. + +## Pre-Installation: Using Prometheus Federator with Rancher and rancher-monitoring + +If you are running your cluster on [Rancher](https://rancher.com/) and already have [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) deployed onto your cluster, Prometheus Federator's default configuration should already be configured to work with your existing Cluster Monitoring Stack; however, here are some notes on how we recommend you configure rancher-monitoring to optimize the security and usability of Prometheus Federator in your cluster: + +### Ensure the cattle-monitoring-system namespace is placed into the System Project (or a similarly locked down Project that has access to other Projects in the cluster) + +Prometheus Operator's security model expects that the namespace it is deployed into (`cattle-monitoring-system`) has limited access for anyone except Cluster Admins to avoid privilege escalation via execing into Pods (such as the Jobs executing Helm operations). In addition, deploying Prometheus Federator and all Project Prometheus stacks into the System Project ensures that the each Project Prometheus is able to reach out to scrape workloads across all Projects (even if Network Policies are defined via Project Network Isolation) but has limited access for Project Owners, Project Members, and other users to be able to access data they shouldn't have access to (i.e. being allowed to exec into pods, set up the ability to scrape namespaces outside of a given Project, etc.). + +### Configure rancher-monitoring to only watch for resources created by the Helm chart itself + +Since each Project Monitoring Stack will watch the other namespaces and collect additional custom workload metrics or dashboards already, it's recommended to configure the following settings on all selectors to ensure that the Cluster Prometheus Stack only monitors resources created by the Helm Chart itself: + +``` +matchLabels: + release: "rancher-monitoring" +``` + +The following selector fields are recommended to have this value: +- `.Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector` +- `.Values.prometheus.prometheusSpec.serviceMonitorSelector` +- `.Values.prometheus.prometheusSpec.podMonitorSelector` +- `.Values.prometheus.prometheusSpec.ruleSelector` +- `.Values.prometheus.prometheusSpec.probeSelector` + +Once this setting is turned on, you can always create ServiceMonitors or PodMonitors that are picked up by the Cluster Prometheus by adding the label `release: "rancher-monitoring"` to them (in which case they will be ignored by Project Monitoring Stacks automatically by default, even if the namespace in which those ServiceMonitors or PodMonitors reside in are not system namespaces). + +> Note: If you don't want to allow users to be able to create ServiceMonitors and PodMonitors that aggregate into the Cluster Prometheus in Project namespaces, you can additionally set the namespaceSelectors on the chart to only target system namespaces (which must contain `cattle-monitoring-system` and `cattle-dashboards`, where resources are deployed into by default by rancher-monitoring; you will also need to monitor the `default` namespace to get apiserver metrics or create a custom ServiceMonitor to scrape apiserver metrics from the Service residing in the default namespace) to limit your Cluster Prometheus from picking up other Prometheus Operator CRs; in that case, it would be recommended to turn `.Values.prometheus.prometheusSpec.ignoreNamespaceSelectors=true` to allow you to define ServiceMonitors that can monitor non-system namespaces from within a system namespace. + +In addition, if you modified the default `.Values.grafana.sidecar.*.searchNamespace` values on the Grafana Helm subchart for Monitoring V2, it is also recommended to remove the overrides or ensure that your defaults are scoped to only system namespaces for the following values: +- `.Values.grafana.sidecar.dashboards.searchNamespace` (default `cattle-dashboards`) +- `.Values.grafana.sidecar.datasources.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) +- `.Values.grafana.sidecar.plugins.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) +- `.Values.grafana.sidecar.notifiers.searchNamespace` (default `null`, which means it uses the release namespace `cattle-monitoring-system`) + +### Increase the CPU / memory limits of the Cluster Prometheus + +Depending on a cluster's setup, it's generally recommended to give a large amount of dedicated memory to the Cluster Prometheus to avoid restarts due to out-of-memory errors (OOMKilled), usually caused by churn created in the cluster that causes a large number of high cardinality metrics to be generated and ingested by Prometheus within one block of time; this is one of the reasons why the default Rancher Monitoring stack expects around 4GB of RAM to be able to operate in a normal-sized cluster. However, when introducing Project Monitoring Stacks that are all sending `/federate` requests to the same Cluster Prometheus and are reliant on the Cluster Prometheus being "up" to federate that system data on their namespaces, it's even more important that the Cluster Prometheus has an ample amount of CPU / memory assigned to it to prevent an outage that can cause data gaps across all Project Prometheis in the cluster. + +> Note: There are no specific recommendations on how much memory the Cluster Prometheus should be configured with since it depends entirely on the user's setup (namely the likelihood of encountering a high churn rate and the scale of metrics that could be generated at that time); it generally varies per setup. + +## How does the operator work? + +1. On deploying this chart, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `monitoring.cattle.io/v1alpha1` (also known as "Project Monitors" in the Rancher UI) in a **Project Registration Namespace (`cattle-project-`)**. +2. On seeing each ProjectHelmChartCR, the operator will automatically deploy a Project Prometheus stack on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--monitoring`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. +3. RBAC will automatically be assigned in the Project Release Namespace to allow users to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack deployed; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). + +### What is a Project? + +In Prometheus Federator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. + +### Configuring the Helm release created by a ProjectHelmChart + +The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: +- View to the chart's definition located at [`rancher/prometheus-federator` under `charts/rancher-project-monitoring`](https://github.com/rancher/prometheus-federator/blob/main/charts/rancher-project-monitoring) (where the chart version will be tied to the version of this operator) +- Look for the ConfigMap named `monitoring.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `prometheus-federator` binary). + +### Namespaces + +As a Project Operator based on [rancher/helm-project-operator](https://github.com/rancher/helm-project-operator), Prometheus Federator has three different classifications of namespaces that the operator looks out for: +1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-monitoring-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** +2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. +> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project +> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace +3. **Project Release Namespace (`cattle-project--monitoring`)**: this is the set of namespaces that the operator deploys Project Monitoring Stacks within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Project Monitoring Stack based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Prometheus Federator.** +> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace +> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) +> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace + +### Helm Resources (HelmChart, HelmRelease) + +On deploying a ProjectHelmChart, the Prometheus Federator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: +- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). +> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** +- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). +> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified + +Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. + +### RBAC + +As described in the section on namespaces above, Prometheus Federator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: +- ClusterRoleBindings +- RoleBindings in the Project Release Namespace + +On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). + +> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. + +If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: +- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` +- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` + +By default, the `rancher-project-monitoring` (the underlying chart deployed by Prometheus Federator) creates three default Roles per Project Release Namespace that provide `admin`, `edit`, and `view` users to permissions to view the Prometheus, Alertmanager, and Grafana UIs of the Project Monitoring Stack to provide least privilege; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. + +### Advanced Helm Project Operator Configuration + +|Value|Configuration| +|---|---------------------------| +|`helmProjectOperator.valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | +|`helmProjectOperator.projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | +|`helmProjectOperator.otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `cattle-monitoring-system`, `cattle-dashboards`, and `kube-system` are explicitly marked as system namespaces as well, regardless of label or annotation. | +|`helmProjectOperator.releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces +|`helmProjectOperator.releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | +|`helmProjectOperator.hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | +|`helmProjectOperator.hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | +|`helmProjectOperator.helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2/K3s clusters before v1.23.14 / v1.24.8 / v1.25.4 since RKE2/K3s clusters already run Helm Controller at a cluster-wide level to manage internal Kubernetes components | +|`helmProjectOperator.helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.1/app-README.md b/charts/prometheus-federator/0.3.1/app-README.md new file mode 100644 index 00000000..99fa7ca1 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/app-README.md @@ -0,0 +1,27 @@ +# Prometheus Federator + +This chart deploys an operator that manages Project Monitoring Stacks composed of the following set of resources that are scoped to project namespaces: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed Prometheus, Grafana, and Alertmanager + +Since this Project Monitoring Stack deploys Prometheus Operator CRs, an existing Prometheus Operator instance must already be deployed in the cluster for Prometheus Federator to successfully be able to deploy Project Monitoring Stacks. It is recommended to use [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) for this. For more information on how the chart works or advanced configurations, please read the `README.md`. + +## Upgrading to Kubernetes v1.25+ + +Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. + +As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. +​ +> **Note:** +> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. + ​ +> **Note:** +> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** +> +> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. +Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. +​ +As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml new file mode 100644 index 00000000..421aabb1 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml @@ -0,0 +1,15 @@ +annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Helm Project Operator + catalog.cattle.io/kube-version: '>=1.16.0-0' + catalog.cattle.io/namespace: cattle-helm-system + catalog.cattle.io/os: linux,windows + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 + catalog.cattle.io/rancher-version: '>= 2.6.0-0' + catalog.cattle.io/release-name: helm-project-operator +apiVersion: v2 +appVersion: 0.1.0 +description: Helm Project Operator +name: helmProjectOperator +version: 0.1.1 diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/README.md b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/README.md new file mode 100644 index 00000000..fc1d39e8 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/README.md @@ -0,0 +1,77 @@ +# Helm Project Operator + +## How does the operator work? + +1. On deploying a Helm Project Operator, users can create ProjectHelmCharts CRs with `spec.helmApiVersion` set to `dummy.cattle.io/v1alpha1` in a **Project Registration Namespace (`cattle-project-`)**. +2. On seeing each ProjectHelmChartCR, the operator will automatically deploy the embedded Helm chart on the Project Owner's behalf in the **Project Release Namespace (`cattle-project--dummy`)** based on a HelmChart CR and a HelmRelease CR automatically created by the ProjectHelmChart controller in the **Operator / System Namespace**. +3. RBAC will automatically be assigned in the Project Release Namespace to allow users to based on Role created in the Project Release Namespace with a given set of labels; this will be based on RBAC defined on the Project Registration Namespace against the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) (see below for more information about configuring RBAC). + +### What is a Project? + +In Helm Project Operator, a Project is a group of namespaces that can be identified by a `metav1.LabelSelector`; by default, the label used to identify projects is `field.cattle.io/projectId`, the label used to identify namespaces that are contained within a given [Rancher](https://rancher.com/) Project. + +### What is a ProjectHelmChart? + +A ProjectHelmChart is an instance of a (project-scoped) Helm chart deployed on behalf of a user who has permissions to create ProjectHelmChart resources in a Project Registration namespace. + +Generally, the best way to think about the ProjectHelmChart model is by comparing it to two other models: +1. Managed Kubernetes providers (EKS, GKE, AKS, etc.): in this model, a user has the ability to say "I want a Kubernetes cluster" but the underlying cloud provider is responsible for provisioning the infrastructure and offering **limited view and access** of the underlying resources created on their behalf; similarly, Helm Project Operator allows a Project Owner to say "I want this Helm chart deployed", but the underlying Operator is responsible for "provisioning" (deploying) the Helm chart and offering **limited view and access** of the underlying Kubernetes resources created on their behalf (based on configuring "least-privilege" Kubernetes RBAC for the Project Owners / Members in the newly created Project Release Namespace). +2. Dynamically-provisioned Persistent Volumes: in this model, a single resource (PersistentVolume) exists that allows you to specify a Storage Class that actually implements provisioning the underlying storage via a Storage Class Provisioner (e.g. Longhorn). Similarly, the ProjectHelmChart exists that allows you to specify a `spec.helmApiVersion` ("storage class") that actually implements deploying the underlying Helm chart via a Helm Project Operator (e.g. [`rancher/prometheus-federator`](https://github.com/rancher/prometheus-federator)). + +### Configuring the Helm release created by a ProjectHelmChart + +The `spec.values` of this ProjectHelmChart resources will correspond to the `values.yaml` override to be supplied to the underlying Helm chart deployed by the operator on the user's behalf; to see the underlying chart's `values.yaml` spec, either: +- View to the chart's definition located at [`rancher/helm-project-operator` under `charts/example-chart`](https://github.com/rancher/helm-project-operator/blob/main/charts/example-chart) (where the chart version will be tied to the version of this operator) +- Look for the ConfigMap named `dummy.cattle.io.v1alpha1` that is automatically created in each Project Registration Namespace, which will contain both the `values.yaml` and `questions.yaml` that was used to configure the chart (which was embedded directly into the `helm-project-operator` binary). + +### Namespaces + +All Helm Project Operators have three different classifications of namespaces that the operator looks out for: +1. **Operator / System Namespace**: this is the namespace that the operator is deployed into (e.g. `cattle-helm-system`). This namespace will contain all HelmCharts and HelmReleases for all ProjectHelmCharts watched by this operator. **Only Cluster Admins should have access to this namespace.** +2. **Project Registration Namespace (`cattle-project-`)**: this is the set of namespaces that the operator watches for ProjectHelmCharts within. The RoleBindings and ClusterRoleBindings that apply to this namespace will also be the source of truth for the auto-assigned RBAC created in the Project Release Namespace (see more details below). **Project Owners (admin), Project Members (edit), and Read-Only Members (view) should have access to this namespace**. +> Note: Project Registration Namespaces will be auto-generated by the operator and imported into the Project it is tied to if `.Values.global.cattle.projectLabel` is provided (which is set to `field.cattle.io/projectId` by default); this indicates that a Project Registration Namespace should be created by the operator if at least one namespace is observed with that label. The operator will not let these namespaces be deleted unless either all namespaces with that label are gone (e.g. this is the last namespace in that project, in which case the namespace will be marked with the label `"helm.cattle.io/helm-project-operator-orphaned": "true"`, which signals that it can be deleted) or it is no longer watching that project (because the project ID was provided under `.Values.helmProjectOperator.otherSystemProjectLabelValues`, which serves as a denylist for Projects). These namespaces will also never be auto-deleted to avoid destroying user data; it is recommended that users clean up these namespaces manually if desired on creating or deleting a project +> Note: if `.Values.global.cattle.projectLabel` is not provided, the Operator / System Namespace will also be the Project Registration Namespace +3. **Project Release Namespace (`cattle-project--dummy`)**: this is the set of namespaces that the operator deploys Helm charts within on behalf of a ProjectHelmChart; the operator will also automatically assign RBAC to Roles created in this namespace by the Helm charts based on bindings found in the Project Registration Namespace. **Only Cluster Admins should have access to this namespace; Project Owners (admin), Project Members (edit), and Read-Only Members (view) will be assigned limited access to this namespace by the deployed Helm Chart and Helm Project Operator.** +> Note: Project Release Namespaces are automatically deployed and imported into the project whose ID is specified under `.Values.helmProjectOperator.projectReleaseNamespaces.labelValue` (which defaults to the value of `.Values.global.cattle.systemProjectId` if not specified) whenever a ProjectHelmChart is specified in a Project Registration Namespace +> Note: Project Release Namespaces follow the same orphaning conventions as Project Registration Namespaces (see note above) +> Note: if `.Values.projectReleaseNamespaces.enabled` is false, the Project Release Namespace will be the same as the Project Registration Namespace + +### Helm Resources (HelmChart, HelmRelease) + +On deploying a ProjectHelmChart, the Helm Project Operator will automatically create and manage two child custom resources that manage the underlying Helm resources in turn: +- A HelmChart CR (managed via an embedded [k3s-io/helm-contoller](https://github.com/k3s-io/helm-controller) in the operator): this custom resource automatically creates a Job in the same namespace that triggers a `helm install`, `helm upgrade`, or `helm uninstall` depending on the change applied to the HelmChart CR; this CR is automatically updated on changes to the ProjectHelmChart (e.g. modifying the values.yaml) or changes to the underlying Project definition (e.g. adding or removing namespaces from a project). +> **Important Note: If a ProjectHelmChart is not deploying or updating the underlying Project Monitoring Stack for some reason, the Job created by this resource in the Operator / System namespace should be the first place you check to see if there's something wrong with the Helm operation; however, this is generally only accessible by a Cluster Admin.** +- A HelmRelease CR (managed via an embedded [rancher/helm-locker](https://github.com/rancher/helm-locker) in the operator): this custom resource automatically locks a deployed Helm release in place and automatically overwrites updates to underlying resources unless the change happens via a Helm operation (`helm install`, `helm upgrade`, or `helm uninstall` performed by the HelmChart CR). +> Note: HelmRelease CRs emit Kubernetes Events that detect when an underlying Helm release is being modified and locks it back to place; to view these events, you can use `kubectl describe helmrelease -n `; you can also view the logs on this operator to see when changes are detected and which resources were attempted to be modified + +Both of these resources are created for all Helm charts in the Operator / System namespaces to avoid escalation of privileges to underprivileged users. + +### RBAC + +As described in the section on namespaces above, Helm Project Operator expects that Project Owners, Project Members, and other users in the cluster with Project-level permissions (e.g. permissions in a certain set of namespaces identified by a single label selector) have minimal permissions in any namespaces except the Project Registration Namespace (which is imported into the project by default) and those that already comprise their projects. Therefore, in order to allow Project Owners to assign specific chart permissions to other users in their Project namespaces, the Helm Project Operator will automatically watch the following bindings: +- ClusterRoleBindings +- RoleBindings in the Project Release Namespace + +On observing a change to one of those types of bindings, the Helm Project Operator will check whether the `roleRef` that the the binding points to matches a ClusterRole with the name provided under `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin`, `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit`, or `helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view`; by default, these roleRefs correspond will correspond to `admin`, `edit`, and `view` respectively, which are the [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles). + +> Note: for Rancher RBAC users, these [default Kubernetes user-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) directly correlate to the `Project Owner`, `Project Member`, and `Read-Only` default Project Role Templates. + +If the `roleRef` matches, the Helm Project Operator will filter the `subjects` of the binding for all Users and Groups and use that to automatically construct a RoleBinding for each Role in the Project Release Namespace with the same name as the role and the following labels: +- `helm.cattle.io/project-helm-chart-role: {{ .Release.Name }}` +- `helm.cattle.io/project-helm-chart-role-aggregate-from: ` + +By default, the `example-chart` (the underlying chart deployed by Helm Project Operator) does not create any default roles; however, if a Cluster Admin would like to assign additional permissions to certain users, they can either directly assign RoleBindings in the Project Release Namespace to certain users or created Roles with the above two labels on them to allow Project Owners to control assigning those RBAC roles to users in their Project Registration namespaces. + +### Advanced Helm Project Operator Configuration + +|Value|Configuration| +|---|---------------------------| +|`valuesOverride`| Allows an Operator to override values that are set on each ProjectHelmChart deployment on an operator-level; user-provided options (specified on the `spec.values` of the ProjectHelmChart) are automatically overridden if operator-level values are provided. For an exmaple, see how the default value overrides `federate.targets` (note: when overriding list values like `federate.targets`, user-provided list values will **not** be concatenated) | +|`projectReleaseNamespaces.labelValues`| The value of the Project that all Project Release Namespaces should be auto-imported into (via label and annotation). Not recommended to be overridden on a Rancher setup. | +|`otherSystemProjectLabelValues`| Other namespaces that the operator should treat as a system namespace that should not be monitored. By default, all namespaces that match `global.cattle.systemProjectId` will not be matched. `kube-system` is explicitly marked as a system namespace as well, regardless of label or annotation. | +|`releaseRoleBindings.aggregate`| Whether to automatically create RBAC resources in Project Release namespaces +|`releaseRoleBindings.clusterRoleRefs.`| ClusterRoles to reference to discover subjects to create RoleBindings for in the Project Release Namespace for all corresponding Project Release Roles. See RBAC above for more information | +|`hardenedNamespaces.enabled`| Whether to automatically patch the default ServiceAccount with `automountServiceAccountToken: false` and create a default NetworkPolicy in all managed namespaces in the cluster; the default values ensure that the creation of the namespace does not break a CIS 1.16 hardened scan | +|`hardenedNamespaces.configuration`| The configuration to be supplied to the default ServiceAccount or auto-generated NetworkPolicy on managing a namespace | +|`helmController.enabled`| Whether to enable an embedded k3s-io/helm-controller instance within the Helm Project Operator. Should be disabled for RKE2 clusters since RKE2 clusters already run Helm Controller to manage internal Kubernetes components | +|`helmLocker.enabled`| Whether to enable an embedded rancher/helm-locker instance within the Helm Project Operator. | diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/app-readme.md b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/app-readme.md new file mode 100644 index 00000000..fd551467 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/app-readme.md @@ -0,0 +1,20 @@ +# Helm Project Operator + +This chart installs the example [Helm Project Operator](https://github.com/rancher/helm-project-operator) onto your cluster. + +## Upgrading to Kubernetes v1.25+ + +Starting in Kubernetes v1.25, [Pod Security Policies](https://kubernetes.io/docs/concepts/security/pod-security-policy/) have been removed from the Kubernetes API. + +As a result, **before upgrading to Kubernetes v1.25** (or on a fresh install in a Kubernetes v1.25+ cluster), users are expected to perform an in-place upgrade of this chart with `global.cattle.psp.enabled` set to `false` if it has been previously set to `true`. +​ +> **Note:** +> In this chart release, any previous field that was associated with any PSP resources have been removed in favor of a single global field: `global.cattle.psp.enabled`. + ​ +> **Note:** +> If you upgrade your cluster to Kubernetes v1.25+ before removing PSPs via a `helm upgrade` (even if you manually clean up resources), **it will leave the Helm release in a broken state within the cluster such that further Helm operations will not work (`helm uninstall`, `helm upgrade`, etc.).** +> +> If your charts get stuck in this state, please consult the Rancher docs on how to clean up your Helm release secrets. +Upon setting `global.cattle.psp.enabled` to false, the chart will remove any PSP resources deployed on its behalf from the cluster. This is the default setting for this chart. +​ +As a replacement for PSPs, [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) should be used. Please consult the Rancher docs for more details on how to configure your chart release namespaces to work with the new Pod Security Admission and apply Pod Security Standards. \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/questions.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/questions.yaml new file mode 100644 index 00000000..054361a7 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/questions.yaml @@ -0,0 +1,43 @@ +questions: +- variable: global.cattle.psp.enabled + default: "false" + description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." + label: "Enable PodSecurityPolicies" + type: boolean + group: "Security Settings" +- variable: helmController.enabled + label: Enable Embedded Helm Controller + description: 'Note: If you are running this chart in an RKE2 cluster, this should be disabled.' + type: boolean + group: Helm Controller +- variable: helmLocker.enabled + label: Enable Embedded Helm Locker + type: boolean + group: Helm Locker +- variable: projectReleaseNamespaces.labelValue + label: Project Release Namespace Project ID + description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) + type: string + required: false + group: Namespaces +- variable: releaseRoleBindings.clusterRoleRefs.admin + label: Admin ClusterRole + description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: admin + required: false + group: RBAC +- variable: releaseRoleBindings.clusterRoleRefs.edit + label: Edit ClusterRole + description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: edit + required: false + group: RBAC +- variable: releaseRoleBindings.clusterRoleRefs.view + label: View ClusterRole + description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: view + required: false + group: RBAC diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/NOTES.txt b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/NOTES.txt new file mode 100644 index 00000000..32baeebc --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/NOTES.txt @@ -0,0 +1,2 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "helm-project-operator.namespace" . }} get pods -l "release={{ $.Release.Name }}" diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/_helpers.tpl b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/_helpers.tpl new file mode 100644 index 00000000..97dd6b36 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/_helpers.tpl @@ -0,0 +1,66 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Helm Project Operator + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "helm-project-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "helm-project-operator.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "helm-project-operator.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "helm-project-operator.labels" -}} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "helm-project-operator.name" . }} +chart: {{ template "helm-project-operator.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end -}} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/cleanup.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/cleanup.yaml new file mode 100644 index 00000000..98675642 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/cleanup.yaml @@ -0,0 +1,82 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "helm-project-operator.name" . }}-cleanup + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": before-hook-creation, hook-succeeded, hook-failed +spec: + template: + metadata: + name: {{ template "helm-project-operator.name" . }}-cleanup + labels: {{ include "helm-project-operator.labels" . | nindent 8 }} + app: {{ template "helm-project-operator.name" . }} + spec: + serviceAccountName: {{ template "helm-project-operator.name" . }} +{{- if .Values.cleanup.securityContext }} + securityContext: {{ toYaml .Values.cleanup.securityContext | nindent 8 }} +{{- end }} + initContainers: + - name: add-cleanup-annotations + image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + command: + - /bin/sh + - -c + - > + echo "Labeling all ProjectHelmCharts with helm.cattle.io/helm-project-operator-cleanup=true"; + EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; + IFS=$'\n'; + for namespace in $(kubectl get namespaces -l helm.cattle.io/helm-project-operated=true --no-headers -o=custom-columns=NAME:.metadata.name); do + for projectHelmChartAndHelmApiVersion in $(kubectl get projecthelmcharts -n ${namespace} --no-headers -o=custom-columns=NAME:.metadata.name,HELMAPIVERSION:.spec.helmApiVersion); do + projectHelmChartAndHelmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | xargs); + projectHelmChart=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f1); + helmApiVersion=$(echo ${projectHelmChartAndHelmApiVersion} | cut -d' ' -f2); + if [[ ${helmApiVersion} != ${EXPECTED_HELM_API_VERSION} ]]; then + echo "Skipping marking ${namespace}/${projectHelmChart} with cleanup annotation since spec.helmApiVersion: ${helmApiVersion} is not ${EXPECTED_HELM_API_VERSION}"; + continue; + fi; + kubectl label projecthelmcharts -n ${namespace} ${projectHelmChart} helm.cattle.io/helm-project-operator-cleanup=true --overwrite; + done; + done; +{{- if .Values.cleanup.resources }} + resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} +{{- end }} +{{- if .Values.cleanup.containerSecurityContext }} + securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} +{{- end }} + containers: + - name: ensure-subresources-deleted + image: {{ template "system_default_registry" . }}{{ .Values.cleanup.image.repository }}:{{ .Values.cleanup.image.tag }} + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - > + SYSTEM_NAMESPACE={{ .Release.Namespace }} + EXPECTED_HELM_API_VERSION={{ .Values.helmApiVersion }}; + HELM_API_VERSION_TRUNCATED=$(echo ${EXPECTED_HELM_API_VERSION} | cut -d'/' -f0); + echo "Ensuring HelmCharts and HelmReleases are deleted from ${SYSTEM_NAMESPACE}..."; + while [[ "$(kubectl get helmcharts,helmreleases -l helm.cattle.io/helm-api-version=${HELM_API_VERSION_TRUNCATED} -n ${SYSTEM_NAMESPACE} 2>&1)" != "No resources found in ${SYSTEM_NAMESPACE} namespace." ]]; do + echo "waiting for HelmCharts and HelmReleases to be deleted from ${SYSTEM_NAMESPACE}... sleeping 3 seconds"; + sleep 3; + done; + echo "Successfully deleted all HelmCharts and HelmReleases in ${SYSTEM_NAMESPACE}!"; +{{- if .Values.cleanup.resources }} + resources: {{ toYaml .Values.cleanup.resources | nindent 12 }} +{{- end }} +{{- if .Values.cleanup.containerSecurityContext }} + securityContext: {{ toYaml .Values.cleanup.containerSecurityContext | nindent 12 }} +{{- end }} + restartPolicy: OnFailure + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + {{- if .Values.cleanup.nodeSelector }} + {{- toYaml .Values.cleanup.nodeSelector | nindent 8 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + {{- if .Values.cleanup.tolerations }} + {{- toYaml .Values.cleanup.tolerations | nindent 8 }} + {{- end }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/clusterrole.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/clusterrole.yaml new file mode 100644 index 00000000..60ed263b --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/clusterrole.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-admin + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/finalizers + - projecthelmcharts/status + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-edit + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/status + verbs: + - 'get' + - 'list' + - 'watch' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "helm-project-operator.name" . }}-view + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + {{- end }} +rules: +- apiGroups: + - helm.cattle.io + resources: + - projecthelmcharts + - projecthelmcharts/status + verbs: + - 'get' + - 'list' + - 'watch' +{{- end }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/configmap.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/configmap.yaml new file mode 100644 index 00000000..d4def157 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/configmap.yaml @@ -0,0 +1,14 @@ +## Note: If you add another entry to this ConfigMap, make sure a corresponding env var is set +## in the deployment of the operator to ensure that a Helm upgrade will force the operator +## to reload the values in the ConfigMap and redeploy +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "helm-project-operator.name" . }}-config + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +data: + hardened.yaml: |- +{{ .Values.hardenedNamespaces.configuration | toYaml | indent 4 }} + values.yaml: |- +{{ .Values.valuesOverride | toYaml | indent 4 }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml new file mode 100644 index 00000000..c7309805 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml @@ -0,0 +1,124 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ template "helm-project-operator.name" . }} + release: {{ $.Release.Name | quote }} + template: + metadata: + labels: {{ include "helm-project-operator.labels" . | nindent 8 }} + app: {{ template "helm-project-operator.name" . }} + spec: + containers: + - name: {{ template "helm-project-operator.name" . }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + args: + - {{ template "helm-project-operator.name" . }} + - --namespace={{ template "helm-project-operator.namespace" . }} + - --controller-name={{ template "helm-project-operator.name" . }} + - --values-override-file=/etc/helmprojectoperator/config/values.yaml +{{- if .Values.global.cattle.systemDefaultRegistry }} + - --system-default-registry={{ .Values.global.cattle.systemDefaultRegistry }} +{{- end }} +{{- if .Values.global.cattle.url }} + - --cattle-url={{ .Values.global.cattle.url }} +{{- end }} +{{- if .Values.global.cattle.projectLabel }} + - --project-label={{ .Values.global.cattle.projectLabel }} +{{- end }} +{{- if not .Values.projectReleaseNamespaces.enabled }} + - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} +{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} + - --system-project-label-values={{ join "," (append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId) }} +{{- else if len .Values.otherSystemProjectLabelValues }} + - --system-project-label-values={{ join "," .Values.otherSystemProjectLabelValues }} +{{- end }} +{{- if .Values.projectReleaseNamespaces.enabled }} +{{- if .Values.projectReleaseNamespaces.labelValue }} + - --project-release-label-value={{ .Values.projectReleaseNamespaces.labelValue }} +{{- else if .Values.global.cattle.systemProjectId }} + - --project-release-label-value={{ .Values.global.cattle.systemProjectId }} +{{- end }} +{{- end }} +{{- if .Values.global.cattle.clusterId }} + - --cluster-id={{ .Values.global.cattle.clusterId }} +{{- end }} +{{- if .Values.releaseRoleBindings.aggregate }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.admin }} + - --admin-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.admin }} +{{- end }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.edit }} + - --edit-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.edit }} +{{- end }} +{{- if .Values.releaseRoleBindings.clusterRoleRefs.view }} + - --view-cluster-role={{ .Values.releaseRoleBindings.clusterRoleRefs.view }} +{{- end }} +{{- end }} +{{- end }} +{{- if .Values.hardenedNamespaces.enabled }} + - --hardening-options-file=/etc/helmprojectoperator/config/hardening.yaml +{{- else }} + - --disable-hardening +{{- end }} +{{- if .Values.debug }} + - --debug + - --debug-level={{ .Values.debugLevel }} +{{- end }} +{{- if not .Values.helmController.enabled }} + - --disable-embedded-helm-controller +{{- else }} + - --helm-job-image={{ template "system_default_registry" . }}{{ .Values.helmController.job.image.repository }}:{{ .Values.helmController.job.image.tag }} +{{- end }} +{{- if not .Values.helmLocker.enabled }} + - --disable-embedded-helm-locker +{{- end }} +{{- if .Values.additionalArgs }} +{{- toYaml .Values.additionalArgs | nindent 10 }} +{{- end }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + ## Note: The below two values only exist to force Helm to upgrade the deployment on + ## a change to the contents of the ConfigMap during an upgrade. Neither serve + ## any practical purpose and can be removed and replaced with a configmap reloader + ## in a future change if dynamic updates are required. + - name: HARDENING_OPTIONS_SHA_256_HASH + value: {{ .Values.hardenedNamespaces.configuration | toYaml | sha256sum }} + - name: VALUES_OVERRIDE_SHA_256_HASH + value: {{ .Values.valuesOverride | toYaml | sha256sum }} +{{- if .Values.resources }} + resources: {{ toYaml .Values.resources | nindent 12 }} +{{- end }} +{{- if .Values.containerSecurityContext }} + securityContext: {{ toYaml .Values.containerSecurityContext | nindent 12 }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/helmprojectoperator/config" + serviceAccountName: {{ template "helm-project-operator.name" . }} +{{- if .Values.securityContext }} + securityContext: {{ toYaml .Values.securityContext | nindent 8 }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} +{{- if .Values.nodeSelector }} +{{- toYaml .Values.nodeSelector | nindent 8 }} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} +{{- if .Values.tolerations }} +{{- toYaml .Values.tolerations | nindent 8 }} +{{- end }} + volumes: + - name: config + configMap: + name: {{ template "helm-project-operator.name" . }}-config diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/psp.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/psp.yaml new file mode 100644 index 00000000..73dcc456 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/psp.yaml @@ -0,0 +1,68 @@ +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +{{- if .Values.global.rbac.pspAnnotations }} + annotations: {{ toYaml .Values.global.rbac.pspAnnotations | nindent 4 }} +{{- end }} +spec: + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +rules: +{{- if semverCompare "> 1.15.0-0" .Capabilities.KubeVersion.GitVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "helm-project-operator.name" . }}-psp +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "helm-project-operator.name" . }}-psp + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "helm-project-operator.name" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/rbac.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/rbac.yaml new file mode 100644 index 00000000..b1c40920 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/rbac.yaml @@ -0,0 +1,32 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "helm-project-operator.name" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: "cluster-admin" # see note below +subjects: +- kind: ServiceAccount + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "helm-project-operator.name" . }} + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} + app: {{ template "helm-project-operator.name" . }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }} +{{- end }} +# --- +# NOTE: +# As of now, due to the fact that the k3s-io/helm-controller can only deploy jobs that are cluster-bound to the cluster-admin +# ClusterRole, the only way for this operator to be able to perform that binding is if it is also bound to the cluster-admin ClusterRole. +# +# As a result, this ClusterRoleBinding will be left as a work-in-progress until changes are made in k3s-io/helm-controller to allow us to grant +# only scoped down permissions to the Job that is deployed. diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml new file mode 100644 index 00000000..f4c85254 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/system-namespaces-configmap.yaml @@ -0,0 +1,62 @@ +{{- if .Values.systemNamespacesConfigMap.create }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +data: + system-namespaces.json: |- + { +{{- if .Values.projectReleaseNamespaces.enabled }} +{{- if .Values.projectReleaseNamespaces.labelValue }} + "projectReleaseLabelValue": {{ .Values.projectReleaseNamespaces.labelValue | quote }}, +{{- else if .Values.global.cattle.systemProjectId }} + "projectReleaseLabelValue": {{ .Values.global.cattle.systemProjectId | quote }}, +{{- else }} + "projectReleaseLabelValue": "", +{{- end }} +{{- else }} + "projectReleaseLabelValue": "", +{{- end }} +{{- if not .Values.projectReleaseNamespaces.enabled }} + "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} +{{- else if and (ne (len .Values.global.cattle.systemProjectId) 0) (ne (len .Values.projectReleaseNamespaces.labelValue) 0) (ne .Values.projectReleaseNamespaces.labelValue .Values.global.cattle.systemProjectId) }} + "systemProjectLabelValues": {{ append .Values.otherSystemProjectLabelValues .Values.global.cattle.systemProjectId | toJson }} +{{- else if len .Values.otherSystemProjectLabelValues }} + "systemProjectLabelValues": {{ .Values.otherSystemProjectLabelValues | toJson }} +{{- else }} + "systemProjectLabelValues": [] +{{- end }} + } +--- +{{- if (and .Values.systemNamespacesConfigMap.rbac.enabled .Values.systemNamespacesConfigMap.rbac.subjects) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + resourceNames: + - "{{ template "helm-project-operator.name" . }}-system-namespaces" + verbs: + - 'get' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "helm-project-operator.name" . }}-system-namespaces + namespace: {{ template "helm-project-operator.namespace" . }} + labels: {{ include "helm-project-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "helm-project-operator.name" . }}-system-namespaces +subjects: {{ .Values.systemNamespacesConfigMap.rbac.subjects | toYaml | nindent 2 }} +{{- end }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/validate-psp-install.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/validate-psp-install.yaml new file mode 100644 index 00000000..a30c59d3 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/validate-psp-install.yaml @@ -0,0 +1,7 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +#{{- if .Values.global.cattle.psp.enabled }} +#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} +#{{- end }} +#{{- end }} +#{{- end }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml new file mode 100644 index 00000000..4905bf1a --- /dev/null +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml @@ -0,0 +1,226 @@ +# Default values for helm-project-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Helm Project Operator Configuration + +global: + cattle: + clusterId: "" + psp: + enabled: false + projectLabel: field.cattle.io/projectId + systemDefaultRegistry: "" + systemProjectId: "" + url: "" + rbac: + ## Create RBAC resources for ServiceAccounts and users + ## + create: true + + userRoles: + ## Create default user ClusterRoles to allow users to interact with ProjectHelmCharts + create: true + ## Aggregate default user ClusterRoles into default k8s ClusterRoles + aggregateToDefaultRoles: true + + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + +helmApiVersion: dummy.cattle.io/v1alpha1 + +## valuesOverride overrides values that are set on each ProjectHelmChart deployment on an operator-level +## User-provided values will be overwritten based on the values provided here +valuesOverride: {} + +## projectReleaseNamespaces are auto-generated namespaces that are created to host Helm Releases +## managed by this operator on behalf of a ProjectHelmChart +projectReleaseNamespaces: + ## Enabled determines whether Project Release Namespaces should be created. If false, the underlying + ## Helm release will be deployed in the Project Registration Namespace + enabled: true + ## labelValue is the value of the Project that the projectReleaseNamespace should be created within + ## If empty, this will be set to the value of global.cattle.systemProjectId + ## If global.cattle.systemProjectId is also empty, project release namespaces will be disabled + labelValue: "" + +## otherSystemProjectLabelValues are project labels that identify namespaces as those that should be treated as system projects +## i.e. they will be entirely ignored by the operator +## By default, the global.cattle.systemProjectId will be in this list +otherSystemProjectLabelValues: [] + +## releaseRoleBindings configures RoleBindings automatically created by the Helm Project Operator +## in Project Release Namespaces where underlying Helm charts are deployed +releaseRoleBindings: + ## aggregate enables creating these RoleBindings off aggregating RoleBindings in the + ## Project Registration Namespace or ClusterRoleBindings that bind users to the ClusterRoles + ## specified under clusterRoleRefs + aggregate: true + + ## clusterRoleRefs are the ClusterRoles whose RoleBinding or ClusterRoleBindings should determine + ## the RoleBindings created in the Project Release Namespace + ## + ## By default, these are set to create RoleBindings based on the RoleBindings / ClusterRoleBindings + ## attached to the default K8s user-facing ClusterRoles of admin, edit, and view. + ## ref: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + ## + clusterRoleRefs: + admin: admin + edit: edit + view: view + +hardenedNamespaces: + # Whether to automatically manage the configuration of the default ServiceAccount and + # auto-create a NetworkPolicy for each namespace created by this operator + enabled: true + + configuration: + # Values to be applied to each default ServiceAccount created in a managed namespace + serviceAccountSpec: + secrets: [] + imagePullSecrets: [] + automountServiceAccountToken: false + # Values to be applied to each default generated NetworkPolicy created in a managed namespace + networkPolicySpec: + podSelector: {} + egress: [] + ingress: [] + policyTypes: ["Ingress", "Egress"] + +## systemNamespacesConfigMap is a ConfigMap created to allow users to see valid entries +## for registering a ProjectHelmChart for a given Project on the Rancher Dashboard UI. +## It does not need to be enabled for a non-Rancher use case. +systemNamespacesConfigMap: + ## Create indicates whether the system namespaces configmap should be created + ## This is a required value for integration with Rancher Dashboard + create: true + + ## RBAC provides options around the RBAC created to allow users to be able to view + ## the systemNamespacesConfigMap; if not specified, only users with the ability to + ## view ConfigMaps in the namespace where this chart is deployed will be able to + ## properly view the system namespaces on the Rancher Dashboard UI + rbac: + ## enabled indicates that we should deploy a RoleBinding and Role to view this ConfigMap + enabled: true + ## subjects are the subjects that should be bound to this default RoleBinding + ## By default, we allow anyone who is authenticated to the system to be able to view + ## this ConfigMap in the deployment namespace + subjects: + - kind: Group + name: system:authenticated + +nameOverride: "" + +namespaceOverride: "" + +image: + repository: rancher/helm-project-operator + tag: v0.1.0 + pullPolicy: IfNotPresent + +helmController: + # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components + enabled: true + + job: + image: + repository: rancher/klipper-helm + tag: v0.7.0-build20220315 + +helmLocker: + enabled: true + +# Additional arguments to be passed into the Helm Project Operator image +additionalArgs: [] + +## Define which Nodes the Pods are scheduled on. +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} + +## Tolerations for use with node taints +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +# - key: "key" +# operator: "Equal" +# value: "value" +# effect: "NoSchedule" + +resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m + +containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + +securityContext: {} + # runAsGroup: 1000 + # runAsUser: 1000 + # supplementalGroups: + # - 1000 + +debug: false +debugLevel: 0 + +cleanup: + image: + repository: rancher/shell + tag: v0.1.19 + pullPolicy: IfNotPresent + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # privileged: false + # readOnlyRootFilesystem: true + + securityContext: + runAsNonRoot: false + runAsUser: 0 + + resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m diff --git a/charts/prometheus-federator/0.3.1/questions.yaml b/charts/prometheus-federator/0.3.1/questions.yaml new file mode 100644 index 00000000..87cf1339 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/questions.yaml @@ -0,0 +1,43 @@ +questions: +- variable: global.cattle.psp.enabled + default: "false" + description: "Flag to enable or disable the installation of PodSecurityPolicies by this chart in the target cluster. If the cluster is running Kubernetes 1.25+, you must update this value to false." + label: "Enable PodSecurityPolicies" + type: boolean + group: "Security Settings" +- variable: helmProjectOperator.helmController.enabled + label: Enable Embedded Helm Controller + description: 'Note: If you are running Prometheus Federator in an RKE2 / K3s cluster before v1.23.14 / v1.24.8 / v1.25.4, this should be disabled.' + type: boolean + group: Helm Controller +- variable: helmProjectOperator.helmLocker.enabled + label: Enable Embedded Helm Locker + type: boolean + group: Helm Locker +- variable: helmProjectOperator.projectReleaseNamespaces.labelValue + label: Project Release Namespace Project ID + description: By default, the System Project is selected. This can be overriden to a different Project (e.g. p-xxxxx) + type: string + required: false + group: Namespaces +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.admin + label: Admin ClusterRole + description: By default, admin selects Project Owners. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: admin + required: false + group: RBAC +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.edit + label: Edit ClusterRole + description: By default, edit selects Project Members. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: edit + required: false + group: RBAC +- variable: helmProjectOperator.releaseRoleBindings.clusterRoleRefs.view + label: View ClusterRole + description: By default, view selects Read-Only users. This can be overridden to a different ClusterRole (e.g. rt-xxxxx) + type: string + default: view + required: false + group: RBAC \ No newline at end of file diff --git a/charts/prometheus-federator/0.3.1/templates/NOTES.txt b/charts/prometheus-federator/0.3.1/templates/NOTES.txt new file mode 100644 index 00000000..f551f366 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/templates/NOTES.txt @@ -0,0 +1,3 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "prometheus-federator.namespace" . }} get pods -l "release={{ $.Release.Name }}" + diff --git a/charts/prometheus-federator/0.3.1/templates/_helpers.tpl b/charts/prometheus-federator/0.3.1/templates/_helpers.tpl new file mode 100644 index 00000000..15ea4e5c --- /dev/null +++ b/charts/prometheus-federator/0.3.1/templates/_helpers.tpl @@ -0,0 +1,66 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Helm Project Operator + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "prometheus-federator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "prometheus-federator.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "prometheus-federator.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "prometheus-federator.labels" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "prometheus-federator.name" . }} +chart: {{ template "prometheus-federator.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} diff --git a/charts/prometheus-federator/0.3.1/values.yaml b/charts/prometheus-federator/0.3.1/values.yaml new file mode 100644 index 00000000..3abc6326 --- /dev/null +++ b/charts/prometheus-federator/0.3.1/values.yaml @@ -0,0 +1,94 @@ +# Default values for helm-project-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Prometheus Federator Configuration + +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectLabel: field.cattle.io/projectId + clusterId: "" + systemProjectId: "" + url: "" + rbac: + pspEnabled: true + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + +helmProjectOperator: + enabled: true + + # ensures that all resources created by subchart show up as prometheus-federator + helmApiVersion: monitoring.cattle.io/v1alpha1 + + nameOverride: prometheus-federator + + helmController: + # Note: should be disabled for RKE2 clusters since they already run Helm Controller to manage internal Kubernetes components + enabled: true + + helmLocker: + enabled: true + + ## valuesOverride overrides values that are set on each Project Prometheus Stack Helm Chart deployment on an operator level + ## all values provided here will override any user-provided values automatically + valuesOverride: + + federate: + # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from + # By default, this matches the default deployment of Rancher Monitoring + targets: + - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 + + image: + repository: rancher/prometheus-federator + tag: v0.3.1 + pullPolicy: IfNotPresent + + # Additional arguments to be passed into the Prometheus Federator image + additionalArgs: [] + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + resources: {} + # limits: + # memory: 500Mi + # cpu: 1000m + # requests: + # memory: 100Mi + # cpu: 100m + + securityContext: {} + # allowPrivilegeEscalation: false + # readOnlyRootFilesystem: true + + debug: false + debugLevel: 0 \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/Chart.yaml b/charts/rancher-project-monitoring/0.3.1/Chart.yaml new file mode 100644 index 00000000..f31f9d54 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/Chart.yaml @@ -0,0 +1,33 @@ +annotations: + catalog.cattle.io/certified: rancher + catalog.cattle.io/display-name: Project Monitoring + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.26.0-0' + catalog.cattle.io/permits-os: linux,windows + catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.8.0-0' + catalog.cattle.io/release-name: rancher-project-monitoring +apiVersion: v2 +appVersion: 0.59.1 +dependencies: +- condition: grafana.enabled + name: grafana + repository: file://./charts/grafana +description: Collects several related Helm charts, Grafana dashboards, and Prometheus + rules combined with documentation and scripts to provide easy to operate end-to-end + Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster + Prometheus deployed via Prometheus Operator +home: https://github.com/prometheus-operator/kube-prometheus +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +keywords: +- prometheus +- monitoring +kubeVersion: '>=1.16.0-0' +maintainers: +- email: arvind.iyengar@suse.com + name: Arvind +- email: amangeet.samra@suse.com + name: Geet + url: https://github.com/geethub97 +name: rancher-project-monitoring +type: application +version: 0.3.1 diff --git a/charts/rancher-project-monitoring/0.3.1/README.md b/charts/rancher-project-monitoring/0.3.1/README.md new file mode 100644 index 00000000..eab333c3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/README.md @@ -0,0 +1,29 @@ +# rancher-project-monitoring + +This chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting), a Helm chart based off of [`kube-prometheus stack`](https://github.com/prometheus-operator/kube-prometheus). It deploys a collection of Kubernetes manifests, [Grafana](http://grafana.com/) dashboards, and [Prometheus rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) combined with documentation and scripts to provide easy to operate end-to-end Kubernetes project monitoring with [Prometheus](https://prometheus.io/) using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator). See the [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus) README for details about components, dashboards, and alerts. + +## Prerequisites + +- Kubernetes 1.16+ +- Helm 3+ + +## Install Chart + +This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). For a Prometheus Stack intended to be deployed standalone, please use [rancher-monitoring](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) or the upstream [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) project. + +## Dependencies + +This chart is designed to be deployed alongside an existing Prometheus Operator deployment in a cluster that has already installed the Prometheus Operator CRDs. Specifically, the chart is configured and intended to be deployed alongside [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), which deploys Prometheus Operator alongside a Cluster Prometheus that `rancher-project-monitoring` is configured to federate namespace-scoped metrics from by default. + +### Configuration + +Since this chart installs a project-scoped version of [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/), a Helm chart based off of [`kube-prometheus-stack`](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack), most of the options that apply to either of those charts will apply to this chart (e.g. support for configuring persistent volumes, ingresses, etc.) and can be passed in as part of the `spec.values` of the ProjectHelmChart that deploys this chart; however, certain advanced functionality (such as Thanos support) and options that pose security risks in Project environments (e.g. ability to `ignoreNamespaceSelectors` or modify the existing namepaceSelectors of the Cluster Prometheus, ability to mount additional scrape configs, etc.) have been removed from the `values.yaml` of the chart. For more information on how to configure values and what they mean, please see the comments and options provided on the `values.yaml` packaged with this chart. + +## Further Information + +For more in-depth documentation of configuration options meanings, please see + +- [`rancher-monitoring`](https://rancher.com/docs/rancher/v2.6/en/monitoring-alerting/) +- [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) +- [Prometheus](https://prometheus.io/docs/introduction/overview/) +- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana#grafana-helm-chart) \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/app-README.md b/charts/rancher-project-monitoring/0.3.1/app-README.md new file mode 100644 index 00000000..6b833291 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/app-README.md @@ -0,0 +1,10 @@ +# Rancher Project Monitoring and Alerting + +The chart installs a Project Monitoring Stack, which contains: +- [Prometheus](https://prometheus.io/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) (managed externally by [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator)) +- [Grafana](https://github.com/helm/charts/tree/master/stable/grafana) (deployed via an embedded Helm chart) +- Default PrometheusRules and Grafana dashboards based on the collection of community-curated resources from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus/) +- Default ServiceMonitors that watch the deployed resources + +Note: This chart is not intended for standalone use; it's intended to be deployed via [Prometheus Federator](https://github.com/rancher/prometheus-federator). \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/.helmignore b/charts/rancher-project-monitoring/0.3.1/charts/grafana/.helmignore new file mode 100644 index 00000000..8cade131 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.vscode +.project +.idea/ +*.tmproj +OWNERS diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/Chart.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/Chart.yaml new file mode 100644 index 00000000..9b0ca179 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/Chart.yaml @@ -0,0 +1,29 @@ +annotations: + catalog.cattle.io/hidden: "true" + catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.27.0-0' + catalog.cattle.io/os: linux + catalog.rancher.io/certified: rancher + catalog.rancher.io/namespace: cattle-monitoring-system + catalog.rancher.io/release-name: rancher-grafana +apiVersion: v2 +appVersion: 9.1.5 +description: The leading tool for querying and visualizing time series and metrics. +home: https://grafana.net +icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png +kubeVersion: ^1.8.0-0 +maintainers: +- email: zanhsieh@gmail.com + name: zanhsieh +- email: rluckie@cisco.com + name: rtluckie +- email: maor.friedman@redhat.com + name: maorfr +- email: miroslav.hadzhiev@gmail.com + name: Xtigyro +- email: mail@torstenwalter.de + name: torstenwalter +name: grafana +sources: +- https://github.com/grafana/grafana +type: application +version: 6.38.6 diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/README.md b/charts/rancher-project-monitoring/0.3.1/charts/grafana/README.md new file mode 100644 index 00000000..f3d31768 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/README.md @@ -0,0 +1,571 @@ +# Grafana Helm Chart + +* Installs the web dashboarding system [Grafana](http://grafana.org/) + +## Get Repo Info + +```console +helm repo add grafana https://grafana.github.io/helm-charts +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install my-release grafana/grafana +``` + +## Uninstalling the Chart + +To uninstall/delete the my-release deployment: + +```console +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Upgrading an existing Release to a new major version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an +incompatible breaking change needing manual actions. + +### To 4.0.0 (And 3.12.1) + +This version requires Helm >= 2.12.0. + +### To 5.0.0 + +You have to add --force to your helm upgrade command as the labels of the chart have changed. + +### To 6.0.0 + +This version requires Helm >= 3.1.0. + +## Configuration + +| Parameter | Description | Default | +|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| +| `replicas` | Number of nodes | `1` | +| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | +| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | +| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | +| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | +| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| +| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | +| `priorityClassName` | Name of Priority Class to assign pods | `nil` | +| `image.repository` | Image repository | `grafana/grafana` | +| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` | +| `image.sha` | Image sha (optional) | `` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` | +| `service.enabled` | Enable grafana service | `true` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Kubernetes port where service is exposed | `80` | +| `service.portName` | Name of the port on the service | `service` | +| `service.appProtocol` | Adds the appProtocol field to the service | `` | +| `service.targetPort` | Internal service is port | `3000` | +| `service.nodePort` | Kubernetes service nodePort | `nil` | +| `service.annotations` | Service annotations (can be templated) | `{}` | +| `service.labels` | Custom labels | `{}` | +| `service.clusterIP` | internal cluster service IP | `nil` | +| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | +| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | +| `service.externalIPs` | service external IP addresses | `[]` | +| `headlessService` | Create a headless service | `false` | +| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | +| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | +| `ingress.labels` | Custom labels | `{}` | +| `ingress.path` | Ingress accepted path | `/` | +| `ingress.pathType` | Ingress type of path | `Prefix` | +| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | +| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | +| `ingress.tls` | Ingress TLS configuration | `[]` | +| `resources` | CPU/Memory resource requests/limits | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Toleration labels for pod assignment | `[]` | +| `affinity` | Affinity settings for pod assignment | `{}` | +| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | +| `extraContainers` | Sidecar containers to add to the grafana pod | `""` | +| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | +| `extraLabels` | Custom labels for all manifests | `{}` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `persistence.enabled` | Use persistent volume to store data | `false` | +| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | +| `persistence.size` | Size of persistent volume claim | `10Gi` | +| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` | +| `persistence.storageClassName` | Type of persistent volume claim | `nil` | +| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | +| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | +| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | +| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` | +| `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` | +| `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` | +| `initChownData.enabled` | If false, don't reset data ownership at startup | true | +| `initChownData.image.repository` | init-chown-data container image repository | `busybox` | +| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | +| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | +| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | +| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | +| `schedulerName` | Alternate scheduler name | `nil` | +| `env` | Extra environment variables passed to pods | `{}` | +| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | +| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | +| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret | `{}` | +| `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` | +| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | +| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | +| `createConfigmap` | Enable creating the grafana configmap | `true` | +| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` | +| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | +| `plugins` | Plugins to be loaded along with Grafana | `[]` | +| `datasources` | Configure grafana datasources (passed through tpl) | `{}` | +| `alerting` | Configure grafana alerting (passed through tpl) | `{}` | +| `notifiers` | Configure grafana notifiers | `{}` | +| `dashboardProviders` | Configure grafana dashboard providers | `{}` | +| `dashboards` | Dashboards to import | `{}` | +| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | +| `grafana.ini` | Grafana's primary configuration | `{}` | +| `ldap.enabled` | Enable LDAP authentication | `false` | +| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | +| `ldap.config` | Grafana's LDAP configuration | `""` | +| `annotations` | Deployment annotations | `{}` | +| `labels` | Deployment labels | `{}` | +| `podAnnotations` | Pod annotations | `{}` | +| `podLabels` | Pod labels | `{}` | +| `podPortName` | Name of the grafana port on the pod | `grafana` | +| `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` | +| `sidecar.image.repository` | Sidecar image repository | `quay.io/kiwigrid/k8s-sidecar` | +| `sidecar.image.tag` | Sidecar image tag | `1.19.2` | +| `sidecar.image.sha` | Sidecar image sha (optional) | `""` | +| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | +| `sidecar.resources` | Sidecar resources | `{}` | +| `sidecar.securityContext` | Sidecar securityContext | `{}` | +| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` | +| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | +| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | +| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | +| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | +| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | +| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | +| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | +| `sidecar.dashboards.provider.type` | Provider type | `file` | +| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | +| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | +| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | +| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | +| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` | +| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | +| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | +| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | +| `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` | +| `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` | +| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | +| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | +| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` | +| `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` | +| `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` | +| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | +| `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | +| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | +| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | +| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` | +| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | +| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | +| `serviceAccount.autoMount` | Automount the service account token in the pod| `true` | +| `serviceAccount.annotations` | ServiceAccount annotations | | +| `serviceAccount.create` | Create service account | `true` | +| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | +| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | +| `rbac.create` | Create and use RBAC resources | `true` | +| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | +| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | +| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `true` | +| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `true` | +| `rbac.extraRoleRules` | Additional rules to add to the Role | [] | +| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | +| `command` | Define command to be executed by grafana container at startup | `nil` | +| `testFramework.enabled` | Whether to create test-related resources | `true` | +| `testFramework.image` | `test-framework` image repository. | `bats/bats` | +| `testFramework.tag` | `test-framework` image tag. | `v1.4.1` | +| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | +| `testFramework.securityContext` | `test-framework` securityContext | `{}` | +| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | +| `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | +| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | +| `downloadDashboardsImage.repository` | Curl docker image repo | `curlimages/curl` | +| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | +| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | +| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | +| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | +| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | +| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | +| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | +| `serviceMonitor.path` | Path to scrape | `/metrics` | +| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` | +| `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` | +| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | +| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | +| `serviceMonitor.relabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | +| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | +| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | +| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | +| `imageRenderer.image.tag` | image-renderer Image tag | `latest` | +| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | +| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | +| `imageRenderer.env` | extra env-vars for image-renderer | `{}` | +| `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | +| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | +| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | +| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | +| `imageRenderer.service.enabled` | Enable the image-renderer service | `true` | +| `imageRenderer.service.portName` | image-renderer service port name | `http` | +| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` | +| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` | +| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` | +| `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` | +| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | +| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | +| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | +| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | +| `imageRenderer.resources` | Set resource limits for image-renderer pdos | `{}` | +| `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` | +| `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` | +| `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` | +| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` | +| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` | +| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` | +| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` | +| `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` | + + + +### Example ingress with path + +With grafana 6.3 and above +```yaml +grafana.ini: + server: + domain: monitoring.example.com + root_url: "%(protocol)s://%(domain)s/grafana" + serve_from_sub_path: true +ingress: + enabled: true + hosts: + - "monitoring.example.com" + path: "/grafana" +``` + +### Example of extraVolumeMounts + +Volume can be type persistentVolumeClaim or hostPath but not both at same time. +If neither existingClaim or hostPath argument is given then type is emptyDir. + +```yaml +- extraVolumeMounts: + - name: plugins + mountPath: /var/lib/grafana/plugins + subPath: configs/grafana/plugins + existingClaim: existing-grafana-claim + readOnly: false + - name: dashboards + mountPath: /var/lib/grafana/dashboards + hostPath: /usr/shared/grafana/dashboards + readOnly: false +``` + +## Import dashboards + +There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: + +```yaml +dashboards: + default: + some-dashboard: + json: | + { + "annotations": + + ... + # Complete json file here + ... + + "title": "Some Dashboard", + "uid": "abcd1234", + "version": 1 + } + custom-dashboard: + # This is a path to a file inside the dashboards directory inside the chart directory + file: dashboards/custom-dashboard.json + prometheus-stats: + # Ref: https://grafana.com/dashboards/2 + gnetId: 2 + revision: 2 + datasource: Prometheus + local-dashboard: + url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json +``` + +## BASE64 dashboards + +Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) +A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. +If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. + +### Gerrit use case + +Gerrit API for download files has the following schema: where {project-name} and +{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard +the url value is + +## Sidecar for dashboards + +If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana +pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with +a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written +to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported +dashboards are deleted/updated. + +A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside +one configmap is currently not properly mirrored in grafana. + +Example dashboard config: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-dashboard + labels: + grafana_dashboard: "1" +data: + k8s-dashboard.json: |- + [...] +``` + +## Sidecar for datasources + +If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the data sources in grafana can be imported. + +Secrets are recommended over configmaps for this usecase because datasources usually contain private +data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): + +```yaml +datasources: + datasources.yaml: + apiVersion: 1 + datasources: + # name of the datasource. Required + - name: Graphite + # datasource type. Required + type: graphite + # access mode. proxy or direct (Server or Browser in the UI). Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://localhost:8080 + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: + # basic auth username + basicAuthUser: + # basic auth password + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: + # fields that will be converted to json and stored in json_data + jsonData: + graphiteVersion: "1.1" + tlsAuth: true + tlsAuthWithCACert: true + # json object of data that will be encrypted. + secureJsonData: + tlsCACert: "..." + tlsClientCert: "..." + tlsClientKey: "..." + version: 1 + # allow users to edit datasources from the UI. + editable: false +``` + +## Sidecar for notifiers + +If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana +pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and +filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in +those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, +the notification channels in grafana can be imported. The secrets must be created before +`helm install` so that the notifiers init container can list the secrets. + +Secrets are recommended over configmaps for this usecase because alert notification channels usually contain +private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. + +Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): + +```yaml +notifiers: + - name: notification-channel-1 + type: slack + uid: notifier1 + # either + org_id: 2 + # or + org_name: Main Org. + is_default: true + send_reminder: true + frequency: 1h + disable_resolve_message: false + # See `Supported Settings` section for settings supporter for each + # alert notification type. + settings: + recipient: 'XXX' + token: 'xoxb' + uploadImage: true + url: https://slack.com + +delete_notifiers: + - name: notification-channel-1 + uid: notifier1 + org_id: 2 + - name: notification-channel-2 + # default org_id: 1 +``` + +## How to serve Grafana with a path prefix (/grafana) + +In order to serve Grafana with a prefix (e.g., ), add the following to your values.yaml. + +```yaml +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: /$1 + nginx.ingress.kubernetes.io/use-regex: "true" + + path: /grafana/?(.*) + hosts: + - k8s.example.dev + +grafana.ini: + server: + root_url: http://localhost:3000/grafana # this host can be localhost +``` + +## How to securely reference secrets in grafana.ini + +This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. + +In grafana.ini: + +```yaml +grafana.ini: + [auth.generic_oauth] + enabled = true + client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} + client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} +``` + +Existing secret, or created along with helm: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: auth-generic-oauth-secret +type: Opaque +stringData: + client_id: + client_secret: +``` + +Include in the `extraSecretMounts` configuration flag: + +```yaml +- extraSecretMounts: + - name: auth-generic-oauth-secret-mount + secretName: auth-generic-oauth-secret + defaultMode: 0440 + mountPath: /etc/secrets/auth_generic_oauth + readOnly: true +``` + +### extraSecretMounts using a Container Storage Interface (CSI) provider + +This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure) + +```yaml +- extraSecretMounts: + - name: secrets-store-inline + mountPath: /run/secrets + readOnly: true + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: "my-provider" + nodePublishSecretRef: + name: akv-creds +``` + +## Image Renderer Plug-In + +This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker) + +```yaml +imageRenderer: + enabled: true +``` + +### Image Renderer NetworkPolicy + +By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance + +### High Availability for unified alerting + +If you want to run Grafana in a high availability cluster you need to enable +the headless service by setting `headlessService: true` in your `values.yaml` +file. + +As next step you have to setup the `grafana.ini` in your `values.yaml` in a way +that it will make use of the headless service to obtain all the IPs of the +cluster. You should replace ``{{ Name }}`` with the name of your helm deployment. + +```yaml +grafana.ini: + ... + unified_alerting: + enabled: true + ha_peers: {{ Name }}-headless:9094 + alerting: + enabled: false +``` diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/dashboards/custom-dashboard.json b/charts/rancher-project-monitoring/0.3.1/charts/grafana/dashboards/custom-dashboard.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/dashboards/custom-dashboard.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/NOTES.txt new file mode 100644 index 00000000..1fc8436d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/NOTES.txt @@ -0,0 +1,54 @@ +1. Get your '{{ .Values.adminUser }}' user password by running: + + kubectl get secret --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo + +2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: + + {{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}.svc.cluster.local +{{ if .Values.ingress.enabled }} + If you bind grafana to 80, please update values in values.yaml and reinstall: + ``` + securityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + + command: + - "setcap" + - "'cap_net_bind_service=+ep'" + - "/usr/sbin/grafana-server &&" + - "sh" + - "/run.sh" + ``` + Details refer to https://grafana.com/docs/installation/configuration/#http-port. + Or grafana would always crash. + + From outside the cluster, the server URL(s) are: +{{- range .Values.ingress.hosts }} + http://{{ . }} +{{- end }} +{{ else }} + Get the Grafana URL to visit by running these commands in the same shell: +{{ if contains "NodePort" .Values.service.type -}} + export NODE_PORT=$(kubectl get --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{ else if contains "LoadBalancer" .Values.service.type -}} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ template "grafana.namespace" . }} -w {{ template "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + http://$SERVICE_IP:{{ .Values.service.port -}} +{{ else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "grafana.namespace" . }} -l "app.kubernetes.io/name={{ template "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ template "grafana.namespace" . }} port-forward $POD_NAME 3000 +{{- end }} +{{- end }} + +3. Login with the password from step 1 and the username: {{ .Values.adminUser }} + +{{- if not .Values.persistence.enabled }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Grafana pod is terminated. ##### +################################################################################# +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_helpers.tpl new file mode 100644 index 00000000..e5e3b287 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,214 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "grafana.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "grafana.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "grafana.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "grafana.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{- define "grafana.serviceAccountNameTest" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} +{{- else -}} + {{ default "default" .Values.serviceAccount.nameTest }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "grafana.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "grafana.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.imageRenderer.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.imageRenderer.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels ImageRenderer +*/}} +{{- define "grafana.imageRenderer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Looks if there's an existing secret and reuse its password. If not it generates +new password and use it. +*/}} +{{- define "grafana.password" -}} +{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) -}} + {{- if $secret -}} + {{- index $secret "data" "admin-password" -}} + {{- else -}} + {{- (randAlphaNum 40) | b64enc | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for rbac. +*/}} +{{- define "grafana.rbac.apiVersion" -}} + {{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} + {{- print "rbac.authorization.k8s.io/v1" -}} + {{- else -}} + {{- print "rbac.authorization.k8s.io/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for HorizontalPodAutoscaler. +*/}} +{{- define "grafana.hpa.apiVersion" -}} + {{- if .Capabilities.APIVersions.Has "autoscaling/v2" }} + {{- print "autoscaling/v2" -}} + {{- else if .Capabilities.APIVersions.Has "autoscaling/v1" }} + {{- print "autoscaling/v1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "grafana.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "grafana.podDisruptionBudget.apiVersion" -}} + {{- if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return if ingress is stable. +*/}} +{{- define "grafana.ingress.isStable" -}} + {{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "grafana.ingress.supportsIngressClassName" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} + +{{/* +Return if ingress supports pathType. +*/}} +{{- define "grafana.ingress.supportsPathType" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_pod.tpl b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_pod.tpl new file mode 100644 index 00000000..ae36c28a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/_pod.tpl @@ -0,0 +1,885 @@ +{{- define "grafana.pod" -}} +{{- if .Values.schedulerName }} +schedulerName: "{{ .Values.schedulerName }}" +{{- end }} +serviceAccountName: {{ template "grafana.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} +{{- with .Values.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.hostAliases }} +hostAliases: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- if .Values.priorityClassName }} +priorityClassName: {{ .Values.priorityClassName }} +{{- end }} +{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.notifiers.enabled .Values.extraInitContainers (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources)) }} +initContainers: +{{- end }} +{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} + - name: init-chown-data + {{- if .Values.initChownData.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} + securityContext: + runAsNonRoot: false + runAsUser: 0 + command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] + {{- with .Values.initChownData.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- end }} +{{- if .Values.dashboards }} + - name: download-dashboards + {{- if .Values.downloadDashboardsImage.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} + command: ["/bin/sh"] + args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] + {{- with .Values.downloadDashboards.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + env: +{{- range $key, $value := .Values.downloadDashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" +{{- end }} + {{- with .Values.downloadDashboards.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if .Values.downloadDashboards.envFromSecret }} + envFrom: + - secretRef: + name: {{ tpl .Values.downloadDashboards.envFromSecret . }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/download_dashboards.sh" + subPath: download_dashboards.sh + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} + - name: {{ template "grafana.name" . }}-init-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end }} +{{- if .Values.sidecar.notifiers.enabled }} + - name: {{ template "grafana.name" . }}-sc-notifiers + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: LIST + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + {{- if .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.notifiers.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/notifiers" + - name: RESOURCE + value: {{ quote .Values.sidecar.notifiers.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} +{{- if .Values.extraInitContainers }} +{{ tpl (toYaml .Values.extraInitContainers) . | indent 2 }} +{{- end }} +{{- if .Values.image.pullSecrets }} +imagePullSecrets: +{{- $root := . }} +{{- range .Values.image.pullSecrets }} + - name: {{ tpl . $root }} +{{- end }} +{{- end }} +{{- if not .Values.enableKubeBackwardCompatibility }} +enableServiceLinks: {{ .Values.enableServiceLinks }} +{{- end }} +containers: +{{- if .Values.sidecar.dashboards.enabled }} + - name: {{ template "grafana.name" . }}-sc-dashboard + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.dashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.dashboards.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.dashboards.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.dashboards.label }}" + {{- if .Values.sidecar.dashboards.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.dashboards.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.dashboards.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.dashboards.folderAnnotation }} + - name: FOLDER_ANNOTATION + value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" + {{- end }} + {{- if .Values.sidecar.dashboards.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.dashboards.script }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchServerTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchServerTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchClientTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchClientTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + {{- if .Values.sidecar.dashboards.extraMounts }} + {{- toYaml .Values.sidecar.dashboards.extraMounts | trim | nindent 6}} + {{- end }} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: {{ template "grafana.name" . }}-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.datasources.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.datasources.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.datasources.script }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.datasources.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.datasources.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.datasources.watchServerTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchServerTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.datasources.watchClientTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchClientTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: {{ template "grafana.name" . }}-sc-plugins + {{- if .Values.sidecar.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.plugins.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.plugins.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.plugins.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.plugins.label }}" + {{- if .Values.sidecar.plugins.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.plugins.labelValue }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/plugins" + - name: RESOURCE + value: {{ quote .Values.sidecar.plugins.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + - name: NAMESPACE + value: "{{ template "project-prometheus-stack.projectNamespaceList" . }}" + {{- if .Values.sidecar.plugins.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.plugins.script }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.plugins.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.plugins.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.plugins.watchServerTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchServerTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.plugins.watchClientTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchClientTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} + - name: {{ .Chart.Name }} + {{- if .Values.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.command }} + command: + {{- range .Values.command }} + - {{ . }} + {{- end }} + {{- end}} + {{- with .Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/grafana.ini" + subPath: grafana.ini + {{- if .Values.ldap.enabled }} + - name: ldap + mountPath: "/etc/grafana/ldap.toml" + subPath: ldap.toml + {{- end }} + {{- $root := . }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ (tpl .subPath $root) | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- if .Values.dashboards }} +{{- range $provider, $dashboards := .Values.dashboards }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} + - name: dashboards-{{ $provider }} + mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" + subPath: "{{ $key }}.json" +{{- end }} +{{- end }} +{{- end }} +{{- end -}} +{{- if .Values.dashboardsConfigMaps }} +{{- range (keys .Values.dashboardsConfigMaps | sortAlpha) }} + - name: dashboards-{{ . }} + mountPath: "/var/lib/grafana/dashboards/{{ . }}" +{{- end }} +{{- end }} +{{- if .Values.datasources }} +{{- range (keys .Values.datasources | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.notifiers }} +{{- range (keys .Values.notifiers | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.alerting }} +{{- range (keys .Values.alerting | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.dashboardProviders }} +{{- range (keys .Values.dashboardProviders | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} +{{ if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" + subPath: provider.yaml +{{- end}} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + ports: + - name: {{ .Values.podPortName }} + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + env: + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if .Values.plugins }} + - name: GF_INSTALL_PLUGINS + valueFrom: + configMapKeyRef: + name: {{ template "grafana.fullname" . }} + key: plugins + {{- end }} + {{- if .Values.smtp.existingSecret }} + - name: GF_SMTP_USER + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.userKey | default "user" }} + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.passwordKey | default "password" }} + {{- end }} + {{- if .Values.imageRenderer.enabled }} + - name: GF_RENDERING_SERVER_URL + value: http://{{ template "grafana.fullname" . }}-image-renderer.{{ template "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render + - name: GF_RENDERING_CALLBACK_URL + value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} + {{- end }} + - name: GF_PATHS_DATA + value: {{ (get .Values "grafana.ini").paths.data }} + - name: GF_PATHS_LOGS + value: {{ (get .Values "grafana.ini").paths.logs }} + - name: GF_PATHS_PLUGINS + value: {{ (get .Values "grafana.ini").paths.plugins }} + - name: GF_PATHS_PROVISIONING + value: {{ (get .Values "grafana.ini").paths.provisioning }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: +{{ tpl (toYaml $value) $ | indent 10 }} + {{- end }} +{{- range $key, $value := .Values.env }} + - name: "{{ tpl $key $ }}" + value: "{{ tpl (print $value) $ }}" +{{- end }} + {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} + envFrom: + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ tpl .Values.envFromSecret . }} + {{- end }} + {{- if .Values.envRenderSecret }} + - secretRef: + name: {{ template "grafana.fullname" . }}-env + {{- end }} + {{- range .Values.envFromSecrets }} + - secretRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- range .Values.envFromConfigMaps }} + - configMapRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- end }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- if .Values.lifecycleHooks }} + lifecycle: {{ tpl (.Values.lifecycleHooks | toYaml) . | nindent 6 }} +{{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- with .Values.extraContainers }} +{{ tpl . $ | indent 2 }} +{{- end }} +nodeSelector: {{ include "linux-node-selector" . | nindent 2 }} +{{- if .Values.nodeSelector }} +{{ toYaml .Values.nodeSelector | indent 2 }} +{{- end }} +{{- $root := . }} +{{- with .Values.affinity }} +affinity: +{{ tpl (toYaml .) $root | indent 2 }} +{{- end }} +{{- with .Values.topologySpreadConstraints }} +topologySpreadConstraints: + {{- toYaml . | nindent 2 }} +{{- end }} +tolerations: {{ include "linux-node-tolerations" . | nindent 2 }} +{{- if .Values.tolerations }} +{{ toYaml .Values.tolerations | indent 2 }} +{{- end }} +volumes: + - name: config + configMap: + name: {{ template "grafana.fullname" . }} +{{- $root := . }} +{{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} + {{- if .items }} + items: {{ toYaml .items | nindent 6 }} + {{- end }} +{{- end }} + {{- if .Values.dashboards }} + {{- range (keys .Values.dashboards | sortAlpha) }} + - name: dashboards-{{ . }} + configMap: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsConfigMaps }} + {{ $root := . }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} + - name: dashboards-{{ $provider }} + configMap: + name: {{ tpl $name $root }} + {{- end }} + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + secret: + {{- if .Values.ldap.existingSecret }} + secretName: {{ .Values.ldap.existingSecret }} + {{- else }} + secretName: {{ template "grafana.fullname" . }} + {{- end }} + items: + - key: ldap-toml + path: ldap.toml + {{- end }} +{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} + - name: storage + persistentVolumeClaim: + claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} +{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} +# nothing +{{- else }} + - name: storage +{{- if .Values.persistence.inMemory.enabled }} + emptyDir: + medium: Memory +{{- if .Values.persistence.inMemory.sizeLimit }} + sizeLimit: {{ .Values.persistence.inMemory.sizeLimit }} +{{- end -}} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume +{{- if .Values.sidecar.dashboards.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.dashboards.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + configMap: + name: {{ template "grafana.fullname" . }}-config-dashboards +{{- end }} +{{- end }} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume +{{- if .Values.sidecar.datasources.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.datasources.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume +{{- if .Values.sidecar.plugins.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.plugins.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume +{{- if .Values.sidecar.notifiers.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.notifiers.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- range .Values.extraSecretMounts }} +{{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- if .items }} + items: {{ toYaml .items | nindent 6 }} + {{- end }} +{{- else if .projected }} + - name: {{ .name }} + projected: {{- toYaml .projected | nindent 6 }} +{{- else if .csi }} + - name: {{ .name }} + csi: {{- toYaml .csi | nindent 6 }} +{{- end }} +{{- end }} +{{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + path: {{ .hostPath }} + {{- else if .csi }} + csi: + data: + {{ toYaml .data | nindent 6 }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} +{{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + emptyDir: {} +{{- end -}} +{{- if .Values.extraContainerVolumes }} +{{ tpl (toYaml .Values.extraContainerVolumes) . | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrole.yaml new file mode 100644 index 00000000..154658b5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled (or .Values.rbac.extraClusterRoleRules (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} +rules: +{{- if or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled) }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end}} +{{- with .Values.rbac.extraClusterRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end}} +{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..4accbfac --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/clusterrolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "grafana.fullname" . }}-clusterrolebinding + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +roleRef: + kind: ClusterRole +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap-dashboard-provider.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap-dashboard-provider.yaml new file mode 100644 index 00000000..65d73858 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap-dashboard-provider.yaml @@ -0,0 +1,29 @@ +{{- if .Values.sidecar.dashboards.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-config-dashboards + namespace: {{ template "grafana.namespace" . }} +data: + provider.yaml: |- + apiVersion: 1 + providers: + - name: '{{ .Values.sidecar.dashboards.provider.name }}' + orgId: {{ .Values.sidecar.dashboards.provider.orgid }} + {{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + folder: '{{ .Values.sidecar.dashboards.provider.folder }}' + {{- end}} + type: {{ .Values.sidecar.dashboards.provider.type }} + disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} + allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} + updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }} + options: + foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} +{{- end}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap.yaml new file mode 100644 index 00000000..2461d175 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/configmap.yaml @@ -0,0 +1,117 @@ +{{- if .Values.createConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +data: +{{- if .Values.plugins }} + plugins: {{ join "," .Values.plugins }} +{{- end }} + grafana.ini: | +{{- range $elem, $elemVal := index .Values "grafana.ini" }} + {{- if not (kindIs "map" $elemVal) }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} +{{- end }} +{{- range $key, $value := index .Values "grafana.ini" }} + {{- if kindIs "map" $value }} + [{{ $key }}] + {{- range $elem, $elemVal := $value }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{- if .Values.datasources }} +{{ $root := . }} + {{- range $key, $value := .Values.datasources }} + {{ $key }}: | +{{ tpl (toYaml $value | indent 4) $root }} + {{- end -}} +{{- end -}} + +{{- if .Values.notifiers }} + {{- range $key, $value := .Values.notifiers }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.alerting }} +{{ $root := . }} + {{- range $key, $value := .Values.alerting }} + {{ $key }}: | +{{ tpl (toYaml $value | indent 4) $root }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboards }} + download_dashboards.sh: | + #!/usr/bin/env sh + set -euf + {{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{- range $value.providers }} + mkdir -p {{ .options.path }} + {{- end }} + {{- end }} + {{- end }} + {{ $dashboardProviders := .Values.dashboardProviders }} + {{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} + curl -skf \ + --connect-timeout 60 \ + --max-time 60 \ + {{- if not $value.b64content }} + -H "Accept: application/json" \ + {{- if $value.token }} + -H "Authorization: token {{ $value.token }}" \ + {{- end }} + {{- if $value.bearerToken }} + -H "Authorization: Bearer {{ $value.bearerToken }}" \ + {{- end }} + {{- if $value.gitlabToken }} + -H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \ + {{- end }} + -H "Content-Type: application/json;charset=UTF-8" \ + {{ end }} + {{- $dpPath := "" -}} + {{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers }} + {{- if eq $kd.name $provider -}} + {{- $dpPath = $kd.options.path -}} + {{- end -}} + {{- end -}} + {{- if $value.url -}}"{{ $value.url }}"{{- else -}}"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download"{{- end -}}{{ if $value.datasource }} | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g'{{ end }}{{- if $value.b64content -}} | base64 -d {{- end -}} \ + > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" + {{- end }} + {{- end -}} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/dashboards-json-configmap.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/dashboards-json-configmap.yaml new file mode 100644 index 00000000..59e0be64 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/dashboards-json-configmap.yaml @@ -0,0 +1,35 @@ +{{- if .Values.dashboards }} +{{ $files := .Files }} +{{- range $provider, $dashboards := .Values.dashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} + namespace: {{ template "grafana.namespace" $ }} + labels: + {{- include "grafana.labels" $ | nindent 4 }} + dashboard-provider: {{ $provider }} +{{- if $dashboards }} +data: +{{- $dashboardFound := false }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} +{{- $dashboardFound = true }} +{{ print $key | indent 2 }}.json: +{{- if hasKey $value "json" }} + |- +{{ $value.json | indent 6 }} +{{- end }} +{{- if hasKey $value "file" }} +{{ toYaml ( $files.Get $value.file ) | indent 4}} +{{- end }} +{{- end }} +{{- end }} +{{- if not $dashboardFound }} + {} +{{- end }} +{{- end }} +--- +{{- end }} + +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/deployment.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/deployment.yaml new file mode 100644 index 00000000..fee9c335 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/deployment.yaml @@ -0,0 +1,50 @@ +{{ if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} + replicas: {{ .Values.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- with .Values.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} +{{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- if .Values.envRenderSecret }} + checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | indent 6 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/headless-service.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/headless-service.yaml new file mode 100644 index 00000000..b5faddcf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/headless-service.yaml @@ -0,0 +1,22 @@ +{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset"))}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-headless + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + clusterIP: None + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} + type: ClusterIP + ports: + - protocol: TCP + port: 3000 + targetPort: {{ .Values.service.targetPort }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/hpa.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/hpa.yaml new file mode 100644 index 00000000..236a06d6 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/hpa.yaml @@ -0,0 +1,21 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: {{ template "grafana.hpa.apiVersion" . }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "grafana.name" . }} + helm.sh/chart: {{ template "grafana.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "grafana.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: +{{ toYaml .Values.autoscaling.metrics | indent 4 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-deployment.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-deployment.yaml new file mode 100644 index 00000000..97a8675b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-deployment.yaml @@ -0,0 +1,123 @@ +{{ if .Values.imageRenderer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.labels }} +{{ toYaml .Values.imageRenderer.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.imageRenderer.replicas }} + revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} +{{- with .Values.imageRenderer.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} +{{- with .Values.imageRenderer.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- with .Values.imageRenderer.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + + {{- if .Values.imageRenderer.schedulerName }} + schedulerName: "{{ .Values.imageRenderer.schedulerName }}" + {{- end }} + {{- if .Values.imageRenderer.serviceAccountName }} + serviceAccountName: "{{ .Values.imageRenderer.serviceAccountName }}" + {{- else }} + serviceAccountName: {{ template "grafana.serviceAccountName" . }} + {{- end }} + {{- if .Values.imageRenderer.securityContext }} + securityContext: + {{- toYaml .Values.imageRenderer.securityContext | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.hostAliases }} + hostAliases: + {{- toYaml .Values.imageRenderer.hostAliases | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.priorityClassName }} + priorityClassName: {{ .Values.imageRenderer.priorityClassName }} + {{- end }} + {{- if .Values.imageRenderer.image.pullSecrets }} + imagePullSecrets: + {{- $root := . }} + {{- range .Values.imageRenderer.image.pullSecrets }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + containers: + - name: {{ .Chart.Name }}-image-renderer + {{- if .Values.imageRenderer.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} + {{- if .Values.imageRenderer.command }} + command: + {{- range .Values.imageRenderer.command }} + - {{ . }} + {{- end }} + {{- end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + containerPort: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: {{ .Values.imageRenderer.service.portName }} + env: + - name: HTTP_PORT + value: {{ .Values.imageRenderer.service.targetPort | quote }} + {{- range $key, $value := .Values.imageRenderer.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + securityContext: + capabilities: + drop: ['all'] + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /tmp + name: image-renderer-tmpfs + {{- with .Values.imageRenderer.resources }} + resources: +{{ toYaml . | indent 12 }} + {{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + {{- if .Values.imageRenderer.nodeSelector }} +{{ toYaml . | indent 8 }} + {{- end }} + {{- $root := . }} + {{- with .Values.imageRenderer.affinity }} + affinity: +{{ tpl (toYaml .) $root | indent 8 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + {{- if .Values.imageRenderer.tolerations }} +{{ toYaml . | indent 8 }} + {{- end }} + volumes: + - name: image-renderer-tmpfs + emptyDir: {} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-network-policy.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-network-policy.yaml new file mode 100644 index 00000000..0d9bdfe4 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-network-policy.yaml @@ -0,0 +1,73 @@ +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-ingress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer ingress traffic from grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Ingress + ingress: + - ports: + - port: {{ .Values.imageRenderer.service.targetPort }} + protocol: TCP + from: + - namespaceSelector: + matchLabels: + name: {{ template "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} + +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-egress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer egress traffic to grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Egress + egress: + # allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # talk only to grafana + - ports: + - port: {{ .Values.service.port }} + protocol: TCP + to: + - podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-service.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-service.yaml new file mode 100644 index 00000000..fcf707a3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/image-renderer-service.yaml @@ -0,0 +1,33 @@ +{{ if .Values.imageRenderer.enabled }} +{{ if .Values.imageRenderer.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.service.labels }} +{{ toYaml .Values.imageRenderer.service.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + type: ClusterIP + {{- if .Values.imageRenderer.service.clusterIP }} + clusterIP: {{ .Values.imageRenderer.service.clusterIP }} + {{end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + port: {{ .Values.imageRenderer.service.port }} + protocol: TCP + targetPort: {{ .Values.imageRenderer.service.targetPort }} + {{- if .Values.imageRenderer.appProtocol }} + appProtocol: {{ .Values.imageRenderer.appProtocol }} + {{- end }} + selector: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} +{{ end }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/ingress.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/ingress.yaml new file mode 100644 index 00000000..7699ceca --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/ingress.yaml @@ -0,0 +1,78 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +{{- $ingressPathType := .Values.ingress.pathType -}} +{{- $extraPaths := .Values.ingress.extraPaths -}} +apiVersion: {{ include "grafana.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels | indent 4 }} +{{- end }} + {{- if .Values.ingress.annotations }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end -}} +{{- if .Values.ingress.tls }} + tls: +{{ tpl (toYaml .Values.ingress.tls) $ | indent 4 }} +{{- end }} + rules: + {{- if .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} + - host: {{ tpl . $}} + http: + paths: +{{- if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + - backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- if $ingressPath }} + path: {{ $ingressPath }} + {{- end }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + {{- end -}} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/networkpolicy.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/networkpolicy.yaml new file mode 100644 index 00000000..b751d943 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/networkpolicy.yaml @@ -0,0 +1,52 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + policyTypes: + {{- if .Values.networkPolicy.ingress }} + - Ingress + {{- end }} + {{- if .Values.networkPolicy.egress.enabled }} + - Egress + {{- end }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + + {{- if .Values.networkPolicy.egress.enabled }} + egress: + - ports: + {{ .Values.networkPolicy.egress.ports | toJson }} + {{- end }} + {{- if .Values.networkPolicy.ingress }} + ingress: + - ports: + - port: {{ .Values.service.targetPort }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "grafana.fullname" . }}-client: "true" + {{- with .Values.networkPolicy.explicitNamespacesSelector }} + - namespaceSelector: + {{- toYaml . | nindent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "grafana.labels" . | nindent 14 }} + role: read + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/nginx-config.yaml new file mode 100644 index 00000000..6b1e8ede --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/nginx-config.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-nginx-proxy-config + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +data: + nginx.conf: |- + worker_processes auto; + error_log /dev/stdout warn; + pid /var/cache/nginx/nginx.pid; + + events { + worker_connections 1024; + } + + http { + include /etc/nginx/mime.types; + log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; + + proxy_connect_timeout 10; + proxy_read_timeout 180; + proxy_send_timeout 5; + proxy_buffering off; + proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + server { + listen 8080; + access_log off; + + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + proxy_set_header Host $http_host; + + location /api/dashboards { + proxy_pass http://localhost:3000; + } + + location /api/search { + proxy_pass http://localhost:3000; + + sub_filter_types application/json; + sub_filter_once off; + } + + location /api/live/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $http_host; + proxy_pass http://localhost:3000; + } + + location / { + proxy_cache my_zone; + proxy_cache_valid 200 302 1d; + proxy_cache_valid 301 30d; + proxy_cache_valid any 5m; + proxy_cache_bypass $http_cache_control; + add_header X-Proxy-Cache $upstream_cache_status; + add_header Cache-Control "public"; + + proxy_pass http://localhost:3000/; + + sub_filter_once off; +{{- if not (empty .Values.global.cattle.clusterId) }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- else }} + sub_filter '"appSubUrl":""' '"appSubUrl":"/api/v1/namespaces/{{ template "grafana.namespace" . }}/services/http:{{ template "grafana.fullname" . }}:{{ .Values.service.port }}/proxy"'; +{{- end }} + sub_filter '"url":"/' '"url":"./'; + sub_filter ':"/avatar/' ':"avatar/'; + + if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { + expires 90d; + } + + rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; + + } + } + } diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/poddisruptionbudget.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/poddisruptionbudget.yaml new file mode 100644 index 00000000..70901b70 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +spec: +{{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/podsecuritypolicy.yaml new file mode 100644 index 00000000..82d295ad --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/podsecuritypolicy.yaml @@ -0,0 +1,45 @@ +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.rbac.pspAnnotations }} + annotations: {{ toYaml .Values.rbac.pspAnnotations | nindent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + # Default set from Docker, with DAC_OVERRIDE and CHOWN + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'csi' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/pvc.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/pvc.yaml new file mode 100644 index 00000000..8a3ee122 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/pvc.yaml @@ -0,0 +1,35 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.persistence.annotations }} + annotations: +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .Values.persistence.finalizers }} + finalizers: +{{ toYaml . | indent 4 }} + {{- end }} +spec: + accessModes: +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClassName }} + storageClassName: {{ .Values.persistence.storageClassName }} + {{- end -}} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 6 }} + {{- end }} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/role.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/role.yaml new file mode 100644 index 00000000..80e2c596 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/role.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +{{- if or .Values.global.cattle.psp.enabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled (or .Values.sidecar.plugins.enabled .Values.rbac.extraRoleRules)))) }} +rules: +{{- if .Values.global.cattle.psp.enabled }} +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}] +{{- end }} +{{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled)) }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end }} +{{- with .Values.rbac.extraRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/rolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/rolebinding.yaml new file mode 100644 index 00000000..e0107255 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/rolebinding.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }} +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret-env.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret-env.yaml new file mode 100644 index 00000000..5c09313e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret-env.yaml @@ -0,0 +1,14 @@ +{{- if .Values.envRenderSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }}-env + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +type: Opaque +data: +{{- range $key, $val := .Values.envRenderSecret }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end -}} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret.yaml new file mode 100644 index 00000000..c8aa750a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/secret.yaml @@ -0,0 +1,26 @@ +{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +type: Opaque +data: + {{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} + admin-user: {{ .Values.adminUser | b64enc | quote }} + {{- if .Values.adminPassword }} + admin-password: {{ .Values.adminPassword | b64enc | quote }} + {{- else }} + admin-password: {{ template "grafana.password" . }} + {{- end }} + {{- end }} + {{- if not .Values.ldap.existingSecret }} + ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/service.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/service.yaml new file mode 100644 index 00000000..d0a1756c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/service.yaml @@ -0,0 +1,55 @@ +{{ if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- $root := . }} +{{- with .Values.service.annotations }} + annotations: +{{ tpl (toYaml . | indent 4) $root }} +{{- end }} +spec: +{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{end}} +{{- else if eq .Values.service.type "LoadBalancer" }} + type: {{ .Values.service.type }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} + {{- end -}} +{{- else }} + type: {{ .Values.service.type }} +{{- end }} +{{- if .Values.service.externalIPs }} + externalIPs: +{{ toYaml .Values.service.externalIPs | indent 4 }} +{{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.service.targetPort }} + {{- if .Values.service.appProtocol }} + appProtocol: {{ .Values.service.appProtocol }} + {{- end }} + {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{.Values.service.nodePort}} + {{ end }} + {{- if .Values.extraExposePorts }} + {{- tpl (toYaml .Values.extraExposePorts) . | nindent 4 }} + {{- end }} + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 00000000..4ccee15e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- $root := . }} +{{- with .Values.serviceAccount.annotations }} + annotations: +{{ tpl (toYaml . | indent 4) $root }} +{{- end }} + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/servicemonitor.yaml new file mode 100644 index 00000000..31ab6b88 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/servicemonitor.yaml @@ -0,0 +1,58 @@ +{{- if .Values.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "grafana.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ tpl .Values.serviceMonitor.namespace . }} + {{- else }} + namespace: {{ template "grafana.namespace" . }} + {{- end }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.serviceMonitor.path }} + scheme: {{ .Values.serviceMonitor.scheme }} + {{- if .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + metricRelabelings: + {{- if .Values.serviceMonitor.metricRelabelings }} + {{- toYaml .Values.serviceMonitor.metricRelabelings | nindent 6 }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} + {{- if .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} + {{- end }} + jobLabel: "{{ .Release.Name }}" + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 8 }} + namespaceSelector: + matchNames: + - {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/statefulset.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/statefulset.yaml new file mode 100644 index 00000000..aa6f305e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/statefulset.yaml @@ -0,0 +1,56 @@ +{{- if (or (.Values.useStatefulSet) (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")))}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + serviceName: {{ template "grafana.fullname" . }}-headless + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} + {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} + {{- if .Values.persistence.enabled}} + volumeClaimTemplates: + - metadata: + name: storage + spec: +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" .Values.persistence.accessModes }} +{{- $_ := required "Must provide at least one access mode for persistent volumes used by Grafana" (first .Values.persistence.accessModes) }} + accessModes: {{ .Values.persistence.accessModes }} + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: {{ required "Must provide size for persistent volumes used by Grafana" .Values.persistence.size }} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 10 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-configmap.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-configmap.yaml new file mode 100644 index 00000000..ff53aaf1 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-configmap.yaml @@ -0,0 +1,17 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +data: + run.sh: |- + @test "Test Health" { + url="http://{{ template "grafana.fullname" . }}/api/health" + + code=$(wget --server-response --spider --timeout 10 --tries 1 ${url} 2>&1 | awk '/^ HTTP/{print $2}') + [ "$code" == "200" ] + } +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-podsecuritypolicy.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-podsecuritypolicy.yaml new file mode 100644 index 00000000..5dd736ef --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-podsecuritypolicy.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }}-test + labels: + {{- include "grafana.labels" . | nindent 4 }} +spec: + allowPrivilegeEscalation: true + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + fsGroup: + rule: RunAsAny + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + volumes: + - configMap + - downwardAPI + - emptyDir + - projected + - csi + - secret +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-role.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-role.yaml new file mode 100644 index 00000000..ea2f8c6b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-role.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}-test] +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-rolebinding.yaml new file mode 100644 index 00000000..7eda2651 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.testFramework.enabled .Values.global.cattle.psp.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }}-test + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "grafana.fullname" . }}-test +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountNameTest" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-serviceaccount.yaml new file mode 100644 index 00000000..5c335073 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test-serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} + name: {{ template "grafana.serviceAccountNameTest" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test.yaml new file mode 100644 index 00000000..3a84fbe0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/templates/tests/test.yaml @@ -0,0 +1,51 @@ +{{- if .Values.testFramework.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ template "grafana.fullname" . }}-test + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" + namespace: {{ template "grafana.namespace" . }} +spec: + serviceAccountName: {{ template "grafana.serviceAccountNameTest" . }} + {{- if .Values.testFramework.securityContext }} + securityContext: {{ toYaml .Values.testFramework.securityContext | nindent 4 }} + {{- end }} + {{- $root := . }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} + {{- if .Values.nodeSelector }} +{{ toYaml .Values.nodeSelector | indent 4 }} + {{- end }} + {{- $root := . }} + {{- with .Values.affinity }} + affinity: +{{ tpl (toYaml .) $root | indent 4 }} + {{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.tolerations }} +{{ toYaml .Values.tolerations | indent 4 }} +{{- end }} + containers: + - name: {{ .Release.Name }}-test + image: "{{ template "system_default_registry" . }}{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" + imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" + command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] + volumeMounts: + - mountPath: /tests + name: tests + readOnly: true + volumes: + - name: tests + configMap: + name: {{ template "grafana.fullname" . }}-test + restartPolicy: Never +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/charts/grafana/values.yaml b/charts/rancher-project-monitoring/0.3.1/charts/grafana/values.yaml new file mode 100644 index 00000000..196a07bf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/charts/grafana/values.yaml @@ -0,0 +1,1062 @@ +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectNamespaces: [] + +rbac: + create: true + ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) + # useExistingRole: name-of-some-(cluster)role + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + namespaced: false + extraRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] + extraClusterRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] +serviceAccount: + create: true + name: + nameTest: +## Service account annotations. Can be templated. +# annotations: +# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + autoMount: true + +replicas: 1 + +## Create a headless service for the deployment +headlessService: false + +## Create HorizontalPodAutoscaler object for deployment type +# +autoscaling: + enabled: false +# minReplicas: 1 +# maxReplicas: 10 +# metrics: +# - type: Resource +# resource: +# name: cpu +# targetAverageUtilization: 60 +# - type: Resource +# resource: +# name: memory +# targetAverageUtilization: 60 + +## See `kubectl explain poddisruptionbudget.spec` for more +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} +# minAvailable: 1 +# maxUnavailable: 1 + +## See `kubectl explain deployment.spec.strategy` for more +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +deploymentStrategy: + type: RollingUpdate + +readinessProbe: + httpGet: + path: /api/health + port: 3000 + +livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 30 + failureThreshold: 10 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: "default-scheduler" + +image: + repository: rancher/mirrored-grafana-grafana + # Overrides the Grafana image tag whose default is the chart appVersion + tag: 9.1.5 + sha: "" + pullPolicy: IfNotPresent + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Can be templated. + ## + # pullSecrets: + # - myRegistrKeySecretName + +testFramework: + enabled: false + image: "rancher/mirrored-bats-bats" + tag: "v1.4.1" + imagePullPolicy: IfNotPresent + securityContext: + runAsNonRoot: true + runAsUser: 1000 + +securityContext: + runAsNonRoot: true + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 + +containerSecurityContext: + {} + +# Enable creating the grafana configmap +createConfigmap: true + +# Extra configmaps to mount in grafana pods +# Values are templated. +extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # subPath: certificates.crt # (optional) + # configMap: certs-configmap + # readOnly: true + + +extraEmptyDirMounts: [] + # - name: provisioning-notifiers + # mountPath: /etc/grafana/provisioning/notifiers + + +# Apply extra labels to common labels. +extraLabels: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: + +downloadDashboardsImage: + repository: rancher/mirrored-curlimages-curl + tag: 7.85.0 + sha: "" + pullPolicy: IfNotPresent + +downloadDashboards: + env: {} + envFromSecret: "" + resources: {} + securityContext: {} + +## Pod Annotations +# podAnnotations: {} + +## Pod Labels +# podLabels: {} + +podPortName: grafana + +## Deployment annotations +# annotations: {} + +## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + enabled: true + type: ClusterIP + port: 80 + targetPort: 3000 + # targetPort: 4181 To be used with a proxy extraContainer + ## Service annotations. Can be templated. + annotations: {} + labels: {} + portName: service + # Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + +serviceMonitor: + ## If true, a ServiceMonitor CRD is created for a prometheus operator + ## https://github.com/coreos/prometheus-operator + ## + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 1m + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + relabelings: [] + +extraExposePorts: [] + # - name: keycloak + # port: 8080 + # targetPort: 8080 + # type: ClusterIP + +# overrides pod.spec.hostAliases in the grafana deployment's pods +hostAliases: [] + # - ip: "1.2.3.4" + # hostnames: + # - "my.host.com" + +ingress: + enabled: false + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + # Values can be templated + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + hosts: + - chart-example.local + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## Or for k8s > 1.19 + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + +## Node labels for pod assignment +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +# +nodeSelector: {} + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Topology Spread Constraints +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] + +## Additional init containers (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +## +extraInitContainers: [] + +## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod +extraContainers: "" +# extraContainers: | +# - name: proxy +# image: quay.io/gambol99/keycloak-proxy:latest +# args: +# - -provider=github +# - -client-id= +# - -client-secret= +# - -github-org= +# - -email-domain=* +# - -cookie-secret= +# - -http-address=http://0.0.0.0:4181 +# - -upstream-url=http://127.0.0.1:3000 +# ports: +# - name: proxy-web +# containerPort: 4181 + +## Volumes that can be used in init containers that will not be mounted to deployment pods +extraContainerVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + type: pvc + enabled: false + # storageClassName: default + accessModes: + - ReadWriteOnce + size: 10Gi + # annotations: {} + finalizers: + - kubernetes.io/pvc-protection + # selectorLabels: {} + ## Sub-directory of the PV to mount. Can be templated. + # subPath: "" + ## Name of an existing PVC. Can be templated. + # existingClaim: + + ## If persistence is not enabled, this allows to mount the + ## local storage in-memory to improve performance + ## + inMemory: + enabled: false + ## The maximum usage on memory medium EmptyDir would be + ## the minimum value between the SizeLimit specified + ## here and the sum of memory limits of all containers in a pod + ## + # sizeLimit: 300Mi + +initChownData: + ## If false, data ownership will not be reset at startup + ## This allows the prometheus-server to be run with an arbitrary user + ## + enabled: true + + ## initChownData container image + ## + image: + repository: rancher/mirrored-library-busybox + tag: "1.31.1" + sha: "" + pullPolicy: IfNotPresent + + ## initChownData resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + +# Administrator credentials when not using an existing secret (see below) +adminUser: admin +# adminPassword: strongpassword + +# Use an existing secret for the admin user. +admin: + ## Name of the secret. Can be templated. + existingSecret: "" + userKey: admin-user + passwordKey: admin-password + +## Define command to be executed at startup by grafana container +## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) +## Default is "run.sh" as defined in grafana's Dockerfile +# command: +# - "sh" +# - "/run.sh" + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Extra environment variables that will be pass onto deployment pods +## +## to provide grafana with access to CloudWatch on AWS EKS: +## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) +## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the +## same oidc eks provider as noted before (same as the existing line) +## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name +## +## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", +## +## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess +## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) +## +## env: +## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here +## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token +## AWS_REGION: us-east-1 +## +## 5. uncomment the EKS section in extraSecretMounts: below +## 6. uncomment the annotation section in the serviceAccount: above +## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn + +env: {} + +## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core +## Renders in container spec as: +## env: +## ... +## - name: +## valueFrom: +## +envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + +## The name of a secret in the same kubernetes namespace which contain values to be added to the environment +## This can be useful for auth tokens, etc. Value is templated. +envFromSecret: "" + +## Sensible environment variables that will be rendered as new secret object +## This can be useful for auth tokens, etc +envRenderSecret: {} + +## The names of secrets in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. +## Name is templated. +envFromSecrets: [] +## - name: secret-name +## optional: true + +## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. +## Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core +envFromConfigMaps: [] +## - name: configmap-name +## optional: true + +# Inject Kubernetes services as environment variables. +# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables +enableServiceLinks: true + +## Additional grafana server secret mounts +# Defines additional mounts with secrets. Secrets must be manually created in the namespace. +extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # secretName: grafana-secret-files + # readOnly: true + # subPath: "" + # + # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) + # - name: aws-iam-token + # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount + # readOnly: true + # projected: + # defaultMode: 420 + # sources: + # - serviceAccountToken: + # audience: sts.amazonaws.com + # expirationSeconds: 86400 + # path: token + # + # for CSI e.g. Azure Key Vault use the following + # - name: secrets-store-inline + # mountPath: /run/secrets + # readOnly: true + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "akv-grafana-spc" + # nodePublishSecretRef: # Only required when using service principal mode + # name: grafana-akv-creds # Only required when using service principal mode + +## Additional grafana server volume mounts +# Defines additional volume mounts. +extraVolumeMounts: [] + # - name: extra-volume-0 + # mountPath: /mnt/volume0 + # readOnly: true + # existingClaim: volume-claim + # - name: extra-volume-1 + # mountPath: /mnt/volume1 + # readOnly: true + # hostPath: /usr/shared/ + # - name: grafana-secrets + # csi: true + # data: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "grafana-env-spc" + +## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request +lifecycleHooks: {} + # postStart: + # exec: + # command: [] + +## Pass the plugins you want installed as a list. +## +plugins: [] + # - digrich-bubblechart-panel + # - grafana-clock-panel + +## Configure grafana datasources +## ref: http://docs.grafana.org/administration/provisioning/#datasources +## +datasources: {} +# datasources.yaml: +# apiVersion: 1 +# datasources: +# - name: Prometheus +# type: prometheus +# url: http://prometheus-prometheus-server +# access: proxy +# isDefault: true +# - name: CloudWatch +# type: cloudwatch +# access: proxy +# uid: cloudwatch +# editable: false +# jsonData: +# authType: default +# defaultRegion: us-east-1 + +## Configure grafana alerting (can be templated) +## ref: http://docs.grafana.org/administration/provisioning/#alerting +## +alerting: {} + # rules.yaml: + # apiVersion: 1 + # groups: + # - orgId: 1 + # name: '{{ .Chart.Name }}_my_rule_group' + # folder: my_first_folder + # interval: 60s + # rules: + # - uid: my_id_1 + # title: my_first_rule + # condition: A + # data: + # - refId: A + # datasourceUid: '-100' + # model: + # conditions: + # - evaluator: + # params: + # - 3 + # type: gt + # operator: + # type: and + # query: + # params: + # - A + # reducer: + # type: last + # type: query + # datasource: + # type: __expr__ + # uid: '-100' + # expression: 1==0 + # intervalMs: 1000 + # maxDataPoints: 43200 + # refId: A + # type: math + # dashboardUid: my_dashboard + # panelId: 123 + # noDataState: Alerting + # for: 60s + # annotations: + # some_key: some_value + # labels: + # team: sre_team_1 + # contactpoints.yaml: + # apiVersion: 1 + # contactPoints: + # - orgId: 1 + # name: cp_1 + # receivers: + # - uid: first_uid + # type: pagerduty + # settings: + # integrationKey: XXX + # severity: critical + # class: ping failure + # component: Grafana + # group: app-stack + # summary: | + # {{ `{{ template "default.message" . }}` }} + +## Configure notifiers +## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels +## +notifiers: {} +# notifiers.yaml: +# notifiers: +# - name: email-notifier +# type: email +# uid: email1 +# # either: +# org_id: 1 +# # or +# org_name: Main Org. +# is_default: true +# settings: +# addresses: an_email_address@example.com +# delete_notifiers: + +## Configure grafana dashboard providers +## ref: http://docs.grafana.org/administration/provisioning/#dashboards +## +## `path` must be /var/lib/grafana/dashboards/ +## +dashboardProviders: {} +# dashboardproviders.yaml: +# apiVersion: 1 +# providers: +# - name: 'default' +# orgId: 1 +# folder: '' +# type: file +# disableDeletion: false +# editable: true +# options: +# path: /var/lib/grafana/dashboards/default + +## Configure grafana dashboard to import +## NOTE: To use dashboards you must also enable/configure dashboardProviders +## ref: https://grafana.com/dashboards +## +## dashboards per provider, use provider name as key. +## +dashboards: {} + # default: + # some-dashboard: + # json: | + # $RAW_JSON + # custom-dashboard: + # file: dashboards/custom-dashboard.json + # prometheus-stats: + # gnetId: 2 + # revision: 2 + # datasource: Prometheus + # local-dashboard: + # url: https://example.com/repository/test.json + # token: '' + # local-dashboard-base64: + # url: https://example.com/repository/test-b64.json + # token: '' + # b64content: true + # local-dashboard-gitlab: + # url: https://example.com/repository/test-gitlab.json + # gitlabToken: '' + # local-dashboard-bitbucket: + # url: https://example.com/repository/test-bitbucket.json + # bearerToken: '' + +## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. +## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. +## ConfigMap data example: +## +## data: +## example-dashboard.json: | +## RAW_JSON +## +dashboardsConfigMaps: {} +# default: "" + +## Grafana's primary configuration +## NOTE: values in map will be converted to ini format +## ref: http://docs.grafana.org/installation/configuration/ +## +grafana.ini: + paths: + data: /var/lib/grafana/ + logs: /var/log/grafana + plugins: /var/lib/grafana/plugins + provisioning: /etc/grafana/provisioning + analytics: + check_for_updates: true + log: + mode: console + grafana_net: + url: https://grafana.net + server: + domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ end }}" +## grafana Authentication can be enabled with the following values on grafana.ini + # server: + # The full public facing url you use in browser, used for redirects and emails + # root_url: + # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana + # auth.github: + # enabled: false + # allow_sign_up: false + # scopes: user:email,read:org + # auth_url: https://github.com/login/oauth/authorize + # token_url: https://github.com/login/oauth/access_token + # api_url: https://api.github.com/user + # team_ids: + # allowed_organizations: + # client_id: + # client_secret: +## LDAP Authentication can be enabled with the following values on grafana.ini +## NOTE: Grafana will fail to start if the value for ldap.toml is invalid + # auth.ldap: + # enabled: true + # allow_sign_up: true + # config_file: /etc/grafana/ldap.toml + +## Grafana's LDAP configuration +## Templated by the template in _helpers.tpl +## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled +## ref: http://docs.grafana.org/installation/configuration/#auth-ldap +## ref: http://docs.grafana.org/installation/ldap/#configuration +ldap: + enabled: false + # `existingSecret` is a reference to an existing secret containing the ldap configuration + # for Grafana in a key `ldap-toml`. + existingSecret: "" + # `config` is the content of `ldap.toml` that will be stored in the created secret + config: "" + # config: |- + # verbose_logging = true + + # [[servers]] + # host = "my-ldap-server" + # port = 636 + # use_ssl = true + # start_tls = false + # ssl_skip_verify = false + # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" + +## Grafana's SMTP configuration +## NOTE: To enable, grafana.ini must be configured with smtp.enabled +## ref: http://docs.grafana.org/installation/configuration/#smtp +smtp: + # `existingSecret` is a reference to an existing secret containing the smtp configuration + # for Grafana. + existingSecret: "" + userKey: "user" + passwordKey: "password" + +## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders +## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards +sidecar: + image: + repository: rancher/mirrored-kiwigrid-k8s-sidecar + tag: 1.19.2 + sha: "" + imagePullPolicy: IfNotPresent + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + securityContext: {} + # skipTlsVerify Set to true to skip tls verification for kube api calls + # skipTlsVerify: true + enableUniqueFilenames: false + readinessProbe: {} + livenessProbe: {} + # Log level default for all sidecars. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. Defaults to INFO + # logLevel: INFO + dashboards: + enabled: false + # Additional environment variables for the dashboards sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + SCProvider: true + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # value of label that the configmaps with dashboards are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) + folder: /tmp/dashboards + # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead + defaultFolderName: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # If specified, the sidecar will look for annotation with this name to create folder and put graph here. + # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. + folderAnnotation: null + # Absolute path to shell script to execute after a configmap got reloaded + script: null + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # provider configuration that lets grafana manage the dashboards + provider: + # name of the provider, should be unique + name: sidecarProvider + # orgid as configured in grafana + orgid: 1 + # folder in which the dashboards should be imported in grafana + folder: '' + # type of the provider + type: file + # disableDelete to activate a import-only behaviour + disableDelete: false + # allow updating provisioned dashboards from the UI + allowUiUpdates: false + # allow Grafana to replicate dashboard structure from filesystem + foldersFromFilesStructure: false + # Additional dashboard sidecar volume mounts + extraMounts: [] + # Sets the size limit of the dashboard sidecar emptyDir volume + sizeLimit: {} + datasources: + enabled: false + # Additional environment variables for the datasourcessidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with datasources are marked with + label: grafana_datasource + # value of label that the configmaps with datasources are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # Endpoint to send request to reload datasources + reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" + # Absolute path to shell script to execute after a datasource got reloaded + script: null + skipReload: true + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any datasources defined at startup time. + initDatasources: true + # Sets the size limit of the datasource sidecar emptyDir volume + sizeLimit: {} + plugins: + enabled: false + # Additional environment variables for the plugins sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with plugins are marked with + label: grafana_plugin + # value of label that the configmaps with plugins are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # Endpoint to send request to reload plugins + reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" + # Absolute path to shell script to execute after a plugin got reloaded + script: null + skipReload: false + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any plugins defined at startup time. + initPlugins: false + # Sets the size limit of the plugin sidecar emptyDir volume + sizeLimit: {} + notifiers: + enabled: false + # Additional environment variables for the notifierssidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with notifiers are marked with + label: grafana_notifier + # value of label that the configmaps with notifiers are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # search in configmap, secret or both + resource: both + # Sets the size limit of the notifier sidecar emptyDir volume + sizeLimit: {} + +## Override the deployment namespace +## +namespaceOverride: "" + +## Number of old ReplicaSets to retain +## +revisionHistoryLimit: 10 + +## Add a seperate remote image renderer deployment/service +imageRenderer: + # Enable the image-renderer deployment & service + enabled: false + replicas: 1 + image: + # image-renderer Image repository + repository: rancher/mirrored-grafana-grafana-image-renderer + # image-renderer Image tag + tag: 3.0.1 + # image-renderer Image sha (optional) + sha: "" + # image-renderer ImagePullPolicy + pullPolicy: Always + # extra environment variables + env: + HTTP_HOST: "0.0.0.0" + # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 + # RENDERING_MODE: clustered + # IGNORE_HTTPS_ERRORS: true + # image-renderer deployment serviceAccount + serviceAccountName: "" + # image-renderer deployment securityContext + securityContext: {} + # image-renderer deployment Host Aliases + hostAliases: [] + # image-renderer deployment priority class + priorityClassName: '' + service: + # Enable the image-renderer service + enabled: true + # image-renderer service port name + portName: 'http' + # image-renderer service port used by both service and deployment + port: 8081 + targetPort: 8081 + # Adds the appProtocol field to the image-renderer service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + # If https is enabled in Grafana, this needs to be set as 'https' to correctly configure the callback used in Grafana + grafanaProtocol: http + # In case a sub_path is used this needs to be added to the image renderer callback + grafanaSubPath: "" + # name of the image-renderer port on the pod + podPortName: http + # number of image-renderer replica sets to keep + revisionHistoryLimit: 10 + networkPolicy: + # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods + limitIngress: true + # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods + limitEgress: false + resources: {} +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + ## Affinity for pod assignment (evaluated as template) + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to grafana port defined. + ## When true, grafana will accept connections from any source + ## (with the correct destination port). + ## + ingress: true + ## @param networkPolicy.ingress When true enables the creation + ## an ingress network policy + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed + ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the grafana. + ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + ## + ## + ## + ## + ## + ## + egress: + ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be + ## created allowing grafana to connect to external data sources from kubernetes cluster. + enabled: false + ## + ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress + ports: [] + ## Add ports to the egress by specifying - port: + ## E.X. + ## ports: + ## - port: 80 + ## - port: 443 + ## + ## + ## + ## + ## + ## + +# Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option +enableKubeBackwardCompatibility: false +useStatefulSet: false diff --git a/charts/rancher-project-monitoring/0.3.1/files/federate/federate-scrape-config.yaml b/charts/rancher-project-monitoring/0.3.1/files/federate/federate-scrape-config.yaml new file mode 100644 index 00000000..b5ceb698 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/files/federate/federate-scrape-config.yaml @@ -0,0 +1,13 @@ +- job_name: 'federate' + scrape_interval: {{ .Values.federate.interval }} + honor_labels: true + metrics_path: '/federate' + + params: + 'match[]': + - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=~"kube-state-metrics|kubelet|k3s-server"}' + - '{namespace=~"{{ include "project-prometheus-stack.projectNamespaceList" . | replace "," "|" }}", job=""}' + + static_configs: + - targets: {{ .Values.federate.targets | toYaml | nindent 6 }} + diff --git a/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod-containers.json b/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod-containers.json new file mode 100644 index 00000000..9e53081a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod-containers.json @@ -0,0 +1,636 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "CFS throttled ({{container}})", + "refId": "A" + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "System ({{container}})", + "refId": "B" + }, + { + "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Total ({{container}})", + "refId": "C" + }, + { + "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "User ({{container}})", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}) by (container)", + "interval": "", + "legendFormat": "({{container}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Total ({{container}})", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Total ({{container}})", + "refId": "B" + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Dropped ({{container}})", + "refId": "C" + }, + { + "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Errors ({{container}})", + "refId": "D" + }, + { + "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Errors ({{container}})", + "refId": "E" + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Dropped ({{container}})", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Receive Total ({{container}})", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Transmit Total ({{container}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{container}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Write ({{container}})", + "refId": "A" + }, + { + "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) by (container)", + "interval": "", + "legendFormat": "Read ({{container}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Pod (Containers)", + "uid": "rancher-pod-containers-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod.json b/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod.json new file mode 100644 index 00000000..65c6bf18 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/files/rancher/pods/rancher-pod.json @@ -0,0 +1,636 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_cfs_throttled_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "CFS throttled", + "refId": "A" + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "System", + "refId": "B" + }, + { + "expr": "sum(rate(container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Total", + "refId": "C" + }, + { + "expr": "sum(rate(container_cpu_user_seconds_total{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval])) OR sum(rate(windows_container_cpu_usage_seconds_usermode{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "User", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"} OR windows_container_memory_usage_commit_bytes{container!=\"POD\",namespace=~\"$namespace\",pod=~\"$pod\", container!=\"\"})", + "interval": "", + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Dropped", + "refId": "C" + }, + { + "expr": "sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Errors", + "refId": "D" + }, + { + "expr": "sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Errors", + "refId": "E" + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Dropped", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval])) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Write", + "refId": "A" + }, + { + "expr": "sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\",pod=~\"$pod\",container!=\"\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Read", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace!=\"\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "query": "label_values({__name__=~\"container_.*|windows_container_.*\", namespace=\"$namespace\", pod!=\"\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Pod", + "uid": "rancher-pod-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload-pods.json b/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload-pods.json new file mode 100644 index 00000000..f6b5078a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload-pods.json @@ -0,0 +1,652 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "CFS throttled ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "System ({{pod}})", + "refId": "B" + }, + { + "expr": "(sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Total ({{pod}})", + "refId": "C" + }, + { + "expr": "(sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "User ({{pod}})", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "({{pod}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Total ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Total ({{pod}})", + "refId": "B" + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Dropped ({{pod}})", + "refId": "C" + }, + { + "expr": "(sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Errors ({{pod}})", + "refId": "D" + }, + { + "expr": "(sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Errors ({{pod}})", + "refId": "E" + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Dropped ({{pod}})", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Receive Total ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Transmit Total ({{pod}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Write ({{pod}})", + "refId": "A" + }, + { + "expr": "(sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"}", + "interval": "", + "legendFormat": "Read ({{pod}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*namespace=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "kind", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_kind=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_name=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Workload (Pods)", + "uid": "rancher-workload-pods-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload.json b/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload.json new file mode 100644 index 00000000..9f5317c2 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/files/rancher/workloads/rancher-workload.json @@ -0,0 +1,652 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 28, + "iteration": 1618265214337, + "links": [], + "panels": [ + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(rate(container_cpu_cfs_throttled_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "CFS throttled", + "refId": "A" + }, + { + "expr": "sum((sum(rate(container_cpu_system_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_kernelmode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "System", + "refId": "B" + }, + { + "expr": "sum((sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Total", + "refId": "C" + }, + { + "expr": "sum((sum(rate(container_cpu_user_seconds_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(rate(windows_container_cpu_usage_seconds_usermode{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "User", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "cpu", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(container_memory_working_set_bytes{namespace=~\"$namespace\"} OR windows_container_memory_usage_commit_bytes{namespace=~\"$namespace\"}) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Total", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Utilization", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum((sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + }, + { + "expr": "sum((sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Dropped", + "refId": "C" + }, + { + "expr": "sum((sum(irate(container_network_receive_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Errors", + "refId": "D" + }, + { + "expr": "sum((sum(irate(container_network_transmit_errors_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Errors", + "refId": "E" + }, + { + "expr": "sum((sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Dropped", + "refId": "F" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_receive_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Receive Total", + "refId": "A" + }, + { + "expr": "sum((sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod) OR sum(irate(windows_container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Transmit Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{{pod}}": "#3797d5" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 7 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum((sum(rate(container_fs_writes_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Write", + "refId": "A" + }, + { + "expr": "sum((sum(rate(container_fs_reads_bytes_total{namespace=~\"$namespace\"}[$__rate_interval])) by (pod)) * on(pod) kube_pod_info{namespace=~\"$namespace\", created_by_kind=\"$kind\", created_by_name=\"$workload\"})", + "interval": "", + "legendFormat": "Read", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "query": "query_result(kube_pod_info{namespace!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*namespace=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "kind", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_kind=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "query": "query_result(kube_pod_info{namespace=\"$namespace\", created_by_kind=\"$kind\", created_by_name!=\"\"} * on(pod) group_right(namespace, created_by_kind, created_by_name) count({__name__=~\"container_.*|windows_container_.*\", pod!=\"\"}) by (pod))", + "refresh": 2, + "regex": "/.*created_by_name=\"([^\"]*)\"/", + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Rancher / Workload", + "uid": "rancher-workload-1", + "version": 8 +} diff --git a/charts/rancher-project-monitoring/0.3.1/questions.yaml b/charts/rancher-project-monitoring/0.3.1/questions.yaml new file mode 100644 index 00000000..0e9bc69d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/questions.yaml @@ -0,0 +1,128 @@ +questions: +- variable: alertmanager.enabled + label: Enable Alertmanager + default: true + type: boolean + group: Alertmanager +- variable: grafana.enabled + label: Enable Grafana + default: true + type: boolean + group: Grafana + show_subquestion_if: true + subquestions: + - variable: grafana.adminUser + label: Grafana Admin User + type: string + default: admin + group: Grafana + - variable: grafana.adminPassword + label: Grafana Admin Password + type: string + default: prom-operator + group: Grafana + - variable: grafana.sidecar.dashboards.label + label: Default Grafana Dashboard Label + default: grafana_dashboard + description: All ConfigMaps with this label are parsed as Grafana Dashboards + type: string + group: Grafana +- variable: grafana.persistence.enabled + type: boolean + required: true + label: Grafana Persistent Volume Enabled + show_subquestion_if: true + group: Grafana + subquestions: + - variable: grafana.persistence.size + type: string + default: 1Gi + label: Size + - variable: grafana.persistence.storageClass + type: storageclass + label: Storage Class Name + - variable: grafana.persistence.accessModes + type: enum + default: + - ReadWriteOnce + options: + - [ReadWriteOnce] + - [ReadWriteMany] + - [ReadOnlyMany] + label: Access Mode +- variable: prometheus.prometheusSpec.scrapeInterval + type: string + required: true + label: Scrape Interval + default: 30s + group: Prometheus +- variable: prometheus.prometheusSpec.evaluationInterval + type: string + required: true + label: Evaluation Interval + default: 1m + group: Prometheus +- variable: prometheus.prometheusSpec.retention + type: string + required: true + label: Retention + default: 10d + group: Prometheus +- variable: prometheus.prometheusSpec.retentionSize + type: string + required: false + label: Retention Size + default: 50GB + group: Prometheus +- variable: prometheus.prometheusSpec.resources.requests.cpu + type: string + required: true + label: Requested CPU + default: 750m + group: Prometheus +- variable: prometheus.prometheusSpec.resources.requests.memory + type: string + required: true + label: Requested Memory + default: 750Mi + group: Prometheus +- variable: prometheus.prometheusSpec.resources.limits.cpu + type: string + required: true + label: CPU Limit + default: 1000m + group: Prometheus +- variable: prometheus.prometheusSpec.resources.limits.memory + type: string + required: true + label: Memory Limit + default: 3000Mi + group: Prometheus +- variable: prometheus.prometheusSpec.storage.enabled + type: boolean + required: true + label: Prometheus Persistent Volume Enabled + show_subquestion_if: true + group: Prometheus + subquestions: + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage + type: string + default: 50Gi + label: Size + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName + type: storageclass + label: Storage Class Name + - variable: prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.accessModes + type: enum + default: + - ReadWriteOnce + options: + - [ReadWriteOnce] + - [ReadWriteMany] + - [ReadOnlyMany] + label: Access Mode +- variable: federate.enabled + label: Enable Federated Metrics From Cluster Prometheus + default: true + type: boolean + group: Federation diff --git a/charts/rancher-project-monitoring/0.3.1/templates/NOTES.txt b/charts/rancher-project-monitoring/0.3.1/templates/NOTES.txt new file mode 100644 index 00000000..9e4d6d87 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/NOTES.txt @@ -0,0 +1,4 @@ +{{ $.Chart.Name }} has been installed. Check its status by running: + kubectl --namespace {{ template "project-prometheus-stack.namespace" . }} get pods -l "release={{ $.Release.Name }}" + +Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator. diff --git a/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl new file mode 100644 index 00000000..59f8e6c6 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl @@ -0,0 +1,233 @@ +# Rancher +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- end -}} +{{- end -}} + +{{/* +https://github.com/helm/helm/issues/4535#issuecomment-477778391 +Usage: {{ include "call-nested" (list . "SUBCHART_NAME" "TEMPLATE") }} +e.g. {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +*/}} +{{- define "call-nested" }} +{{- $dot := index . 0 }} +{{- $subchart := index . 1 | splitList "." }} +{{- $template := index . 2 }} +{{- $values := $dot.Values }} +{{- range $subchart }} +{{- $values = index $values . }} +{{- end }} +{{- include $template (dict "Chart" (dict "Name" (last $subchart)) "Values" $values "Release" $dot.Release "Capabilities" $dot.Capabilities) }} +{{- end }} + +# Windows Support + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} + +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +beta.kubernetes.io/os: linux +{{- else -}} +kubernetes.io/os: linux +{{- end -}} +{{- end -}} + +# Prometheus Operator + +{{/* Comma-delimited list of namespaces that need to be watched to configure Project Prometheus Stack components */}} +{{- define "project-prometheus-stack.projectNamespaceList" -}} +{{ append .Values.global.cattle.projectNamespaces .Release.Namespace | uniq | join "," }} +{{- end }} + +{{/* vim: set filetype=mustache: */}} +{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} +{{- define "project-prometheus-stack.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +The components in this chart create additional resources that expand the longest created name strings. +The longest name that gets created adds and extra 37 characters, so truncation should be 63-35=26. +*/}} +{{- define "project-prometheus-stack.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 26 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Prometheus custom resource instance name */}} +{{- define "project-prometheus-stack.prometheus.crname" -}} +{{- if .Values.cleanPrometheusOperatorObjectNames }} +{{- include "project-prometheus-stack.fullname" . }} +{{- else }} +{{- print (include "project-prometheus-stack.fullname" .) "-prometheus" }} +{{- end }} +{{- end }} + +{{/* Alertmanager custom resource instance name */}} +{{- define "project-prometheus-stack.alertmanager.crname" -}} +{{- if .Values.cleanPrometheusOperatorObjectNames }} +{{- include "project-prometheus-stack.fullname" . }} +{{- else }} +{{- print (include "project-prometheus-stack.fullname" .) "-alertmanager" -}} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "project-prometheus-stack.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "project-prometheus-stack.labels" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: "{{ replace "+" "_" .Chart.Version }}" +app.kubernetes.io/part-of: {{ template "project-prometheus-stack.name" . }} +chart: {{ template "project-prometheus-stack.chartref" . }} +release: {{ $.Release.Name | quote }} +heritage: {{ $.Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} + +{{/* Create the name of prometheus service account to use */}} +{{- define "project-prometheus-stack.prometheus.serviceAccountName" -}} +{{- if .Values.prometheus.serviceAccount.create -}} + {{ default (print (include "project-prometheus-stack.fullname" .) "-prometheus") .Values.prometheus.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.prometheus.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* Create the name of alertmanager service account to use */}} +{{- define "project-prometheus-stack.alertmanager.serviceAccountName" -}} +{{- if .Values.alertmanager.serviceAccount.create -}} + {{ default (print (include "project-prometheus-stack.fullname" .) "-alertmanager") .Values.alertmanager.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.alertmanager.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "project-prometheus-stack.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Use the grafana namespace override for multi-namespace deployments in combined charts +*/}} +{{- define "project-prometheus-stack-grafana.namespace" -}} + {{- if .Values.grafana.namespaceOverride -}} + {{- .Values.grafana.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* Allow KubeVersion to be overridden. */}} +{{- define "project-prometheus-stack.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} +{{- end -}} + +{{/* Get Ingress API Version */}} +{{- define "project-prometheus-stack.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" (include "project-prometheus-stack.kubeVersion" .)) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* Check Ingress stability */}} +{{- define "project-prometheus-stack.ingress.isStable" -}} + {{- eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* Check Ingress supports pathType */}} +{{/* pathType was added to networking.k8s.io/v1beta1 in Kubernetes 1.18 */}} +{{- define "project-prometheus-stack.ingress.supportsPathType" -}} + {{- or (eq (include "project-prometheus-stack.ingress.isStable" .) "true") (and (eq (include "project-prometheus-stack.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" (include "project-prometheus-stack.kubeVersion" .))) -}} +{{- end -}} + +{{/* Get Policy API Version */}} +{{- define "project-prometheus-stack.pdb.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">= 1.21-0" (include "project-prometheus-stack.kubeVersion" .)) -}} + {{- print "policy/v1" -}} + {{- else -}} + {{- print "policy/v1beta1" -}} + {{- end -}} + {{- end -}} + +{{/* Get value based on current Kubernetes version */}} +{{- define "project-prometheus-stack.kubeVersionDefaultValue" -}} + {{- $values := index . 0 }} + {{- $kubeVersion := index . 1 }} + {{- $old := index . 2 }} + {{- $new := index . 3 }} + {{- $default := index . 4 }} + {{- if kindIs "invalid" $default -}} + {{- if semverCompare $kubeVersion (include "project-prometheus-stack.kubeVersion" $values) -}} + {{- print $new -}} + {{- else -}} + {{- print $old -}} + {{- end -}} + {{- else -}} + {{- print $default }} + {{- end -}} +{{- end -}} + +{{/* +To help compatibility with other charts which use global.imagePullSecrets. +Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). +global: + imagePullSecrets: + - name: pullSecret1 + - name: pullSecret2 + +or + +global: + imagePullSecrets: + - pullSecret1 + - pullSecret2 +*/}} +{{- define "project-prometheus-stack.imagePullSecrets" -}} +{{- range .Values.global.imagePullSecrets }} + {{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml . | trim }} + {{- else }} +- name: {{ . }} + {{- end }} +{{- end }} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/alertmanager.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/alertmanager.yaml new file mode 100644 index 00000000..6bc14320 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/alertmanager.yaml @@ -0,0 +1,165 @@ +{{- if .Values.alertmanager.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: Alertmanager +metadata: + name: {{ template "project-prometheus-stack.alertmanager.crname" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.annotations }} + annotations: +{{ toYaml .Values.alertmanager.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.alertmanager.alertmanagerSpec.image }} + {{- if and .Values.alertmanager.alertmanagerSpec.image.tag .Values.alertmanager.alertmanagerSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" + {{- else if .Values.alertmanager.alertmanagerSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}@sha256:{{ .Values.alertmanager.alertmanagerSpec.image.sha }}" + {{- else if .Values.alertmanager.alertmanagerSpec.image.tag }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.alertmanager.alertmanagerSpec.image.repository }}" + {{- end }} + version: {{ .Values.alertmanager.alertmanagerSpec.image.tag }} + {{- if .Values.alertmanager.alertmanagerSpec.image.sha }} + sha: {{ .Values.alertmanager.alertmanagerSpec.image.sha }} + {{- end }} +{{- end }} + replicas: {{ .Values.alertmanager.alertmanagerSpec.replicas }} + listenLocal: {{ .Values.alertmanager.alertmanagerSpec.listenLocal }} + serviceAccountName: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} +{{- if .Values.alertmanager.alertmanagerSpec.externalUrl }} + externalUrl: "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}" +{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} + externalUrl: "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy" +{{- else }} + externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.nodeSelector }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.nodeSelector | indent 4 }} +{{- end }} + paused: {{ .Values.alertmanager.alertmanagerSpec.paused }} + logFormat: {{ .Values.alertmanager.alertmanagerSpec.logFormat | quote }} + logLevel: {{ .Values.alertmanager.alertmanagerSpec.logLevel | quote }} + retention: {{ .Values.alertmanager.alertmanagerSpec.retention | quote }} +{{- if .Values.alertmanager.alertmanagerSpec.secrets }} + secrets: +{{ toYaml .Values.alertmanager.alertmanagerSpec.secrets | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.configSecret }} + configSecret: {{ .Values.alertmanager.alertmanagerSpec.configSecret }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.configMaps }} + configMaps: +{{ toYaml .Values.alertmanager.alertmanagerSpec.configMaps | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector }} + alertmanagerConfigSelector: +{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector | indent 4}} +{{ else }} + alertmanagerConfigSelector: {} +{{- end }} + alertmanagerConfigNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.web }} + web: +{{ toYaml .Values.alertmanager.alertmanagerSpec.web | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration }} + alertmanagerConfiguration: +{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfiguration | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.resources }} + resources: +{{ toYaml .Values.alertmanager.alertmanagerSpec.resources | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} + routePrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.alertmanagerSpec.securityContext | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.storage }} + storage: +{{ tpl (toYaml .Values.alertmanager.alertmanagerSpec.storage | indent 4) . }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.podMetadata }} + podMetadata: +{{ toYaml .Values.alertmanager.alertmanagerSpec.podMetadata | indent 4 }} +{{- end }} +{{- if or .Values.alertmanager.alertmanagerSpec.podAntiAffinity .Values.alertmanager.alertmanagerSpec.affinity }} + affinity: +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.affinity }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.affinity | indent 4 }} +{{- end }} +{{- if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} + - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} +{{- else if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [alertmanager]} + - {key: alertmanager, operator: In, values: [{{ template "project-prometheus-stack.alertmanager.crname" . }}]} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.alertmanager.alertmanagerSpec.tolerations }} +{{ toYaml .Values.alertmanager.alertmanagerSpec.tolerations | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.alertmanager.alertmanagerSpec.topologySpreadConstraints | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} + imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.containers }} + containers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.containers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.initContainers }} + initContainers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.initContainers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.priorityClassName }} + priorityClassName: {{.Values.alertmanager.alertmanagerSpec.priorityClassName }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.additionalPeers }} + additionalPeers: +{{ toYaml .Values.alertmanager.alertmanagerSpec.additionalPeers | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.volumes }} + volumes: +{{ toYaml .Values.alertmanager.alertmanagerSpec.volumes | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.volumeMounts }} + volumeMounts: +{{ toYaml .Values.alertmanager.alertmanagerSpec.volumeMounts | indent 4 }} +{{- end }} + portName: {{ .Values.alertmanager.alertmanagerSpec.portName }} +{{- if .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} + clusterAdvertiseAddress: {{ .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} + forceEnableClusterMode: {{ .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} +{{- end }} +{{- if .Values.alertmanager.alertmanagerSpec.minReadySeconds }} + minReadySeconds: {{ .Values.alertmanager.alertmanagerSpec.minReadySeconds }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/extrasecret.yaml new file mode 100644 index 00000000..af469be7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/extrasecret.yaml @@ -0,0 +1,20 @@ +{{- if .Values.alertmanager.extraSecret.data -}} +{{- $secretName := printf "alertmanager-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ default $secretName .Values.alertmanager.extraSecret.name }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.alertmanager.extraSecret.annotations }} + annotations: +{{ toYaml .Values.alertmanager.extraSecret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/component: alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- range $key, $val := .Values.alertmanager.extraSecret.data }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/ingress.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/ingress.yaml new file mode 100644 index 00000000..022922b0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/ingress.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }} +{{- $pathType := .Values.alertmanager.ingress.pathType | default "ImplementationSpecific" }} +{{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} +{{- $servicePort := .Values.alertmanager.ingress.servicePort | default .Values.alertmanager.service.port -}} +{{- $routePrefix := list .Values.alertmanager.alertmanagerSpec.routePrefix }} +{{- $paths := .Values.alertmanager.ingress.paths | default $routePrefix -}} +{{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} +apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $serviceName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.alertmanager.ingress.annotations }} + annotations: +{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{- if .Values.alertmanager.ingress.labels }} +{{ toYaml .Values.alertmanager.ingress.labels | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if $apiIsStable }} + {{- if .Values.alertmanager.ingress.ingressClassName }} + ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }} + {{- end }} + {{- end }} + rules: + {{- if .Values.alertmanager.ingress.hosts }} + {{- range $host := .Values.alertmanager.ingress.hosts }} + - host: {{ tpl $host $ }} + http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- else }} + - http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- if .Values.alertmanager.ingress.tls }} + tls: +{{ tpl (toYaml .Values.alertmanager.ingress.tls | indent 4) . }} + {{- end -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/podDisruptionBudget.yaml new file mode 100644 index 00000000..a8d7feaf --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/podDisruptionBudget.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.podDisruptionBudget.enabled }} +apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if .Values.alertmanager.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.alertmanager.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: alertmanager + alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-role.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-role.yaml new file mode 100644 index 00000000..b959bf00 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-role.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-rolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-rolebinding.yaml new file mode 100644 index 00000000..d027f8e5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp-rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp.yaml new file mode 100644 index 00000000..138f1180 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/psp.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{- if .Values.global.rbac.pspAnnotations }} + annotations: +{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + privileged: false + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/secret.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/secret.yaml new file mode 100644 index 00000000..848d085f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/secret.yaml @@ -0,0 +1,33 @@ +{{- if .Values.alertmanager.enabled }} +{{/* This file is applied when the operation is helm install and the target secret does not exist. */}} +{{- $secretName := (printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .)) }} +{{- if (not (lookup "v1" "Secret" (include "project-prometheus-stack.namespace" .) $secretName)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + annotations: + "helm.sh/hook": pre-install, pre-upgrade + "helm.sh/hook-weight": "3" + "helm.sh/resource-policy": keep +{{- if .Values.alertmanager.secret.annotations }} +{{ toYaml .Values.alertmanager.secret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- if .Values.alertmanager.tplConfig }} +{{- if eq (typeOf .Values.alertmanager.config) "string" }} + alertmanager.yaml: {{ tpl (.Values.alertmanager.config) . | b64enc | quote }} +{{- else }} + alertmanager.yaml: {{ tpl (toYaml .Values.alertmanager.config) . | b64enc | quote }} +{{- end }} +{{- else }} + alertmanager.yaml: {{ toYaml .Values.alertmanager.config | b64enc | quote }} +{{- end}} +{{- range $key, $val := .Values.alertmanager.templateFiles }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }}{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/service.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/service.yaml new file mode 100644 index 00000000..3fb5cb3c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/service.yaml @@ -0,0 +1,53 @@ +{{- if .Values.alertmanager.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + self-monitor: {{ .Values.alertmanager.serviceMonitor.selfMonitor | quote }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.service.labels }} +{{ toYaml .Values.alertmanager.service.labels | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.service.annotations }} + annotations: +{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.alertmanager.service.clusterIP }} + clusterIP: {{ .Values.alertmanager.service.clusterIP }} +{{- end }} +{{- if .Values.alertmanager.service.externalIPs }} + externalIPs: +{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if ne .Values.alertmanager.service.type "ClusterIP" }} + externalTrafficPolicy: {{ .Values.alertmanager.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if eq .Values.alertmanager.service.type "NodePort" }} + nodePort: {{ .Values.alertmanager.service.nodePort }} + {{- end }} + port: {{ .Values.alertmanager.service.port }} + targetPort: {{ .Values.alertmanager.service.targetPort }} + protocol: TCP +{{- if .Values.alertmanager.service.additionalPorts }} +{{ toYaml .Values.alertmanager.service.additionalPorts | indent 2 }} +{{- end }} + selector: + app.kubernetes.io/name: alertmanager + alertmanager: {{ template "project-prometheus-stack.alertmanager.crname" . }} + type: "{{ .Values.alertmanager.service.type }}" +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/serviceaccount.yaml new file mode 100644 index 00000000..00b4b177 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.alertmanager.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-alertmanager + app.kubernetes.io/component: alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.alertmanager.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.alertmanager.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2}} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/servicemonitor.yaml new file mode 100644 index 00000000..1cc9c6f7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/alertmanager/servicemonitor.yaml @@ -0,0 +1,55 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app: {{ template "project-prometheus-stack.name" . }}-alertmanager + release: {{ $.Release.Name | quote }} + self-monitor: "true" + namespaceSelector: + matchNames: + - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} + endpoints: + - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if .Values.alertmanager.serviceMonitor.interval }} + interval: {{ .Values.alertmanager.serviceMonitor.interval }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.proxyUrl }} + proxyUrl: {{ .Values.alertmanager.serviceMonitor.proxyUrl}} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.scheme }} + scheme: {{ .Values.alertmanager.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.alertmanager.serviceMonitor.bearerTokenFile }} + {{- end }} + {{- if .Values.alertmanager.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" + metricRelabelings: + {{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName }} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +{{- if .Values.alertmanager.serviceMonitor.relabelings }} + relabelings: +{{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml new file mode 100644 index 00000000..b42c6626 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml @@ -0,0 +1,161 @@ +{{- if and .Values.global.rbac.create .Values.global.rbac.userRoles.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-admin + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: admin + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' + - 'create' + - 'update' + - 'patch' + - 'delete' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch + - update + - patch + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-edit + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: edit + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' + - 'create' + - 'update' + - 'patch' + - 'delete' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-view + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/project-helm-chart-role: {{ .Release.Name }} + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + helm.cattle.io/project-helm-chart-role-aggregate-from: view + {{- end }} +rules: +- apiGroups: + - "" + resources: + - services/proxy + resourceNames: + - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" + - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" + - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- if .Values.grafana.enabled }} + - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" + - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" +{{- end }} + verbs: + - 'get' +- apiGroups: + - "" + resources: + - endpoints + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus + - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- if .Values.grafana.enabled }} + - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} +{{- end }} + verbs: + - list +- apiGroups: + - "" + resources: + - "secrets" + resourceNames: + - {{ printf "%s-alertmanager-secret" (include "project-prometheus-stack.fullname" .) }} + verbs: + - get + - list + - watch +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/dashboard-values-configmap.yaml b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-values-configmap.yaml new file mode 100644 index 00000000..16acc46d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-values-configmap.yaml @@ -0,0 +1,57 @@ +{{- $rancherDashboards := dict }} +{{- range $glob := tuple "files/rancher/workloads/*" "files/rancher/pods/*" -}} +{{- range $dashboard, $_ := ($.Files.Glob $glob) }} +{{- $dashboardMap := ($.Files.Get $dashboard | fromJson) }} +{{- $_ := set $rancherDashboards (get $dashboardMap "uid") (get $dashboardMap "title") -}} +{{- end }} +{{- end }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-dashboard-values + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} + helm.cattle.io/dashboard-values-configmap: {{ .Release.Name }} +data: + values.json: |- + { +{{- if not .Values.prometheus.enabled }} + "prometheusURL": "", +{{- else if .Values.prometheus.prometheusSpec.externalUrl }} + "prometheusURL": "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}", +{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} + "prometheusURL": "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "prometheusURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy", +{{- else }} + "prometheusURL": "http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}", +{{- end }} + +{{- if not .Values.grafana.enabled }} + "grafanaURL": "", +{{- else if and .Values.grafana.ingress.enabled .Values.grafana.ingress.hosts }} + "grafanaURL": "http://{{ tpl (index .Values.grafana.ingress.hosts 0) . }}{{ .Values.grafana.grafanaSpec.ingress.path }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "grafanaURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}/proxy", +{{- else }} + "grafanaURL": "http://{{ include "call-nested" (list . "grafana" "grafana.fullname") }}.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.grafana.service.port }}", +{{- end }} + +{{- if not .Values.alertmanager.enabled }} + "alertmanagerURL": "", +{{- else if .Values.alertmanager.alertmanagerSpec.externalUrl }} + "alertmanagerURL": "{{ tpl .Values.alertmanager.alertmanagerSpec.externalUrl . }}", +{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} + "alertmanagerURL": "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}", +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + "alertmanagerURL": "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}/proxy", +{{- else }} + "alertmanagerURL": "http://{{ template "project-prometheus-stack.fullname" . }}-alertmanager.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }}", +{{- end }} + +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} + "rancherDashboards": {{- $rancherDashboards | toPrettyJson | nindent 8 }} +{{- else }} + "rancherDashboards": [] +{{- end }} + } \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/pods-dashboards.yaml b/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/pods-dashboards.yaml new file mode 100644 index 00000000..6214dc5c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/pods-dashboards.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: rancher-default-dashboards-pods + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: +{{ (.Files.Glob "files/rancher/pods/*").AsConfig | indent 2 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/workload-dashboards.yaml b/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/workload-dashboards.yaml new file mode 100644 index 00000000..7934818f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/dashboards/rancher/workload-dashboards.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: rancher-default-dashboards-workloads + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: +{{ (.Files.Glob "files/rancher/workloads/*").AsConfig | indent 2 }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmap-dashboards.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmap-dashboards.yaml new file mode 100644 index 00000000..c2763573 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmap-dashboards.yaml @@ -0,0 +1,24 @@ +{{- if or (and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled) .Values.grafana.forceDeployDashboards }} +{{- $files := .Files.Glob "dashboards-1.14/*.json" }} +{{- if $files }} +apiVersion: v1 +kind: ConfigMapList +items: +{{- range $path, $fileContents := $files }} +{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} +- apiVersion: v1 + kind: ConfigMap + metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) $dashboardName | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 6 }} + data: + {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmaps-datasources.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmaps-datasources.yaml new file mode 100644 index 00000000..7f2c5b55 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/configmaps-datasources.yaml @@ -0,0 +1,46 @@ +{{- if or (and .Values.grafana.enabled .Values.grafana.sidecar.datasources.enabled) .Values.grafana.forceDeployDatasources }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-grafana-datasource + namespace: {{ include "project-prometheus-stack.namespace" . }} +{{- if .Values.grafana.sidecar.datasources.annotations }} + annotations: +{{ toYaml .Values.grafana.sidecar.datasources.annotations | indent 4 }} +{{- end }} + labels: + {{ $.Values.grafana.sidecar.datasources.label }}: "1" + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + datasource.yaml: |- + apiVersion: 1 +{{- if .Values.grafana.deleteDatasources }} + deleteDatasources: +{{ tpl (toYaml .Values.grafana.deleteDatasources | indent 6) . }} +{{- end }} + datasources: +{{- $scrapeInterval := .Values.grafana.sidecar.datasources.defaultDatasourceScrapeInterval | default .Values.prometheus.prometheusSpec.scrapeInterval | default "30s" }} +{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }} + - name: Prometheus + type: prometheus + uid: {{ .Values.grafana.sidecar.datasources.uid }} + {{- if .Values.grafana.sidecar.datasources.url }} + url: {{ .Values.grafana.sidecar.datasources.url }} + {{- else }} + url: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }}/{{ trimPrefix "/" .Values.prometheus.prometheusSpec.routePrefix }} + {{- end }} + access: proxy + isDefault: true + jsonData: + timeInterval: {{ $scrapeInterval }} +{{- if .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations }} + exemplarTraceIdDestinations: + - datasourceUid: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.datasourceUid }} + name: {{ .Values.grafana.sidecar.datasources.exemplarTraceIdDestinations.traceIdLabelName }} +{{- end }} +{{- end }} +{{- if .Values.grafana.additionalDataSources }} +{{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/alertmanager-overview.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/alertmanager-overview.yaml new file mode 100644 index 00000000..8f8e6ffe --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/alertmanager-overview.yaml @@ -0,0 +1,616 @@ +{{- /* +Generated from 'alertmanager-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "alertmanager-overview" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + alertmanager-overview.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 1, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "30s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "current set of alerts stored in the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(alertmanager_alerts{namespace=~\"$namespace\",service=~\"$service\"}) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "rate of successful and invalid alerts received by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(alertmanager_alerts_received_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Received", + "refId": "A" + }, + { + "expr": "sum(rate(alertmanager_alerts_invalid_total{namespace=~\"$namespace\",service=~\"$service\"}[$__rate_interval])) by (namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Invalid", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts receive rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Alerts", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "rate of successful and invalid notifications sent by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "integration", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(alertmanager_notifications_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Total", + "refId": "A" + }, + { + "expr": "sum(rate(alertmanager_notifications_failed_total{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (integration,namespace,service,instance)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Failed", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "$integration: Notifications Send Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "description": "latency of notifications sent by the Alertmanager", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 5, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": "integration", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} 99th Percentile", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.50,\n sum(rate(alertmanager_notification_latency_seconds_bucket{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (le,namespace,service,instance)\n) \n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Median", + "refId": "B" + }, + { + "expr": "sum(rate(alertmanager_notification_latency_seconds_sum{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n/\nsum(rate(alertmanager_notification_latency_seconds_count{namespace=~\"$namespace\",service=~\"$service\", integration=\"$integration\"}[$__rate_interval])) by (namespace,service,instance)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}instance{{`}}`}} Average", + "refId": "C" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "$integration: Notification Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Notifications", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "alertmanager-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "namespace", + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(alertmanager_alerts, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "service", + "multi": false, + "name": "service", + "options": [ + + ], + "query": "label_values(alertmanager_alerts, service)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "all", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": true, + "label": null, + "multi": false, + "name": "integration", + "options": [ + + ], + "query": "label_values(alertmanager_notifications_total{integration=~\".*\"}, integration)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Alertmanager / Overview", + "uid": "alertmanager-overview", + "version": 0 + } +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/cluster-total.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/cluster-total.yaml new file mode 100644 index 00000000..70764069 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/cluster-total.yaml @@ -0,0 +1,1646 @@ +{{- /* +Generated from 'cluster-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "cluster-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + cluster-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "Value #G", + "value": "Value #G" + }, + { + "text": "Value #H", + "value": "Value #H" + }, + { + "text": "namespace", + "value": "namespace" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "90%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Current Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?orgId=1&refresh=30s&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 6, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 9, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth History", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 13, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 15, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$interval:$resolution])) by (namespace))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Project", + "uid": "ff635a025bcfea7bc3dd4f508990a3e9", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/grafana-overview.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/grafana-overview.yaml new file mode 100644 index 00000000..ef663df7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/grafana-overview.yaml @@ -0,0 +1,635 @@ +{{- /* +Generated from 'grafana-overview' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack-grafana.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "grafana-overview" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + grafana-overview.json: |- + { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [ + + ], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 3085, + "iteration": 1631554945276, + "links": [ + + ], + "panels": [ + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "mappings": [ + + ], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": { + + }, + "textMode": "auto" + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "grafana_alerting_result_total{job=~\"$job\", instance=~\"$instance\", state=\"alerting\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Firing Alerts", + "type": "stat" + }, + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "mappings": [ + + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": { + + }, + "textMode": "auto" + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "sum(grafana_stat_totals_dashboard{job=~\"$job\", instance=~\"$instance\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Dashboards", + "type": "stat" + }, + { + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "auto" + }, + "mappings": [ + + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 10, + "options": { + "showHeader": true + }, + "pluginVersion": "8.1.3", + "targets": [ + { + "expr": "grafana_build_info{job=~\"$job\", instance=~\"$instance\"}", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Build Info", + "transformations": [ + { + "id": "labelsToFields", + "options": { + + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true, + "branch": true, + "container": true, + "goversion": true, + "namespace": true, + "pod": true, + "revision": true + }, + "indexByName": { + "Time": 7, + "Value": 11, + "branch": 4, + "container": 8, + "edition": 2, + "goversion": 6, + "instance": 1, + "job": 0, + "namespace": 9, + "pod": 10, + "revision": 5, + "version": 3 + }, + "renameByName": { + + } + } + } + ], + "type": "table" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "links": [ + + ] + }, + "overrides": [ + + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (status_code) (irate(grafana_http_request_duration_seconds_count{job=~\"$job\", instance=~\"$instance\"}[1m])) ", + "interval": "", + "legendFormat": "{{`{{`}}status_code{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeRegions": [ + + ], + "timeShift": null, + "title": "RPS", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "$$hashKey": "object:157", + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:158", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fieldConfig": { + "defaults": { + "links": [ + + ] + }, + "overrides": [ + + ] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", + "interval": "", + "legendFormat": "99th Percentile", + "refId": "A" + }, + { + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(irate(grafana_http_request_duration_seconds_bucket{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) by (le)) * 1", + "interval": "", + "legendFormat": "50th Percentile", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(irate(grafana_http_request_duration_seconds_sum{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval])) * 1 / sum(irate(grafana_http_request_duration_seconds_count{instance=~\"$instance\", job=~\"$job\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "Average", + "refId": "C" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeRegions": [ + + ], + "timeShift": null, + "title": "Request Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "$$hashKey": "object:210", + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:211", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "schemaVersion": 30, + "style": "dark", + "tags": [ + + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": [ + "default/grafana" + ], + "value": [ + "default/grafana" + ] + }, + "datasource": "$datasource", + "definition": "label_values(grafana_build_info, job)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "job", + "options": [ + + ], + "query": { + "query": "label_values(grafana_build_info, job)", + "refId": "Billing Admin-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "definition": "label_values(grafana_build_info, instance)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "instance", + "options": [ + + ], + "query": { + "query": "label_values(grafana_build_info, instance)", + "refId": "Billing Admin-instance-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Grafana Overview", + "uid": "6be0s85Mk", + "version": 2 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml new file mode 100644 index 00000000..c87b4188 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml @@ -0,0 +1,2770 @@ +{{- /* +Generated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-namespace" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-namespace.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "100px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "CPU Utilisation (from requests)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "CPU Utilisation (from limits)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Memory Utilisation (from requests)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "format": "percentunit", + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "70,80", + "timeFrom": null, + "timeShift": null, + "title": "Memory Utilisation (from limits)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "singlestat", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Headlines", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_cache{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(container_memory_swap{namespace=\"$namespace\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 14, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 16, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 17, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", namespace=\"$namespace\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 18, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\",namespace=\"$namespace\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Namespace (Pods)", + "uid": "85a562078cdf77779eaa1add43ccec1e", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-node.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-node.yaml new file mode 100644 index 00000000..e2e8d2aa --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-node.yaml @@ -0,0 +1,963 @@ +{{- /* +Generated from 'k8s-resources-node' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-node" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-node.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{node=~\"$node\"}) by (pod) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\", container!=\"\"}) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{node=~\"$node\",container!=\"\"}) by (pod) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{node=~\"$node\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_rss{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_cache{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_memory_swap{node=~\"$node\",container!=\"\"}) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": true, + "name": "node", + "options": [ + + ], + "query": "label_values(kube_pod_info, node)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Node (Pods)", + "uid": "200ac8fdbfbb74b39aff88118e4d1c2c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml new file mode 100644 index 00000000..c8d57cfd --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml @@ -0,0 +1,2442 @@ +{{- /* +Generated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-pod" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-pod.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "requests", + "color": "#F2495C", + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "limits", + "color": "#FF9830", + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"cpu\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(increase(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container) /sum(increase(container_cpu_cfs_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}[$__rate_interval])) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.25, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Throttling", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": 1, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Throttling", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(cluster:namespace:pod_cpu:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\", resource=\"memory\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (WSS)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage (WSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Usage (RSS)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Cache)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Usage (Swap)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_requests{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_working_set_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container) / sum(cluster:namespace:pod_memory:active:kube_pod_container_resource_limits{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_cache{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sum(container_memory_swap{namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(pod) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Reads", + "legendLink": null, + "step": 10 + }, + { + "expr": "ceil(sum by(pod) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Writes", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(pod) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Reads", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by(pod) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=~\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Writes", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution(Pod - Read & Writes)", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 14, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(container) (rate(container_fs_reads_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}container{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution(Containers)", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 16, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Container", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "container", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_writes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_writes_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(container) (rate(container_fs_reads_bytes_total{device=~\"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+)\", container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]) + rate(container_fs_writes_bytes_total{container!=\"\", namespace=\"$namespace\", pod=\"$pod\"}[$__rate_interval]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "options": [ + + ], + "query": "label_values(kube_pod_info{namespace=\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Pod", + "uid": "6581e46e4e5c7ba40a07646395ef7b23", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-project.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-project.yaml new file mode 100644 index 00000000..56d9c77f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-project.yaml @@ -0,0 +1,2480 @@ +{{- /* +Generated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-cluster" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-cluster.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workloads", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to workloads", + "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(kube_pod_owner{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage (w/o cache)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workloads", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to workloads", + "linkUrl": "/d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(kube_pod_owner{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{}) by (workload, namespace)) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(container_memory_rss{container!=\"\"}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{}) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Requests by Namespace", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Requests", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 11, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(container_network_receive_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Namespace: Received", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "avg(irate(container_network_transmit_bytes_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Namespace: Transmitted", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Namespace", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 17, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 18, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 19, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\".+\"}[$__rate_interval])) by (namespace)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": -1, + "fill": 10, + "id": 20, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "ceil(sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m])))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "IOPS(Reads+Writes)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 21, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}namespace{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "ThroughPut(Read+Write)", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 22, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "sort": { + "col": 4, + "desc": true + }, + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "IOPS(Reads)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "IOPS(Reads + Writes)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": -1, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Throughput(Read)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Throughput(Read + Write)", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Namespace", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "/d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", + "pattern": "namespace", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_writes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_total{container!=\"\"}[5m]) + rate(container_fs_writes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum by(namespace) (rate(container_fs_reads_bytes_total{container!=\"\"}[5m]) + rate(container_fs_writes_bytes_total{container!=\"\"}[5m]))", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Storage IO", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage IO - Distribution", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "default", + "value": "default" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Project", + "uid": "efa86fd1d0c121a26444b636a3f509a8", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml new file mode 100644 index 00000000..4e72d70a --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml @@ -0,0 +1,1997 @@ +{{- /* +Generated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workload" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-workload.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Pod: Received", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Pod: Transmitted", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Pod", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\"}, workload)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=\"$workload\"}, workload_type)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Workload", + "uid": "a164a7f0339f99e89cea5cb47e9be617", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml new file mode 100644 index 00000000..c6548c43 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml @@ -0,0 +1,2162 @@ +{{- /* +Generated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "k8s-resources-workloads-namespace" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + k8s-resources-workloads-namespace.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 1, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Running Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "CPU Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"cpu\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "CPU Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CPU Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "quota - requests", + "color": "#F2495C", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + }, + { + "alias": "quota - limits", + "color": "#FF9830", + "dashes": true, + "fill": 0, + "hiddenSeries": true, + "hideTooltip": true, + "legend": true, + "linewidth": 2, + "stack": false + } + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - requests", + "legendLink": null, + "step": 10 + }, + { + "expr": "scalar(kube_resourcequota{namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "quota - limits", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Running Pods", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Memory Usage", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Requests %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Memory Limits", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Memory Limits %", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(\n container_memory_working_set_bytes{namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits{namespace=\"$namespace\", resource=\"memory\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory Quota", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Memory Quota", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Current Receive Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Transmit Bandwidth", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": false, + "linkTooltip": "Drill down to pods", + "linkUrl": "d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$type", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Workload Type", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "workload_type", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Network Usage", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Network Usage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Workload: Received", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Container Bandwidth by Workload: Transmitted", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Container Bandwidth by Workload", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 11, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 12, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 13, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": false, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Rate of Packets Dropped", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kube_pod_info, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Compute Resources / Namespace (Workloads)", + "uid": "a87fb0d919ec0ea5f6543124e16c42a5", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-pod.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-pod.yaml new file mode 100644 index 00000000..0d4fdc0f --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-pod.yaml @@ -0,0 +1,1438 @@ +{{- /* +Generated from 'namespace-by-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-pod" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + namespace-by-pod.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "height": 9, + "id": 3, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "height": 9, + "id": 4, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "pod", + "value": "pod" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Pod", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?orgId=1&refresh=30s&var-namespace=$namespace&var-pod=$__cell", + "pattern": "pod", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 6, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 9, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Namespace (Pods)", + "uid": "8b7a8b326d7a6f1f04244066368c67af", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-workload.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-workload.yaml new file mode 100644 index 00000000..aa2a3573 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/namespace-by-workload.yaml @@ -0,0 +1,1710 @@ +{{- /* +Generated from 'namespace-by-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "namespace-by-workload" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + namespace-by-workload.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "columns": [ + { + "text": "Time", + "value": "Time" + }, + { + "text": "Value #A", + "value": "Value #A" + }, + { + "text": "Value #B", + "value": "Value #B" + }, + { + "text": "Value #C", + "value": "Value #C" + }, + { + "text": "Value #D", + "value": "Value #D" + }, + { + "text": "Value #E", + "value": "Value #E" + }, + { + "text": "Value #F", + "value": "Value #F" + }, + { + "text": "Value #G", + "value": "Value #G" + }, + { + "text": "Value #H", + "value": "Value #H" + }, + { + "text": "workload", + "value": "workload" + } + ], + "datasource": "$datasource", + "fill": 1, + "fontSize": "90%", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null as zero", + "renderer": "flot", + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": false + }, + "spaceLength": 10, + "span": 24, + "styles": [ + { + "alias": "Time", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Time", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Current Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Current Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Received", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #C", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Average Bandwidth Transmitted", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #D", + "thresholds": [ + + ], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Rate of Received Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #E", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #F", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Received Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #G", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Rate of Transmitted Packets Dropped", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #H", + "thresholds": [ + + ], + "type": "number", + "unit": "pps" + }, + { + "alias": "Workload", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Drill down", + "linkUrl": "d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?orgId=1&refresh=30s&var-namespace=$namespace&var-type=$type&var-workload=$__cell", + "pattern": "workload", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "C", + "step": 10 + }, + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "E", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "F", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "G", + "step": 10 + }, + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "H", + "step": 10 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Status", + "type": "table" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 6, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} workload {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 9, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth HIstory", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 12, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 15, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 17, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}workload{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=\"$namespace\", workload=~\".+\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Namespace (Workload)", + "uid": "bbb2a765a623ae38130206c7d94a160f", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml new file mode 100644 index 00000000..cd599c62 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml @@ -0,0 +1,561 @@ +{{- /* +Generated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "persistentvolumesusage" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + persistentvolumesusage.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "10s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 9, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used Space", + "refId": "A" + }, + { + "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Free Space", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Volume Space Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$datasource", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + + }, + "id": 3, + "interval": "1m", + "legend": { + "alignAsTable": true, + "rightSide": true + }, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "max without(instance,node) (\n(\n topk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n topk(1, kubelet_volume_stats_available_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n/\ntopk(1, kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "80, 90", + "title": "Volume Space Usage", + "tooltip": { + "shared": false + }, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "interval": "1m", + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 9, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used inodes", + "refId": "A" + }, + { + "expr": "(\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n -\n sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})))\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": " Free inodes", + "refId": "B" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Volume inodes Usage", + "tooltip": { + "shared": false, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$datasource", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + + }, + "id": 5, + "interval": "1m", + "legend": { + "alignAsTable": true, + "rightSide": true + }, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "max without(instance,node) (\ntopk(1, kubelet_volume_stats_inodes_used{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n/\ntopk(1, kubelet_volume_stats_inodes{metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n* 100)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "80, 90", + "title": "Volume inodes Usage", + "tooltip": { + "shared": false + }, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\"}, namespace)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": "PersistentVolumeClaim", + "multi": false, + "name": "volume", + "options": [ + + ], + "query": "label_values(kubelet_volume_stats_capacity_bytes{metrics_path=\"/metrics\", namespace=\"$namespace\"}, persistentvolumeclaim)", + "refresh": 2, + "regex": "", + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-7d", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Persistent Volumes", + "uid": "919b92a8e8041bd567af9edab12c840c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/pod-total.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/pod-total.yaml new file mode 100644 index 00000000..48b0db9b --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/pod-total.yaml @@ -0,0 +1,1202 @@ +{{- /* +Generated from 'pod-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "pod-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + pod-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "height": 9, + "id": 3, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace: $pod", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "$datasource", + "decimals": 0, + "format": "time_series", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "height": 9, + "id": 4, + "interval": null, + "links": [ + + ], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "minSpan": 12, + "nullPointMode": "connected", + "nullText": null, + "options": { + "fieldOptions": { + "calcs": [ + "last" + ], + "defaults": { + "max": 10000000000, + "min": 0, + "title": "$namespace: $pod", + "unit": "Bps" + }, + "mappings": [ + + ], + "override": { + + }, + "thresholds": [ + { + "color": "dark-green", + "index": 0, + "value": null + }, + { + "color": "dark-yellow", + "index": 1, + "value": 5000000000 + }, + { + "color": "dark-red", + "index": 2, + "value": 7000000000 + } + ], + "values": false + } + }, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 12, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", + "format": "time_series", + "instant": null, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "type": "gauge", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 8, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "pod", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total{namespace=~\"$namespace\"}, pod)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Pod", + "uid": "7a18067ce943a40ae25454675c19ff5c", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml new file mode 100644 index 00000000..08279580 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml @@ -0,0 +1,1674 @@ +{{- /* +Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.grafana.defaultDashboards.namespace }} + name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "kube-prometheus-stack.name" $ }}-grafana +{{ include "kube-prometheus-stack.labels" $ | indent 4 }} +data: + prometheus-remote-write.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "refresh": "60s", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(\n prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} \n- \n ignoring(remote_name, url) group_right(instance) (prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} != 0)\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Highest Timestamp In vs. Highest Timestamp Sent", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "clamp_min(\n rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) \n- \n ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n, 0)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate[5m]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Timestamps", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(\n prometheus_remote_storage_samples_in_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n- \n ignoring(remote_name, url) group_right(instance) (rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n- \n (rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]))\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate, in vs. succeeded or dropped [5m]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Samples", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 5, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "minSpan": 6, + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_max{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Max Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_min{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Min Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shards_desired{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Desired Shards", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Shards", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_shard_capacity{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Shard Capacity", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_remote_storage_pending_samples{cluster=~\"$cluster\", instance=~\"$instance\"} or prometheus_remote_storage_samples_pending{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Pending Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Shard Details", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 11, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_wal_segment_current{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "TSDB Current Segment", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_wal_watcher_current_segment{cluster=~\"$cluster\", instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}consumer{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Remote Write Current Segment", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Segments", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_dropped_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Dropped Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 14, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_failed_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Failed Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_retried_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) or rate(prometheus_remote_storage_samples_retried_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Retried Samples", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": { + + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 3, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", + "refId": "A" + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Enqueue Retries", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Misc. Rates", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "prometheus-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": { + "text": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "value": { + "selected": true, + "text": "All", + "value": "$__all" + } + }, + "datasource": "$datasource", + "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster.global.enabled }}0{{ else }}2{{ end }}, + "includeAll": true, + "label": null, + "multi": false, + "name": "cluster", + "options": [ + + ], + "query": "label_values(kube_pod_container_info{image=~\".*prometheus.*\"}, cluster)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "value": { + "selected": true, + "text": "All", + "value": "$__all" + } + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "instance", + "options": [ + + ], + "query": "label_values(prometheus_build_info{cluster=~\"$cluster\"}, instance)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "url", + "options": [ + + ], + "query": "label_values(prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}, url)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Prometheus / Remote Write", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus.yaml new file mode 100644 index 00000000..c94ce252 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus.yaml @@ -0,0 +1,1235 @@ +{{- /* +Generated from 'prometheus' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + prometheus.json: |- + { + "annotations": { + "list": [ + + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "links": [ + + ], + "refresh": "60s", + "rows": [ + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": false, + "steppedLine": false, + "styles": [ + { + "alias": "Time", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "hidden" + }, + { + "alias": "Count", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #A", + "thresholds": [ + + ], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Uptime", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "Value #B", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Instance", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "instance", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Job", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "job", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "Version", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "linkTargetBlank": false, + "linkTooltip": "Drill down", + "linkUrl": "", + "pattern": "version", + "thresholds": [ + + ], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [ + + ], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count by (job, instance, version) (prometheus_build_info{job=~\"$job\", instance=~\"$instance\"})", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 10 + }, + { + "expr": "max by (job, instance) (time() - process_start_time_seconds{job=~\"$job\", instance=~\"$instance\"})", + "format": "table", + "instant": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Prometheus Stats", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "transform": "table", + "type": "table", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Prometheus Stats", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(prometheus_target_sync_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m])) by (scrape_job) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}scrape_job{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Target Sync", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(prometheus_sd_discovered_targets{job=~\"$job\",instance=~\"$instance\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Targets", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Targets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Discovery", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_target_interval_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{job=~\"$job\",instance=~\"$instance\"}[5m]) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}interval{{`}}`}} configured", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Scrape Interval Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_body_size_limit_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "exceeded body size limit: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_sample_limit_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "exceeded sample limit: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "duplicate timestamp: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_bounds_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "out of bounds: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + }, + { + "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_order_total[1m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "out of order: {{`{{`}}job{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Scrape failures", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 4, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_head_samples_appended_total{job=~\"$job\",instance=~\"$instance\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Appended Samples", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Retrieval", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_series{job=~\"$job\",instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head series", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Head Series", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_chunks{job=~\"$job\",instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head chunks", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Head Chunks", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Storage", + "titleSize": "h6" + }, + { + "collapse": false, + "height": "250px", + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_engine_query_duration_seconds_count{job=~\"$job\",instance=~\"$instance\",slice=\"inner_eval\"}[5m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 10, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 0, + "links": [ + + ], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "max by (slice) (prometheus_engine_query_duration_seconds{quantile=\"0.9\",job=~\"$job\",instance=~\"$instance\"}) * 1e3", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{`{{`}}slice{{`}}`}}", + "legendLink": null, + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Stage Duration", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Query", + "titleSize": "h6" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [ + "prometheus-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "job", + "multi": true, + "name": "job", + "options": [ + + ], + "query": "label_values(prometheus_build_info{job=\"prometheus-k8s\",namespace=\"monitoring\"}, job)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": true, + "label": "instance", + "multi": true, + "name": "instance", + "options": [ + + ], + "query": "label_values(prometheus_build_info{job=~\"$job\"}, instance)", + "refresh": 1, + "regex": "", + "sort": 2, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Prometheus / Overview", + "uid": "", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/workload-total.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/workload-total.yaml new file mode 100644 index 00000000..0dfd208c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/workload-total.yaml @@ -0,0 +1,1412 @@ +{{- /* +Generated from 'workload-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "workload-total" | trunc 63 | trimSuffix "-" }} + annotations: +{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} +data: + workload-total.json: |- + { + "__inputs": [ + + ], + "__requires": [ + + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [ + + ], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Current Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "panels": [ + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Received", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 7, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "links": [ + + ], + "minSpan": 24, + "nullPointMode": "null", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 24, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}} pod {{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Average Rate of Bytes Transmitted", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": false, + "values": [ + "current" + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Average Bandwidth", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 8, + "panels": [ + + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Bandwidth HIstory", + "titleSize": "h6", + "type": "row" + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Receive Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 10, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Transmit Bandwidth", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 11, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 12, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Packets", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 14, + "panels": [ + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 15, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Received Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": { + + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 16, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [ + + ], + "minSpan": 12, + "nullPointMode": "connected", + "paceLength": 10, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + + ], + "spaceLength": 10, + "span": 12, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{`{{`}}pod{{`}}`}}", + "refId": "A", + "step": 10 + } + ], + "thresholds": [ + + ], + "timeFrom": null, + "timeShift": null, + "title": "Rate of Transmitted Packets Dropped", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + + ] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Errors", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "10s", + "rows": [ + + ], + "schemaVersion": 18, + "style": "dark", + "tags": [ + "kubernetes-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "datasource", + "options": [ + + ], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": ".+", + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "$datasource", + "definition": "label_values(container_network_receive_packets_total, namespace)", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "namespace", + "options": [ + + ], + "query": "label_values(container_network_receive_packets_total, namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "", + "value": "" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "workload", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\"}, workload)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "deployment", + "value": "deployment" + }, + "datasource": "$datasource", + "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "type", + "options": [ + + ], + "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "resolution", + "options": [ + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": true, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + } + ], + "query": "30s,5m,1h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + }, + { + "allValue": null, + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "text": "5m", + "value": "5m" + }, + "datasource": "$datasource", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "interval", + "options": [ + { + "selected": true, + "text": "4h", + "value": "4h" + } + ], + "query": "4h", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [ + + ], + "tagsQuery": "", + "type": "interval", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "{{ .Values.grafana.defaultDashboardsTimezone }}", + "title": "Kubernetes / Networking / Workload", + "uid": "728bf77cc1166d2f3133bf25846876cc", + "version": 0 + } +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/_rules.tpl b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/_rules.tpl new file mode 100644 index 00000000..d82cc2d3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/_rules.tpl @@ -0,0 +1,8 @@ +{{- define "rules.names" }} +rules: + - "alertmanager.rules" + - "general.rules" + - "kubernetes-storage" + - "prometheus" + - "kubernetes-apps" +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrole.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrole.yaml new file mode 100644 index 00000000..b5d97aec --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +# This permission are not in the kube-prometheus repo +# they're grabbed from https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml +- apiGroups: [""] + resources: + - nodes + - nodes/metrics + - services + - endpoints + - pods + verbs: ["get", "list", "watch"] +- apiGroups: + - "networking.k8s.io" + resources: + - ingresses + verbs: ["get", "list", "watch"] +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrolebinding.yaml new file mode 100644 index 00000000..18249a0c --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} + diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/extrasecret.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/extrasecret.yaml new file mode 100644 index 00000000..61664d01 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/extrasecret.yaml @@ -0,0 +1,20 @@ +{{- if .Values.prometheus.extraSecret.data -}} +{{- $secretName := printf "prometheus-%s-extra" (include "project-prometheus-stack.fullname" . ) -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ default $secretName .Values.prometheus.extraSecret.name }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- if .Values.prometheus.extraSecret.annotations }} + annotations: +{{ toYaml .Values.prometheus.extraSecret.annotations | indent 4 }} +{{- end }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/component: prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +data: +{{- range $key, $val := .Values.prometheus.extraSecret.data }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/federate.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/federate.yaml new file mode 100644 index 00000000..29d4ba20 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/federate.yaml @@ -0,0 +1,10 @@ +{{- if and .Values.prometheus.enabled .Values.federate.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-federate + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: {{ include "project-prometheus-stack.labels" . | nindent 4 }} +data: + federate-scrape-config.yaml: {{ tpl (.Files.Get "files/federate/federate-scrape-config.yaml" ) $ | b64enc | quote }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/ingress.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/ingress.yaml new file mode 100644 index 00000000..387e2b5d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/ingress.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.ingress.enabled -}} + {{- $pathType := .Values.prometheus.ingress.pathType | default "ImplementationSpecific" -}} + {{- $serviceName := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" -}} + {{- $servicePort := .Values.prometheus.ingress.servicePort | default .Values.prometheus.service.port -}} + {{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix -}} + {{- $paths := .Values.prometheus.ingress.paths | default $routePrefix -}} + {{- $apiIsStable := eq (include "project-prometheus-stack.ingress.isStable" .) "true" -}} + {{- $ingressSupportsPathType := eq (include "project-prometheus-stack.ingress.supportsPathType" .) "true" -}} +apiVersion: {{ include "project-prometheus-stack.ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.prometheus.ingress.annotations }} + annotations: +{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }} +{{- end }} + name: {{ $serviceName }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.ingress.labels }} +{{ toYaml .Values.prometheus.ingress.labels | indent 4 }} +{{- end }} +spec: + {{- if $apiIsStable }} + {{- if .Values.prometheus.ingress.ingressClassName }} + ingressClassName: {{ .Values.prometheus.ingress.ingressClassName }} + {{- end }} + {{- end }} + rules: + {{- if .Values.prometheus.ingress.hosts }} + {{- range $host := .Values.prometheus.ingress.hosts }} + - host: {{ tpl $host $ }} + http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- else }} + - http: + paths: + {{- range $p := $paths }} + - path: {{ tpl $p $ }} + {{- if and $pathType $ingressSupportsPathType }} + pathType: {{ $pathType }} + {{- end }} + backend: + {{- if $apiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} + {{- end -}} + {{- if .Values.prometheus.ingress.tls }} + tls: +{{ tpl (toYaml .Values.prometheus.ingress.tls | indent 4) . }} + {{- end -}} +{{- end -}} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/nginx-config.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/nginx-config.yaml new file mode 100644 index 00000000..c28edc07 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/nginx-config.yaml @@ -0,0 +1,68 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-nginx-proxy-config + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.annotations }} + annotations: +{{ toYaml .Values.prometheus.annotations | indent 4 }} +{{- end }} +data: + nginx.conf: |- + worker_processes auto; + error_log /dev/stdout warn; + pid /var/cache/nginx/nginx.pid; + + events { + worker_connections 1024; + } + + http { + include /etc/nginx/mime.types; + log_format main '[$time_local - $status] $remote_addr - $remote_user $request ($http_referer)'; + + proxy_connect_timeout 10; + proxy_read_timeout 180; + proxy_send_timeout 5; + proxy_buffering off; + proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=my_zone:100m inactive=1d max_size=10g; + + server { + listen 8081; + access_log off; + + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript image/jpeg image/gif image/png; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + proxy_set_header Host $host; + + location / { + proxy_cache my_zone; + proxy_cache_valid 200 302 1d; + proxy_cache_valid 301 30d; + proxy_cache_valid any 5m; + proxy_cache_bypass $http_cache_control; + add_header X-Proxy-Cache $upstream_cache_status; + add_header Cache-Control "public"; + + proxy_pass http://localhost:9090/; + + sub_filter_once off; + sub_filter 'var PATH_PREFIX = "";' 'var PATH_PREFIX = ".";'; + + if ($request_filename ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$) { + expires 90d; + } + + rewrite ^/k8s/clusters/.*/proxy(.*) /$1 break; + + } + } + } diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/podDisruptionBudget.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/podDisruptionBudget.yaml new file mode 100644 index 00000000..24e4c6a7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/podDisruptionBudget.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.podDisruptionBudget.enabled }} +apiVersion: {{ include "project-prometheus-stack.pdb.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + {{- if .Values.prometheus.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.prometheus.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.prometheus.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.prometheus.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: prometheus + prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/prometheus.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/prometheus.yaml new file mode 100644 index 00000000..2e4cfe52 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/prometheus.yaml @@ -0,0 +1,319 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: Prometheus +metadata: + name: {{ template "project-prometheus-stack.prometheus.crname" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.annotations }} + annotations: +{{ toYaml .Values.prometheus.annotations | indent 4 }} +{{- end }} +spec: + alerting: + alertmanagers: +{{- if .Values.prometheus.prometheusSpec.alertingEndpoints }} +{{ toYaml .Values.prometheus.prometheusSpec.alertingEndpoints | indent 6 }} +{{- else if .Values.alertmanager.enabled }} + - namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ template "project-prometheus-stack.fullname" . }}-alertmanager + port: {{ .Values.alertmanager.alertmanagerSpec.portName }} + {{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} + pathPrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" + {{- end }} + apiVersion: {{ .Values.alertmanager.apiVersion }} +{{- else }} + [] +{{- end }} +{{- if .Values.prometheus.prometheusSpec.apiserverConfig }} + apiserverConfig: +{{ toYaml .Values.prometheus.prometheusSpec.apiserverConfig | indent 4}} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.image }} + {{- if and .Values.prometheus.prometheusSpec.image.tag .Values.prometheus.prometheusSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" + {{- else if .Values.prometheus.prometheusSpec.image.sha }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}@sha256:{{ .Values.prometheus.prometheusSpec.image.sha }}" + {{- else if .Values.prometheus.prometheusSpec.image.tag }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }}" + {{- else }} + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.image.repository }}" + {{- end }} + version: {{ .Values.prometheus.prometheusSpec.image.tag }} + {{- if .Values.prometheus.prometheusSpec.image.sha }} + sha: {{ .Values.prometheus.prometheusSpec.image.sha }} + {{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.externalLabels }} + externalLabels: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.externalLabels | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.prometheusExternalLabelNameClear }} + prometheusExternalLabelName: "" +{{- else if .Values.prometheus.prometheusSpec.prometheusExternalLabelName }} + prometheusExternalLabelName: "{{ .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} + enableRemoteWriteReceiver: {{ .Values.prometheus.prometheusSpec.enableRemoteWriteReceiver }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.externalUrl }} + externalUrl: "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}" +{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} + externalUrl: "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}" +{{- else if not (or (empty .Values.global.cattle.url) (empty .Values.global.cattle.clusterId)) }} + externalUrl: "{{ .Values.global.cattle.url }}/k8s/clusters/{{ .Values.global.cattle.clusterId }}/api/v1/namespaces/{{ template "project-prometheus-stack.namespace" . }}/services/http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/proxy" +{{- else }} + externalUrl: http://{{ template "project-prometheus-stack.fullname" . }}-prometheus.{{ template "project-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }} +{{- end }} + nodeSelector: {{ include "linux-node-selector" . | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.nodeSelector }} +{{ toYaml .Values.prometheus.prometheusSpec.nodeSelector | indent 4 }} +{{- end }} + paused: {{ .Values.prometheus.prometheusSpec.paused }} + replicas: {{ .Values.prometheus.prometheusSpec.replicas }} + shards: {{ .Values.prometheus.prometheusSpec.shards }} + logLevel: {{ .Values.prometheus.prometheusSpec.logLevel }} + logFormat: {{ .Values.prometheus.prometheusSpec.logFormat }} + listenLocal: {{ .Values.prometheus.prometheusSpec.listenLocal }} + enableAdminAPI: {{ .Values.prometheus.prometheusSpec.enableAdminAPI }} +{{- if .Values.prometheus.prometheusSpec.web }} + web: +{{ toYaml .Values.prometheus.prometheusSpec.web | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.exemplars }} + exemplars: + {{ toYaml .Values.prometheus.prometheusSpec.exemplars | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enableFeatures }} + enableFeatures: +{{- range $enableFeatures := .Values.prometheus.prometheusSpec.enableFeatures }} + - {{ tpl $enableFeatures $ }} +{{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.scrapeInterval }} + scrapeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.prometheusSpec.scrapeTimeout }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.evaluationInterval }} + evaluationInterval: {{ .Values.prometheus.prometheusSpec.evaluationInterval }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.resources }} + resources: +{{ toYaml .Values.prometheus.prometheusSpec.resources | indent 4 }} +{{- end }} + retention: {{ .Values.prometheus.prometheusSpec.retention | quote }} +{{- if .Values.prometheus.prometheusSpec.retentionSize }} + retentionSize: {{ .Values.prometheus.prometheusSpec.retentionSize | quote }} +{{- end }} +{{- if eq .Values.prometheus.prometheusSpec.walCompression false }} + walCompression: false +{{ else }} + walCompression: true +{{- end }} +{{- if .Values.prometheus.prometheusSpec.routePrefix }} + routePrefix: {{ .Values.prometheus.prometheusSpec.routePrefix | quote }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.secrets }} + secrets: +{{ toYaml .Values.prometheus.prometheusSpec.secrets | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.configMaps }} + configMaps: +{{ toYaml .Values.prometheus.prometheusSpec.configMaps | indent 4 }} +{{- end }} + serviceAccountName: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} +{{- if .Values.prometheus.prometheusSpec.serviceMonitorSelector }} + serviceMonitorSelector: +{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues }} + serviceMonitorSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + serviceMonitorSelector: {} +{{- end }} + serviceMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.podMonitorSelector }} + podMonitorSelector: +{{ toYaml .Values.prometheus.prometheusSpec.podMonitorSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues }} + podMonitorSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + podMonitorSelector: {} +{{- end }} + podMonitorNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.probeSelector }} + probeSelector: +{{ toYaml .Values.prometheus.prometheusSpec.probeSelector | indent 4 }} +{{ else if .Values.prometheus.prometheusSpec.probeSelectorNilUsesHelmValues }} + probeSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + probeSelector: {} +{{- end }} +{{- if (or .Values.prometheus.prometheusSpec.remoteWrite .Values.prometheus.prometheusSpec.additionalRemoteWrite) }} + remoteWrite: +{{- if .Values.prometheus.prometheusSpec.remoteWrite }} +{{ tpl (toYaml .Values.prometheus.prometheusSpec.remoteWrite | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.additionalRemoteWrite }} +{{ toYaml .Values.prometheus.prometheusSpec.additionalRemoteWrite | indent 4 }} +{{- end }} +{{- end }} + probeNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.securityContext }} + securityContext: +{{ toYaml .Values.prometheus.prometheusSpec.securityContext | indent 4 }} +{{- end }} + ruleNamespaceSelector: {{ .Values.global.cattle.projectNamespaceSelector | toYaml | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.ruleSelector }} + ruleSelector: +{{ toYaml .Values.prometheus.prometheusSpec.ruleSelector | indent 4}} +{{- else if .Values.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues }} + ruleSelector: + matchLabels: + release: {{ $.Release.Name | quote }} +{{ else }} + ruleSelector: {} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.storage.enabled }} + storage: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.storageSpec | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.podMetadata }} + podMetadata: +{{ tpl (toYaml .Values.prometheus.prometheusSpec.podMetadata | indent 4) . }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.query }} + query: +{{ toYaml .Values.prometheus.prometheusSpec.query | indent 4}} +{{- end }} +{{- if or .Values.prometheus.prometheusSpec.podAntiAffinity .Values.prometheus.prometheusSpec.affinity }} + affinity: +{{- if .Values.prometheus.prometheusSpec.affinity }} +{{ toYaml .Values.prometheus.prometheusSpec.affinity | indent 4 }} +{{- end }} +{{- if eq .Values.prometheus.prometheusSpec.podAntiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} + - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} +{{- else if eq .Values.prometheus.prometheusSpec.podAntiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} + labelSelector: + matchExpressions: + - {key: app.kubernetes.io/name, operator: In, values: [prometheus]} + - {key: prometheus, operator: In, values: [{{ template "project-prometheus-stack.fullname" . }}-prometheus]} +{{- end }} +{{- end }} + tolerations: {{ include "linux-node-tolerations" . | nindent 4 }} +{{- if .Values.prometheus.prometheusSpec.tolerations }} +{{ toYaml .Values.prometheus.prometheusSpec.tolerations | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.prometheus.prometheusSpec.topologySpreadConstraints | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} + imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 4 }} +{{- end }} +{{- if .Values.federate.enabled }} + additionalScrapeConfigs: + name: {{ template "project-prometheus-stack.fullname" . }}-federate + key: federate-scrape-config.yaml +{{- end }} +{{- if .Values.prometheus.prometheusSpec.containers }} + containers: +{{ tpl .Values.prometheus.prometheusSpec.containers $ | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.initContainers }} + initContainers: +{{ toYaml .Values.prometheus.prometheusSpec.initContainers | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.priorityClassName }} + priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.disableCompaction }} + disableCompaction: {{ .Values.prometheus.prometheusSpec.disableCompaction }} +{{- end }} + portName: {{ .Values.prometheus.prometheusSpec.portName }} +{{- if .Values.prometheus.prometheusSpec.volumes }} + volumes: +{{ toYaml .Values.prometheus.prometheusSpec.volumes | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.volumeMounts }} + volumeMounts: +{{ toYaml .Values.prometheus.prometheusSpec.volumeMounts | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs }} + arbitraryFSAccessThroughSMs: +{{ toYaml .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs | indent 4 }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.overrideHonorLabels }} + overrideHonorLabels: {{ .Values.prometheus.prometheusSpec.overrideHonorLabels }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} + overrideHonorTimestamps: {{ .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} +{{- end }} + ignoreNamespaceSelectors: true # always hard-coded to true for security reasons +{{- if .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} + enforcedNamespaceLabel: {{ .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} +{{- $prometheusDefaultRulesExcludedFromEnforce := (include "rules.names" .) | fromYaml }} + prometheusRulesExcludedFromEnforce: +{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} + - ruleNamespace: "{{ template "project-prometheus-stack.namespace" $ }}" + ruleName: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce }} +{{ toYaml .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce | indent 4 }} +{{- end }} + excludedFromEnforcement: +{{- range $prometheusDefaultRulesExcludedFromEnforce.rules }} + - resource: prometheusrules + namespace: "{{ template "project-prometheus-stack.namespace" $ }}" + name: "{{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) . | trunc 63 | trimSuffix "-" }}" +{{- end }} +{{- if .Values.prometheus.prometheusSpec.excludedFromEnforcement }} +{{ tpl (toYaml .Values.prometheus.prometheusSpec.excludedFromEnforcement | indent 4) . }} +{{- end }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.queryLogFile }} + queryLogFile: {{ .Values.prometheus.prometheusSpec.queryLogFile }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedSampleLimit }} + enforcedSampleLimit: {{ .Values.prometheus.prometheusSpec.enforcedSampleLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedTargetLimit }} + enforcedTargetLimit: {{ .Values.prometheus.prometheusSpec.enforcedTargetLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelLimit }} + enforcedLabelLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} + enforcedLabelNameLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelNameLengthLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit}} + enforcedLabelValueLengthLimit: {{ .Values.prometheus.prometheusSpec.enforcedLabelValueLengthLimit }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} + allowOverlappingBlocks: {{ .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} +{{- end }} +{{- if .Values.prometheus.prometheusSpec.minReadySeconds }} + minReadySeconds: {{ .Values.prometheus.prometheusSpec.minReadySeconds }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrole.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrole.yaml new file mode 100644 index 00000000..8a3cbea5 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrolebinding.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrolebinding.yaml new file mode 100644 index 00000000..736525c9 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp-clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus-psp +subjects: + - kind: ServiceAccount + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} +{{- end }} + diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp.yaml new file mode 100644 index 00000000..b0130af7 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/psp.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{- if .Values.global.rbac.pspAnnotations }} + annotations: +{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} +{{- end }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + privileged: false + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' +{{- if .Values.prometheus.podSecurityPolicy.volumes }} +{{ toYaml .Values.prometheus.podSecurityPolicy.volumes | indent 4 }} +{{- end }} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Permits the container to run with root privileges as well. + rule: 'RunAsAny' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Allow adding the root group. + - min: 0 + max: 65535 + readOnlyRootFilesystem: false +{{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} + allowedCapabilities: +{{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/alertmanager.rules.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/alertmanager.rules.yaml new file mode 100644 index 00000000..0cca1fb3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/alertmanager.rules.yaml @@ -0,0 +1,217 @@ +{{- /* +Generated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/alertmanager-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }} +{{- $alertmanagerJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager" }} +{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "alertmanager.rules" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: alertmanager.rules + rules: +{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedReload | default false) }} + - alert: AlertmanagerFailedReload + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Configuration has failed to load for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedreload + summary: Reloading an Alertmanager configuration has failed. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(alertmanager_config_last_reload_successful{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) == 0 + for: 10m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerMembersInconsistent | default false) }} + - alert: AlertmanagerMembersInconsistent + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} has only found {{`{{`}} $value {{`}}`}} members of the {{`{{`}}$labels.job{{`}}`}} cluster. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagermembersinconsistent + summary: A member of an Alertmanager cluster has not found all other cluster members. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + < on (namespace,service) group_left + count by (namespace,service) (max_over_time(alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m])) + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerFailedToSendAlerts | default false) }} + - alert: AlertmanagerFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} failed to send {{`{{`}} $value | humanizePercentage {{`}}`}} of notifications to {{`{{`}} $labels.integration {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerfailedtosendalerts + summary: An Alertmanager instance failed to send notifications. + expr: |- + ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} + - alert: AlertmanagerClusterFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts + summary: All Alertmanager instances in a cluster failed to send notifications to a critical integration. + expr: |- + min by (namespace,service, integration) ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration=~`.*`}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterFailedToSendAlerts | default false) }} + - alert: AlertmanagerClusterFailedToSendAlerts + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The minimum notification failure rate to {{`{{`}} $labels.integration {{`}}`}} sent from any instance in the {{`{{`}}$labels.job{{`}}`}} cluster is {{`{{`}} $value | humanizePercentage {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterfailedtosendalerts + summary: All Alertmanager instances in a cluster failed to send notifications to a non-critical integration. + expr: |- + min by (namespace,service, integration) ( + rate(alertmanager_notifications_failed_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) + / + rate(alertmanager_notifications_total{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}", integration!~`.*`}[5m]) + ) + > 0.01 + for: 5m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerConfigInconsistent | default false) }} + - alert: AlertmanagerConfigInconsistent + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have different configurations. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerconfiginconsistent + summary: Alertmanager instances within the same cluster have different configurations. + expr: |- + count by (namespace,service) ( + count_values by (namespace,service) ("config_hash", alertmanager_config_hash{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) + ) + != 1 + for: 20m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterDown | default false) }} + - alert: AlertmanagerClusterDown + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have been up for less than half of the last 5m.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclusterdown + summary: Half or more of the Alertmanager instances within the same cluster are down. + expr: |- + ( + count by (namespace,service) ( + avg_over_time(up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[5m]) < 0.5 + ) + / + count by (namespace,service) ( + up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} + ) + ) + >= 0.5 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.AlertmanagerClusterCrashlooping | default false) }} + - alert: AlertmanagerClusterCrashlooping + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of Alertmanager instances within the {{`{{`}}$labels.job{{`}}`}} cluster have restarted at least 5 times in the last 10m.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/alertmanager/alertmanagerclustercrashlooping + summary: Half or more of the Alertmanager instances within the same cluster are crashlooping. + expr: |- + ( + count by (namespace,service) ( + changes(process_start_time_seconds{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}[10m]) > 4 + ) + / + count by (namespace,service) ( + up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} + ) + ) + >= 0.5 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/general.rules.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/general.rules.yaml new file mode 100644 index 00000000..13c158c0 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/general.rules.yaml @@ -0,0 +1,98 @@ +{{- /* +Generated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubePrometheus-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "general.rules" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: general.rules + rules: +{{- if not (.Values.defaultRules.disabled.TargetDown | default false) }} + - alert: TargetDown + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.4g" $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.service {{`}}`}} targets in {{`{{`}} $labels.namespace {{`}}`}} namespace are down.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/targetdown + summary: One or more targets are unreachable. + expr: 100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) > 10 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.Watchdog | default false) }} + - alert: Watchdog + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'This is an alert meant to ensure that the entire alerting pipeline is functional. + + This alert is always firing, therefore it should always be firing in Alertmanager + + and always fire against a receiver. There are integrations with various notification + + mechanisms that send a notification when this alert is not firing. For example the + + "DeadMansSnitch" integration in PagerDuty. + + ' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/watchdog + summary: An alert that should always be firing to certify that Alertmanager is working properly. + expr: vector(1) + labels: + severity: none +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.InfoInhibitor | default false) }} + - alert: InfoInhibitor + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'This is an alert that is used to inhibit info alerts. + + By themselves, the info-level alerts are sometimes very noisy, but they are relevant when combined with + + other alerts. + + This alert fires whenever there''s a severity="info" alert, and stops firing when another alert with a + + severity of ''warning'' or ''critical'' starts firing on the same namespace. + + This alert should be routed to a null receiver and configured to inhibit alerts with severity="info". + + ' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/general/infoinhibitor + summary: Info-level alert inhibition. + expr: ALERTS{severity = "info"} == 1 unless on(namespace) ALERTS{alertname != "InfoInhibitor", severity =~ "warning|critical", alertstate="firing"} == 1 + labels: + severity: none +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-apps.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-apps.yaml new file mode 100644 index 00000000..c956157e --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-apps.yaml @@ -0,0 +1,375 @@ +{{- /* +Generated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }} +{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-apps" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: kubernetes-apps + rules: +{{- if not (.Values.defaultRules.disabled.KubePodCrashLooping | default false) }} + - alert: KubePodCrashLooping + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: 'Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is in waiting state (reason: "CrashLoopBackOff").' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodcrashlooping + summary: Pod is crash looping. + expr: max_over_time(kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff", job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) >= 1 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePodNotReady | default false) }} + - alert: KubePodNotReady + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepodnotready + summary: Pod has been in a non-ready state for more than 15 minutes. + expr: |- + sum by (namespace, pod, cluster) ( + max by(namespace, pod, cluster) ( + kube_pod_status_phase{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}", phase=~"Pending|Unknown"} + ) * on(namespace, pod, cluster) group_left(owner_kind) topk by(namespace, pod, cluster) ( + 1, max by(namespace, pod, owner_kind, cluster) (kube_pod_owner{owner_kind!="Job"}) + ) + ) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDeploymentGenerationMismatch | default false) }} + - alert: KubeDeploymentGenerationMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentgenerationmismatch + summary: Deployment generation mismatch due to possible roll-back + expr: |- + kube_deployment_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_deployment_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDeploymentReplicasMismatch | default false) }} + - alert: KubeDeploymentReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedeploymentreplicasmismatch + summary: Deployment has not matched the expected number of replicas. + expr: |- + ( + kube_deployment_spec_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + > + kube_deployment_status_replicas_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) and ( + changes(kube_deployment_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetReplicasMismatch | default false) }} + - alert: KubeStatefulSetReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetreplicasmismatch + summary: Deployment has not matched the expected number of replicas. + expr: |- + ( + kube_statefulset_status_replicas_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_status_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) and ( + changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[10m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetGenerationMismatch | default false) }} + - alert: KubeStatefulSetGenerationMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetgenerationmismatch + summary: StatefulSet generation mismatch due to possible roll-back + expr: |- + kube_statefulset_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeStatefulSetUpdateNotRolledOut | default false) }} + - alert: KubeStatefulSetUpdateNotRolledOut + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubestatefulsetupdatenotrolledout + summary: StatefulSet update has not been rolled out. + expr: |- + ( + max without (revision) ( + kube_statefulset_status_current_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + unless + kube_statefulset_status_update_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + * + ( + kube_statefulset_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + ) and ( + changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetRolloutStuck | default false) }} + - alert: KubeDaemonSetRolloutStuck + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} has not finished or progressed for at least 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetrolloutstuck + summary: DaemonSet rollout is stuck. + expr: |- + ( + ( + kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) or ( + kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + 0 + ) or ( + kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) or ( + kube_daemonset_status_number_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + ) + ) and ( + changes(kube_daemonset_status_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) + == + 0 + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeContainerWaiting | default false) }} + - alert: KubeContainerWaiting + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: pod/{{`{{`}} $labels.pod {{`}}`}} in namespace {{`{{`}} $labels.namespace {{`}}`}} on container {{`{{`}} $labels.container{{`}}`}} has been in waiting state for longer than 1 hour. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubecontainerwaiting + summary: Pod container waiting longer than 1 hour + expr: sum by (namespace, pod, container, cluster) (kube_pod_container_status_waiting_reason{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) > 0 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetNotScheduled | default false) }} + - alert: KubeDaemonSetNotScheduled + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetnotscheduled + summary: DaemonSet pods are not scheduled. + expr: |- + kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + - + kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeDaemonSetMisScheduled | default false) }} + - alert: KubeDaemonSetMisScheduled + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubedaemonsetmisscheduled + summary: DaemonSet pods are misscheduled. + expr: kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeJobNotCompleted | default false) }} + - alert: KubeJobNotCompleted + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than {{`{{`}} "43200" | humanizeDuration {{`}}`}} to complete. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobnotcompleted + summary: Job did not complete in time + expr: |- + time() - max by(namespace, job_name, cluster) (kube_job_status_start_time{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + and + kube_job_status_active{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0) > 43200 + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeJobFailed | default false) }} + - alert: KubeJobFailed + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. Removing failed job after investigation should clear this alert. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubejobfailed + summary: Job failed to complete. + expr: kube_job_failed{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeHpaReplicasMismatch | default false) }} + - alert: KubeHpaReplicasMismatch + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has not matched the desired number of replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpareplicasmismatch + summary: HPA has not matched desired number of replicas. + expr: |- + (kube_horizontalpodautoscaler_status_desired_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + != + kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + > + kube_horizontalpodautoscaler_spec_min_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + (kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + < + kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) + and + changes(kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[15m]) == 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubeHpaMaxedOut | default false) }} + - alert: KubeHpaMaxedOut + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.horizontalpodautoscaler {{`}}`}} has been running at max replicas for longer than 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubehpamaxedout + summary: HPA is running at max replicas + expr: |- + kube_horizontalpodautoscaler_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + == + kube_horizontalpodautoscaler_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-storage.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-storage.yaml new file mode 100644 index 00000000..b6fe43fb --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/kubernetes-storage.yaml @@ -0,0 +1,160 @@ +{{- /* +Generated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/kubernetesControlPlane-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }} +{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "kubernetes-storage" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: kubernetes-storage + rules: +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} + - alert: KubePersistentVolumeFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} $value | humanizePercentage {{`}}`}} free. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup + summary: PersistentVolume is filling up. + expr: |- + kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + < 0.03 + and + kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeFillingUp | default false) }} + - alert: KubePersistentVolumeFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} is available. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumefillingup + summary: PersistentVolume is filling up. + expr: |- + ( + kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_capacity_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.15 + and + kubelet_volume_stats_used_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + and + predict_linear(kubelet_volume_stats_available_bytes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} + - alert: KubePersistentVolumeInodesFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} only has {{`{{`}} $value | humanizePercentage {{`}}`}} free inodes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup + summary: PersistentVolumeInodes are filling up. + expr: |- + ( + kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.03 + and + kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeInodesFillingUp | default false) }} + - alert: KubePersistentVolumeInodesFillingUp + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to run out of inodes within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} of its inodes are free. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeinodesfillingup + summary: PersistentVolumeInodes are filling up. + expr: |- + ( + kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + / + kubelet_volume_stats_inodes{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} + ) < 0.15 + and + kubelet_volume_stats_inodes_used{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} > 0 + and + predict_linear(kubelet_volume_stats_inodes_free{namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_access_mode{ access_mode="ReadOnlyMany"} == 1 + unless on(namespace, persistentvolumeclaim) + kube_persistentvolumeclaim_labels{label_excluded_from_alerts="true"} == 1 + for: 1h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.KubePersistentVolumeErrors | default false) }} + - alert: KubePersistentVolumeErrors + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/kubernetes/kubepersistentvolumeerrors + summary: PersistentVolume is having issues with provisioning. + expr: kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/prometheus.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/prometheus.yaml new file mode 100644 index 00000000..d3aa167d --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/rules-1.14/prometheus.yaml @@ -0,0 +1,448 @@ +{{- /* +Generated from 'prometheus' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/prometheus-prometheusRule.yaml +Do not change in-place! In order to change this file first read following link: +https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack +*/ -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }} +{{- $prometheusJob := printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" }} +{{- $namespace := printf "%s" (include "project-prometheus-stack.namespace" .) }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" .) "prometheus" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.defaultRules.labels }} +{{ toYaml .Values.defaultRules.labels | indent 4 }} +{{- end }} +{{- if .Values.defaultRules.annotations }} + annotations: +{{ toYaml .Values.defaultRules.annotations | indent 4 }} +{{- end }} +spec: + groups: + - name: prometheus + rules: +{{- if not (.Values.defaultRules.disabled.PrometheusBadConfig | default false) }} + - alert: PrometheusBadConfig + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to reload its configuration. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusbadconfig + summary: Failed Prometheus configuration reload. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(prometheus_config_last_reload_successful{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) == 0 + for: 10m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotificationQueueRunningFull | default false) }} + - alert: PrometheusNotificationQueueRunningFull + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Alert notification queue of Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is running full. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotificationqueuerunningfull + summary: Prometheus alert notification queue predicted to run full in less than 30m. + expr: |- + # Without min_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + predict_linear(prometheus_notifications_queue_length{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m], 60 * 30) + > + min_over_time(prometheus_notifications_queue_capacity{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToSomeAlertmanagers | default false) }} + - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.alertmanager{{`}}`}}.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstosomealertmanagers + summary: Prometheus has encountered more than 1% errors sending alerts to a specific Alertmanager. + expr: |- + ( + rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + / + rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + * 100 + > 1 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotConnectedToAlertmanagers | default false) }} + - alert: PrometheusNotConnectedToAlertmanagers + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not connected to any Alertmanagers. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotconnectedtoalertmanagers + summary: Prometheus is not connected to any Alertmanagers. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + max_over_time(prometheus_notifications_alertmanagers_discovered{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) < 1 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTSDBReloadsFailing | default false) }} + - alert: PrometheusTSDBReloadsFailing + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} reload failures over the last 3h. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbreloadsfailing + summary: Prometheus has issues reloading blocks from disk. + expr: increase(prometheus_tsdb_reloads_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 + for: 4h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTSDBCompactionsFailing | default false) }} + - alert: PrometheusTSDBCompactionsFailing + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last 3h. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustsdbcompactionsfailing + summary: Prometheus has issues compacting blocks. + expr: increase(prometheus_tsdb_compactions_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 + for: 4h + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusNotIngestingSamples | default false) }} + - alert: PrometheusNotIngestingSamples + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not ingesting samples. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusnotingestingsamples + summary: Prometheus is not ingesting samples. + expr: |- + ( + rate(prometheus_tsdb_head_samples_appended_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) <= 0 + and + ( + sum without(scrape_job) (prometheus_target_metadata_cache_entries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 + or + sum without(rule_group) (prometheus_rule_group_rules{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}) > 0 + ) + ) + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusDuplicateTimestamps | default false) }} + - alert: PrometheusDuplicateTimestamps + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with different values but duplicated timestamp. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusduplicatetimestamps + summary: Prometheus is dropping samples with duplicate timestamps. + expr: rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusOutOfOrderTimestamps | default false) }} + - alert: PrometheusOutOfOrderTimestamps + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with timestamps arriving out of order. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusoutofordertimestamps + summary: Prometheus drops samples with out-of-order timestamps. + expr: rate(prometheus_target_scrapes_sample_out_of_order_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 10m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteStorageFailures | default false) }} + - alert: PrometheusRemoteStorageFailures + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} failed to send {{`{{`}} printf "%.1f" $value {{`}}`}}% of the samples to {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}} + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotestoragefailures + summary: Prometheus fails to send samples to remote storage. + expr: |- + ( + (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + / + ( + (rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + + + (rate(prometheus_remote_storage_succeeded_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) or rate(prometheus_remote_storage_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m])) + ) + ) + * 100 + > 1 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteBehind | default false) }} + - alert: PrometheusRemoteWriteBehind + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write is {{`{{`}} printf "%.1f" $value {{`}}`}}s behind for {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritebehind + summary: Prometheus remote write is behind. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + - ignoring(remote_name, url) group_right + max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + > 120 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRemoteWriteDesiredShards | default false) }} + - alert: PrometheusRemoteWriteDesiredShards + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write desired shards calculation wants to run {{`{{`}} $value {{`}}`}} shards for queue {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}, which is more than the max of {{`{{`}} printf `prometheus_remote_storage_shards_max{instance="%s",job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}` $labels.instance | query | first | value {{`}}`}}. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusremotewritedesiredshards + summary: Prometheus remote write desired shards calculation wants to run more than configured max shards. + expr: |- + # Without max_over_time, failed scrapes could create false negatives, see + # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. + ( + max_over_time(prometheus_remote_storage_shards_desired{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + > + max_over_time(prometheus_remote_storage_shards_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) + ) + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusRuleFailures | default false) }} + - alert: PrometheusRuleFailures + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to evaluate {{`{{`}} printf "%.0f" $value {{`}}`}} rules in the last 5m. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusrulefailures + summary: Prometheus is failing rule evaluations. + expr: increase(prometheus_rule_evaluation_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusMissingRuleEvaluations | default false) }} + - alert: PrometheusMissingRuleEvaluations + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has missed {{`{{`}} printf "%.0f" $value {{`}}`}} rule group evaluations in the last 5m. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusmissingruleevaluations + summary: Prometheus is missing rule evaluations due to slow rule group evaluation. + expr: increase(prometheus_rule_group_iterations_missed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTargetLimitHit | default false) }} + - alert: PrometheusTargetLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because the number of targets exceeded the configured target_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetlimithit + summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit. + expr: increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusLabelLimitHit | default false) }} + - alert: PrometheusLabelLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because some samples exceeded the configured label_limit, label_name_length_limit or label_value_length_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuslabellimithit + summary: Prometheus has dropped targets because some scrape configs have exceeded the labels limit. + expr: increase(prometheus_target_scrape_pool_exceeded_label_limits_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusScrapeBodySizeLimitHit | default false) }} + - alert: PrometheusScrapeBodySizeLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured body_size_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapebodysizelimithit + summary: Prometheus has dropped some targets that exceeded body size limit. + expr: increase(prometheus_target_scrapes_exceeded_body_size_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusScrapeSampleLimitHit | default false) }} + - alert: PrometheusScrapeSampleLimitHit + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed {{`{{`}} printf "%.0f" $value {{`}}`}} scrapes in the last 5m because some targets exceeded the configured sample_limit. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheusscrapesamplelimithit + summary: Prometheus has failed scrapes that have exceeded the configured sample limit. + expr: increase(prometheus_target_scrapes_exceeded_sample_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusTargetSyncFailure | default false) }} + - alert: PrometheusTargetSyncFailure + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.0f" $value {{`}}`}} targets in Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} have failed to sync because invalid configuration was supplied.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheustargetsyncfailure + summary: Prometheus has failed to sync targets. + expr: increase(prometheus_target_sync_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[30m]) > 0 + for: 5m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusHighQueryLoad | default false) }} + - alert: PrometheusHighQueryLoad + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} query API has less than 20% available capacity in its query engine for the last 15 minutes. + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheushighqueryload + summary: Prometheus is reaching its maximum capacity serving concurrent requests. + expr: avg_over_time(prometheus_engine_queries{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) / max_over_time(prometheus_engine_queries_concurrent_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0.8 + for: 15m + labels: + severity: warning +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- if not (.Values.defaultRules.disabled.PrometheusErrorSendingAlertsToAnyAlertmanager | default false) }} + - alert: PrometheusErrorSendingAlertsToAnyAlertmanager + annotations: +{{- if .Values.defaultRules.additionalRuleAnnotations }} +{{ toYaml .Values.defaultRules.additionalRuleAnnotations | indent 8 }} +{{- end }} + description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% minimum errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to any Alertmanager.' + runbook_url: {{ .Values.defaultRules.runbookUrl }}/prometheus/prometheuserrorsendingalertstoanyalertmanager + summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager. + expr: |- + min without (alertmanager) ( + rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) + / + rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}",alertmanager!~``}[5m]) + ) + * 100 + > 3 + for: 15m + labels: + severity: critical +{{- if .Values.defaultRules.additionalRuleLabels }} +{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/service.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/service.yaml new file mode 100644 index 00000000..411ec5fa --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/service.yaml @@ -0,0 +1,56 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + self-monitor: {{ .Values.prometheus.serviceMonitor.selfMonitor | quote }} +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.service.labels }} +{{ toYaml .Values.prometheus.service.labels | indent 4 }} +{{- end }} +{{- if .Values.prometheus.service.annotations }} + annotations: +{{ toYaml .Values.prometheus.service.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.prometheus.service.clusterIP }} + clusterIP: {{ .Values.prometheus.service.clusterIP }} +{{- end }} +{{- if .Values.prometheus.service.externalIPs }} + externalIPs: +{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} +{{- if ne .Values.prometheus.service.type "ClusterIP" }} + externalTrafficPolicy: {{ .Values.prometheus.service.externalTrafficPolicy }} +{{- end }} + ports: + - name: {{ .Values.prometheus.prometheusSpec.portName }} + {{- if eq .Values.prometheus.service.type "NodePort" }} + nodePort: {{ .Values.prometheus.service.nodePort }} + {{- end }} + port: {{ .Values.prometheus.service.port }} + targetPort: {{ .Values.prometheus.service.targetPort }} +{{- if .Values.prometheus.service.additionalPorts }} +{{ toYaml .Values.prometheus.service.additionalPorts | indent 2 }} +{{- end }} + publishNotReadyAddresses: {{ .Values.prometheus.service.publishNotReadyAddresses }} + selector: + app.kubernetes.io/name: prometheus + prometheus: {{ template "project-prometheus-stack.prometheus.crname" . }} +{{- if .Values.prometheus.service.sessionAffinity }} + sessionAffinity: {{ .Values.prometheus.service.sessionAffinity }} +{{- end }} + type: "{{ .Values.prometheus.service.type }}" +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/serviceaccount.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/serviceaccount.yaml new file mode 100644 index 00000000..b4d44164 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/serviceaccount.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.prometheus.serviceAccountName" . }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/name: {{ template "project-prometheus-stack.name" . }}-prometheus + app.kubernetes.io/component: prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +{{- if .Values.prometheus.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{ include "project-prometheus-stack.imagePullSecrets" . | trim | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/prometheus/servicemonitor.yaml b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/servicemonitor.yaml new file mode 100644 index 00000000..2d995511 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/prometheus/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.selfMonitor }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-prometheus + namespace: {{ template "project-prometheus-stack.namespace" . }} + labels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus +{{ include "project-prometheus-stack.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app: {{ template "project-prometheus-stack.name" . }}-prometheus + release: {{ $.Release.Name | quote }} + self-monitor: "true" + namespaceSelector: + matchNames: + - {{ printf "%s" (include "project-prometheus-stack.namespace" .) | quote }} + endpoints: + - port: {{ .Values.prometheus.prometheusSpec.portName }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.scheme }} + scheme: {{ .Values.prometheus.serviceMonitor.scheme }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} + {{- end }} + path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" + metricRelabelings: + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + {{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + {{ if .Values.global.cattle.clusterId }} + - sourceLabels: [__address__] + targetLabel: cluster_id + replacement: {{ .Values.global.cattle.clusterId }} + {{- end }} + {{ if .Values.global.cattle.clusterName}} + - sourceLabels: [__address__] + targetLabel: cluster_name + replacement: {{ .Values.global.cattle.clusterName }} + {{- end }} +{{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: +{{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} +{{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml new file mode 100644 index 00000000..508e4cc3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml @@ -0,0 +1,131 @@ +{{- $namespaces := dict "_0" .Release.Namespace -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + annotations: + "helm.sh/hook": post-install, post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded, before-hook-creation +spec: + template: + metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + spec: + serviceAccountName: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +{{- if .Values.global.kubectl.securityContext }} + securityContext: {{ toYaml .Values.global.kubectl.securityContext | nindent 8 }} +{{- end }} + restartPolicy: Never + nodeSelector: {{ include "linux-node-selector" . | nindent 8 }} + tolerations: {{ include "linux-node-tolerations" . | nindent 8 }} + containers: + {{- range $_, $ns := $namespaces }} + - name: patch-sa-{{ $ns }} + image: {{ template "system_default_registry" $ }}{{ $.Values.global.kubectl.repository }}:{{ $.Values.global.kubectl.tag }} + imagePullPolicy: {{ $.Values.global.kubectl.pullPolicy }} + command: ["kubectl", "patch", "serviceaccount", "default", "-p", "{\"automountServiceAccountToken\": false}"] + args: ["-n", "{{ $ns }}"] +{{- if $.Values.global.kubectl.resources }} + resources: {{ toYaml $.Values.global.kubectl.resources | nindent 10 }} +{{- end }} +{{- if $.Values.global.kubectl.containerSecurityContext }} + securityContext: {{ toYaml $.Values.global.kubectl.containerSecurityContext | nindent 10 }} +{{- end }} + {{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: ['get', 'patch'] +{{- if .Values.global.cattle.psp.enabled }} +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "project-prometheus-stack.fullname" . }}-patch-sa +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +subjects: +- kind: ServiceAccount + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +--- +{{- if .Values.global.cattle.psp.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "project-prometheus-stack.fullname" . }}-patch-sa + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "project-prometheus-stack.fullname" . }}-patch-sa +spec: + privileged: false + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false + volumes: + - 'secret' +{{- end }} +{{- range $_, $ns := $namespaces }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-allow-all + namespace: {{ $ns }} +spec: + podSelector: {} + ingress: + - {} + egress: + - {} + policyTypes: + - Ingress + - Egress +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/validate-install-crd.yaml b/charts/rancher-project-monitoring/0.3.1/templates/validate-install-crd.yaml new file mode 100644 index 00000000..b0dcf188 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/validate-install-crd.yaml @@ -0,0 +1,21 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +# {{- $found := dict -}} +# {{- set $found "monitoring.coreos.com/v1alpha1/AlertmanagerConfig" false -}} +# {{- set $found "monitoring.coreos.com/v1/Alertmanager" false -}} +# {{- set $found "monitoring.coreos.com/v1/PodMonitor" false -}} +# {{- set $found "monitoring.coreos.com/v1/Probe" false -}} +# {{- set $found "monitoring.coreos.com/v1/Prometheus" false -}} +# {{- set $found "monitoring.coreos.com/v1/PrometheusRule" false -}} +# {{- set $found "monitoring.coreos.com/v1/ServiceMonitor" false -}} +# {{- set $found "monitoring.coreos.com/v1/ThanosRuler" false -}} +# {{- range .Capabilities.APIVersions -}} +# {{- if hasKey $found (toString .) -}} +# {{- set $found (toString .) true -}} +# {{- end -}} +# {{- end -}} +# {{- range $_, $exists := $found -}} +# {{- if (eq $exists false) -}} +# {{- required "Required Prometheus Operator CRDs are missing. Please install Prometheus Operator (e.g. rancher-monitoring) before installing this chart." "" -}} +# {{- end -}} +# {{- end -}} +#{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/validate-psp-install.yaml b/charts/rancher-project-monitoring/0.3.1/templates/validate-psp-install.yaml new file mode 100644 index 00000000..a30c59d3 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/templates/validate-psp-install.yaml @@ -0,0 +1,7 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +#{{- if .Values.global.cattle.psp.enabled }} +#{{- if not (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} +#{{- fail "The target cluster does not have the PodSecurityPolicy API resource. Please disable PSPs in this chart before proceeding." -}} +#{{- end }} +#{{- end }} +#{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/values.yaml b/charts/rancher-project-monitoring/0.3.1/values.yaml new file mode 100644 index 00000000..7415c413 --- /dev/null +++ b/charts/rancher-project-monitoring/0.3.1/values.yaml @@ -0,0 +1,1537 @@ +# Default values for project-prometheus-stack. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Rancher Project Monitoring Configuration + +## Provide a name in place of project-prometheus-stack for `app:` labels +## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url +## +nameOverride: "rancher-project-monitoring" + +## Override the deployment namespace +## NOTE: If you change this value, you must update the prometheus-adapter.prometheus.url +## +namespaceOverride: "" + +## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6 +## +kubeTargetVersionOverride: "" + +## Allow kubeVersion to be overridden while creating the ingress +## +kubeVersionOverride: "" + +## Provide a name to substitute for the full names of resources +## +fullnameOverride: "" + +## Labels to apply to all resources +## +commonLabels: {} +# scmhash: abc123 +# myLabel: aakkmd + +## Create default rules for monitoring the cluster +## +defaultRules: + create: true + rules: + general: true + prometheus: true + alertmanager: true + kubernetesApps: true + kubernetesStorage: true + + ## Reduce app namespace alert scope + appNamespacesTarget: ".*" + + ## Labels for default rules + labels: {} + ## Annotations for default rules + annotations: {} + + ## Additional labels for PrometheusRule alerts + additionalRuleLabels: {} + + ## Additional annotations for PrometheusRule alerts + additionalRuleAnnotations: {} + + ## Prefix for runbook URLs. Use this to override the first part of the runbookURLs that is common to all rules. + runbookUrl: "https://runbooks.prometheus-operator.dev/runbooks" + + ## Disabled PrometheusRule alerts + disabled: {} + +## +global: + cattle: + psp: + enabled: false + systemDefaultRegistry: "" + projectNamespaceSelector: {} + projectNamespaces: [] + kubectl: + repository: rancher/kubectl + tag: v1.20.2 + pullPolicy: IfNotPresent + securityContext: + runAsNonRoot: true + runAsUser: 1000 + rbac: + ## Create RBAC resources for ServiceAccounts and users + ## + create: true + + userRoles: + ## Create default user Roles that the Helm Project Operator will automatically create RoleBindings for + ## + ## How does this work? + ## + ## The operator will watch for all subjects bound to each Kubernetes default ClusterRole in the project registration namespace + ## where the ProjectHelmChart that deployed this chart belongs to; if it observes a subject bound to a particular role in + ## the project registration namespace (e.g. edit) and if a Role exists that is deployed by this chart with the label + ## 'helm.cattle.io/project-helm-chart-role-aggregate-from': '', it will automaticaly create a RoleBinding + ## in the release namespace binding all such subjects to that Role. + ## + ## Note: while the default behavior is to use the Kubernetes default ClusterRole, the operator deployment (prometheus-federator) + ## can be configured to use a different set of ClusterRoles as the source of truth for admin, edit, and view permissions. + ## + create: true + ## Add labels to Roles + aggregateToDefaultRoles: true + + pspAnnotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Reference to one or more secrets to be used when pulling images + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + imagePullSecrets: [] + # - name: "image-pull-secret" + # or + # - "image-pull-secret" + +federate: + ## enabled indicates whether to add federation to any Project Prometheus Stacks by default + ## If not enabled, no federation will be turned on + enabled: true + + # Change this to point at all Prometheuses you want all your Project Prometheus Stacks to federate from + # By default, this matches the default deployment of Rancher Monitoring + targets: + - rancher-monitoring-prometheus.cattle-monitoring-system.svc:9090 + + ## Scrape interval + interval: "15s" + +## Configuration for alertmanager +## ref: https://prometheus.io/docs/alerting/alertmanager/ +## +alertmanager: + + ## Deploy alertmanager + ## + enabled: true + + ## Annotations for Alertmanager + ## + annotations: {} + + ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2 + ## + apiVersion: v2 + + ## Service account for Alertmanager to use. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## + serviceAccount: + create: true + name: "" + annotations: {} + + ## Configure pod disruption budgets for Alertmanager + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + ## This configuration is immutable once created and will require the PDB to be deleted to be changed + ## https://github.com/kubernetes/kubernetes/issues/45398 + ## + podDisruptionBudget: + enabled: false + minAvailable: 1 + maxUnavailable: "" + + ## Alertmanager configuration directives + ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file + ## https://prometheus.io/webtools/alerting/routing-tree-editor/ + ## + config: + global: + resolve_timeout: 5m + inhibit_rules: + - source_matchers: + - 'severity = critical' + target_matchers: + - 'severity =~ warning|info' + equal: + - 'namespace' + - 'alertname' + - source_matchers: + - 'severity = warning' + target_matchers: + - 'severity = info' + equal: + - 'namespace' + - 'alertname' + - source_matchers: + - 'alertname = InfoInhibitor' + target_matchers: + - 'severity = info' + equal: + - 'namespace' + route: + group_by: ['namespace'] + group_wait: 30s + group_interval: 5m + repeat_interval: 12h + receiver: 'null' + routes: + - receiver: 'null' + matchers: + - alertname =~ "InfoInhibitor|Watchdog" + receivers: + - name: 'null' + templates: + - '/etc/alertmanager/config/*.tmpl' + + ## Pass the Alertmanager configuration directives through Helm's templating + ## engine. If the Alertmanager configuration contains Alertmanager templates, + ## they'll need to be properly escaped so that they are not interpreted by + ## Helm + ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function + ## https://prometheus.io/docs/alerting/configuration/#tmpl_string + ## https://prometheus.io/docs/alerting/notifications/ + ## https://prometheus.io/docs/alerting/notification_examples/ + tplConfig: false + + ## Alertmanager template files to format alerts + ## By default, templateFiles are placed in /etc/alertmanager/config/ and if + ## they have a .tmpl file suffix will be loaded. See config.templates above + ## to change, add other suffixes. If adding other suffixes, be sure to update + ## config.templates above to include those suffixes. + ## ref: https://prometheus.io/docs/alerting/notifications/ + ## https://prometheus.io/docs/alerting/notification_examples/ + ## + + templateFiles: + rancher_defaults.tmpl: |- + {{- define "slack.rancher.text" -}} + {{ template "rancher.text_multiple" . }} + {{- end -}} + + {{- define "rancher.text_multiple" -}} + *[GROUP - Details]* + One or more alarms in this group have triggered a notification. + + {{- if gt (len .GroupLabels.Values) 0 }} + *Group Labels:* + {{- range .GroupLabels.SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- if .ExternalURL }} + *Link to AlertManager:* {{ .ExternalURL }} + {{- end }} + + {{- range .Alerts }} + {{ template "rancher.text_single" . }} + {{- end }} + {{- end -}} + + {{- define "rancher.text_single" -}} + {{- if .Labels.alertname }} + *[ALERT - {{ .Labels.alertname }}]* + {{- else }} + *[ALERT]* + {{- end }} + {{- if .Labels.severity }} + *Severity:* `{{ .Labels.severity }}` + {{- end }} + {{- if .Labels.cluster }} + *Cluster:* {{ .Labels.cluster }} + {{- end }} + {{- if .Annotations.summary }} + *Summary:* {{ .Annotations.summary }} + {{- end }} + {{- if .Annotations.message }} + *Message:* {{ .Annotations.message }} + {{- end }} + {{- if .Annotations.description }} + *Description:* {{ .Annotations.description }} + {{- end }} + {{- if .Annotations.runbook_url }} + *Runbook URL:* <{{ .Annotations.runbook_url }}|:spiral_note_pad:> + {{- end }} + {{- with .Labels }} + {{- with .Remove (stringSlice "alertname" "severity" "cluster") }} + {{- if gt (len .) 0 }} + *Additional Labels:* + {{- range .SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Annotations }} + {{- with .Remove (stringSlice "summary" "message" "description" "runbook_url") }} + {{- if gt (len .) 0 }} + *Additional Annotations:* + {{- range .SortedPairs }} + • *{{ .Name }}:* `{{ .Value }}` + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end -}} + + ingress: + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + annotations: {} + + labels: {} + + ## Redirect ingress to an additional defined port on the service + # servicePort: 8081 + + ## Hosts must be provided if Ingress is enabled. + ## + hosts: [] + # - alertmanager.domain.com + + ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix + ## + paths: [] + # - / + + ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) + ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types + # pathType: ImplementationSpecific + + ## TLS configuration for Alertmanager Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: alertmanager-general-tls + # hosts: + # - alertmanager.example.com + + ## Configuration for Alertmanager secret + ## + secret: + annotations: {} + + ## Configuration for Alertmanager service + ## + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Port for Alertmanager Service to listen on + ## + port: 9093 + ## To be used with a proxy extraContainer port + ## + targetPort: 9093 + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30903 + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + + ## Additional ports to open for Alertmanager service + additionalPorts: [] + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + + externalIPs: [] + loadBalancerIP: "" + loadBalancerSourceRanges: [] + + ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + ## + externalTrafficPolicy: Cluster + + ## Service type + ## + type: ClusterIP + + ## If true, create a serviceMonitor for alertmanager + ## + serviceMonitor: + ## Scrape interval. If not set, the Prometheus default scrape interval is used. + ## + interval: "" + selfMonitor: true + + ## proxyUrl: URL of a proxy that should be used for scraping. + ## + proxyUrl: "" + + ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. + scheme: "" + + ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. + ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + + bearerTokenFile: + + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + ## RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + ## Settings affecting alertmanagerSpec + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerspec + ## + alertmanagerSpec: + ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata + ## Metadata Labels and Annotations gets propagated to the Alertmanager pods. + ## + podMetadata: {} + + ## Image of Alertmanager + ## + image: + repository: rancher/mirrored-prometheus-alertmanager + tag: v0.24.0 + sha: "" + + ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the + ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. + ## + secrets: [] + + ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. + ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/. + ## + configMaps: [] + + ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for + ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config. + ## + # configSecret: + + ## WebTLSConfig defines the TLS parameters for HTTPS + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerwebspec + web: {} + + ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. + ## + alertmanagerConfigSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## AlermanagerConfig to be used as top level configuration + ## + alertmanagerConfiguration: {} + ## Example with select a global alertmanagerconfig + # alertmanagerConfiguration: + # name: global-alertmanager-Configuration + + ## Define Log Format + # Use logfmt (default) or json logging + logFormat: logfmt + + ## Log level for Alertmanager to be configured with. + ## + logLevel: info + + ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the + ## running cluster equal to the expected size. + replicas: 1 + + ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression + ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours). + ## + retention: 120h + + ## Storage is the definition of how storage will be used by the Alertmanager instances. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md + ## + storage: {} + # volumeClaimTemplate: + # spec: + # storageClassName: gluster + # accessModes: ["ReadWriteOnce"] + # resources: + # requests: + # storage: 50Gi + # selector: {} + + + ## The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. string false + ## + externalUrl: + + ## The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, + ## but the server serves requests under a different route prefix. For example for use with kubectl proxy. + ## + routePrefix: / + + ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions. + ## + paused: false + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Define resources requests and limits for single Pods. + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + memory: 500Mi + cpu: 1000m + requests: + memory: 100Mi + cpu: 100m + + ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. + ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. + ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. + ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. + ## + podAntiAffinity: "" + + ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. + ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone + ## + podAntiAffinityTopologyKey: kubernetes.io/hostname + + ## Assign custom affinity rules to the alertmanager instance + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/e2e-az-name + # operator: In + # values: + # - e2e-az1 + # - e2e-az2 + + ## If specified, the pod's tolerations. + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + ## If specified, the pod's topology spread constraints. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app: alertmanager + + ## SecurityContext holds pod-level security attributes and common container settings. + ## This defaults to non root user with uid 1000 and gid 2000. *v1.PodSecurityContext false + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + + ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. + ## Note this is only for the Alertmanager UI, not the gossip communication. + ## + listenLocal: false + + ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. + ## + containers: [] + # containers: + # - name: oauth-proxy + # image: quay.io/oauth2-proxy/oauth2-proxy:v7.3.0 + # args: + # - --upstream=http://127.0.0.1:9093 + # - --http-address=0.0.0.0:8081 + # - ... + # ports: + # - containerPort: 8081 + # name: oauth-proxy + # protocol: TCP + # resources: {} + + # Additional volumes on the output StatefulSet definition. + volumes: [] + + # Additional VolumeMounts on the output StatefulSet definition. + volumeMounts: [] + + ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes + ## (permissions, dir tree) on mounted volumes before starting prometheus + initContainers: [] + + ## Priority class assigned to the Pods + ## + priorityClassName: "" + + ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster. + ## + additionalPeers: [] + + ## PortName to use for Alert Manager. + ## + portName: "http-web" + + ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918 + ## + clusterAdvertiseAddress: false + + ## ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. + ## Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. + forceEnableClusterMode: false + + ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to + ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). + minReadySeconds: 0 + + ## ExtraSecret can be used to store various data in an extra secret + ## (use it for example to store hashed basic auth credentials) + extraSecret: + ## if not set, name will be auto generated + # name: "" + annotations: {} + data: {} + # auth: | + # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 + # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. + +## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml +## +grafana: + enabled: true + namespaceOverride: "" + + ## Grafana's primary configuration + ## NOTE: values in map will be converted to ini format + ## ref: http://docs.grafana.org/installation/configuration/ + ## + grafana.ini: + users: + auto_assign_org_role: Viewer + auth: + disable_login_form: false + auth.anonymous: + enabled: true + org_role: Viewer + auth.basic: + enabled: false + security: + # Required to embed dashboards in Rancher Cluster Overview Dashboard on Cluster Explorer + allow_embedding: true + + deploymentStrategy: + type: Recreate + + ## ForceDeployDatasources Create datasource configmap even if grafana deployment has been disabled + ## + forceDeployDatasources: false + + ## ForceDeployDashboard Create dashboard configmap even if grafana deployment has been disabled + ## + forceDeployDashboards: false + + ## Deploy default dashboards + ## + defaultDashboardsEnabled: true + + ## Timezone for the default dashboards + ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg + ## + defaultDashboardsTimezone: utc + + adminPassword: prom-operator + + ingress: + ## If true, Grafana Ingress will be created + ## + enabled: false + + ## IngressClassName for Grafana Ingress. + ## Should be provided if Ingress is enable. + ## + # ingressClassName: nginx + + ## Annotations for Grafana Ingress + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + ## Labels to be added to the Ingress + ## + labels: {} + + ## Hostnames. + ## Must be provided if Ingress is enable. + ## + # hosts: + # - grafana.domain.com + hosts: [] + + ## Path for grafana ingress + path: / + + ## TLS configuration for grafana Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: grafana-general-tls + # hosts: + # - grafana.example.com + + sidecar: + dashboards: + enabled: true + label: grafana_dashboard + labelValue: "1" + + ## Annotations for Grafana dashboard configmaps + ## + annotations: {} + provider: + allowUiUpdates: false + datasources: + enabled: true + defaultDatasourceEnabled: true + + uid: prometheus + + ## URL of prometheus datasource + ## + # url: http://prometheus-stack-prometheus:9090/ + + # If not defined, will use prometheus.prometheusSpec.scrapeInterval or its default + # defaultDatasourceScrapeInterval: 15s + + ## Annotations for Grafana datasource configmaps + ## + annotations: {} + + label: grafana_datasource + labelValue: "1" + + ## Field with internal link pointing to existing data source in Grafana. + ## Can be provisioned via additionalDataSources + exemplarTraceIdDestinations: {} + # datasourceUid: Jaeger + # traceIdLabelName: trace_id + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # configMap: certs-configmap + # readOnly: true + + deleteDatasources: [] + # - name: example-datasource + # orgId: 1 + + ## Configure additional grafana datasources (passed through tpl) + ## ref: http://docs.grafana.org/administration/provisioning/#datasources + additionalDataSources: [] + # - name: prometheus-sample + # access: proxy + # basicAuth: true + # basicAuthPassword: pass + # basicAuthUser: daco + # editable: false + # jsonData: + # tlsSkipVerify: true + # orgId: 1 + # type: prometheus + # url: https://{{ printf "%s-prometheus.svc" .Release.Name }}:9090 + # version: 1 + + ## Passed to grafana subchart and used by servicemonitor below + ## + service: + portName: nginx-http + ## Port for Grafana Service to listen on + ## + port: 80 + ## To be used with a proxy extraContainer port + ## + targetPort: 8080 + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30950 + ## Service type + ## + type: ClusterIP + + proxy: + image: + repository: rancher/mirrored-library-nginx + tag: 1.24.0-alpine + + ## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod + extraContainers: | + - name: grafana-proxy + args: + - nginx + - -g + - daemon off; + - -c + - /nginx/nginx.conf + image: "{{ template "system_default_registry" . }}{{ .Values.proxy.image.repository }}:{{ .Values.proxy.image.tag }}" + ports: + - containerPort: 8080 + name: nginx-http + protocol: TCP + volumeMounts: + - mountPath: /nginx + name: grafana-nginx + - mountPath: /var/cache/nginx + name: nginx-home + securityContext: + runAsUser: 101 + runAsGroup: 101 + + ## Volumes that can be used in containers + extraContainerVolumes: + - name: nginx-home + emptyDir: {} + - name: grafana-nginx + configMap: + name: grafana-nginx-proxy-config + items: + - key: nginx.conf + mode: 438 + path: nginx.conf + + ## If true, create a serviceMonitor for grafana + ## + serviceMonitor: + # If true, a ServiceMonitor CRD is created for a prometheus operator + # https://github.com/coreos/prometheus-operator + # + enabled: true + + # Path to use for scraping metrics. Might be different if server.root_url is set + # in grafana.ini + path: "/metrics" + + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + + # labels for the ServiceMonitor + labels: {} + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + # + interval: "" + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + ## RelabelConfigs to apply to samples before scraping + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + resources: + limits: + memory: 200Mi + cpu: 200m + requests: + memory: 100Mi + cpu: 100m + + testFramework: + enabled: false + +## Deploy a Prometheus instance +## +prometheus: + + enabled: true + + ## Annotations for Prometheus + ## + annotations: {} + + ## Service account for Prometheuses to use. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## + serviceAccount: + create: true + name: "" + annotations: {} + + ## Configuration for Prometheus service + ## + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Port for Prometheus Service to listen on + ## + port: 9090 + + ## To be used with a proxy extraContainer port + targetPort: 8081 + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + nodePort: 30090 + + ## Loadbalancer IP + ## Only use if service.type is "LoadBalancer" + loadBalancerIP: "" + loadBalancerSourceRanges: [] + + ## Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints + ## + externalTrafficPolicy: Cluster + + ## Service type + ## + type: ClusterIP + + ## Additional port to define in the Service + additionalPorts: [] + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + + ## Consider that all endpoints are considered "ready" even if the Pods themselves are not + ## Ref: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec + publishNotReadyAddresses: false + + sessionAffinity: "" + + ## Configure pod disruption budgets for Prometheus + ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget + ## This configuration is immutable once created and will require the PDB to be deleted to be changed + ## https://github.com/kubernetes/kubernetes/issues/45398 + ## + podDisruptionBudget: + enabled: false + minAvailable: 1 + maxUnavailable: "" + + ## ExtraSecret can be used to store various data in an extra secret + ## (use it for example to store hashed basic auth credentials) + extraSecret: + ## if not set, name will be auto generated + # name: "" + annotations: {} + data: {} + # auth: | + # foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0 + # someoneelse:$apr1$DMZX2Z4q$6SbQIfyuLQd.xmo/P0m2c. + + ingress: + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + annotations: {} + labels: {} + + ## Redirect ingress to an additional defined port on the service + # servicePort: 8081 + + ## Hostnames. + ## Must be provided if Ingress is enabled. + ## + # hosts: + # - prometheus.domain.com + hosts: [] + + ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix + ## + paths: [] + # - / + + ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched) + ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types + # pathType: ImplementationSpecific + + ## TLS configuration for Prometheus Ingress + ## Secret must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-general-tls + # hosts: + # - prometheus.example.com + + ## Configure additional options for default pod security policy for Prometheus + ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + podSecurityPolicy: + allowedCapabilities: [] + volumes: [] + + serviceMonitor: + ## Scrape interval. If not set, the Prometheus default scrape interval is used. + ## + interval: "" + selfMonitor: true + + ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. + scheme: "" + + ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. + ## Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + + bearerTokenFile: + + ## Metric relabel configs to apply to samples before ingestion. + ## + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + ## + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # targetLabel: nodename + # replacement: $1 + # action: replace + + ## Settings affecting prometheusSpec + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#prometheusspec + ## + prometheusSpec: + ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos + ## + disableCompaction: false + ## APIServerConfig + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#apiserverconfig + ## + apiserverConfig: {} + + ## Interval between consecutive scrapes. + ## Defaults to 30s. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 + ## + scrapeInterval: "30s" + + ## Number of seconds to wait for target to respond before erroring + ## + scrapeTimeout: "" + + ## Interval between consecutive evaluations. + ## + evaluationInterval: "1m" + + ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. + ## + listenLocal: false + + ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series. + ## This is disabled by default. + ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis + ## + enableAdminAPI: false + + ## WebTLSConfig defines the TLS parameters for HTTPS + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#webtlsconfig + web: {} + + ## Exemplars related settings that are runtime reloadable. + ## It requires to enable the exemplar storage feature to be effective. + exemplars: "" + ## Maximum number of exemplars stored in memory for all series. + ## If not set, Prometheus uses its default value. + ## A value of zero or less than zero disables the storage. + # maxSize: 100000 + + # EnableFeatures API enables access to Prometheus disabled features. + # ref: https://prometheus.io/docs/prometheus/latest/disabled_features/ + enableFeatures: [] + # - exemplar-storage + + ## Image of Prometheus. + ## + image: + repository: rancher/mirrored-prometheus-prometheus + tag: v2.38.0 + sha: "" + + ## Tolerations for use with node taints + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + + ## If specified, the pod's topology spread constraints. + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app: prometheus + + ## Alertmanagers to which alerts will be sent + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerendpoints + ## + ## Default configuration will connect to the alertmanager deployed as part of this release + ## + alertingEndpoints: [] + # - name: "" + # namespace: "" + # port: http + # scheme: http + # pathPrefix: "" + # tlsConfig: {} + # bearerTokenFile: "" + # apiVersion: v2 + + ## External labels to add to any time series or alerts when communicating with external systems + ## + externalLabels: {} + + ## enable --web.enable-remote-write-receiver flag on prometheus-server + ## + enableRemoteWriteReceiver: false + + ## Name of the external label used to denote Prometheus instance name + ## + prometheusExternalLabelName: "" + + ## If true, the Operator won't add the external label used to denote Prometheus instance name + ## + prometheusExternalLabelNameClear: false + + ## External URL at which Prometheus will be reachable. + ## + externalUrl: "" + + ## Define which Nodes the Pods are scheduled on. + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. + ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not + ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated + ## with the new list of secrets. + ## + secrets: [] + + ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. + ## The ConfigMaps are mounted into /etc/prometheus/configmaps/. + ## + configMaps: [] + + ## QuerySpec defines the query command line flags when starting Prometheus. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#queryspec + ## + query: {} + + ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the PrometheusRule resources created + ## + ruleSelectorNilUsesHelmValues: false + + ## PrometheusRules to be selected for target discovery. + ## If {}, select all PrometheusRules + ## + ruleSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the servicemonitors created + ## + serviceMonitorSelectorNilUsesHelmValues: false + + ## ServiceMonitors to be selected for target discovery. + ## If {}, select all ServiceMonitors + ## + serviceMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the podmonitors created + ## + podMonitorSelectorNilUsesHelmValues: false + + ## PodMonitors to be selected for target discovery. + ## If {}, select all PodMonitors + ## + podMonitorSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the + ## prometheus resource to be created with selectors based on values in the helm deployment, + ## which will also match the probes created + ## + probeSelectorNilUsesHelmValues: true + + ## Probes to be selected for target discovery. + ## If {}, select all Probes + ## + probeSelector: + # default ignores resources created by Rancher Monitoring + matchExpressions: + - key: release + operator: NotIn + values: + - rancher-monitoring + + ## How long to retain metrics + ## + retention: 10d + + ## Maximum size of metrics + ## + retentionSize: "50GiB" + + ## Enable compression of the write-ahead log using Snappy. + ## + walCompression: true + + ## If true, the Operator won't process any Prometheus configuration changes + ## + paused: false + + ## Number of replicas of each shard to deploy for a Prometheus deployment. + ## Number of replicas multiplied by shards is the total number of Pods created. + ## + replicas: 1 + + ## EXPERIMENTAL: Number of shards to distribute targets onto. + ## Number of replicas multiplied by shards is the total number of Pods created. + ## Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved. + ## Increasing shards will not reshard data either but it will continue to be available from the same instances. + ## To query globally use Thanos sidecar and Thanos querier or remote write data to a central location. + ## Sharding is done on the content of the `__address__` target meta-label. + ## + shards: 1 + + ## Log level for Prometheus be configured in + ## + logLevel: info + + ## Log format for Prometheus be configured in + ## + logFormat: logfmt + + ## Prefix used to register routes, overriding externalUrl route. + ## Useful for proxies that rewrite URLs. + ## + routePrefix: / + + ## Standard object's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata + ## Metadata Labels and Annotations gets propagated to the prometheus pods. + ## + podMetadata: {} + # labels: + # app: prometheus + # k8s-app: prometheus + + ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. + ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. + ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. + ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. + podAntiAffinity: "" + + ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. + ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone + ## + podAntiAffinityTopologyKey: kubernetes.io/hostname + + ## Assign custom affinity rules to the prometheus instance + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/e2e-az-name + # operator: In + # values: + # - e2e-az1 + # - e2e-az2 + + ## The remote_write spec configuration for Prometheus. + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec + remoteWrite: [] + # - url: http://remote1/push + ## additionalRemoteWrite is appended to remoteWrite + additionalRemoteWrite: [] + + ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature + remoteWriteDashboards: false + + ## Resource limits & requests + ## + resources: + limits: + memory: 3000Mi + cpu: 1000m + requests: + memory: 750Mi + cpu: 750m + + storage: + enabled: false + ## Prometheus StorageSpec for persistent data + ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md + ## + storageSpec: {} + ## Using PersistentVolumeClaim + ## + # volumeClaimTemplate: + # spec: + # storageClassName: gluster + # accessModes: ["ReadWriteOnce"] + # resources: + # requests: + # storage: 50Gi + # selector: {} + + ## Using tmpfs volume + ## + # emptyDir: + # medium: Memory + + # Additional volumes on the output StatefulSet definition. + volumes: + - name: nginx-home + emptyDir: {} + - name: prometheus-nginx + configMap: + name: prometheus-nginx-proxy-config + defaultMode: 438 + + # Additional VolumeMounts on the output StatefulSet definition. + volumeMounts: [] + + ## SecurityContext holds pod-level security attributes and common container settings. + ## This defaults to non root user with uid 1000 and gid 2000. + ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md + ## + securityContext: + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 2000 + + ## Priority class assigned to the Pods + ## + priorityClassName: "" + + proxy: + image: + repository: rancher/mirrored-library-nginx + tag: 1.24.0-alpine + + ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. + ## if using proxy extraContainer update targetPort with proxy container port + containers: | + - name: prometheus-proxy + args: + - nginx + - -g + - daemon off; + - -c + - /nginx/nginx.conf + image: "{{ template "system_default_registry" . }}{{ .Values.prometheus.prometheusSpec.proxy.image.repository }}:{{ .Values.prometheus.prometheusSpec.proxy.image.tag }}" + ports: + - containerPort: 8081 + name: nginx-http + protocol: TCP + volumeMounts: + - mountPath: /nginx + name: prometheus-nginx + - mountPath: /var/cache/nginx + name: nginx-home + securityContext: + runAsUser: 101 + runAsGroup: 101 + + ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes + ## (permissions, dir tree) on mounted volumes before starting prometheus + initContainers: [] + + ## PortName to use for Prometheus. + ## + portName: "http-web" + + ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files + ## on the file system of the Prometheus container e.g. bearer token files. + arbitraryFSAccessThroughSMs: false + + ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor + ## or PodMonitor to true, this overrides honor_labels to false. + overrideHonorLabels: false + + ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. + overrideHonorTimestamps: false + + ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. + ## The label value will always be the namespace of the object that is being created. + ## Disabled by default + enforcedNamespaceLabel: "" + + ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels. + ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair + ## Deprecated, use `excludedFromEnforcement` instead + prometheusRulesExcludedFromEnforce: [] + + ## ExcludedFromEnforcement - list of object references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects + ## to be excluded from enforcing a namespace label of origin. + ## Works only if enforcedNamespaceLabel set to true. + ## See https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#objectreference + excludedFromEnforcement: [] + + ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable, + ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such + ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions + ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/) + queryLogFile: false + + ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit + ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall + ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead. + enforcedSampleLimit: false + + ## EnforcedTargetLimit defines a global limit on the number of scraped targets. This overrides any TargetLimit set + ## per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the TargetLimit to keep the overall + ## number of targets under the desired limit. Note that if TargetLimit is lower, that value will be taken instead, except + ## if either value is zero, in which case the non-zero value will be used. If both values are zero, no limit is enforced. + enforcedTargetLimit: false + + + ## Per-scrape limit on number of labels that will be accepted for a sample. If more than this number of labels are present + ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions + ## 2.27.0 and newer. + enforcedLabelLimit: false + + ## Per-scrape limit on length of labels name that will be accepted for a sample. If a label name is longer than this number + ## post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions + ## 2.27.0 and newer. + enforcedLabelNameLengthLimit: false + + ## Per-scrape limit on length of labels value that will be accepted for a sample. If a label value is longer than this + ## number post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus + ## versions 2.27.0 and newer. + enforcedLabelValueLengthLimit: false + + ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental + ## in Prometheus so it may change in any upcoming release. + allowOverlappingBlocks: false + + ## Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to + ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). + minReadySeconds: 0 + +## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. +## +cleanPrometheusOperatorObjectNames: false From 5c38e8a3a3362d5488f4a498d27c1b6ddcd7d852 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 20:10:52 -0700 Subject: [PATCH 08/21] Combining commits: 7d5978a, 601b1e7, e0df9ab, e9e7bf0 --- .../alertmanager/alertmanager.yaml.patch | 7 ++ .../rancher-monitoring/hardened.yaml.patch | 36 ++++++++- .../generated-changes/patch/values.yaml.patch | 81 +++++++++++-------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/alertmanager.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/alertmanager.yaml.patch index 80f14415..99a86f0a 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/alertmanager.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/alertmanager/alertmanager.yaml.patch @@ -81,3 +81,10 @@ {{- end }} {{- if .Values.alertmanager.alertmanagerSpec.containers }} containers: +@@ -167,4 +162,4 @@ + {{- if .Values.alertmanager.alertmanagerSpec.minReadySeconds }} + minReadySeconds: {{ .Values.alertmanager.alertmanagerSpec.minReadySeconds }} + {{- end }} +-{{- end }} ++{{- end }} +\ No newline at end of file diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch index 686fd7f9..b0db173c 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch @@ -110,17 +110,47 @@ spec: privileged: false hostNetwork: false -@@ -108,6 +111,7 @@ +@@ -108,21 +111,38 @@ readOnlyRootFilesystem: false volumes: - 'secret' +{{- end }} ++{{- $root := . }} ++{{- $projectNamespaceSelector := .Values.global.cattle.projectNamespaceSelector }} ++{{- $limitIngressToProject := .Values.global.networkPolicy.limitIngressToProject }} ++{{- $egressPolicy := .Values.global.networkPolicy.egress }} ++{{- $ingressPolicy := .Values.global.networkPolicy.ingress }} {{- range $_, $ns := $namespaces }} --- apiVersion: networking.k8s.io/v1 -@@ -125,4 +129,3 @@ + kind: NetworkPolicy + metadata: +- name: default-allow-all ++ name: project-monitoring-policy + namespace: {{ $ns }} + spec: + podSelector: {} + ingress: ++{{- if or $ingressPolicy $limitIngressToProject }} ++{{- if $ingressPolicy }} ++{{ $ingressPolicy | toYaml | indent 4 }} ++{{- end }} ++{{- if $limitIngressToProject }} ++ - from: ++ - namespaceSelector: {{ $projectNamespaceSelector | toYaml | nindent 10 }} ++ - namespaceSelector: ++ matchLabels: ++ kubernetes.io/metadata.name: {{ $ns }} ++{{- end }} ++{{- else }} + - {} +- egress: +- - {} ++{{- end }} ++ egress: {{ $egressPolicy | toYaml | nindent 4 }} + policyTypes: - Ingress - Egress - {{- end }} -{{- end }} + {{- end }} \ No newline at end of file diff --git a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch index 61c4a015..cd534de2 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch @@ -701,7 +701,7 @@ ## global: -@@ -725,30 +69,36 @@ +@@ -725,30 +69,47 @@ psp: enabled: false systemDefaultRegistry: "" @@ -725,6 +725,17 @@ + securityContext: + runAsNonRoot: true + runAsUser: 1000 ++ networkPolicy: ++ # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. ++ # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, ++ # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs ++ # through the Rancher/Kubernetes API Proxy in the Rancher UI. ++ limitIngressToProject: false ++ # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. ++ ingress: null ++ # By default, all egress traffic is allowed. ++ egress: ++ - {} rbac: ## Create RBAC resources for ServiceAccounts and users ## @@ -751,7 +762,7 @@ aggregateToDefaultRoles: true pspAnnotations: {} -@@ -769,6 +119,19 @@ +@@ -769,6 +130,19 @@ # or # - "image-pull-secret" @@ -771,7 +782,7 @@ ## Configuration for alertmanager ## ref: https://prometheus.io/docs/alerting/alertmanager/ ## -@@ -978,50 +341,6 @@ +@@ -978,50 +352,6 @@ secret: annotations: {} @@ -822,7 +833,7 @@ ## Configuration for Alertmanager service ## service: -@@ -1062,36 +381,6 @@ +@@ -1062,36 +392,6 @@ ## type: ClusterIP @@ -859,7 +870,7 @@ ## If true, create a serviceMonitor for alertmanager ## serviceMonitor: -@@ -1148,11 +437,6 @@ +@@ -1148,11 +448,6 @@ tag: v0.24.0 sha: "" @@ -871,7 +882,7 @@ ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. ## -@@ -1174,39 +458,13 @@ +@@ -1174,39 +469,13 @@ ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. ## @@ -918,7 +929,7 @@ ## AlermanagerConfig to be used as top level configuration ## -@@ -1417,9 +675,6 @@ +@@ -1417,9 +686,6 @@ org_role: Viewer auth.basic: enabled: false @@ -928,7 +939,7 @@ security: # Required to embed dashboards in Rancher Cluster Overview Dashboard on Cluster Explorer allow_embedding: true -@@ -1439,18 +694,6 @@ +@@ -1439,18 +705,6 @@ ## defaultDashboardsEnabled: true @@ -947,7 +958,7 @@ ## Timezone for the default dashboards ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg ## -@@ -1500,17 +743,11 @@ +@@ -1500,17 +754,11 @@ dashboards: enabled: true label: grafana_dashboard @@ -965,7 +976,7 @@ provider: allowUiUpdates: false datasources: -@@ -1530,11 +767,6 @@ +@@ -1530,11 +778,6 @@ ## annotations: {} @@ -977,7 +988,7 @@ label: grafana_datasource labelValue: "1" -@@ -1652,292 +884,8 @@ +@@ -1652,292 +895,8 @@ tlsConfig: {} scrapeTimeout: 30s @@ -1271,7 +1282,7 @@ ## metricRelabelings: [] # - action: keep -@@ -1955,734 +903,16 @@ +@@ -1955,734 +914,16 @@ # replacement: $1 # action: replace @@ -2010,7 +2021,7 @@ ## Deploy a Prometheus instance ## -@@ -2702,96 +932,6 @@ +@@ -2702,96 +943,6 @@ name: "" annotations: {} @@ -2107,7 +2118,7 @@ ## Configuration for Prometheus service ## service: -@@ -2842,36 +982,6 @@ +@@ -2842,36 +993,6 @@ sessionAffinity: "" @@ -2144,7 +2155,7 @@ ## Configure pod disruption budgets for Prometheus ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget ## This configuration is immutable once created and will require the PDB to be deleted to be changed -@@ -2882,46 +992,6 @@ +@@ -2882,46 +1003,6 @@ minAvailable: 1 maxUnavailable: "" @@ -2191,7 +2202,7 @@ ## ExtraSecret can be used to store various data in an extra secret ## (use it for example to store hashed basic auth credentials) extraSecret: -@@ -2970,55 +1040,10 @@ +@@ -2970,55 +1051,10 @@ # hosts: # - prometheus.example.com @@ -2247,7 +2258,7 @@ volumes: [] serviceMonitor: -@@ -3031,7 +1056,7 @@ +@@ -3031,7 +1067,7 @@ scheme: "" ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. @@ -2256,7 +2267,7 @@ tlsConfig: {} bearerTokenFile: -@@ -3069,7 +1094,7 @@ +@@ -3069,7 +1105,7 @@ ## Defaults to 30s. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 ## @@ -2265,7 +2276,7 @@ ## Number of seconds to wait for target to respond before erroring ## -@@ -3077,7 +1102,7 @@ +@@ -3077,7 +1113,7 @@ ## Interval between consecutive evaluations. ## @@ -2274,7 +2285,7 @@ ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. ## -@@ -3156,14 +1181,6 @@ +@@ -3156,14 +1192,6 @@ ## enableRemoteWriteReceiver: false @@ -2289,7 +2300,7 @@ ## Name of the external label used to denote Prometheus instance name ## prometheusExternalLabelName: "" -@@ -3198,12 +1215,6 @@ +@@ -3198,12 +1226,6 @@ ## query: {} @@ -2302,7 +2313,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, ## which will also match the PrometheusRule resources created -@@ -3213,21 +1224,13 @@ +@@ -3213,21 +1235,13 @@ ## PrometheusRules to be selected for target discovery. ## If {}, select all PrometheusRules ## @@ -2331,7 +2342,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3238,19 +1241,13 @@ +@@ -3238,19 +1252,13 @@ ## ServiceMonitors to be selected for target discovery. ## If {}, select all ServiceMonitors ## @@ -2358,7 +2369,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3261,16 +1258,13 @@ +@@ -3261,16 +1269,13 @@ ## PodMonitors to be selected for target discovery. ## If {}, select all PodMonitors ## @@ -2382,7 +2393,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3281,16 +1275,13 @@ +@@ -3281,16 +1286,13 @@ ## Probes to be selected for target discovery. ## If {}, select all Probes ## @@ -2406,7 +2417,7 @@ ## How long to retain metrics ## -@@ -3298,7 +1289,7 @@ +@@ -3298,7 +1300,7 @@ ## Maximum size of metrics ## @@ -2415,7 +2426,7 @@ ## Enable compression of the write-ahead log using Snappy. ## -@@ -3368,13 +1359,6 @@ +@@ -3368,13 +1370,6 @@ # - e2e-az1 # - e2e-az2 @@ -2429,7 +2440,7 @@ ## The remote_write spec configuration for Prometheus. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec remoteWrite: [] -@@ -3395,6 +1379,8 @@ +@@ -3395,6 +1390,8 @@ memory: 750Mi cpu: 750m @@ -2438,7 +2449,7 @@ ## Prometheus StorageSpec for persistent data ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md ## -@@ -3427,122 +1413,9 @@ +@@ -3427,122 +1424,9 @@ # Additional VolumeMounts on the output StatefulSet definition. volumeMounts: [] @@ -2562,7 +2573,7 @@ ## securityContext: runAsGroup: 2000 -@@ -3554,20 +1427,6 @@ +@@ -3554,20 +1438,6 @@ ## priorityClassName: "" @@ -2583,7 +2594,7 @@ proxy: image: repository: rancher/mirrored-library-nginx -@@ -3575,7 +1434,7 @@ +@@ -3575,7 +1445,7 @@ ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. ## if using proxy extraContainer update targetPort with proxy container port @@ -2592,7 +2603,7 @@ - name: prometheus-proxy args: - nginx -@@ -3616,10 +1475,6 @@ +@@ -3616,10 +1486,6 @@ ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. overrideHonorTimestamps: false @@ -2603,7 +2614,7 @@ ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. ## The label value will always be the namespace of the object that is being created. ## Disabled by default -@@ -3677,514 +1532,6 @@ +@@ -3677,514 +1543,6 @@ ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). minReadySeconds: 0 @@ -3117,4 +3128,6 @@ - ## Setting to true produces cleaner resource names, but requires a data migration because the name of the persistent volume changes. Therefore this should only be set once on initial installation. ## - cleanPrometheusOperatorObjectNames: false +-cleanPrometheusOperatorObjectNames: false ++cleanPrometheusOperatorObjectNames: false +\ No newline at end of file From 2bb54f9089c28f059d21f03ea7bcb1295224240a Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Tue, 11 Apr 2023 10:53:58 -0700 Subject: [PATCH 09/21] Fix semver constraint to not include 2.8.0 --- .../rancher-project-monitoring-0.3.1.tgz | Bin 124333 -> 124722 bytes .../templates/alertmanager/alertmanager.yaml | 2 +- .../rancher-monitoring/hardened.yaml | 25 +++++++++++++++--- .../0.3.1/values.yaml | 13 ++++++++- index.yaml | 4 +-- .../prometheus-federator/charts/Chart.yaml | 2 +- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/assets/rancher-project-monitoring/rancher-project-monitoring-0.3.1.tgz b/assets/rancher-project-monitoring/rancher-project-monitoring-0.3.1.tgz index e7c7e74813fb7a46c5b786e385272f3ea06cb2ca..9db907da4e070a709a1f3580301795307531ca05 100644 GIT binary patch literal 124722 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 E08!DuWB>pF literal 124333 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 z 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 z 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 2.6.5-0 <= 2.6.100-0' + catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 appVersion: 0.3.0 From b7a5de74525d3200595f69f2f57d0cc321e5dfdf Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Tue, 11 Apr 2023 10:58:01 -0700 Subject: [PATCH 10/21] nit: Modify label for enabling persistent volume --- .../generated-changes/overlay/questions.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml b/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml index 0e9bc69d..c15f36e7 100644 --- a/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml +++ b/packages/rancher-project-monitoring/generated-changes/overlay/questions.yaml @@ -30,7 +30,7 @@ questions: - variable: grafana.persistence.enabled type: boolean required: true - label: Grafana Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Grafana subquestions: @@ -101,7 +101,7 @@ questions: - variable: prometheus.prometheusSpec.storage.enabled type: boolean required: true - label: Prometheus Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Prometheus subquestions: From e249a33303486b5f0e819f1967ae6e94933f47ea Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Tue, 11 Apr 2023 11:06:04 -0700 Subject: [PATCH 11/21] Ensure that disabling Alertmanager also removes RBAC like Grafana --- .../overlay/templates/dashboard-roles.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml b/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml index b42c6626..535bc94e 100644 --- a/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml +++ b/packages/rancher-project-monitoring/generated-changes/overlay/templates/dashboard-roles.yaml @@ -17,8 +17,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -35,12 +37,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -54,6 +59,7 @@ rules: - update - patch - delete +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -73,8 +79,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -91,12 +99,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -109,6 +120,7 @@ rules: - watch - update - patch +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -128,8 +140,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -142,12 +156,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -159,3 +176,4 @@ rules: - list - watch {{- end }} +{{- end }} From caf5d6ffc4742ed6545b4614256ec607d8e42aea Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Tue, 11 Apr 2023 12:06:12 -0700 Subject: [PATCH 12/21] Simplify hardened namespace network policy ingress with helper function --- .../patch/templates/_helpers.tpl.patch | 24 +++++++++++++++++ .../rancher-monitoring/hardened.yaml.patch | 27 ++++--------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch index 32f08393..b534b678 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch @@ -360,3 +360,27 @@ {{- range .Values.global.imagePullSecrets }} {{- if eq (typeOf .) "map[string]interface {}" }} - {{ toYaml . | trim }} +@@ -382,3 +231,22 @@ + {{- end }} + {{- end }} + {{- end -}} ++ ++ ++{{/* Define ingress for all hardened namespaces */}} ++{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} ++{{- $root := index . 0 }} ++{{- $ns := index . 1 }} ++{{- if $root.Values.global.networkPolicy.ingress }} ++{{ toYaml $root.Values.global.networkPolicy.ingress }} ++{{- end }} ++{{- if $root.Values.global.networkPolicy.limitIngressToProject }} ++- from: ++{{- if $root.Values.global.cattle.projectNamespaceSelector }} ++ - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} ++{{- end }} ++ - namespaceSelector: ++ matchLabels: ++ kubernetes.io/metadata.name: {{ $ns }} ++{{- end }} ++{{- end -}} +\ No newline at end of file diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch index b0db173c..5ee22f48 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/rancher-monitoring/hardened.yaml.patch @@ -110,16 +110,11 @@ spec: privileged: false hostNetwork: false -@@ -108,21 +111,38 @@ +@@ -108,21 +111,19 @@ readOnlyRootFilesystem: false volumes: - 'secret' +{{- end }} -+{{- $root := . }} -+{{- $projectNamespaceSelector := .Values.global.cattle.projectNamespaceSelector }} -+{{- $limitIngressToProject := .Values.global.networkPolicy.limitIngressToProject }} -+{{- $egressPolicy := .Values.global.networkPolicy.egress }} -+{{- $ingressPolicy := .Values.global.networkPolicy.ingress }} {{- range $_, $ns := $namespaces }} --- apiVersion: networking.k8s.io/v1 @@ -130,24 +125,12 @@ namespace: {{ $ns }} spec: podSelector: {} - ingress: -+{{- if or $ingressPolicy $limitIngressToProject }} -+{{- if $ingressPolicy }} -+{{ $ingressPolicy | toYaml | indent 4 }} -+{{- end }} -+{{- if $limitIngressToProject }} -+ - from: -+ - namespaceSelector: {{ $projectNamespaceSelector | toYaml | nindent 10 }} -+ - namespaceSelector: -+ matchLabels: -+ kubernetes.io/metadata.name: {{ $ns }} -+{{- end }} -+{{- else }} - - {} +- ingress: +- - {} - egress: - - {} -+{{- end }} -+ egress: {{ $egressPolicy | toYaml | nindent 4 }} ++ ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} ++ egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} policyTypes: - Ingress - Egress From eea1d038c3a56012a2c8537865133c0c68b8741a Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 20:21:04 -0700 Subject: [PATCH 13/21] 1f6e1042a8dd3ee5af32359488a851a807001513: Fix broken prometheus-remote-write Grafana ConfigMap --- .../prometheus-remote-write.yaml.patch | 31 +++++ .../generated-changes/patch/values.yaml.patch | 111 +++++++++--------- 2 files changed, 86 insertions(+), 56 deletions(-) create mode 100644 packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch new file mode 100644 index 00000000..442c9e7a --- /dev/null +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch @@ -0,0 +1,31 @@ +--- charts-original/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml ++++ charts/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +@@ -1,23 +1,23 @@ + {{- /* + Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml + Do not change in-place! In order to change this file first read following link: +-https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack ++https://github.com/prometheus-community/helm-charts/tree/main/charts/project-prometheus-stack/hack + */ -}} + {{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} + {{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} + apiVersion: v1 + kind: ConfigMap + metadata: +- namespace: {{ .Values.grafana.defaultDashboards.namespace }} +- name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} ++ namespace: {{ template "project-prometheus-stack.namespace" . }} ++ name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + annotations: + {{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} + labels: + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} + {{- end }} +- app: {{ template "kube-prometheus-stack.name" $ }}-grafana +-{{ include "kube-prometheus-stack.labels" $ | indent 4 }} ++ app: {{ template "project-prometheus-stack.name" $ }}-grafana ++{{ include "project-prometheus-stack.labels" $ | indent 4 }} + data: + prometheus-remote-write.json: |- + { diff --git a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch index cd534de2..b0748f5c 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/values.yaml.patch @@ -958,7 +958,7 @@ ## Timezone for the default dashboards ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg ## -@@ -1500,17 +754,11 @@ +@@ -1500,7 +754,6 @@ dashboards: enabled: true label: grafana_dashboard @@ -966,17 +966,16 @@ labelValue: "1" ## Annotations for Grafana dashboard configmaps - ## - annotations: {} -- multicluster: -- global: -- enabled: false +@@ -1509,8 +762,6 @@ + multicluster: + global: + enabled: false - etcd: - enabled: false provider: allowUiUpdates: false datasources: -@@ -1530,11 +778,6 @@ +@@ -1530,11 +781,6 @@ ## annotations: {} @@ -988,7 +987,7 @@ label: grafana_datasource labelValue: "1" -@@ -1652,292 +895,8 @@ +@@ -1652,538 +898,8 @@ tlsConfig: {} scrapeTimeout: 30s @@ -1035,7 +1034,7 @@ - component: apiserver - provider: kubernetes - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. +- ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - ## - metricRelabelings: @@ -1278,14 +1277,23 @@ - - ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -+ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## - metricRelabelings: [] - # - action: keep -@@ -1955,734 +914,16 @@ - # replacement: $1 - # action: replace - +- ## +- metricRelabelings: [] +- # - action: keep +- # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' +- # sourceLabels: [__name__] +- +- ## RelabelConfigs to apply to samples before scraping +- ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig +- ## +- relabelings: [] +- # - sourceLabels: [__meta_kubernetes_pod_node_name] +- # separator: ; +- # regex: ^(.*)$ +- # targetLabel: nodename +- # replacement: $1 +- # action: replace +- - ## Additional labels - ## - additionalLabels: {} @@ -1513,25 +1521,16 @@ - ## Name of the server to use when validating TLS certificate - serverName: null - -- ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. -- ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -- ## -- metricRelabelings: [] -- # - action: keep -- # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' -- # sourceLabels: [__name__] -- -- ## RelabelConfigs to apply to samples before scraping + ## MetricRelabelConfigs to apply to samples after scraping, but before ingestion. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig -- ## -- relabelings: [] -- # - sourceLabels: [__meta_kubernetes_pod_node_name] -- # separator: ; -- # regex: ^(.*)$ -- # targetLabel: nodename -- # replacement: $1 -- # action: replace -- ++ ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + ## + metricRelabelings: [] + # - action: keep +@@ -2201,488 +917,16 @@ + # replacement: $1 + # action: replace + - ## Additional labels - ## - additionalLabels: {} @@ -2021,7 +2020,7 @@ ## Deploy a Prometheus instance ## -@@ -2702,96 +943,6 @@ +@@ -2702,96 +946,6 @@ name: "" annotations: {} @@ -2118,7 +2117,7 @@ ## Configuration for Prometheus service ## service: -@@ -2842,36 +993,6 @@ +@@ -2842,36 +996,6 @@ sessionAffinity: "" @@ -2155,7 +2154,7 @@ ## Configure pod disruption budgets for Prometheus ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget ## This configuration is immutable once created and will require the PDB to be deleted to be changed -@@ -2882,46 +1003,6 @@ +@@ -2882,46 +1006,6 @@ minAvailable: 1 maxUnavailable: "" @@ -2202,7 +2201,7 @@ ## ExtraSecret can be used to store various data in an extra secret ## (use it for example to store hashed basic auth credentials) extraSecret: -@@ -2970,55 +1051,10 @@ +@@ -2970,55 +1054,10 @@ # hosts: # - prometheus.example.com @@ -2258,7 +2257,7 @@ volumes: [] serviceMonitor: -@@ -3031,7 +1067,7 @@ +@@ -3031,7 +1070,7 @@ scheme: "" ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. @@ -2267,7 +2266,7 @@ tlsConfig: {} bearerTokenFile: -@@ -3069,7 +1105,7 @@ +@@ -3069,7 +1108,7 @@ ## Defaults to 30s. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 ## @@ -2276,7 +2275,7 @@ ## Number of seconds to wait for target to respond before erroring ## -@@ -3077,7 +1113,7 @@ +@@ -3077,7 +1116,7 @@ ## Interval between consecutive evaluations. ## @@ -2285,7 +2284,7 @@ ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. ## -@@ -3156,14 +1192,6 @@ +@@ -3156,14 +1195,6 @@ ## enableRemoteWriteReceiver: false @@ -2300,7 +2299,7 @@ ## Name of the external label used to denote Prometheus instance name ## prometheusExternalLabelName: "" -@@ -3198,12 +1226,6 @@ +@@ -3198,12 +1229,6 @@ ## query: {} @@ -2313,7 +2312,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, ## which will also match the PrometheusRule resources created -@@ -3213,21 +1235,13 @@ +@@ -3213,21 +1238,13 @@ ## PrometheusRules to be selected for target discovery. ## If {}, select all PrometheusRules ## @@ -2342,7 +2341,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3238,19 +1252,13 @@ +@@ -3238,19 +1255,13 @@ ## ServiceMonitors to be selected for target discovery. ## If {}, select all ServiceMonitors ## @@ -2369,7 +2368,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3261,16 +1269,13 @@ +@@ -3261,16 +1272,13 @@ ## PodMonitors to be selected for target discovery. ## If {}, select all PodMonitors ## @@ -2393,7 +2392,7 @@ ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the ## prometheus resource to be created with selectors based on values in the helm deployment, -@@ -3281,16 +1286,13 @@ +@@ -3281,16 +1289,13 @@ ## Probes to be selected for target discovery. ## If {}, select all Probes ## @@ -2417,7 +2416,7 @@ ## How long to retain metrics ## -@@ -3298,7 +1300,7 @@ +@@ -3298,7 +1303,7 @@ ## Maximum size of metrics ## @@ -2426,7 +2425,7 @@ ## Enable compression of the write-ahead log using Snappy. ## -@@ -3368,13 +1370,6 @@ +@@ -3368,13 +1373,6 @@ # - e2e-az1 # - e2e-az2 @@ -2440,7 +2439,7 @@ ## The remote_write spec configuration for Prometheus. ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#remotewritespec remoteWrite: [] -@@ -3395,6 +1390,8 @@ +@@ -3395,6 +1393,8 @@ memory: 750Mi cpu: 750m @@ -2449,7 +2448,7 @@ ## Prometheus StorageSpec for persistent data ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md ## -@@ -3427,122 +1424,9 @@ +@@ -3427,122 +1427,9 @@ # Additional VolumeMounts on the output StatefulSet definition. volumeMounts: [] @@ -2573,7 +2572,7 @@ ## securityContext: runAsGroup: 2000 -@@ -3554,20 +1438,6 @@ +@@ -3554,20 +1441,6 @@ ## priorityClassName: "" @@ -2594,7 +2593,7 @@ proxy: image: repository: rancher/mirrored-library-nginx -@@ -3575,7 +1445,7 @@ +@@ -3575,7 +1448,7 @@ ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. ## if using proxy extraContainer update targetPort with proxy container port @@ -2603,7 +2602,7 @@ - name: prometheus-proxy args: - nginx -@@ -3616,10 +1486,6 @@ +@@ -3616,10 +1489,6 @@ ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. overrideHonorTimestamps: false @@ -2614,7 +2613,7 @@ ## EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. ## The label value will always be the namespace of the object that is being created. ## Disabled by default -@@ -3677,514 +1543,6 @@ +@@ -3677,514 +1546,6 @@ ## be considered available. Defaults to 0 (pod will be considered available as soon as it is ready). minReadySeconds: 0 From 086a7f3b678e9663f3a59d0f9a2a226d77d147be Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Wed, 12 Apr 2023 08:57:03 -0700 Subject: [PATCH 14/21] Do not change link --- .../dashboards-1.14/prometheus-remote-write.yaml.patch | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch index 442c9e7a..21943276 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml.patch @@ -1,14 +1,6 @@ --- charts-original/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ charts/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml -@@ -1,23 +1,23 @@ - {{- /* - Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/main/manifests/grafana-dashboardDefinitions.yaml - Do not change in-place! In order to change this file first read following link: --https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -+https://github.com/prometheus-community/helm-charts/tree/main/charts/project-prometheus-stack/hack - */ -}} - {{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} - {{- if and (or .Values.grafana.enabled .Values.grafana.forceDeployDashboards) (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} +@@ -8,16 +8,16 @@ apiVersion: v1 kind: ConfigMap metadata: From f004d4e16845dfb2a5f2f56e7b6b0055e13417fc Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Wed, 12 Apr 2023 09:35:25 -0700 Subject: [PATCH 15/21] Fix newline in front of global.networkPolicy.ingress field --- .../generated-changes/patch/templates/_helpers.tpl.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch index b534b678..1858ea46 100644 --- a/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch +++ b/packages/rancher-project-monitoring/generated-changes/patch/templates/_helpers.tpl.patch @@ -370,7 +370,7 @@ +{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} +{{- $root := index . 0 }} +{{- $ns := index . 1 }} -+{{- if $root.Values.global.networkPolicy.ingress }} ++{{- if $root.Values.global.networkPolicy.ingress -}} +{{ toYaml $root.Values.global.networkPolicy.ingress }} +{{- end }} +{{- if $root.Values.global.networkPolicy.limitIngressToProject }} From ab9280a09ff7e42f60d1d8b2bf98ec78860c16e4 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 20:38:57 -0700 Subject: [PATCH 16/21] make charts --- .../prometheus-federator-0.3.1.tgz | Bin 20568 -> 20566 bytes .../rancher-project-monitoring-0.3.1.tgz | Bin 124722 -> 124772 bytes charts/prometheus-federator/0.3.1/Chart.yaml | 2 +- .../0.3.1/questions.yaml | 4 +-- .../0.3.1/templates/_helpers.tpl | 19 +++++++++++++++ .../0.3.1/templates/dashboard-roles.yaml | 18 ++++++++++++++ .../prometheus-remote-write.yaml | 8 +++--- .../rancher-monitoring/hardened.yaml | 23 ++---------------- .../0.3.1/values.yaml | 3 +++ index.yaml | 6 ++--- 10 files changed, 52 insertions(+), 31 deletions(-) diff --git a/assets/prometheus-federator/prometheus-federator-0.3.1.tgz b/assets/prometheus-federator/prometheus-federator-0.3.1.tgz index f8cef683d78f9f5a34497a7949f1b86347eaec5f..2a5f65a5ed8ac56a874bee32646ffd3ab4f15d75 100644 GIT binary patch delta 18716 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 E08!DuWB>pF diff --git a/charts/prometheus-federator/0.3.1/Chart.yaml b/charts/prometheus-federator/0.3.1/Chart.yaml index 5c54735e..bd6eae7d 100644 --- a/charts/prometheus-federator/0.3.1/Chart.yaml +++ b/charts/prometheus-federator/0.3.1/Chart.yaml @@ -6,7 +6,7 @@ annotations: catalog.cattle.io/os: linux,windows catalog.cattle.io/permits-os: linux,windows catalog.cattle.io/provides-gvr: helm.cattle.io.projecthelmchart/v1alpha1 - catalog.cattle.io/rancher-version: '>= 2.6.5-0 <= 2.6.100-0' + catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 appVersion: 0.3.1 diff --git a/charts/rancher-project-monitoring/0.3.1/questions.yaml b/charts/rancher-project-monitoring/0.3.1/questions.yaml index 0e9bc69d..c15f36e7 100644 --- a/charts/rancher-project-monitoring/0.3.1/questions.yaml +++ b/charts/rancher-project-monitoring/0.3.1/questions.yaml @@ -30,7 +30,7 @@ questions: - variable: grafana.persistence.enabled type: boolean required: true - label: Grafana Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Grafana subquestions: @@ -101,7 +101,7 @@ questions: - variable: prometheus.prometheusSpec.storage.enabled type: boolean required: true - label: Prometheus Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Prometheus subquestions: diff --git a/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl index 59f8e6c6..5333d28b 100644 --- a/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl +++ b/charts/rancher-project-monitoring/0.3.1/templates/_helpers.tpl @@ -231,3 +231,22 @@ global: {{- end }} {{- end }} {{- end -}} + + +{{/* Define ingress for all hardened namespaces */}} +{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} +{{- $root := index . 0 }} +{{- $ns := index . 1 }} +{{- if $root.Values.global.networkPolicy.ingress -}} +{{ toYaml $root.Values.global.networkPolicy.ingress }} +{{- end }} +{{- if $root.Values.global.networkPolicy.limitIngressToProject }} +- from: +{{- if $root.Values.global.cattle.projectNamespaceSelector }} + - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} +{{- end }} + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ $ns }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml index b42c6626..535bc94e 100644 --- a/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml +++ b/charts/rancher-project-monitoring/0.3.1/templates/dashboard-roles.yaml @@ -17,8 +17,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -35,12 +37,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -54,6 +59,7 @@ rules: - update - patch - delete +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -73,8 +79,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -91,12 +99,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -109,6 +120,7 @@ rules: - watch - update - patch +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -128,8 +140,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -142,12 +156,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -159,3 +176,4 @@ rules: - list - watch {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml index 08279580..2f0a6bfa 100644 --- a/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ b/charts/rancher-project-monitoring/0.3.1/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml @@ -8,16 +8,16 @@ https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-promet apiVersion: v1 kind: ConfigMap metadata: - namespace: {{ .Values.grafana.defaultDashboards.namespace }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} annotations: {{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} labels: {{- if $.Values.grafana.sidecar.dashboards.label }} {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} data: prometheus-remote-write.json: |- { diff --git a/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml index 885f5aaa..42f13a0f 100644 --- a/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml +++ b/charts/rancher-project-monitoring/0.3.1/templates/rancher-monitoring/hardened.yaml @@ -112,11 +112,6 @@ spec: volumes: - 'secret' {{- end }} -{{- $root := . }} -{{- $projectNamespaceSelector := .Values.global.cattle.projectNamespaceSelector }} -{{- $limitIngressToProject := .Values.global.networkPolicy.limitIngressToProject }} -{{- $egressPolicy := .Values.global.networkPolicy.egress }} -{{- $ingressPolicy := .Values.global.networkPolicy.ingress }} {{- range $_, $ns := $namespaces }} --- apiVersion: networking.k8s.io/v1 @@ -126,22 +121,8 @@ metadata: namespace: {{ $ns }} spec: podSelector: {} - ingress: -{{- if or $ingressPolicy $limitIngressToProject }} -{{- if $ingressPolicy }} -{{ $ingressPolicy | toYaml | indent 4 }} -{{- end }} -{{- if $limitIngressToProject }} - - from: - - namespaceSelector: {{ $projectNamespaceSelector | toYaml | nindent 10 }} - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: {{ $ns }} -{{- end }} -{{- else }} - - {} -{{- end }} - egress: {{ $egressPolicy | toYaml | nindent 4 }} + ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} + egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} policyTypes: - Ingress - Egress diff --git a/charts/rancher-project-monitoring/0.3.1/values.yaml b/charts/rancher-project-monitoring/0.3.1/values.yaml index 831e3d28..1f0f1654 100644 --- a/charts/rancher-project-monitoring/0.3.1/values.yaml +++ b/charts/rancher-project-monitoring/0.3.1/values.yaml @@ -759,6 +759,9 @@ grafana: ## Annotations for Grafana dashboard configmaps ## annotations: {} + multicluster: + global: + enabled: false provider: allowUiUpdates: false datasources: diff --git a/index.yaml b/index.yaml index b0061fa6..8b56af1f 100755 --- a/index.yaml +++ b/index.yaml @@ -13,7 +13,7 @@ entries: catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 appVersion: 0.3.1 - created: "2023-05-24T21:18:24.966511-07:00" + created: "2023-05-24T20:38:36.529187-07:00" dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator @@ -276,7 +276,7 @@ entries: catalog.cattle.io/release-name: rancher-project-monitoring apiVersion: v2 appVersion: 0.59.1 - created: "2023-05-24T20:11:25.743576-07:00" + created: "2023-05-24T20:37:10.984676-07:00" dependencies: - condition: grafana.enabled name: grafana @@ -285,7 +285,7 @@ entries: rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus. Depends on the existence of a Cluster Prometheus deployed via Prometheus Operator - digest: b13438e440adf7b5b2dcf1284b4c01e1cb8c309abc5f7b73cd46739f634520de + digest: 4c3c45ed36f38d3302e9023984240384b6404194faac49ccf462e0bd09d6987f home: https://github.com/prometheus-operator/kube-prometheus icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png keywords: From c8717bab7b41681a6283dff82bdde14994583ec8 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 21:16:31 -0700 Subject: [PATCH 17/21] reverting accidental changes to v0.2.2 --- .../0.2.2/questions.yaml | 4 ++-- .../0.2.2/templates/_helpers.tpl | 19 +++++++++++++++++++ .../0.2.2/templates/dashboard-roles.yaml | 18 ++++++++++++++++++ .../prometheus-remote-write.yaml | 8 ++++---- .../rancher-monitoring/hardened.yaml | 8 +++----- .../0.2.2/values.yaml | 14 ++++++++++++++ 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/charts/rancher-project-monitoring/0.2.2/questions.yaml b/charts/rancher-project-monitoring/0.2.2/questions.yaml index 0e9bc69d..c15f36e7 100644 --- a/charts/rancher-project-monitoring/0.2.2/questions.yaml +++ b/charts/rancher-project-monitoring/0.2.2/questions.yaml @@ -30,7 +30,7 @@ questions: - variable: grafana.persistence.enabled type: boolean required: true - label: Grafana Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Grafana subquestions: @@ -101,7 +101,7 @@ questions: - variable: prometheus.prometheusSpec.storage.enabled type: boolean required: true - label: Prometheus Persistent Volume Enabled + label: Enable Persistent Volume show_subquestion_if: true group: Prometheus subquestions: diff --git a/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl b/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl index 59f8e6c6..5333d28b 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl +++ b/charts/rancher-project-monitoring/0.2.2/templates/_helpers.tpl @@ -231,3 +231,22 @@ global: {{- end }} {{- end }} {{- end -}} + + +{{/* Define ingress for all hardened namespaces */}} +{{- define "project-prometheus-stack.hardened.networkPolicy.ingress" -}} +{{- $root := index . 0 }} +{{- $ns := index . 1 }} +{{- if $root.Values.global.networkPolicy.ingress -}} +{{ toYaml $root.Values.global.networkPolicy.ingress }} +{{- end }} +{{- if $root.Values.global.networkPolicy.limitIngressToProject }} +- from: +{{- if $root.Values.global.cattle.projectNamespaceSelector }} + - namespaceSelector: {{- $root.Values.global.cattle.projectNamespaceSelector | toYaml | nindent 6 }} +{{- end }} + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ $ns }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml b/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml index b42c6626..535bc94e 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/dashboard-roles.yaml @@ -17,8 +17,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -35,12 +37,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -54,6 +59,7 @@ rules: - update - patch - delete +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -73,8 +79,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -91,12 +99,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -109,6 +120,7 @@ rules: - watch - update - patch +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -128,8 +140,10 @@ rules: resourceNames: - "http:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}" +{{- if .Values.alertmanager.enabled }} - "http:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" - "https:{{ template "project-prometheus-stack.fullname" . }}-alertmanager:{{ .Values.alertmanager.service.port }}" +{{- end }} {{- if .Values.grafana.enabled }} - "http:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" - "https:{{ include "call-nested" (list . "grafana" "grafana.fullname") }}:{{ .Values.grafana.service.port }}" @@ -142,12 +156,15 @@ rules: - endpoints resourceNames: - {{ template "project-prometheus-stack.fullname" . }}-prometheus +{{- if .Values.alertmanager.enabled }} - {{ template "project-prometheus-stack.fullname" . }}-alertmanager +{{- end }} {{- if .Values.grafana.enabled }} - {{ include "call-nested" (list . "grafana" "grafana.fullname") }} {{- end }} verbs: - list +{{- if .Values.alertmanager.enabled }} - apiGroups: - "" resources: @@ -159,3 +176,4 @@ rules: - list - watch {{- end }} +{{- end }} diff --git a/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml index 08279580..2f0a6bfa 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml @@ -8,16 +8,16 @@ https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-promet apiVersion: v1 kind: ConfigMap metadata: - namespace: {{ .Values.grafana.defaultDashboards.namespace }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} + namespace: {{ template "project-prometheus-stack.namespace" . }} + name: {{ printf "%s-%s" (include "project-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} annotations: {{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} labels: {{- if $.Values.grafana.sidecar.dashboards.label }} {{ $.Values.grafana.sidecar.dashboards.label }}: {{ ternary $.Values.grafana.sidecar.dashboards.labelValue "1" (not (empty $.Values.grafana.sidecar.dashboards.labelValue)) | quote }} {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} + app: {{ template "project-prometheus-stack.name" $ }}-grafana +{{ include "project-prometheus-stack.labels" $ | indent 4 }} data: prometheus-remote-write.json: |- { diff --git a/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml b/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml index 508e4cc3..2ea6b1f8 100644 --- a/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml +++ b/charts/rancher-project-monitoring/0.2.2/templates/rancher-monitoring/hardened.yaml @@ -117,14 +117,12 @@ spec: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: default-allow-all + name: project-monitoring-policy namespace: {{ $ns }} spec: podSelector: {} - ingress: - - {} - egress: - - {} + ingress: {{- default (list dict | toYaml) (include "project-prometheus-stack.hardened.networkPolicy.ingress" (list $ $ns)) | nindent 4 }} + egress: {{- $.Values.global.networkPolicy.egress | toYaml | nindent 4 }} policyTypes: - Ingress - Egress diff --git a/charts/rancher-project-monitoring/0.2.2/values.yaml b/charts/rancher-project-monitoring/0.2.2/values.yaml index cb2b3695..23f317ff 100644 --- a/charts/rancher-project-monitoring/0.2.2/values.yaml +++ b/charts/rancher-project-monitoring/0.2.2/values.yaml @@ -78,6 +78,17 @@ global: securityContext: runAsNonRoot: true runAsUser: 1000 + networkPolicy: + # If activated, creates ingress network policies to only allow ingress traffic from workloads within the project. + # This only works correctly, if Project Network Isolation is activated for the cluster in Rancher. Otherwise, + # Ingress traffic from the nodes and thus from the Kubernetes API will be blocked, which breaks accessing the UIs + # through the Rancher/Kubernetes API Proxy in the Rancher UI. + limitIngressToProject: false + # Custom ingress restrictions. If null and limitIngressToProject=false, all ingress traffic will be allowed. + ingress: null + # By default, all egress traffic is allowed. + egress: + - {} rbac: ## Create RBAC resources for ServiceAccounts and users ## @@ -748,6 +759,9 @@ grafana: ## Annotations for Grafana dashboard configmaps ## annotations: {} + multicluster: + global: + enabled: false provider: allowUiUpdates: false datasources: From 39d567d6b0ef3145c81e1e27f19476079413dfaa Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 21:18:53 -0700 Subject: [PATCH 18/21] fixing index.yaml --- index.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.yaml b/index.yaml index 8b56af1f..d4b93dbf 100755 --- a/index.yaml +++ b/index.yaml @@ -13,7 +13,7 @@ entries: catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 appVersion: 0.3.1 - created: "2023-05-24T20:38:36.529187-07:00" + created: "2023-05-24T21:18:24.966511-07:00" dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator @@ -276,7 +276,7 @@ entries: catalog.cattle.io/release-name: rancher-project-monitoring apiVersion: v2 appVersion: 0.59.1 - created: "2023-05-24T20:37:10.984676-07:00" + created: "2023-05-24T21:18:25.019667-07:00" dependencies: - condition: grafana.enabled name: grafana From 20d6089a9c2b11b6db387ff6d9d2a367676aff53 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 21:54:29 -0700 Subject: [PATCH 19/21] updating helm-project-operator dependency --- packages/prometheus-federator/charts/Chart.yaml | 4 ++-- .../dependencies/helmProjectOperator/dependency.yaml | 2 +- packages/rancher-project-monitoring/package.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/prometheus-federator/charts/Chart.yaml b/packages/prometheus-federator/charts/Chart.yaml index ba842552..bd6eae7d 100755 --- a/packages/prometheus-federator/charts/Chart.yaml +++ b/packages/prometheus-federator/charts/Chart.yaml @@ -9,7 +9,7 @@ annotations: catalog.cattle.io/rancher-version: '>= 2.6.5-0 < 2.8.0-0' catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 -appVersion: 0.3.0 +appVersion: 0.3.1 dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator @@ -17,4 +17,4 @@ dependencies: description: Prometheus Federator icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg name: prometheus-federator -version: 0.3.0 +version: 0.3.1 diff --git a/packages/prometheus-federator/generated-changes/dependencies/helmProjectOperator/dependency.yaml b/packages/prometheus-federator/generated-changes/dependencies/helmProjectOperator/dependency.yaml index e234c3e5..b355cb93 100644 --- a/packages/prometheus-federator/generated-changes/dependencies/helmProjectOperator/dependency.yaml +++ b/packages/prometheus-federator/generated-changes/dependencies/helmProjectOperator/dependency.yaml @@ -1,3 +1,3 @@ url: https://github.com/rancher/helm-project-operator.git subdirectory: charts/helm-project-operator -commit: b1784fcdd8286209c14fd63ffdaf10cfc2f364cd +commit: 565e8dfff12302cfa94dd485d09d6a7ea573bea2 diff --git a/packages/rancher-project-monitoring/package.yaml b/packages/rancher-project-monitoring/package.yaml index 75712fe0..ad0ea2ea 100644 --- a/packages/rancher-project-monitoring/package.yaml +++ b/packages/rancher-project-monitoring/package.yaml @@ -2,7 +2,7 @@ workingDir: "" url: https://github.com/rancher/charts.git subdirectory: charts/rancher-monitoring/102.0.1+up40.1.2 commit: 598c78312178f1c5b8dfe92c8faf9b75ed0b7aa2 -version: 0.3.0 +version: 0.3.1 ignoreDependencies: - hardenedKubelet - hardenedNodeExporter From 1c7dcb569ee89dd0b097d41ae64bc7a7e0dc4e04 Mon Sep 17 00:00:00 2001 From: Geet Samra Date: Wed, 24 May 2023 21:54:38 -0700 Subject: [PATCH 20/21] make charts --- .../prometheus-federator-0.3.1.tgz | Bin 20566 -> 20585 bytes .../charts/helmProjectOperator/Chart.yaml | 4 ++-- .../templates/deployment.yaml | 4 +++- .../charts/helmProjectOperator/values.yaml | 4 +++- index.yaml | 6 +++--- .../prometheus-federator/charts/values.yaml | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/assets/prometheus-federator/prometheus-federator-0.3.1.tgz b/assets/prometheus-federator/prometheus-federator-0.3.1.tgz index 2a5f65a5ed8ac56a874bee32646ffd3ab4f15d75..e3b3c473d0a4331827b5e6d0b274b3cb52689d41 100644 GIT binary patch literal 20585 zcmZtN19L81ur}z}ww>(Qwr$(CZQHi9V{6B@ZQFL9?>%RxW@@Tt{e@Mvy6@Fj6UIQH z0sYSbPyx{xNh&j%NXoIxdU3HCv#2wgs<2sUt8lR^sH?NfY1mpD*_(Q)Dmm~;n%UX` zUH{m4Y;|-}#=o%%fXDNG5l(HD-f&L1(y%mV8~C_{rSKdVuGNHvpHraN9}=1Sw% zS`ho~N_gPn=jZo-JV*Za@%7#QeLH@5NZHHd^>+3Ce4jXyFbMeRI!YO

}bRh!>dL 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 ArvLx| literal 20566 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 diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml index 421aabb1..e61767ca 100644 --- a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/Chart.yaml @@ -9,7 +9,7 @@ annotations: catalog.cattle.io/rancher-version: '>= 2.6.0-0' catalog.cattle.io/release-name: helm-project-operator apiVersion: v2 -appVersion: 0.1.0 +appVersion: 0.2.0 description: Helm Project Operator name: helmProjectOperator -version: 0.1.1 +version: 0.2.0 diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml index c7309805..33b81e72 100644 --- a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/templates/deployment.yaml @@ -6,7 +6,9 @@ metadata: labels: {{ include "helm-project-operator.labels" . | nindent 4 }} app: {{ template "helm-project-operator.name" . }} spec: - replicas: 1 + {{- if .Values.replicas }} + replicas: {{ .Values.replicas }} + {{- end }} selector: matchLabels: app: {{ template "helm-project-operator.name" . }} diff --git a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml index 4905bf1a..0f3fe2bb 100644 --- a/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml +++ b/charts/prometheus-federator/0.3.1/charts/helmProjectOperator/values.yaml @@ -126,9 +126,11 @@ nameOverride: "" namespaceOverride: "" +replicas: 1 + image: repository: rancher/helm-project-operator - tag: v0.1.0 + tag: v0.2.0 pullPolicy: IfNotPresent helmController: diff --git a/index.yaml b/index.yaml index d4b93dbf..3acaac58 100755 --- a/index.yaml +++ b/index.yaml @@ -13,13 +13,13 @@ entries: catalog.cattle.io/release-name: prometheus-federator apiVersion: v2 appVersion: 0.3.1 - created: "2023-05-24T21:18:24.966511-07:00" + created: "2023-05-24T21:59:43.2827-07:00" dependencies: - condition: helmProjectOperator.enabled name: helmProjectOperator repository: file://./charts/helmProjectOperator description: Prometheus Federator - digest: 6d73736f0f4507f08c792eb888ee2b22821e2f4cabc90cca39d401f3f39dc4b4 + digest: beca13955157507f2b9fe504bb0fdbff5b11060d20c4a8e0e56733b4f32c3a13 icon: https://raw.githubusercontent.com/rancher/prometheus-federator/main/assets/logos/prometheus-federator.svg name: prometheus-federator urls: @@ -630,4 +630,4 @@ entries: urls: - assets/rancher-project-monitoring/rancher-project-monitoring-0.0.1.tgz version: 0.0.1 -generated: "2022-04-18T09:31:51.970932-07:00" \ No newline at end of file +generated: "2022-04-18T09:31:51.970932-07:00" diff --git a/packages/prometheus-federator/charts/values.yaml b/packages/prometheus-federator/charts/values.yaml index 4f22c1dd..3abc6326 100755 --- a/packages/prometheus-federator/charts/values.yaml +++ b/packages/prometheus-federator/charts/values.yaml @@ -58,7 +58,7 @@ helmProjectOperator: image: repository: rancher/prometheus-federator - tag: v0.3.0 + tag: v0.3.1 pullPolicy: IfNotPresent # Additional arguments to be passed into the Prometheus Federator image From 40538ebc0be2f1c1fc26ffb288f8f0ae1b5c709c Mon Sep 17 00:00:00 2001 From: Arvind Iyengar Date: Tue, 11 Apr 2023 10:47:29 -0700 Subject: [PATCH 21/21] Github action: Explicitly install go, kubectl and helm so that you can also run the e2e tests locally with act (partially cherry-picked from 15d22c6f58747e0fa7fd867e8df91d8f75f9f981) The act base image does not have all the same tools installed as the github action base image. --- .github/workflows/e2e-ci.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/e2e-ci.yaml b/.github/workflows/e2e-ci.yaml index 62879638..919d8d0b 100644 --- a/.github/workflows/e2e-ci.yaml +++ b/.github/workflows/e2e-ci.yaml @@ -54,6 +54,11 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 + - uses: actions/setup-go@v4 + with: + go-version: '>=1.17.0' + - uses: azure/setup-kubectl@v3 + - uses: azure/setup-helm@v3 - name: Install mikefarah/yq run: |