From 094e655a58699715fb6b7ef75c7ee65b3d990bb6 Mon Sep 17 00:00:00 2001 From: elenalape Date: Wed, 25 Aug 2021 13:10:10 +0100 Subject: [PATCH 1/2] add updated package, patch and clean --- assets/logos/kubecost.png | Bin 0 -> 17732 bytes .../generated-changes/overlay/app-readme.md | 8 +- .../generated-changes/overlay/questions.yaml | 160 ++++++++++++++++++ .../generated-changes/overlay/questions.yml | 160 ------------------ .../generated-changes/patch/Chart.yaml.patch | 20 ++- packages/kubecost/package.yaml | 2 +- 6 files changed, 180 insertions(+), 170 deletions(-) create mode 100644 assets/logos/kubecost.png create mode 100644 packages/kubecost/generated-changes/overlay/questions.yaml delete mode 100644 packages/kubecost/generated-changes/overlay/questions.yml diff --git a/assets/logos/kubecost.png b/assets/logos/kubecost.png new file mode 100644 index 0000000000000000000000000000000000000000..845f832134d5cbeefca1f8208bf370310469df55 GIT binary patch literal 17732 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 Hu0mjflA^}b literal 0 HcmV?d00001 diff --git a/packages/kubecost/generated-changes/overlay/app-readme.md b/packages/kubecost/generated-changes/overlay/app-readme.md index dfb1e5854..90fd50607 100644 --- a/packages/kubecost/generated-changes/overlay/app-readme.md +++ b/packages/kubecost/generated-changes/overlay/app-readme.md @@ -1,21 +1,23 @@ # Kubecost + [Kubecost](https://kubecost.com/) is an open-source Kubernetes cost monitoring solution. -Kubecost gives teams visibility into current and historical Kubernetes spend and resource allocation. These models provide cost transparency in Kubernetes environments that support multiple applications, teams, departments, etc. +Kubecost gives teams visibility into current and historical Kubernetes spend and resource allocation. These models provide cost transparency in Kubernetes environments that support multiple applications, teams, departments, etc. To see more on the functionality of the full Kubecost product, please visit the [features page](https://kubecost.com/#features) on our website. Here is a summary of features enabled by this cost model: - Real-time cost allocation by Kubernetes service, deployment, namespace, label, statefulset, daemonset, pod, and container -- Dynamic asset pricing enabled by integrations with AWS, Azure, and GCP billing APIs +- Dynamic asset pricing enabled by integrations with AWS, Azure, and GCP billing APIs - Supports on-prem k8s clusters with custom pricing sheets - Allocation for in-cluster resources like CPU, GPU, memory, and persistent volumes. - Allocation for AWS & GCP out-of-cluster resources like RDS instances and S3 buckets with key (optional) -- Easily export pricing data to Prometheus with /metrics endpoint ([learn more](PROMETHEUS.md)) +- Easily export pricing data to Prometheus with /metrics endpoint ([learn more](https://github.com/kubecost/cost-model/blob/develop/PROMETHEUS.md)) - Free and open source distribution (Apache2 license) ## Requirements + - Kubernetes 1.8+ - kube-state-metrics - Grafana diff --git a/packages/kubecost/generated-changes/overlay/questions.yaml b/packages/kubecost/generated-changes/overlay/questions.yaml new file mode 100644 index 000000000..3569a25e0 --- /dev/null +++ b/packages/kubecost/generated-changes/overlay/questions.yaml @@ -0,0 +1,160 @@ +questions: + # General Settings + - variable: kubecostProductConfigs.clusterName + label: Cluster Name + description: "Used for display in the cost-analyzer UI (Can be renamed in the UI)" + type: string + required: true + default: "" + group: General Settings + - variable: persistentVolume.enabled + label: Enable Persistent Volume for CostAnalyzer + description: "If true, Kubecost will create a Persistent Volume Claim for product config data" + type: boolean + default: false + show_subquestion_if: true + group: "General Settings" + subquestions: + - variable: persistentVolume.size + label: CostAnalyzer Persistent Volume Size + type: string + default: "0.2Gi" + + # Prometheus Server + - variable: global.prometheus.enabled + label: Enable Prometheus + description: If false, use an existing Prometheus install + type: boolean + default: true + group: "Prometheus" + - variable: prometheus.kubeStateMetrics.enabled + label: Enable KubeStateMetrics + description: "If true, deploy kube-state-metrics for Kubernetes metrics" + type: boolean + default: true + show_if: "global.prometheus.enabled=true" + group: "Prometheus" + - variable: prometheus.server.retention + label: Prometheus Server Retention + description: "Determines when to remove old data" + type: string + default: "15d" + show_if: "global.prometheus.enabled=true" + group: "Prometheus" + - variable: prometheus.server.persistentVolume.enabled + label: Create Persistent Volume for Prometheus + description: "If true, prometheus will create a persistent volume claim" + type: boolean + required: true + default: false + group: "Prometheus" + show_if: "global.prometheus.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.server.persistentVolume.size + label: Prometheus Persistent Volume Size + type: string + default: "8Gi" + - variable: prometheus.server.persistentVolume.storageClass + label: Prometheus Persistent Volume StorageClass + description: "Prometheus data persistent volume storageClass, if not set use default StorageClass" + default: "" + type: storageclass + - variable: prometheus.server.persistentVolume.existingClaim + label: Existing Persistent Volume Claim for Prometheus + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + default: "" + + # Prometheus Node Exporter + - variable: prometheus.nodeExporter.enabled + label: Enable NodeExporter + description: "If false, do not create NodeExporter daemonset" + type: boolean + default: true + group: "NodeExporter" + - variable: prometheus.serviceAccounts.nodeExporter.create + label: Enable Service Accounts NodeExporter + description: "If false, do not create NodeExporter daemonset" + type: boolean + default: true + group: "NodeExporter" + + # Prometheus AlertManager + - variable: prometheus.alertmanager.enabled + label: Enable AlertManager + type: boolean + default: true + group: "AlertManager" + - variable: prometheus.alertmanager.persistentVolume.enabled + label: Create Persistent Volume for AlertManager + description: "If true, alertmanager will create a persistent volume claim" + type: boolean + required: true + default: false + group: "AlertManager" + show_if: "prometheus.alertmanager.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.alertmanager.persistentVolume.size + default: "2Gi" + description: "AlertManager data persistent volume size" + type: string + label: AlertManager Persistent Volume Size + - variable: prometheus.alertmanager.persistentVolume.storageClass + default: "" + description: "Alertmanager data persistent volume storageClass, if not set use default StorageClass" + type: storageclass + label: AlertManager Persistent Volume StorageClass + - variable: prometheus.alertmanager.persistentVolume.existingClaim + default: "" + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + label: Existing Persistent Volume Claim for AlertManager + + # PushGateway + - variable: prometheus.pushgateway.enabled + label: Enable PushGateway + type: boolean + default: true + group: "PushGateway" + - variable: prometheus.pushgateway.persistentVolume.enabled + label: Create Persistent Volume for PushGateway + description: "If true, PushGateway will create a persistent volume claim" + required: true + type: boolean + default: false + group: "PushGateway" + show_if: "prometheus.pushgateway.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.prometheus.pushgateway.persistentVolume.size + label: PushGateway Persistent Volume Size + type: string + default: "2Gi" + - variable: prometheus.pushgateway.persistentVolume.storageClass + label: PushGateway Persistent Volume StorageClass + description: "PushGateway data persistent volume storageClass, if not set use default StorageClass" + type: storageclass + default: "" + - variable: prometheus.pushgateway.persistentVolume.existingClaim + label: Existing Persistent Volume Claim for PushGateway + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + default: "" + + # Services and Load Balancing + - variable: ingress.enabled + label: Enable Ingress + description: "Expose app using Ingress (Layer 7 Load Balancer)" + default: true + type: boolean + show_subquestion_if: true + group: "Services and Load Balancing" + subquestions: + - variable: ingress.hosts[0] + default: "xip.io" + description: "Hostname to your CostAnalyzer installation" + type: hostname + required: true + label: Hostname diff --git a/packages/kubecost/generated-changes/overlay/questions.yml b/packages/kubecost/generated-changes/overlay/questions.yml deleted file mode 100644 index ce86c64fb..000000000 --- a/packages/kubecost/generated-changes/overlay/questions.yml +++ /dev/null @@ -1,160 +0,0 @@ -questions: -# General Settings -- variable: kubecostProductConfigs.clusterName - label: Cluster Name - description: "Used for display in the cost-analyzer UI (Can be renamed in the UI)" - type: string - required: true - default: "" - group: General Settings -- variable: persistentVolume.enabled - label: Enable Persistent Volume for CostAnalyzer - description: "If true, Kubecost will create a Persistent Volume Claim for product config data" - type: boolean - default: false - show_subquestion_if: true - group: "General Settings" - subquestions: - - variable: persistentVolume.size - label: CostAnalyzer Persistent Volume Size - type: string - default: "0.2Gi" - -# Prometheus Server -- variable: global.prometheus.enabled - label: Enable Prometheus - description: If false, use an existing Prometheus install - type: boolean - default: true - group: "Prometheus" -- variable: prometheus.kubeStateMetrics.enabled - label: Enable KubeStateMetrics - description: "If true, deploy kube-state-metrics for Kubernetes metrics" - type: boolean - default: true - show_if: "global.prometheus.enabled=true" - group: "Prometheus" -- variable: prometheus.server.retention - label: Prometheus Server Retention - description: "Determines when to remove old data" - type: string - default: "15d" - show_if: "global.prometheus.enabled=true" - group: "Prometheus" -- variable: prometheus.server.persistentVolume.enabled - label: Create Persistent Volume for Prometheus - description: "If true, prometheus will create a persistent volume claim" - type: boolean - required: true - default: false - group: "Prometheus" - show_if: "global.prometheus.enabled=true" - show_subquestion_if: true - subquestions: - - variable: prometheus.server.persistentVolume.size - label: Prometheus Persistent Volume Size - type: string - default: "8Gi" - - variable: prometheus.server.persistentVolume.storageClass - label: Prometheus Persistent Volume StorageClass - description: "Prometheus data persistent volume storageClass, if not set use default StorageClass" - default: "" - type: storageclass - - variable: prometheus.server.persistentVolume.existingClaim - label: Existing Persistent Volume Claim for Prometheus - description: "If not empty, uses the specified existing PVC instead of creating new one" - type: pvc - default: "" - -# Prometheus Node Exporter -- variable: prometheus.nodeExporter.enabled - label: Enable NodeExporter - description: "If false, do not create NodeExporter daemonset" - type: boolean - default: true - group: "NodeExporter" -- variable: prometheus.serviceAccounts.nodeExporter.create - label: Enable Service Accounts NodeExporter - description: "If false, do not create NodeExporter daemonset" - type: boolean - default: true - group: "NodeExporter" - -# Prometheus AlertManager -- variable: prometheus.alertmanager.enabled - label: Enable AlertManager - type: boolean - default: true - group: "AlertManager" -- variable: prometheus.alertmanager.persistentVolume.enabled - label: Create Persistent Volume for AlertManager - description: "If true, alertmanager will create a persistent volume claim" - type: boolean - required: true - default: false - group: "AlertManager" - show_if: "prometheus.alertmanager.enabled=true" - show_subquestion_if: true - subquestions: - - variable: prometheus.alertmanager.persistentVolume.size - default: "2Gi" - description: "AlertManager data persistent volume size" - type: string - label: AlertManager Persistent Volume Size - - variable: prometheus.alertmanager.persistentVolume.storageClass - default: "" - description: "Alertmanager data persistent volume storageClass, if not set use default StorageClass" - type: storageclass - label: AlertManager Persistent Volume StorageClass - - variable: prometheus.alertmanager.persistentVolume.existingClaim - default: "" - description: "If not empty, uses the specified existing PVC instead of creating new one" - type: pvc - label: Existing Persistent Volume Claim for AlertManager - -# PushGateway -- variable: prometheus.pushgateway.enabled - label: Enable PushGateway - type: boolean - default: true - group: "PushGateway" -- variable: prometheus.pushgateway.persistentVolume.enabled - label: Create Persistent Volume for PushGateway - description: "If true, PushGateway will create a persistent volume claim" - required: true - type: boolean - default: false - group: "PushGateway" - show_if: "prometheus.pushgateway.enabled=true" - show_subquestion_if: true - subquestions: - - variable: prometheus.prometheus.pushgateway.persistentVolume.size - label: PushGateway Persistent Volume Size - type: string - default: "2Gi" - - variable: prometheus.pushgateway.persistentVolume.storageClass - label: PushGateway Persistent Volume StorageClass - description: "PushGateway data persistent volume storageClass, if not set use default StorageClass" - type: storageclass - default: "" - - variable: prometheus.pushgateway.persistentVolume.existingClaim - label: Existing Persistent Volume Claim for PushGateway - description: "If not empty, uses the specified existing PVC instead of creating new one" - type: pvc - default: "" - -# Services and Load Balancing -- variable: ingress.enabled - label: Enable Ingress - description: "Expose app using Ingress (Layer 7 Load Balancer)" - default: true - type: boolean - show_subquestion_if: true - group: "Services and Load Balancing" - subquestions: - - variable: ingress.hosts[0] - default: "xip.io" - description: "Hostname to your CostAnalyzer installation" - type: hostname - required: true - label: Hostname diff --git a/packages/kubecost/generated-changes/patch/Chart.yaml.patch b/packages/kubecost/generated-changes/patch/Chart.yaml.patch index ae62a6bf4..09502c669 100644 --- a/packages/kubecost/generated-changes/patch/Chart.yaml.patch +++ b/packages/kubecost/generated-changes/patch/Chart.yaml.patch @@ -1,10 +1,18 @@ --- charts-original/Chart.yaml +++ charts/Chart.yaml -@@ -4,3 +4,7 @@ - cloud costs. - name: cost-analyzer - version: 1.70.0 -+icon: https://kubecost.com/images/logo-white.png -+annotations: +@@ -2,9 +2,14 @@ + artifacthub.io/links: | + - name: Homepage + url: https://www.kubecost.com + catalog.cattle.io/certified: partner ++ catalog.cattle.io/display-name: Kubecost + catalog.cattle.io/release-name: kubecost + apiVersion: v2 + appVersion: 1.83.2 +-description: A Helm chart that sets up Kubecost, Prometheus, and Grafana to monitor ++description: ++ A Helm chart that sets up Kubecost, Prometheus, and Grafana to monitor + cloud costs. ++icon: https://partner-charts.rancher.io/assets/logos/kubecost.png + name: cost-analyzer + version: 1.83.2 diff --git a/packages/kubecost/package.yaml b/packages/kubecost/package.yaml index d620b1097..7ea33c129 100644 --- a/packages/kubecost/package.yaml +++ b/packages/kubecost/package.yaml @@ -1,2 +1,2 @@ -url: https://kubecost.github.io/rancher-helm-chart/cost-analyzer-1.70.0.tgz +url: https://kubecost.github.io/cost-analyzer/cost-analyzer-1.83.2.tgz packageVersion: 01 From f75c11dfc804f0e53da9b23c5584c9bcb1204726 Mon Sep 17 00:00:00 2001 From: elenalape Date: Thu, 26 Aug 2021 13:34:20 +0100 Subject: [PATCH 2/2] make charts --- assets/kubecost/cost-analyzer-1.83.201.tgz | Bin 0 -> 113809 bytes .../cost-analyzer/1.83.201/Chart.yaml | 14 + .../kubecost/cost-analyzer/1.83.201/README.md | 43 + .../cost-analyzer/1.83.201/app-readme.md | 25 + .../1.83.201/attached-disks.json | 444 ++ .../1.83.201/charts/grafana/Chart.yaml | 15 + .../1.83.201/charts/grafana/README.md | 162 + .../charts/grafana/templates/NOTES.txt | 37 + .../charts/grafana/templates/_helpers.tpl | 43 + .../charts/grafana/templates/clusterrole.yaml | 25 + .../grafana/templates/clusterrolebinding.yaml | 25 + .../configmap-dashboard-provider.yaml | 28 + .../charts/grafana/templates/configmap.yaml | 76 + .../templates/dashboards-json-configmap.yaml | 24 + .../charts/grafana/templates/deployment.yaml | 276 + .../charts/grafana/templates/ingress.yaml | 44 + .../grafana/templates/podsecuritypolicy.yaml | 45 + .../charts/grafana/templates/pvc.yaml | 26 + .../charts/grafana/templates/role.yaml | 20 + .../charts/grafana/templates/rolebinding.yaml | 20 + .../charts/grafana/templates/secret.yaml | 22 + .../charts/grafana/templates/service.yaml | 51 + .../grafana/templates/serviceaccount.yaml | 13 + .../1.83.201/charts/grafana/values.yaml | 276 + .../1.83.201/charts/prometheus/.helmignore | 23 + .../1.83.201/charts/prometheus/Chart.yaml | 18 + .../1.83.201/charts/prometheus/README.md | 471 ++ .../charts/kube-state-metrics/.helmignore | 21 + .../charts/kube-state-metrics/Chart.yaml | 20 + .../charts/kube-state-metrics/OWNERS | 8 + .../charts/kube-state-metrics/README.md | 73 + .../kube-state-metrics/templates/NOTES.txt | 10 + .../kube-state-metrics/templates/_helpers.tpl | 47 + .../templates/clusterrole.yaml | 182 + .../templates/clusterrolebinding.yaml | 21 + .../templates/deployment.yaml | 192 + .../templates/podsecuritypolicy.yaml | 41 + .../templates/psp-clusterrole.yaml | 19 + .../templates/psp-clusterrolebinding.yaml | 21 + .../kube-state-metrics/templates/service.yaml | 38 + .../templates/serviceaccount.yaml | 16 + .../templates/servicemonitor.yaml | 27 + .../templates/stsdiscovery-role.yaml | 29 + .../templates/stsdiscovery-rolebinding.yaml | 22 + .../charts/kube-state-metrics/values.yaml | 126 + .../charts/prometheus/requirements.lock | 6 + .../charts/prometheus/requirements.yaml | 7 + .../charts/prometheus/templates/NOTES.txt | 112 + .../charts/prometheus/templates/_helpers.tpl | 276 + .../templates/alertmanager-clusterrole.yaml | 23 + .../alertmanager-clusterrolebinding.yaml | 18 + .../templates/alertmanager-configmap.yaml | 20 + .../templates/alertmanager-deployment.yaml | 141 + .../templates/alertmanager-ingress.yaml | 44 + .../templates/alertmanager-networkpolicy.yaml | 21 + .../templates/alertmanager-pdb.yaml | 15 + .../alertmanager-podsecuritypolicy.yaml | 50 + .../templates/alertmanager-pvc.yaml | 34 + .../alertmanager-service-headless.yaml | 32 + .../templates/alertmanager-service.yaml | 54 + .../alertmanager-serviceaccount.yaml | 10 + .../templates/alertmanager-statefulset.yaml | 154 + .../templates/node-exporter-daemonset.yaml | 125 + .../node-exporter-podsecuritypolicy.yaml | 57 + .../templates/node-exporter-role.yaml | 19 + .../templates/node-exporter-rolebinding.yaml | 21 + .../templates/node-exporter-service.yaml | 46 + .../node-exporter-serviceaccount.yaml | 10 + .../templates/pushgateway-clusterrole.yaml | 23 + .../pushgateway-clusterrolebinding.yaml | 18 + .../templates/pushgateway-deployment.yaml | 99 + .../templates/pushgateway-ingress.yaml | 41 + .../templates/pushgateway-networkpolicy.yaml | 21 + .../prometheus/templates/pushgateway-pdb.yaml | 15 + .../pushgateway-podsecuritypolicy.yaml | 46 + .../prometheus/templates/pushgateway-pvc.yaml | 34 + .../templates/pushgateway-service.yaml | 42 + .../templates/pushgateway-serviceaccount.yaml | 10 + .../templates/server-clusterrole.yaml | 49 + .../templates/server-clusterrolebinding.yaml | 18 + .../templates/server-configmap.yaml | 83 + .../templates/server-deployment.yaml | 216 + .../prometheus/templates/server-ingress.yaml | 46 + .../templates/server-networkpolicy.yaml | 19 + .../prometheus/templates/server-pdb.yaml | 15 + .../templates/server-podsecuritypolicy.yaml | 55 + .../prometheus/templates/server-pvc.yaml | 36 + .../templates/server-service-headless.yaml | 28 + .../prometheus/templates/server-service.yaml | 61 + .../templates/server-serviceaccount.yaml | 12 + .../templates/server-statefulset.yaml | 224 + .../prometheus/templates/server-vpa.yaml | 26 + .../1.83.201/charts/prometheus/values.yaml | 1387 ++++ .../1.83.201/charts/thanos/.helmignore | 21 + .../1.83.201/charts/thanos/Chart.yaml | 18 + .../1.83.201/charts/thanos/requirements.yaml | 0 .../charts/thanos/templates/NOTES.txt | 0 .../charts/thanos/templates/_helpers.tpl | 51 + .../thanos/templates/bucket-deployment.yaml | 91 + .../thanos/templates/bucket-ingress.yaml | 42 + .../templates/bucket-poddisruptionbudget.yaml | 27 + .../thanos/templates/bucket-service.yaml | 30 + .../thanos/templates/compact-deployment.yaml | 112 + .../charts/thanos/templates/compact-pvc.yaml | 27 + .../thanos/templates/compact-service.yaml | 30 + .../templates/compact-servicemonitor.yaml | 32 + .../thanos/templates/query-deployment.yaml | 152 + .../templates/query-frontend-deployment.yaml | 126 + ...uery-frontend-horizontalpodautoscaler.yaml | 37 + .../templates/query-frontend-ingress.yml | 45 + .../query-frontend-poddisruptionbudget.yaml | 27 + .../templates/query-frontend-service.yaml | 34 + .../query-frontend-servicemonitor.yaml | 32 + .../query-horizontalpodautoscaler.yaml | 37 + .../charts/thanos/templates/query-ingress.yml | 89 + .../templates/query-poddisruptionbudget.yaml | 27 + .../thanos/templates/query-service.yaml | 65 + .../templates/query-servicemonitor.yaml | 32 + .../thanos/templates/sidecar-service.yaml | 61 + .../templates/sidecar-servicemonitor.yaml | 32 + .../thanos/templates/store-deployment.yaml | 138 + .../thanos/templates/store-ingress.yaml | 85 + .../charts/thanos/templates/store-pvc.yaml | 27 + .../thanos/templates/store-service.yaml | 65 + .../templates/store-servicemonitor.yaml | 32 + .../1.83.201/charts/thanos/values.yaml | 764 +++ .../1.83.201/cluster-metrics.json | 1682 +++++ .../1.83.201/cluster-utilization.json | 3492 ++++++++++ .../1.83.201/deployment-utilization.json | 1385 ++++ .../1.83.201/label-cost-utilization.json | 1212 ++++ .../1.83.201/namespace-utilization.json | 1175 ++++ .../1.83.201/node-utilization.json | 1389 ++++ .../1.83.201/pod-utilization.json | 950 +++ .../1.83.201/prom-benchmark.json | 5689 +++++++++++++++++ .../cost-analyzer/1.83.201/questions.yaml | 160 + .../1.83.201/templates/NOTES.txt | 10 + .../1.83.201/templates/_helpers.tpl | 211 + .../templates/aws-service-key-secret.yaml | 17 + .../awsstore-deployment-template.yaml | 26 + .../awsstore-service-account-template.yaml | 12 + .../templates/azure-service-key-secret.yaml | 21 + .../azure-storage-config-secret.yaml | 22 + .../cost-analyzer-alerts-configmap.yaml | 10 + ...cost-analyzer-asset-reports-configmap.yaml | 13 + .../cost-analyzer-cluser-role-template.yaml | 105 + ...nalyzer-cluster-role-binding-template.yaml | 33 + .../cost-analyzer-config-map-template.yaml | 30 + .../cost-analyzer-db-pvc-template.yaml | 29 + .../cost-analyzer-deployment-template.yaml | 784 +++ ...analyzer-frontend-config-map-template.yaml | 195 + .../cost-analyzer-ingress-template.yaml | 40 + ...zer-network-costs-config-map-template.yaml | 15 + ...zer-network-costs-podmonitor-template.yaml | 31 + ...alyzer-network-costs-service-template.yaml | 26 + .../cost-analyzer-network-costs-template.yaml | 114 + .../cost-analyzer-network-policy.yaml | 50 + .../cost-analyzer-pkey-configmap.yaml | 16 + .../cost-analyzer-pricing-configmap.yaml | 128 + ...rometheus-postgres-adapter-deployment.yaml | 57 + ...r-prometheus-postgres-adapter-service.yaml | 20 + ...cost-analyzer-prometheusrule-template.yaml | 21 + .../cost-analyzer-psp-role.template.yaml | 18 + ...ost-analyzer-psp-rolebinding.template.yaml | 16 + .../templates/cost-analyzer-psp.template.yaml | 20 + .../templates/cost-analyzer-pvc-template.yaml | 25 + ...ost-analyzer-saml-config-map-template.yaml | 13 + ...cost-analyzer-saved-reports-configmap.yaml | 12 + .../cost-analyzer-server-configmap.yaml | 69 + ...ost-analyzer-service-account-template.yaml | 12 + .../cost-analyzer-service-template.yaml | 69 + ...cost-analyzer-servicemonitor-template.yaml | 27 + .../external-grafana-config-map-template.yaml | 10 + ...rafana-attached-disk-metrics-template.yaml | 25 + ...na-dashboard-cluster-metrics-template.yaml | 27 + ...ashboard-cluster-utilization-template.yaml | 25 + ...board-deployment-utilization-template.yaml | 25 + ...board-label-cost-utilization-template.yaml | 25 + ...hboard-namespace-utilization-template.yaml | 25 + ...a-dashboard-node-utilization-template.yaml | 25 + ...na-dashboard-pod-utilization-template.yaml | 25 + ...dashboard-prometheus-metrics-template.yaml | 25 + .../grafana-datasource-template.yaml | 56 + .../kubecost-cluster-controller-template.yaml | 282 + ...st-cluster-manager-configmap-template.yaml | 13 + .../kubecost-priority-class-template.yaml | 11 + .../templates/network-costs-psp.template.yaml | 36 + .../network-costs-role.template.yaml | 22 + .../network-costs-rolebinding.template.yaml | 20 + .../cost-analyzer/1.83.201/values-thanos.yaml | 134 + .../cost-analyzer/1.83.201/values.yaml | 675 ++ index.yaml | 18 + 191 files changed, 30441 insertions(+) create mode 100644 assets/kubecost/cost-analyzer-1.83.201.tgz create mode 100644 charts/kubecost/cost-analyzer/1.83.201/Chart.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/README.md create mode 100644 charts/kubecost/cost-analyzer/1.83.201/app-readme.md create mode 100644 charts/kubecost/cost-analyzer/1.83.201/attached-disks.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/Chart.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/README.md create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/NOTES.txt create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/_helpers.tpl create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap-dashboard-provider.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/dashboards-json-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/role.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/rolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/secret.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/grafana/values.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/.helmignore create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/Chart.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/README.md create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/.helmignore create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/Chart.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/OWNERS create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/README.md create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/values.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.lock create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/NOTES.txt create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/_helpers.tpl create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-networkpolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pdb.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service-headless.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-statefulset.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-daemonset.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-role.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-rolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-networkpolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pdb.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrole.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrolebinding.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-networkpolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pdb.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-podsecuritypolicy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service-headless.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-serviceaccount.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-statefulset.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-vpa.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/values.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/.helmignore create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/Chart.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/requirements.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/NOTES.txt create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/_helpers.tpl create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-poddisruptionbudget.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-horizontalpodautoscaler.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-ingress.yml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-poddisruptionbudget.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-horizontalpodautoscaler.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-ingress.yml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-poddisruptionbudget.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-ingress.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-pvc.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-servicemonitor.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/charts/thanos/values.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/cluster-metrics.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/cluster-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/deployment-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/label-cost-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/namespace-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/node-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/pod-utilization.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/prom-benchmark.json create mode 100644 charts/kubecost/cost-analyzer/1.83.201/questions.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/NOTES.txt create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/_helpers.tpl create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/aws-service-key-secret.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-deployment-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-service-account-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/azure-service-key-secret.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/azure-storage-config-secret.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-alerts-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-asset-reports-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluser-role-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluster-role-binding-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-config-map-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-db-pvc-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-deployment-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-frontend-config-map-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-ingress-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-config-map-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-podmonitor-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-service-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-policy.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pkey-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pricing-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-deployment.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-service.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheusrule-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-role.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-rolebinding.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pvc-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saml-config-map-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saved-reports-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-server-configmap.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-account-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-servicemonitor-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/external-grafana-config-map-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-attached-disk-metrics-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-metrics-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-deployment-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-label-cost-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-namespace-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-node-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-pod-utilization-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-prometheus-metrics-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/grafana-datasource-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-controller-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-manager-configmap-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-priority-class-template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-psp.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-role.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-rolebinding.template.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/values-thanos.yaml create mode 100644 charts/kubecost/cost-analyzer/1.83.201/values.yaml diff --git a/assets/kubecost/cost-analyzer-1.83.201.tgz b/assets/kubecost/cost-analyzer-1.83.201.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c8fda057a1729481a7fa3e315680a9453d4d2ab4 GIT binary patch literal 113809 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 z zZ90tRXx{>M<7NX0?PIl%$KnGzW+F5z9cejMG4V2a(R|Z3($@{`U4?Vx5e7Jq14iJ8 zvtxuXI3D(a_k-4Z?nU4nG^L%XY#gXYZ_i7rKU#PhQOghcT(K z3?F8JJF^#Z4Ru(#F{kRhnzMjYg;My+^N$MEI%2_ zbCS8a^_v@@&+ewir;ioZ0`L<+ei)IN{#^Dpd;g<}8e<7C388@v;3a*k5$FDR>d*|7oxdHK^OxNPSrha%efEKm>CQc)eA8oM!0iW2!GaE@= zbai_xcTP65pxr{ZmvH#H(3tW-(4r=o*1nBej^PX2|72EB9b|aY_T2UFQ?ID(G1N%^ zCYuTKOWaGSBnCNT5rTuLkq6aJL~k#Xg&P4Mpic3!jT0u! z!H=2SNS70ihzQnJSHLoVnku~)Bu4R^6RmVaQTW1hP`o#(_BaV*4nlV}WdW3Mw+OE_ z*bBR@yxgtI#-zC`g&>2P`GQ3gawUwfOci5q(P#I9?$D-+{u((r2%+CCle0_dY0C^e z3O;TneJ+@Q`qt=JI*U>Js{ju(Y#*r9v7}Ge+oTrl)v>y~UBy_cC31Y+uya}ASwZj0 z`x&Xz+-;yd?55_KxTwo?;`Y+&P3*OM!_oj~k^@>UFTe{ec{(-8t|)b-dU&6(o9Ngp zSPEF>`&r^VRC(*jm(iI8*8pzJt@*JTy)iqopnJUZfFW0#GU~ZK{-9n;qHpdYJ!y3K z(GdKQ2CDfdR$_<|%nSavMG>k4kLT5KC)A|djF8`9Mr)$;D$IR7+m7LCB*|f!ybo)D z7Y~9w*PB;Xy-+aAUE%Xkzjns*pewi0)KtiF<`WE9EOr=r)YR*$g)sy@COdsk(X>LF zht}OxmjiBIe2Yr8oc9RLQVr*-o3vTn7vwdpIp3itu9#5J#yo4X7*ZM=D|K?dh9iQW z7S@B8UJVDMnYNNT2A$W*t8o)A6ZARHhRR#eU+jv+D7<5sIw3}>`NQze`|IGBaYbcy5*r=`ro!`g@(XBYf_&S71i0Ik-%6*=xzBL^&7 zq3@l+EyH84ptp^3+F!bGrRb3I3fgN1PdXJ=vaHXfj_2*2PepCHyQ2Fr+ZW4k*WYiO zuUx%5bG!gj^1ONMXe_Ix)?K!4{oYNgV%zEkKW+Malj?Ume&stWN$Te9*p}g@!>HP- zv~sxb`{<$R4PB&%N`tE>kw6GiKoFm(^wK5ee^%Psu>j;DONd= zC5PC~oQ>CD*}`pP*4bmXo8T2SS{b5To!Yq~WC<(x`vU^6%+m|2az=5T4t5m;D{9ZGs{`!5KWk6!(c&=)ZqMrG!V3Ol|DYP!Bk z!msn2W8tMuo;)*u%>h-8B!w6Sb0MWEmbJg6V_HcT(eM=aKeu{cyn~AV*8o`F zKD5!nTrEDE(!WYMO)45+avYY#;FZ@0jB5*?tX1~s#o1VVUZsCYY2rHLQ?9R;CW^r< z)4Gm#^O2p;cwEVslGGTsd#r(!452q-_lX~k)J4*#Ds%5|LJJQkcs3&UeV$#fpjLHZ z)+=94IGPFcf;OQ$`r4Uqzo(H_{Y(w!n_Ce?2sgCG3ZKymuKOMBc*=(hult*L)81%! z-z~iACbTowen&0fO5Q0sGflkel&NG)Ht?c+8$zcJi<`omfwXJa@h$wyC=J#uuXCyf zuQ%+dRXOhjkDz%-^Pj&?`K^hA#sARZvzo(IRWFh$?SvZXEPxC_YMtvzkQ%`qd2cHi zm_pp&?=f7M#AQQFWKG=%(>XKHI-_+D?q=5$^sFeh<=UeS9TwEVe>v}Fz6kq%X4y%* zJi`*{#Y&OcNu!2EDw+7_&ArxEz2x)8y(S zb9dJvZq50PY|eO_sidsVG5Ue#9Im6$^q)hzZFb;=bHb30AHkBcv`$YJHn1RwX zBO3Bi^vA#MI)3-bOY9)07>XJeb{!AixYDiFPD3GT#QIvq6!gjFK zndBcH>8hZ!#>RDtBS9@9og6-UrVD|sn6UPW1FQo+{X`E`q9O&meP$hvw^P4`cY1x{>sXMWM`Ur9> z+7ia>`8VHoC4&IaPTf18w{MeroYz;{&@W*!cHmVksyYU`Kgga0rBtedyC%fy$5%i>21i^WlasR@JJ}ZitcV7Ia|E$kd)E^CyHOn1Z})zxnV6?=)<5(N z{s4fHgH1jxlK;Ti@38OwkK}r$qrI7PTm*7bB~&?mINh@GFqGog0kO;tgUQ4#t-=X} zG}-gu8Q4+U?4?yXn)jzcz$VM?i&bQPx{WLPZ2?w}==N=-wGuMj=Eb#d?X3;h$(8A> zS}S?t4<8B1Y@qnw8Eu+0=)O*Tf7;H<8Dm-o2-Sra8PHjk+DHlNpx^^d7{CN0h@im> zahc;T!@r~0bBpMmz;g25f*z9$ZzrGM2Me#ohepltH9(>TK^HX<#^#}BH<%K#kV*EW z2$ZQC5qVxZ+8+qZ*{(bRNYKVNZlZ{bp4D^yv;dMNRyt&nDlM(VGe9#96jmJkr6LfQ zk@oPsj?TnRm=ZDo7n@1eZ)8m1nTEXcUnUs$pj#sixSVd9`;GBy!>@4RAUYf}07MQ2 zn-U!dtIM+W!Tib*nmO6?umT=GEG80{|$;jCVHS!CsfafyFdUzK$4(JhPXfZzJE@H_ZW z;psqz+)Shp5O3ySMY-;J~o(5w$Eo*!sk4DB|ooc_Na=nT7zAG{OAG&fg?3iT$<=Kmr z-td`GT9w*)f4^okYXXW=h4#k&EyWd{vmF1#c^F@wAR<1#s))PT2#~w7w@)9^i1~lH zRf@MWjrxr43htd&-Dy5WxRX}(+VtVRhySqkOB8NmRh^3Dm$I0xxQ;3CA;W*MD8swj zbIu6wq&y5`YBI1I_%$pLi>nV{dy+OZ{~lp$eJuwdG&RInlHI1lM_P01i7POznTD3ywJTdgp~rCS0Eb3=~Cho4z~X<(L3UahH-w z_v1_KZ;WvSLQJN=^PBRqaJj}9(+;ar@*sJNpnX12c4c*=GBTj?RLU(q{~idbl$;U3 zBH#p|k`W01V|~3eM8t@u_u*=w#LBIo>$c40n^*KBhJ7XQoKTH3|p_U%+ZRe zBQYaJ;#3&S77%4Z{C)eJc+|s`;=J$?++Sn;DjVjnELiA#Rq9Vl9QGqfTDeN=Cz4cE zMMOo;wkAf!X$B}gzFsv0IDhI``AA(rfH?&BlN2tROVvuoA z)_|Eps|7Os^8a-fIzSXk#jZt-FL~{I>gHTKSCQ3KU6a+dxZTa@+nln+MkPtDYXe%xPq+rJGZAQw^My~x<7*f!sVOmQ%080(p|=yh>$;juq3h^5u})=b{E>8CJI$rx~3ovHt=ZHLikim#|zb z3jv6-5&Fl7?N^BH?1}_j+G7OgM}*#)o889yi0RgEK17hpjn=LKyw3lc4eOy~#)_UL zf6a!UWNMpZj>#kVEQ$8l5F1!Ycd3{D3D=y05?Vn>u#zkk<*<@v20maiR}3cmghs~T zJ%ci%w@~5UoHoe(L@>TldA!a(e=-by166jHN%t^!!@nB{klN+|_r`$1BT%e$K$YEzBXGKV&Kd)5g1C4m`rwL!OVMH6TsxPMPEZRFQ{fq1}>^9-~F&BApV-Rc@+<- zsw$6Sz_Eja#)Z-GMH}@iNXla?J32%%b^P77!LckLwHvg0yZhQIHhA(hlk$yaSyg_+ z-wD=d%SoS=)~PL>;dLVqP?_OzuZ%?C>G51N^4pp5{{~jFHJl#T$PJzKVIIajZ^ZY5 zCFymh1IyAJr|Ul!k9!5l6HPqsN{@S92mSu)h~~0iC>-~Ln-x!zH%O_uE>`#Hyo*^{ zPPPQ0W0~PDb`~qu8tijbUR*1@g*vB9_w%J>K!cS5rUe<{GedtO|E4Z7&D%`>xeX7u ze0d*RFJ(j3&MMy{PTYD87TlzAvaWv#z6(V=Vg*YF4r)4WHs74b_+x|+Er=E(*yQlt zJs9hqMxwv96IkVWM~Yv4qq{^r3tx65gc`VMy*%F*3@S?-N&=$c&Wadam*m5xhn%ee z2m)!8#^^hc{J33yw3wozzjQ58a=K}R;SwMwB|JooKJlD*$L)15)-1)1G*{PDZaQO% zig&jYGjJq&kL3GuO96!vD?V3Xs6nErKxq~1wCw(P%7b$|gb-lFHLWJr8HAf?qcVSH1VaE z$_YJvfK@P_G6r((zqScU27G$}{etB`*&c*^$0{F{Z1HVq&yE-vnPo__L##;Q6Z0ESIz0kFpx9Hm`RWEKLM?K_{cZ zy5w2-SM!>Zyr2cP!V?TdSaQ_4=AOpWFxQo1{DvylY#8H)dbCanyGpW)0{S35Ri*eX zdl(#M8|syMuhl=X2gD(SSxsXZ$xpyxuXrlaDtv!YJ*U`tVs%sGX6uw;LsqOD9Qjr9 zP2itm;KqAeHjk#+PACKPqQ(#^@klW=AXj@!ewa{Fok(B!qFgaqgL!6hL5F6t2xOSY z5c`8G;1gynt;Sk7B^UL_oY`Ad5{--50noIjCS0V(dDlO>O$|*@_G1gPeHtkM`4}U} zB7qdW6up!5_1+yGCOHL8PKA?tS4rvsD2|nHNDfU!kA{Sa-1M@Chxjon;x`XZzc%GD z3P?J*p9Y7}gVDq|o(pKa#A7%%ohIw9zn^frLvEB2(zKDvJ0lr-IO%G59-f9`)0K9b z4{3rA97#A*vozi)>t!i??k`Z%dT>|&2-18DuIfpyy=5D~k#VZV4F_hL6opE42uYi6 zwInIB9cjd+)rmCvG9=N)*5P=PFz)K|wwYw^A}m9Alb&jU=y4T{5ndNDIAI!Bog{(^ z)}oP*$eS=WgKo-B`nkFV;o1BfNZDZWugTb7H#0stHq}}b0R|-f`Lj_4K7Hq>1F-c1 z69e_EQ1j9;>)Uz`b=zg3x=W+gBXV;47YtLt7gHxr6lP(XXk-mCMtR*z7_K!@<;$4a zQK(2Pea;sbQ|SUoMduL)#l~F_bY6&!iC>`<+y|lUgqlQ3hCjOJ+1uN)1qcEN_k zF@Cf))&j@oA@20m55q!cfnu!w4B~S5J?HeET7Jax##00g(PIphpRvF-s?N#-v1#9E5B z8^Qy}iQ{bae?gqO9MzRlYH!xe#xET%K?+qm7yk#fpgR=pj(v$E+}*bp%fzD0d>#Zy zoH&V?f6=XDWBjzNxTWRHjoS$?GM;fGXT-GP9)xCi30^`^#0J^vkm4P1MU-d1N0$nW zHQEVufynTVd{mx_@T!|&bhc)x4TozKXazkYd0W9XnzNG$SG#pXhYtF| zYQDcY-izM(TB;!3$gc6^wOv&JZ7nLtxRdA-F)HS35X)rOYr#$GXP)txJYi@frAG_y z`hk20+%5QHp-H+*gw9=wPQ8W{o8(J)!QYnC(aS^2aqv}2pecI914Vn3!tguZaKq!_xJaj*RTJqE;l)s zMOJ@_;k2f5tzGP)AG-w5hhLmvH;(Lr^8e&J=tqT&v{a2IEW040v8HlmYxjCfM~Q`NYnY4bzV;+Uek_UWGr~`pZj+nq z)r~0}+>*V()4;i_0rE+M`< zgRDR4D=peNqU;B^(KCovJd`cILqIkE(QS9S#lL+Ju#eRdm zq{-q!g#5W6Hlk@TeGq=LR|E0CZz(5U5BkBFIYO^r$PYYbk z83Gf(=fddxGrgYb>s^`oV!ea1b}f9c8DzASd8ZYnwboJ zwvD}=+Y^UPqV%Er$^oZ5FOw7?CXG(I!J@3c z?8Q_sP_+de17Y(wY3Y3DXFe>0h+&CIXyB2<8NL~?q!`ZOMW!fLNMLeYj$$acu}CX2 zNcbxO9V#(U+VoIhy8BEYxXA%Y#L-9T@Rhl0_B$OpTvzl=#)O_Nk;iHcI0pS=sF*|f zjwBZ>?}s66Xxf#}8-W}V>(L8W2XqRLag zzoM$McLE5H+1>Fo%aV7~SCu+pmMm@nne~7zHw!#7l0rsTyf>N!R@{3B?E%R<;CUxf zQnBukxp!h5`KWf;Sawz4w~TB?4sO!-)gJO2Q)kAVuIl-r%FE${&ejeLP5a%yd;{Wn zffbR@A}gIu^QmZ}`>-QJ-bv&2@P6$N$_de7acA$n9m3Yg$OW zOURJNCpD7Js@9|B2=eZyi}Gd)JGao#at9SBWak>QEZYjMU84kVkM}D_-mf*$c(pdr zjEQm1BV8kjH#ud)(vsz*1b;B^omO!bSGb`B3^$7__c*Yf+y;_YU3`;Zlikz{~o}}9Pm`nVV za5y?0_ja>n+O?VXW_{G5I{Cyne%ECD+YX?WbV@A@hYkc}=2)i*azlOe{AqOI<`CmY zf7OG5BF+3MHg%O-|HgZdWd;gj-pUFxhae#APf5@R63MmN3(-`+-;II26aBrneE{bR zf0KTWiO0ug^6kH|3A&SUSWLy-g3D?*U1VhfGY$#ZC{^3= z9<%0c$R+7h9uNAyGNMbeTzS4a(g?l=<3mRo>IMqeU>{wzp-bH1z(6IGBM+N1Kg?i+ zFy_}Ektb%cJl3%EKpv9Bz&X!h^oamjK?BSa;%77{yv@gno>NbLE1U31q5O&pVt90| zT->OEzR@Fj6^j(3kBrFB48>u@2ZWuuii+b|^i3ThMirHWQ0N?45V7UOaD2KJKJX9* zNzua-rHO{Mjvy;PnCpeoNHSgifESL1;@M-(VK)ZSRMG-)0@u-TGFxV5JDQ>BD8<>RBCFh`9L0-aHRRFX=`e!Bc zJ2>^_u8t~ks%q&sqJE~88z)@uelc&usmcBO`dF-NepXv-968?Jq;joeoKzP2LT7kR zK*Q7KrnsmiUD6vX+1imuLDaD{AkI)p$aUmTWLu?dGyeZM>31RZrVd^rNAAN({2Ked z|6EhDNDp-Jw%Im!dRsUlzwB*{b))}AjycVZ|0iftw035rbBYLBq|e2~eheh&cuih& zIQ4RIIc>X1&wVx*+$QsNeuh5xV&r?L%qpznp?8v?Q>@0pApgbPFj@bjmQb^~ z2vhSvA@lhE5i)2$FB__zi*+3-CN}B3PK(xQE5Ac404Im-s-GeUpu)eLZaTv=ya}_{ z6RTiP-vj~H@a;P9A66xa{J$@kwfDERy=?!dYes68iy)c4*feSHY(VJq-~}s9>Tt$F zPu=g8d?gYnUK5bCx$o9t@jMa7{y!2YI#uL7p+2=4<$r#9B14>Up?2VUVlH_7BMgrB z$%)?wist)=l+*F0_Zy}Wd{`C%WFLYDVVi4Weiu978MlA#UeMGif6anGOy&`nIgEEw zms8aC^>j7dJ8r-ITRc8?1_z{_6Zer+Ad%)u&GO}MXuW;WR?8Hg-{>z}DK)j8-$1YM zSz>3PJKvZy23vd8P{JFI&$NG7y&J23&;zR&?hrvZ$vz_CFxqJyh2TC6`hj7%LHdy) zq%7)+N)+4QCb_rE=6WlehTB|=-1}8*qg9ecL1>E5YD5x2(J+|Z)%E}c8@PRdc`}>D zV2BV1vJpBF4vmQbY{E>L7gQ?`YojwdHFWr(%Uc9zhS5|-NJ*3J#$P9xjZ=eIz0H*( zLb^*BPEvA75XJ~*=ZL~y*gFBcVR>_sIfEP;=pJ7jb^W$3@>9o?pOa50J@`+T8CyW} zvMo^7toH7D0#jFAb&ieAyo6bhSSikZq5I*lLF}X4#eI#717O#ul^g4Nq~6@z)u?4U z@y@xfXHp_?09II*FPw*yGFT#zhzE0PPmm{J_IVf}E^X-Qvqj?yOzX-4sohufs{HoA zc09j;Vwyeq@xkEs&h|vaC)s0Qiq^iMp`I)d_1EZSShZYuQCj$)WW-hhUw>lo+lsrv z&-VB8%m~WpT(?$%d)@*1o3SnvgL{6;IflPI;Umo3C%ozqr-!3&dBbSyzHTyg$~h60 z^olMp;qq#TGgx#z zCm~Dy!Qv%C_Hd%myTIw@U(H7@q((0yN?MFJ9>iLQFKBnF^Xei|vSr!T^`#{09{!F7 zra+r>&6$>fVb``g zqeRSLGypm)DH*>VSH*NZmHnwYjN7wmhcdU6 zu+6Nf1KNEU@MM?GIZFWiMJ*;KRB5{OEtl%KmVx(4+m${_*JIM2^rsfEG;7Nl!5MzE z;uz1KBDVSoW3vUh7ix~zs$fPsXze1)Uk*Z35l|VE6y7*2=*a>25;kcr?SV~94wIWMQJWc! z428;Xv?_ztY)}le5X<7QNeyvAxp6Kz6v z;!*!nT}e8F{myuEU(5^=g&-tKISa2nFTg>r+#=Ds&Dr;4f|HnCQd5{1Ed2?61#N0;H3tI{R2)y{!#P#0@%(C=@?gS&H#L2( zirCAB+j}qPY@=9Ew3u*x`XBMnc;Z;iDO}>&)R6tT&x68kQaS7Uzdb)FUO4AC2b}aqD9J;!bkG@EjivJU76XlS590N+sH@jOBQQcS zUfQ|2l{`Xttf5yTO9F~~AAX8`TMWNV7S>%oupa(U$br;mX1~L!QJ`*ojxcolFwvo_ zD3R_m>X2BYm&CRYi0CA3pRD%&!1bmD91Eb#nOd~zQnS633?+K_(wM#B5Gx~HXdiG8 z3!uPApiLVjJ{cV01hcS)Q!94N4nF%tOpNMg08wg*)9afFkaKS*LT@!q>A-8W8t3g) zYdSklO%}ZxWPoDpn?ew$bKhX=Bi(xD+4ZBx&cvBgv}wOxpql}ZhZ0K$t&2G%Z;tW% z!!enhG53}q|JS|GA)(uIfj~EYbJ`Fji!R8+au-A?U*G#Igqi<#=^zBj$skU-9FhM# zgJF!*aF4||LnbQBw1{$I9rI93w1<5w559)m zjP2A0M1!$40%4!H{As&B7)=$Szdu5Qe?^?t8Sm*`T=KVP3s!Vp?bP z4gtsNPl0aD*vNKqQi`JKUHzkUOlbg}V{`o0LsCCdXN)ICI;b`v+&Tv<_zfpp%?je+z(K(B*^lA;}}xkQXC%gFMs zT9&E6$kVQNYwSN&W9U9*o83R|l@KQu%F8L6ciT5s&M&WFr954ZLvp`?3p3x*tb&#A za^q`00Dy}hg_(7=U*r&|P$%vX6 z&FNdoc#0o8#orXXUjZiZu&0Yf`>tWTMn)+f0ZjcVp4>SA{`Jl17waLK%v=vip=*#V zrpKAY8QVDkrHiuIN(_R0v~_~B0d4gnor9=*2SU>L2gsqo(pnrzaoy_sZG9?JA3git z(Vj+Mr=~Q4c!!3#815!8wFvUHGb9qV)x}I{=#7#^pxYaYnmqDKDY8a`CwD>wjsq~& z8)(wG+8I2n&^DP|KYip8&%gKv2vr3bRAaIhjps-5Q0eX^licRuT&?6HFm;zlClJU0 zNSO01kLSXpwg+@JdMTSe9=eQP?_eVJqnVV6PKL4QYAcf7BV0#nicITxDb+fEDWCp_ z$eJykS}$S5m7;L8SN#CnWmjsU?P~KxkLDoi0olfS#^}~U#i1ZhMj?zMrsI@!w=KhF z5^*}uMM7AR_W|ov!5(*UvUZ&lVwcSk%~G3fkTcv!7nrPiO2PVSgtmScVJVsOqPZz| zXY`r!?H_E`aK{g6?){G+`)0~A_1nK~Yd7iZf3JLevt$44ng?}9$SQGOY*TPweno!w z^|h;+RcFbdt~q?TRVKkSrA_#*Kl@w{&L6=G?)F58hp7EC!v_Dak;s>sm~B+gB1m7* zD0JCYXzn-|Ssy!ok4tvP>RdjoK4*WXW2UdE4J*jX_4vz176UP@j<8AA-608YZ2*(6 zeZnX@NDvwvZOR$c*0oNLT4B_guzMIMXp{W&SyOSBv*NoXT5lcs@0kB9v2o2Iqf?dRsvMl!;s39{<~u8!w=S696fe(n z08kkt-&^-VD?Qoy9O18t3@@J z;o<*Pi4{t~*Q~v(?}>{UJ`0QCMMD6U=*Ya@t% z6du7BIJd^C8%qpZ!y~T*?(vaRLw)ik?V4BedJeu@+FJQ~9t!*g}D z^QWoPH(5@;>)P$PrMC6^c9Qsj~U; zob&|9h~N`TKNZCZ)xDOjC14T*{4^a(2$A!qXl4BIT5A1{y|9$*ziD{?%>Pvk4vXv|`8HFBWjF5${qY z*e;W2CDgpgEj}dJAmd67C$@PDF46ej(c!5ffZ99?y0B>l z#LRall<6^d%7@&kciigNZ5O}-QtLmyJ-2&LAqS8Wp6uRZ-M3 zyr_F@F$6RQucYUTXN-j+XDn$Q*bezpQ*v<)L=<+dv}v?Hyh~L0m-pl_HVU7KwIhv( z|89N@oN!_=MkG7fUS`$hrP&^dsPaKujN;%)B8(4G<8NXdGk)BsxD=G}jQ3pxxXW0` zy@pO@j8uQjUg6TKjvoO!TXpDIdfc>RH*<1fUwA+G#>g?B;{K~?4#F(rqTF!4*qG4< z>Zk|_LaZrM#yAaPqDMjL{^!())a?#@vll-oV1ENt=Wknk*Yim?PNo}e<4T0MornHE z2JYvd`Ela);@k>}%f!CbV%m)bucn&4%oApSU8HP~V-`%k_-1rA48 zJGJMWdq{WkeNP~5i^qj~$cD}x?=Wr0zs@c$0fX}=WpFYQ))~Y*icV!V75f1fYGP>I zhciSFa&54f9B49%M(2S6?$^Nq7l!`Qi6s1g!`IyUCy2_Uq{<9V9z(8-{V(Gp)!;|B zTm}2v3~!nWu&j}KXlVaf3a}<76pLYYwIBfI?tOEZRnzEqX4}gC!V`AOO<$)n`|lTG zaN$(nT$pVaJ|Hv0o?q{IK=fDG6N$*bq&0S3X?dT3*c+nWDdl2&K4Amgs0;9>Ij{=TXFELx9XZ5 zjQx~iwTWLRX9Ag}KwTrP@9AkAiHWUSBUm!-HPC@YD(~@(>!Zs!oEx+pglI~q9M5f_ zj0Z3BH;zZ`lGIH|YeYfXA*=qC6Rc!TT^a)fOd6TsPyA7Ow86r`pm(>kbH!FuvJ)lm z`$@xZL$}68sW!E-o=x6>MrM}IS+5}X{{x0VdB697dimuDS9%~^w}FBmqrX+5e5fQ5zF^Sr?3;&?vaLlJ`d&RRL2%6DJY zI4+7ZBm$6JfXWk=n|k$R3J-pY$z*=~YER?-(TSeJ>E%K6<}?EI3e?e(Wu zPw3(%lzIK0ax#VMZ^dLX*S)o8lkK^yFE@rk8m;NcUEJhKuEwXF;Bl*UHr9F^2Fb?J zTkv7;P*3r~r}$tQruZW{62H^QeQ|zaotq`JSQjg!i|ua5Ube}5TOTM-2F24)>q?=x z?4Z6%V4|nbfIHO#6WrKB0mX`U7RXsN|8ZtCK^QnVjXFXFWgmK9PG9!>{_m7R*0n zO!4*qv-hU$ZR1M5_`Gd>iW<3RlJvD?$y*Z5WY$Uj9^CCOci|&{Nu@r!+Uo9x)wZIu@na6HZsGJTC$bKBp!CvKJj-vrU zrmr=gtC)Zk`_aw?!x|tAW&r;V$?SkILQ{tt6(%Wevy_WBr+C~VuCn2&6%*UOQsHj! zEwNz8Xty-gQxR{_?WCULqT(}{y$p`FWjst77RBj2VE_cq%DjM4U__kMg9(X%YhMw? zK!(!th=Ra%6xl8*IE;c$tC=)hV0M(xm9H>8mV39(i3q&Jpe7!?50ULi$7%9HhUb}c zS8Bg|X|#XEr_high4#ChT)%YKp0PC)Hb0fYJ6Xa>gWh)Xw~Xye(_F{*nH^3C`DORN zjP%PrO+3rlH%8Q7;X4`nmwP2bJn~N+zu>7637C5)13|Lpdm|<=gGjUq(ufR9y*fy& zkH#AnBA9Dk2jdi5D^<8)W=fKf!31g)nPW3igOCavRAtP_!OZ#y+-T(ZaS#hMU$*6$ zDgEAzE;J0jI>InhT@qyoI?Pa0EgNZQ4k8t3XtFjHY?x^!6>ylQ+sse~U5@f`bYNO%BX4i*!XkHjlgzYj* zBSXrnN#NvH{eMwH+qacSs#vK^A*?jMI>93&*v5D<1$gNT;y7GT_YRr-D~{1L1ynjv zGsoIhv}W$PG)0cScPz=eb6e7Gb>j-#id!=45yvLSt(Q~ zwqkKo09;gXXBqcPn25?QYAz)eYL(#vaolBQ`%BTBQ{<&=Zgw)8HW|p&ZJYE_$AlJi zGS}`x-ON2!{giQYaYu7IW0Ie7ZTQFmB_oPdwAU~zeVPiv$==6WA-D~NAobu@HGwsP+fH2p}EyDRS zoLuAiCxPeVWLYXtR*llt-?LfwZx5!wtYLZ$(`%SM4W<{T8~eeqpOLuCD76|Gy)d!a z4>mtZinJoiuLd|za;oV!H8QV}dAgT1GGC359eKkJ8)Nu4AVUan=!jIcV;o{YB0q>j zVSpWf1Z*4<#$0T-LFOp~dHd!tBp!5HUE^fdeOn0s^&KJnI)JCf_z#Zp z7YpF&b~=Cf0KW*2;b4*pnn~huj9Bd#@Z9mO5F?sBm}d=XKjwaY#UvE~EsEAzzm+or zH^1+2yvm2Macjf4=g!X!ukR@aDc$Rvo0SIC`^R5m;R|ZB*XX(qh=20vx}mByQnAK0 zWK%A~=B|7!lP-hKx-5joD4BJgd0G5BoqJi1U1wj`ZJYU*rzadtQZZ+jtC?xnBx*L@ zuJKN1ySs=6xJ4(FVJ|)5an?JtL?I%cMR|~b+wmQ(D5SC?)5x1E1XcyEN_$HpolDpGZzIg3Q*)gJ-=rKINcIyai@i<*gPR=v=g!bh&pWJ1jTi8?*1&wbiqj z7uM{Hr|9|vML6;QByqL81wjMrq0*aua@CS|1jy=$de}^Tr|(11U#rZ7sqPfrlMn-U zbwz^uW6S)bn?P-Oxq*Ie{vmHn&~FT_chmTHS0()Ust1$0J|XE#X)9*MyJp2^D+#su zABJ`CrET_C_a#L~dA$NO2O+tlirFRRhht*PBuM{Wa@_*owZahHM68u$>8B2DY2=Yy zz5ol~zL3fP9}=%Mz`iy1PHn+q|8IAjifQh*?oyto8gg0-dey_V%mI?arpWd0_Ty1Y8u*JO-G}hg$05 zGuP09N%zH2w-bk5G6d5itT^vmL^X#^t%gtv!d3J?FXPHhVX$PX3o+NN264{h&wVvz zuDiKTO!wSwC;cdN($49HoyVP8Y(1aq;w%K^(|w#>^XXI{Cx7sxxHlIJVNCFQpUXJA z@AyOV?Vn`u<`3iDAI)|1=Ffz8_g;5icm8PJEa0EJH6NUUgf}F>wwcj;&kbDV@K)~gbaEvzBb~>+i zw>QmlAJH{fNkyHV&9^(h|uI|X%QKx!7#?- z5(~L~%1DStSO<6(eLY8hjE6*&Jr$X0oe=0-!m zZ+c%BNoF*2uyi$8O4#7MILQ%?2b@qsF6ze!m`>#gG+44XYP9rVXsJ$vw0c*L(Zhul8!(c9&U7Z|4l#?gF^&!Gq3g+_o@oE9S0(#qjSpKBDXPFB=))qt;~w z^II7^m}F(EXZ=#VdR{cAtX@{Z*N+6m39DCT^fh{`ZCy2fdvN?#!?RU0tL4rFE&|WC z9~z$3vHnlZswNps-wH8ekJhHPFMB^X1`~ttlVDj>T8U(wnff92$mOG@{)z1U9Z~=7 zW5K|+4fBpsFe$qysm8!H2ClSWY7V6w&sL}4&Vw2uubSg|F$?BSjgf1Nd>ckbhZ0wu zChU)$(YSww7!ExYUd)fr(r0WlmAm9>nYtei_8mCGAr7%`mEJJ=q>6E8s4s-5i>Z??Bz;(>Mh(D^ck6S&u<{=N&Fw|-@~avzKUTb4EQn%{KW80jbm+M5TkMjnGjRt4-}>1VpQG?f zhXitPu%Of5}R$pi7(}^VeH1Zx@(8K$E zfm#+g#&tI^|G_a_o**@ZyAvaLZ2+&4S&hsdD>BPPIV=Rtx(^-+Ttlfcnt@+nx1&><=+w8z4)&++>$j0{S8Q$KC?!gDqy}99=%dP?0n+m2S-c~ z5A1#{tK7`Ut_E#S2()D#tBZlQ2TzY#gSICG+OCk>AJU0`tDaTZfO#7eXz9^8a^La6 zzz4*zZ%tMNIhM%ssjGm6k#8Y}Z)+iRrz`~C9(a#-#7%-{At zfY>7cUP_!=si^(@chk*UqquF2!YK63V8u4}NIN8hh%$k@0^WSvA&M`r=Nb8p*|%Cx zSv5T+7iO@SqVnMRU~5I?i76@;3ByRRmq%-5=8$MV8O9^l8ML{7h#WTx@uQs)Y3PP` zY8Wd5+ZUM;<2Kd4Pgs9QB7cDpnunec5fLmU3w$CB-tl4F%e3s@$+TDrCKH=wiCldT zJTnQpyx;9|a7PS`VP6;?tca1}@F}n|H6qv-Bf8&NI=q|RGsf11z%(+?=o8pR0t3Xu zf_*it`<<m+V^rx zvbMynTA1gnTrXxg@AKeCv1>!z6Eeh^>g*$hbS4*F4FlXmqBnyYHFm49TaDf7GuSmG zgEB~#3*uY^l5K50G$gB!U_VVvc5BglOChuwaaaw$OqWWX0Vf$n9T``nFKF($eETzO z!(hU&L{INtzukNFE)T;V4x<@`PEJq7n^&(p?>d_`dRsa4mJe-P1isa2&uj2@d*Dr= zsW=$np^R#?o^o(JtfC7_ZD%f`_Zx~voxdIr1y7y7mZ9KkpZLf|pwt#cxMM(DTNED` zrhRC%T4T~x!=za!@Al3DkaY9qLu1m~qWF|RsbNu+7cPd#7Y4Ycjf!Pwf~T~&@S))Q zz;uFd7u`ex@S_?w-#H;=M!eEG>|Ktalu$J|y!R_xn06I-B}UPVeZIc0rN)mneuS07 zk6DlOLilm(!LL5A@#B-mkHSVL+&K3F9x3tyce%Fi8Z^G;#Mn3$9jyUl31BQFQVkaG z8!Sry>x1L38Yk8`vBrtF<@;U?DAu>f)Ijl0f#UMWZElqK2#kvo0@deLsx6CID%D8w zzLDZx`=e{1n0h`lP_&5aqJWBZy#S~xMIGG?>e$@Qz>chYb7wQR@C2~fF+?5mv76%y zafpfR9DJcDsyEF@RW`Ji%9nCZ*Ix0}0W-kEGEXhGKlxdfVPZ{Ky_rq5v)7ndOw zGZo*NulAj)+8gL_kAxFxnqKz4$$9g2ot{?U`SNZq z92!~ziwf@IOe+zRy8SUmfnmtMXKI~^P5|!&@J^JGZbUe-C_{|)5toydL|ZzyoY|a@ zuUUU&JqUR|;cEu(_h+F>s+%QrSvnVD$u!(ERbrrYJF8{2HRF$hN7Tyiod#UrxhtfO zxHg~HrwDUPwf3Z}Sj5djs?dW6Y}cyLBX*;dz?OxNzUA-Hy0vUu3ICPB9Hl;trv$~+ zpi?QvYCKlsu^$$XJ*$Hs?Vz$Q!L zq0kwP*{Nd}^{K{6j~XjEIu1k_Q>`G1&yy{jBcK#0%?O8%c$el5<8b^D7I7OoWJNB) zMWIoNxXMQA+#1z(mZjQ`2X{}m)y}Q3fBdC}lGCB2IfGoH#DCXG7MAU14KZtod5aMQ zyPX9P=F3hEF>8pqLJ%{TjB4Tyh}#z&;1-?bw;xx0viA|b&~ne{ePPju#8jtZvOus4 z3a4gNK@G9)6=Kz9yc%QG7;9;am32)nhOxRe#;P&aDq}2#L;HkHRAd)Ak{LL5v>L!siD)#9+uyInOj{l&MFaum51d|ad_!i z7!Dk2ai}v{{Ji`R4+8JiHM+>PMBAG+2COmQlJ+%f_ie>2u&oaM-X~g`;kZFHj{5eE z%ki6=*0*n#U>!F%Gr-4(gjEMIz2QvFSPiUdVD%J%RgEd)Zrr~sa1l)Ly3W{AV~ShJ z_DJo16xe8)LyGw*@`nHxD~={kvCrU(r1aF=_i7|jxQ16wLf1&5MiLK)B=Rn*g`h;8 z@t}qhw*@6aY+>gT*O=m-uJx7Fu5m?;E1o#6SQ*#P%lz#OQj8{N?5kZrR)_+}AJrZo z$k1^mFja24cNc(E-Ohtw+g4+$d%#pFvfRyG95TbJhA(|r^k&KXem6_*;;3$G(aSjU zDXi`n$>|SP9?c2KfZ<3Fy@qnjLAi&AM>UMAq0H(ynihmI4}P&&4P~AZl%Yb((LTPm zFt+2fPJP$$9CnL&GVc>)9ICOXd#>OEAItK=(Nid>2xmuu>sW~4J|8G$$O|4R84vVG z;7pICgoyjMO+*s0J{k50B)Z)sWcNwF&k=*qLwGC3040<=xFgDu(8l2-CL9^UXFh}y zvK_9Lj&K~3fs4J`;JdVzP~VGJD+)ilqLA|=FQh5Fu5F&RqOfch2?;Sg%n;v`eG6IR z`%lz$3r0r?lKTH7gOxWsepJMUeNOCIQa03}qHsOmW9o$(RivIjJ}>gCd=__k5$9II z*Q>n9{~h6Q0*C&{@o(j>-G{zrDMyWaOk*a`O)H^$=6D!rfPDsz4;Wcv;A~}`cN(NC zEcv$1b~c+6{nhpYcyhBgJlA;gHVn^LaLN9koMrayC=}QKOmm^%y)CpliP*Pq)OD;} z2;vM$#MF(nf)R7(_BbzUk^)Xn9Wcjp{Lyr4SDj02gd^Y{o zqY`0RIUksB8;O92$Z?}^i8DG&d2Q#RH}5nB-rqZ<_w<|f9}*86>keO{$Q4rv!K{AZ z8X2$nxu6;yo6l=>T%+SV_i`@=kGE=gT*KpAhR3rSB_B9?b4H{l;U(xn{h$WS!-NvN zFpwdHF@~!F8{9QutHIjJfi=_no{~HF?0kRS&8;hWzfzJ3C2_tN&te(wglX6l=D?pY z3kHRma44i#WChQ}}iM1~5O4CPQ6D&aCrgUnC`o1qjs!xZ=oWe^%N92csf zv`?5bbS!0Irr2NnAX(0)3A5p7sKnAR9Zy3MrvCN~xj1AV^3e!~nP3386+8_Um>P<4 zH5jk~Oy~d=7#k{ZHdJA4sKVQj!rY&XbpWT>XB!z9SOm3UI^2c|$PLA?8)kvtkmEze z5FCnOI8;G#sDR^83dy0G)8?Uheh7Jp4n=#p3I{_K7KREu4CR;@O5uBU%vD%mm4;FH zs&pKs`!x^up#t(l73@zpRHgyd*ty2eD}tS~&u#}hzpSw{)Y$n^VrRib7LN!h$t-n? z_&jIhh8mwgPJDjIml~Y#KWdP^@*q8TP9AEEUSsqcqt_Vyt}%Ld_f9~1(FyJvq}L$* z5rA|TG3;BDC8I^UvtadXQ;Q~ntnjS^OX0H#GpTWb_mauX;32{Do;ju(Iaea*6s;h+P`pOZE03OQgLe&} z^~)MS*8tjl_y9pEO9SZFHGqa1K(8o(t~Ns3A>qwEk(llSIhq}h^>s48o}C@TDGo1<3oz^3WEPmx%xyBsi^rUmv6Fgmw^zly z&R>i)Jt^Z>vdrtGjCE4RC6Y3Z84LO${xiaq<5KVmi(U=eer(vb zGQQ_-r;}S*LY(g=Vy?*f9O3{cH%Gk>Nfa0o#v%c>|ADfYG%1>aP87S?VtHzamkeKv zhBh#>HY@?iHp0lo^gs5GzoZw9*e~T}b2ELD=Tzb%EYZmx{9G`$2llHU88T_@)$7i% zlY0FDQ3eP4?k-+t`1Yms{QXGN!TWZ7G2-I@?=jy^;Vk*| zzzMOXH~#ohv*VSsUzgmBuDG$*PUhB3)|1NK{J%e%iNN`zdGm+Au*Nc@UJ?tFhf_*Q zpkX!HT~weMJ~G;;CG}lR!1QbAbC~xYwZeqty*w#uWw2HT@1~oprVQ2^L#;8y-MD*= zA@yK!m0`EG_dh0;p;iv=TR9M8d1R=Rw?=xV)0OB{ub5QN-G3-qky)4tVwqn`3GOu} zl$A)Og|5m_{yp9t8yg>;~Svfv$Np(pVvzsiz~%7kIP%iy`x#|Ng&! zG{63z7fRr@e=#ef7f$dcbWbO~Rm4;Cypy4kSRwSk)c`U?O07QQSy^$#U?n+>7ZJs0 zvZ_M3dgp6)FPld_Uadd(`^a_gcByWbE!B)*Sa7B0J%=+a)Vnl7-psYQ4aoLK^LhK1 z|L?^@%eq^&tW&cxZBeHSFTbRxFWlVK0eamkMZI+q4X{=9RoUVnSXS>x0qBm~=`fr}>K_`t>(QcDuP9KrK_{Ids?g^oWG4?_HBEZ6fGs3IA0cjkED@c%6OI89sBGb#Em@M#y)>xo1;7w zkKi~i3bL#i+CHIdPYtDj1V=+Db>Z)duyEzLE?6N(3v0T&)7 zIR=Ed82RbJCm?|UN0v5^{)d(jd1Y;3QQnO@{-_aOgQc zrf@aJJ}?3y_Q)j$;@Y`QW-Q5MId*pxn7I1^&%&SfB{M1JPgP4iSrbXa8UB>C50|o1 zi}RLlh({HxE4$csK!hm8XxTG3hs-p@VHhK>TB0NCu2-AVayC_;Vj$0arLOqYo~vLK$Z}H8AdydOtV>mhj88_fV%DIWLCmVHWO)+rLQ@>Ql{_xmE&3&$);vHRa>Qm zTx@v7A}lXg3dZP78RO!DtyGB3OqTqx7TbD-QgAwb?nSiCBaBl#LGsIpj^87Ouh68N zF$EDFk7S`LtuIy8oQhlWZ3Tlg`>{NN&vdthJsQR4;f@8oa3=FY2|-GjW5LAS1#g^n z3JQ_ELBHjo{pM6?U){MXd|%zk834Xf!M!rVJQG@I?<^1VGrQ@5m|+g*E67R#`8IqY z$cDGbMZP7Mm`N+gABC7!S%Z#bi2`oHK`6z5f&e1QyQ+%9^ABi(LwIR6jYDOA&9lQi zi3FdFil?3~s|Vq>?l2B(Z; z4i8QAwg7g8(FNx*ob6KLVZFQPIt(Hvn5yhjOZeei!;tt4`*veZ0+`HM*S1 zGom^N#CIocIJ^!x<59vOjDt#fK~Wu-j(nsp@j1vB9fA<~BTU=ySvtLY5TdJf*zwk( zJBAhjSE7{po5gm}ktoC5XYcvw^$j2mYU}_$(S%~(+QOqor@NF|{589sNw+1e; zE?PR+rU#qj!jkBE#*(oKz6YCEl4oNp3LVC2%7 zbvGG@6xM1eE#Ta<2W0S1Y_S&a18zx(qPvBy5Xa5&IXLub#8)1lS@~8}0v=-4SWKN@ zd!nvW@&1#^&}sZAafB*XX>6K3+jIQAz%e1JV`B@2oB+u2ahMr`TIH&gYR>V{D1PUV z4YfNjJMHf4b|)EP5os%kTTEU6WUP@Eq`T6BR?8)$wu>*Z`^LtDXk@$*vmPKeezU<5 zp(`z|D2vdRF&*{%~jG@q%b$B2!4oT`W~i?#uc z0unNsZBI>0i!YM6GE486V-hlPnyRyz`EC>jR#o|Kro0MOsQN^&Ny$w<3KMa*yK0H1 z7!H8P%gTX^bsJ=z2JvVm%dGmIQ!QaV(Lg>n)T3$qFW(*6Y4N&|NPF>Vk=O@;%mYgv zRr`ppQ&MtMl1WH~(}`~ty%cQwFu%Coe}2E8URXV7b~~Ny;NE{eIDGr%eXgj7>`R;Y z%*WV%)76#=89GOMpaqG#Xe3#j5*BbByuBl}a3P1)7x~fiZ9*c}gDt5|uE9ri?Rb#~ ze&h{s$T<$L!NHX4s1`>6HeVZR1G^I#Oq8tmiH+qp^bAU}9=s~8TE=F^;{XrYI9+>y zLqHnc`}b_}v=lr?8K#F@}8;^{FEI83ydIu^_vLu7&Aa^864vzF_bCvBR)O z+o0(#Di?M4Vvd{bp}7PUd=-^*p*F@~iJmz=3?__2#y!FDfkwlja}Ce`{&pQczFmj+ zZ(j(MJ-`~Owq@n24UQq5zi_I24%pa*F92p({6nxd2ZUfY4sV1BY7V5{DB}=)j?9!1sv? z8<7fu5kR5whtQEE^9Usm23yzEmf8mvc$JEJ*%&cEuB!zYg%BfK)*|dr9LNfjolt~4 z!lbDVi&dx^E#4jSm|5nX-sF7aAS?Seaf~6RaJeR4)+i@zYYAnAZTXXup`z**uOlnE zlztjQwYKcc)X^f9~Ul0!JMH?7?NXfr23Z zbC;`Wjg)Z8+X&!zClq zXCd-wfH)ZHZ+AM^?Z6)iD^NVh|LwM4wL7g&!{hQ>tLH7i9&+3s{Du56b@2GVM*MHy zbOV&g(XW!ip&MBj4*oBT^YK*KkjYmKt+a?lcrL%Mg$C5pu!C^+&2Q>IX@m>(@g&qmj z<8%O4K}BN0HyR-hT*pGR2i-2O=jzLt60~9AXB9I!u7d?7jwIXw-w3?Va{6r?W_V;yPT9J{o=^ z>^Q^}`%Hk)HDz!@t~*ga#|a=GP#B^KhwY-p(h@yt1)+0^7;c4l z%GZ|EctglF>JAo0+Xj<(cFH?b=@IVDIoZt4Vzr~ENUp-qp9W(5U7NP^Ho3~yLb=;~>45yO;K&db^w91|P%e4j9(^w7o{1jIHT^x)f# zD0mRBeL$)5sGzX&$MT6$iv`q%14e|7XDOS5&;v-sI0TmJmO6X$`~yL@cG&8#U$lAc zBvjvn!(;_l4jXHIPk*lt@f;l|AHyk@{+YNllK=||FF-X36SFHgOtclRqvB=6#d~WM zIX2!ty09Q~X$x6g!Z&sJiqVgl?Qm{HVtum(Lh82gHSz)%w?*axK4AWtNY1e)Z1RTw zk@}#;T&lKBQtg^nkBjPV7`C!+H;pxrwsP8Qh|jDb5_*>>|J1s0ck|Uphd)Zx<>|%w z+>5|uNe6jwiP*wvH}d&5Xw1N6jOF1I8@Hrk%pv|pW39oTNJ|%&N^0kv5m#khTC`1z z_!bUW!rVk{8=SLoz+|^r+=N)F$)9rCcpG~|aVCFqyIqi#2v*C-zOjZ>Goo9_XHH8$ z;T_ZePPmE;1Bn%N3#(|4lE4@`-v&+$07|KsTiIx?a3ijzB8%iYS5X_{tz=aniH!{@ zae|TkTj((S*|$_B(z>OM2Knv1mNBNUK`Lsf*JvQyb9^aJ#6RVOV?^l{32hPCMf_2q z{uU(tBF}&!m*LPy33l9mGz6W?H&U~Td3;9mSL{*%&7r{}&q$Iyn zz9h}nV{ednDg2$9lV@Ewssrk+DGSuVS_PGG5dGPACvh0Z8t_#trL;(qM`1!DxI*H3 zb`gDnIgqtw(AJg#5{}~ipqO9~l1qoH!;U}NSW8#bF#gmM&UhsBStYzo^G8=cGC!72VxMSi zF5GM=0jomy5vPMuluaP{qdK z(&W@oSum9~IOoXaJYMx1mnhtDok46UNIuy3Pu+(;C)(fSbf~w-x_im2s5f!Pr%X;< zE;BXH6iJ_H(vfg)Zbn7! z=)Yr(S3w~y)uv4*Bj9)(8pfUku-b`_aFq98SjwvgLJqY%oB_=ta_U&xRTAy|^H3<~M( zAyP46TYCxzlY)*=u71UmP^|iO5m@Z_Fd%H)PF4r+g7EAp6yJ;Ih9UlM;Xae9K-`)3 zKPji!cljFNWbe2B|2_TuDLp$$Z?f~GCFpy(IG#}mLdQelBpni$tV|`*9UnXt#E8No z{v{5X6z`7js3@4J+{p~I&7faC0$tScot{#wlrkk~QndS2FojD-RKF)9!vq5m3%cCb z>P;hNK#EZ+*&G)$UJ1<-xfAACs%O?1TNnKy3Hy<-aU~vTmyBc)kJvJ_gc6s(P!;!m zZMKS~O4e*H-1Or%@`*q3NK_cbskmZ4B%F!Cq3tjd#!n?1{m8-D=Wx^(lmFph?-=$X zHpV`4EMx{csj4M9;&@_6T$fyNEkdmX;)5|w$wE;pN-mKha$I365b;}%bajggWU!=- zf;JKCNQE&Vf@ z2oc+SkBfj+^?>h#{usMl>1ngTO>uD9SJSG)DHL-L!+R;H8;>;(>0e^^tnu1fytesj z;a_a5r3sMG|6Hq366T(ZNLgNc!ivod847$WWk7g}##l^thQz#Xz7F)7aeP36J)iT! zEj~}@ZLUnFnvWH`b6K0{j!Y~g97tSoIgcm$Jgox>UvCWKHL90AZs?U0x1j(0-cl>; z5{Cmqao;7Q5g*ta1-<3l-+z|?kbYHW9bvG6H_-GZVp0@9Y^t}yl=cR8w|3Qoh~hq_ zuC7*T1AO!JnM>h~p-lr&>h|e{6Z9`}=nN;Bw*$ww`?k*;j~x5WztMFPz2Ry+UAL__ z-h_lB{tt_ISxIpE@vLAkWR~~(OlzBZ>~@wluc*QQbBha-S2uk@Uf>CZb56K(ff~-W zVW4bf@^Pvd5~Y7z#1(;FYK;z^k;egoq)>dWNLbKB6Jm|ZC9QJg*#gLlM;u5?t>j(-cVPv0yYVWTT}BSCbnoo4ZJ9#by0Ysc7p^c@_3LI{c&kkxtzy1 zeudbwAr%TUCa$d-b!A#dlk}z@w86Y!BlRw&_AWj+W8!BSoi6^ELuelLuhRdo;SAm2 z-2Jr8uGu1OOo{*5-rmXh|2I2Z+b?VX|9$+rZFrBFJnQ)E+c#*-l(p^H2o5(l&$tK( zK?^nxcEiXQ8W2Y|G8~S%Fv3iW(pD=m{qkB*Fc&qr{V9HWbHiW6fVrt9{V;M}k*yWl zyiAJ#S7pTkljgU!I7=Y<*3#X%X~K6HAc}Xlq1CdnMQjZJ0oWRoMq{%r?A7nn)?a;E zLwipz9VD@qK>+1?Y>VeNH(Z}d>p2IXPNikQbe#%1Dto;o&J2TWmr+O<2)}*fijnSC z=6EmM2$$u%68GoW9_Ex!3sit)-61WGfafL{%+lEXF&?pYhMIZ_9rI zb}3dR-z$%>CiIt+4;)NzeV7^Rg_ogRYZJKf$&@p!1o*J%#VpJx_IVK@%=4M8C zom;x6SR~MaPoEDC`^TS8&ffg|++3G4Ey&DblVV;|Hqe zKxzO-Oa!1abb$fE5MP1k_z}Z2js#CdBpe-UFVH1&T)w8;aS-tTkVtIRt0cl#jFKyG z#+rJT;y;(xjD)X7BXye>w2`g=IB|^9%YFGI-bOFPuZc2o;+y1E<0pPd2lTSyV-uIGV0Sj~OS~*YbfBn~g z75i4$Q(Qu^6p6xqEfQ)1WNM6mru^WVjYC1^;zTSy#!~ziR|GS&pb^PzW{JwqL_ysN_D9F8{{kWUnysWVzBgNvHE#UU*w-1YbQ@fHOyJK5xzd7$0_n?ZH-5vic2S=3Huxwg46ubF zie)~Ezo+9^>B&Fr&k^fRV}tR*FQlfI^& z&fUQvbbL01=D*R_ztLu#XeGsr6?}tT+%OBN+IkipfPu%JA^oJIeKaSpC&Z>&BgaqcE9VOUnFDx%R8Sw8}O-You-SatgW$L_w8G} zxSlIxcOg7{QC6RVhv~JEsaaoLlhbbsD=An256#6F|IH}>l|3OOE}s85&=mRK-F%tJ z|FpT;t?hsJ^GjQoRAP0#zYLWkvuVQtvh-HHxoKQDz8weWpAZ)}%-Aha7)5MMLgz2x zNNZob67jB=-Goi zp^thiItYy}*3ps(V_AtAa?EvXM*atRF0|o0IKGX22HP23QJ)f=K?QCZ8&S^*2@|#@ z-DmB@vlGu@zDN=fY0R^@@wV4!0SX*(iiY;!_h$1etUnZGaP zjDz2siEpU+wIMy@;`s=(<~lTmQHTFS+#LBe;m>g=;P3)8*^8Yzl`plf|aj<_mtc?8A$7e+)@yVfY-{7Cb@u9ii zEGn7e|K=Gc_-+Jb{d|EZ>+rKY1=D*YB*?X{E*YrfJ54=?-@knmpTW(|S7qCdYr`(~ z*5&{Hfm~jpsyZ=)ix&i;PT7 z`d8$j$uI5vosoK+t;`u*DYT3uxJIhZ?0MjnfXrq6H4g))7Hx|8w)5Et=LiurV)5>J zB!&df6Lt8f?PonD`L&WgGBEp+Df@ED%9(A+ly;PY{7~l->Kl-Sj(M9R4CP-pA{uTC z9Df7*mq2CAJH-rII2y*AX$DGU_VAq4$bBylt_Ims-i7Ui&A?PZejaj7da;{SwhEl!-) zT>8LN`%gCic12`;7LhL|<}U=VE%vP~rh)j63Pi6Ow~S3Y@j!r+}D__(TMGnM8!wqJ$j z(;oPd>!w5o$O}yL*c1_r#RiaGL~~MP3QclzpU&-@)H8hvyvo@D0rWDE#)7O1eqLXF z)=_8XgG_pwP7?`D(<_ttqM1G6l#1O=Wn(t#&!%ZMs8RB5DUGH;Phs2g9hSXb4-8M2 zR!Li#bO`EenTWz9LP^r-c9Jm~Zf<%re8A91&@j`QnbBf~T9Vw;=As3CkhTZEH>n7w zOC>WZwpKO28Wj}Xah4{XacNlcGtyJe)MV!KI0I{O@xp$n?66fG$te4!tr`S3574Ri zX$t2LO6T%)87fH+K4&v5vmqMS@X?&Br8?B0pxr8l-=bD4om0gaeTEOJcEzhX_HgREV5b5!@=RnLKVk8`Qn-nPfk9c^v`}h`FwWv z;jn-D;qdTyp>}W>lCaOlAz{qLed=NyWLh<{{S*ikRb^Z#5h>lxH2J5qJ#(F8FQ<~f z%qE^nzwhv8L>SJ-Hk7RO!r<(M7JHHz_bDv*gf2_0_tLbD8%6_nv)YY$UAg5R_igHe zpOu1HzMqy4#__dOcMDdhQ;oiy1+bP=iL7oL7@2PSGF)Qj%PeY9q-~tBy*R&NX=_QU z%R95}!oohia_YOWDed>QXEe6={LgMu@FZ7)y zf5#JbKq&j0$6t{B0HQ!$zg^&ox~r!Z(F{K*@Bi`M>FIBuPYzaY4Dr=M=KHDu)WXpo zeL6kc`|zQE{Nc;{qfe)^kJ8eJ;SL9Crqnk_nA>W(fy>2fqsM0KDd_Akrk$iU25kz(l4amaErZ{mdf8cE#-m9s?TiKuVa zE2LkJdKI-7b}n-jXBd+8j{O{_KkV zvJA7}6m7}cTFxaiO?{tv66Vm0t99ZchLGLf$=}&Mrk37EaWxe$YCOpKccBjHd~ClN z<3DwF_ytb?PS5|^-Oa}TcQ@;aoB1ylE)OHS};ZG=5@)M zGrC@;OlhQQPIb~B-dYrFN#~iX>SdDn1<^>^l3X4d*XyUgNndUuiVEE$=XJ=Tf@u=7 zEC@^G)2r%vs#CJ>+4w1OcsTB~ao?pLMVwnBwL>zpe1NPA?AuwytajR`l9gXjG`3== zHg5$TYEZDMzZvC!Kx`ea8;EF$d62*~`M=f4<^S7yS`7M+GFQCC;@d**RMl#~| znAoRk4ata`hdM8k4m@flPjvR|Stafaayumtl_0T*7sTQ3ZR7@H)V_$5&9@!0A+D~) z_Hjstjw?7b?ZGpfSQj|lNM&uBsXFzAQC$y;t1Fr2FBIF3IZ2<*k{O9S%b@p4ynxLSoU7K;ZF!*?;ID?31!&Rovks&E&pbf|CiQcy8pk- zlK*!%d;d#k>*Y=@|L@~Br~F60U1bi+O?6Nt1%L7y z;B>vY=*A84`~6vBxqkLFeZ7V%kTuIVSe8_mZN$IdpG6d>>QK6vNF6zi-d{`ZxUBi< zL;a@l|4#n?r%rwU$Nl_nf&XXyZSx2KeNV`fmjlMt7_(ewp)b&w_vQ@a z7Ld|AKo+?Hq=wN?^fx2_msZIIHGpaSe{-vwjsNJ>`M>Vxw^aUj8Ibmr%`-Cn)#m{H z8R0n3Vsg@`|IMxKn*ZO& zZ%O_y54%2L0gy|0C-*^BP+g|X>_K(_8Dg6y}*MZSf@rrF7YcElG& z(m0+pqcYu_^s~Zxi#{uoqgCIX3d7t9@<-a=Quekuo#K=lr(S{)BZsNft4atdOX6#W zLm#~w9<#~gW1m77oCJ>C>&vC9G;hK@;UPDik+I}i<3BfdH*5X>UVe+-|CurrmUsfQI8mD*Z}I-m`wZn=#%{W@thI9gpB(NTd^~J> z_Hu1h@Bhv1?aj^f{_pN?cIx==d-<)wdpX(gD|S5)o2SwE1&(~mkn2)lV+>b#kQ{b* z{1M2YO!!@W`}MiH-A?ZZ5{@=rG#YDbaQ5Lp4o?1~(KtUpw}?-PiyJ?~m^bCf7JxF& zWb~)Jp!iUAfValGpgML&;_vuVv0kMT#s5?rSnO0d_a-g%;JjDWfmTbDPl}gy>5K1_ zbt=-YHf-!-hQ({6#v~VhVOP{g$p^B{Gd@I_;u}KjkxNWL5B=|PU^Fih5Fh)D0-}^y z4r16&s3M8P>yXV*lUD797@ACU5Xr&3U(^s_C?W^ZY#v=jqy$ z8#?049jbeix}{~_|nsqXemo^J7{L*%$o zh|k6$reosT%^q|+aB~i7#?8z+nPHt^`R?wAb#pFylesz}J45Li&s?)m(wk;{2%y=6 z?U$RJA~I56{(V!p3`B3Txp~jCwTn9pz)0R(`TGv%nWVY1u0W$V42_Dv(!F75)Q0Eh zA0x_OfZ=a%V5i+_cg|nrd$ZHtYA>)qjou_lhD&I}3#da=)pf%8(eM*t$04TJ&rSTa z-k9c!f^WZ@LPeDo#-Q@v#CE{>=#%OVU*gkxBTP0|V;thRV-5v;9T1A`xHqpl3$f8u zZwy=Od8#*BSxALsm)8mB--`FlT)mO%QLdivupd!IJf%KOuXDNHWKR3%`Hc)`r20ht z^xlZmJd5tB{MqyLOzB?S%S@$@(67o&i8JN-Y7E+lduy>RPJ?m$TiCVlaQ^$(<$J>l z2$Sl~*@sh=;YUHx;yRb>O&mU3CK>jRzifQO9+yzMYIv1;$gPD0~b6dSJj#8b+wI3%1 z)X^;P%GJds_f$bL?(`}adBp$$jRs&lLV0E5qJ^z{(`+t*Z_G>PisaOuD;$9gCs)-; zvrciH%gq$_FRQ-&4u{t)M1cKECnS=&T%ypCm?uD#V^F@RiA`a7ev`^CTSOaSk|sky z0wMdM!s{Xs>$#^i8V~sqa@`3?+q?~qFXof-kA=VwkcD69RN;JYiX^*~k7R%W*|r=N z|HvGDEbHg!d%nLE{<(FDi`P(Yar}svE65n<}Z@o9gll2{v z3lRBaIiAq}%ImzX-X!^6&&}G6G_WBa;!tpGHbzYE9%|%*UA8yIEkMQVMy=9k6oSz4 zP&lcC&P(>DAlNf4HqOS%-p(14A?VfqHrNYiB2Tf`>EO9faqst=I)V;I?y67=S$TMlh zx6qsN+_C3iSPg9Hq>zRrxN>X^6r<1@3ruh9E9Bc;D$$Kd*rn-);m+{5c+-q4i?GXj zBNUl)Jyvm_a=feg^78nG7lOg)1s#*fwbf!ZB<0MoKGU0AR@w78Xp@MG*@;t0o6Plk z=QGhJ>BX|dk-f>^POuEiIsJHc%t4TiedZvSma!ZP=Mlx>xgh1aj+-~RPh)KjP9>=_ zYqQZfQfN7Ln^i7S^zHGXD&$PuHa0Z_GfQ<>osu!XYD8z6TI*ehT zuLlI`mM5`Vg~o$z7);`u?_hr{gB2C-%v9wO-{C5?Eh^vzBr?EuicfHzTdaOt?FPFI zdk|uacpmm`DG40WNJIr0l7_gxlT^0ODS~_mu^n0BGcp7(a+wpj*lg4BIju5P@p+2E z5c|xXh!Ye+NCF(X6Y!ic6yr!XX1j5Cjl5K~s;ZuF1{Vg_#K5E=1e=Q5TB`cgt+%PG z(p7=v3g#Yk*Vr?j-WAD>qm|o27kk9pBFirCXkP&F zfie`bC}_hMsyG|PFhQOxn_CxM7v>brj18u5Az$c(#CC=bw%ZM3vFR~rG9eoY!|*U9 z1rZ)Lv1r>2^AN|39N|}Xh@ZZJYz@m+jFjj)4?FMli`!b+y7Ka+txF_p`zK=oax#i_ z{nJltnhd;ya4GxM_~|FJlih|W=sJ{feqahfAtIF&9K>u$(o#>*08!ld=_mQ_Ao;l0 z_~|F(I-n2*V~1h!5P*cEBfGk35gLO-rkEbzE?Azf=AT@R5u<=Ek>m2+rZlhf3(*j+6 zM2-g75<5(M9M4&*=YNAJbj716bbFxol}jw-iqyZaI2D*k3bi2FB?ynDlTs9044L>&uI#KxkS_;W8}<6KKgLD3W5 zUiynKMg23rif^S#eRZ6rL}4!lb2lI%j4`rtNX19|<$m%mQXeNPOr}755a^;weIX*RfMz=Bo@3t%CtPT> z#it_V1pnVm2boKCBh7ZZ-83G%4)$5atH0xk`Q|cV#HqOvc|65(65J5m4oh*!mcC51S8=!new{T0Ul1|jh<8{>#>$Y|@ciVwKYIw*|3WG?Pf<5H8Js3I252JxY{%gb^@OESD8NW-4|AqW9b?~^L zw0_l)e&#PAiGOfBmZ8~5?GP_;`s zk>qI>|7=l)7;br(g^ooV3CHfXJMGOMjK{9>ZyNuXKEdS#Kqde0ZgsX^ZfE)b%T9g% z|6YFK0EyJF(o3xHUn9t->gPq2nI;BHBDVE7a$RYorM<>la;>X)*$N`pZAr6iQy7X4 zgi!?2=cS}OS{RR#qYQ0*U_fBG`1vym!^m|f@MnZvp=yb*+l{rgM!HsE1TeX$Gzz2! z3i=AUhCG3LsCe9zq6Y7rQc^m*D+@KUeOz0EqoE}7dTIa?Z*x6!fc5DWY>O|<>5)?i zajd^=T`JQjSoT7mcQeEMd*DZ|+mP+2T1|{Oc@WM1;TVI3V4H+>0JGo2mvQYN2E_C>%u| zU#2njuUUxp!Vwi0`^jp~xT9=}q1-RRZ%+W(HXwmw`qI>6PU4||Y0P0+v!`bG3NNZy8|9VjFH~@g zFgHjpNZaa5<$$UP)QMws+PY_EpiK{c|0*^^!gFN{!m>)$E0A3{7PmufU}mXAZpnKU z3MM8merDWtWe&Pk*n+;WAz?i6d9sfv0CI`L(6OhJSmD)*ZMq?$|Ihl05ZFGDIFT9so_wq{VJPC~3$?t3QNt2m@r^7FVQC-j? z6@taLWSS|gt${e2;~}OP<^`UJjpX>5I#nIQxD$7CL#3umcQU>+CbhaIo)CK~SY1jb zDTDcf&WK^uGuS9T$e~5Ze(GLmRcc_m+OgW&QSPIgeCD3hZE6i zdhIE%qeCH*GW%+beYhgwg`-0XlbIBP&eqVEwi99=i~IachAyx3+xR8!ed_AIHDSC> zUE4>g+X}ICdF0E;#4-`Zt)x5E^Oif1p-ay#z07%IZg$p8QIlw$Ezu|1VlFiXV_fRE zreZJb8JQ^mOdyeP_dBSCRkp}!(~~WIFex;l@KaRihe3sS$JrPI{YgSVk1YR zML5C3#MG6!;EGsu!y>+g11A2F%)o{`+RzG!-QpE*Xy#^gD7A>hJ?PB~JV_)w33y2o z_Mmyl6{zor*A8VgDInDS9yG=OlgD^C#1?1mpU9~S$NqjSLLrR@pUB}gwjzd~ciX!_ ze0TDqX%fyjHgtv#=*I)4rS z4xa<;pE6`!yf9~CE!CYKC&*lLqOLvwzH^JFL@rcSiWlm^f99V3Z81XT>Y0aF(jbY_b$k2#_ z&m4Hlf)i?p>AfPwYz@w^>l*k~N0uTT5M+rN$PQiAEoyLl$}qBJ88=@JhMZ9qAL7c> zXhI?tEty2Cs)RpOYtg0k=<3oQ+8`u@tUZWf0;J(rph$uIv|BRE_~(S$>c(OYu64$gmU?FNGw&2B*40yE2-1fxk^;BU zxix)n?k!iV?iIf6S|`+EZd|GU$1;~9|MG0UT8gd^F1!kv*SPSd#Q8gk4U`V23^Be{ zPch>wT&0uRm%cEJZM}^~Vkw8f#>j^*Jf|4L0K4SsgNJLYy{hst0p(NSt4!CqueEXlb;tUDc$sm8H@*dOCov}5OUXyXvu z9LP>$Ns`j%#~9fzN9A#<8p(Be&joW!Mwv1msn0Z6F5bUx#=s>lM7;A{90r&(98AY? z+t{}uAY8{6?PFb%cjVVS$u`0CYUMZ8^!SgBflCHD#3fG77_U}I+mD!zk9q%0H78>V zdetfNmF1FNh+rO>_@XhV(!w`l#BeK4y0MWg+4vT_*s>|xNNhV+5cQzjNvwCCNXyZK zt<8^)dYHagboy5fZNHLo#8UaNW)=RKJX-qxYJGDybUU4H^6V4wPY7X#sv;h%d!OR6 z!_<>TJWJ)0#aNg8Pa~_k0l02+o!;sytz4rVM5ws-qhmfJA*LL!r2M97Yg>{EDz=Ce zcDj14YLo27TI^kQf~?Iu&R!0`f0g~sriE7?w9=&Q+BTQniIOl$0`RR)r_)g-Dc4x` zV*Au5;>!VMv+y_8*5IRz#iNF^#!|KH){`h?GPqfJGHhGjwgPkKjlBblKl z9kUQuWyCF{BNwVjCQIumhAkDuP#wmQ^*vW~(hNmNJ89x@gc<5nW)ZDQIXGXP)XWZ? zQ0;+Ps*U~Q>8kd1xr{U0bZ6(>0da}ES6dcn+eVSBV_S&`y)~-q&-%1W*UA);c^g7A zrd(EV=3|@cZC7u*dfVOUwrk|0n{zRH`68SwEuE~oEQSw`RrYC&i=^@xyPgivWg*5I zVX0)*1&zvpO65WvxL76lDG3*wN(^LeKdbF$ zPtkss+2e}@_o{rXGU_>w1kqp0v(u+Vq0?rxbUr$?Y}3yaDO_5QU`~jQjX=}5j$hTg z(tuEguNfz4%hqo2j0~sYoOXHdYD3Pg6gm5>BzgyhLF z-rF;>uj$fgOu;0{Ff0)Z6k~wGkr)S`3NS}m4TYhrg+V^)S*fFZW{UF33FP|=^Qmy} z=YP#cRJHe#6>pZ&dfIA z@`=wHiIe^tmf}vOp;v3EDd#J-Ld0cIlk=%&!P4SQ9I9;ihyuzvM>Gj$Sy|d1+EQ5D z@kjdE#+t5JU$#iIc4%RvoZX_Nz~1 z&2l1ZZ4Ex6$v}mN2w-Ez^Xs*k9Na26qm^4Jg~^lSaM3mR9}=l(nTbl!rvvv~=K_m} zmMf7~2|&azvBt#pUGp*HoOT@Pv0#n9mc{szl)J#%f_IEBC#nzz%XNm> znpg?THr|O);uZ=V7`jNDRAM1=MJTXJ^N-cYLIlY`nRKk#EU`CN2Sp ztTCY2@Fx;$32dIEp-4_@sIWwlUQO+!b_}MA`fEy!wK(Xn&8R(S`=sR(>p~oBN)PMp z0q{3*s3WvWzpQHD3b`!~ltSqVl#O6@+lu)@W#qaF9fn(o3u$o42%i78_u)lx4>DD2 zX3v#P;Up|LxkdZ}Mx1Q%cc<}DE5k@EADG!X)PXB`*=X#!_?2A2P#`vuFHr=RaMYtN zW2VN0nG}qDgdE2vLh62`$IE$<=b8xAoH zVdQ2^_wtQH{A}0O)=F}q2oPiV)Wu;vmQfGWf31bsBMkS&v?uVHKNHd43V_~4lU#RB zw|Ih)U2M~+LJ;%XM~-}lCD2A@y%SfxIe$s1ECY^`s?r~5J~pj`W>|N+Yx0d@t(dvC zqIzboVkt|IG=P+uf%q;p^0!#ASElTMuwfml{5Ef2xm%M@QC}A|165AOk8=8()A&A5 zeM|D*{&{a%@7@-UK@GnFXE#sD)f_(xakDMGoIQlZZ&sax9ps6 z7Vb-oWVoA5`&S*bSO+aW#h}Id&~Je;Ylg#(D}F8*@+Oh^Ty36%h8Wq7FD-R8xXvXO ze~7dS+Jyl&cF`nGp)WmCGi*btU?tiV--fY=#dxk;ZN;5wscWTLq90}mmMU<}pC8HY z9q``uV5^fWaHhRw1@GP=$BjaKHV!cz6W8v+R<6uxB-9O~Ot%3sk;?jzdY|q>>Q!+M zQbme7P(G6@bxeAvFbJ+Y^`LaccXAZ}z#(%iw0Kq?w_wio07yn2OfsE**TOYcg)AlMu#``X{oIN+PI+RJ3lP9N<8S;m~t@>5mzO z$P$--IY|V9@%}x3eJtLdVvG1T6-WK^)e9vx#C%A+T3I1H*J^S0syV(Px;tQ_2{jO+ z`nm_r?vCATG%{Bfq^z69yZMjyt-h^zZ7nszs?&Vtr8rez&K~w^R0wh0Yq#B*?HHfg z`m#3}6pthqezUeF6NAW`J9~+x-NJ3I>L^>IIWln(YEk4)sY~4K%i_-PqFNr@4PMl# zd-PbFvog(PonGuevd_9`(jH9;?2Jt)*^qedoA1cLi;G;;93V z>hPnX+5mNtbyDb?EPzZ+c=ge4ENXJufW)uPMnS?$=5_P znK>>e)$KJ&%F9Vrzx}3jY)FJ8Rw#l+Kz7`A&ToGfZX^JLH%V5UD)B>Nk-)~rZDV6! zQ#?;Du3@P8N2<5Ex8uPqlcfs;OHocyf*{qZ?oIiK7iI3wVHe-zfP1+?0CAWfnXJ?T z-jIAc!+3JRT|T>Ng0nY#ily777!sn~0Mx{t%2cGpQ(_!mbKn6xu~}aB6~2zO@9fk` z(gBz!;N?ruGro**DhEG*C;3(59h>bdlyVJJBIViHCyO!GYXyjm(l8O~g~zwI;E{mt zXDL>{eq}rMS3CsTSN8MkS1^SH3=xV!fUjdNaL5fu4!|so=ZuwkY-2i~%^9ejAY&5 zdCGmA$up3MaEzRPEKISQcU`=4jz%~Q?q$`b9JI0QtXKNFTV>ZB&3J0T%C4KP-ReFT zp^LGifnrJP?%-~)#d6M(=Uw~(Mfe)fYb=oF5i+!HD?TknGkm4;gYv)<>PQmNFhS;m zUqCVQ>2@L|9lfN#xJ7F_Z1rE*5mhrZ=P>fUR?bQ92e%#3AdO}U@8=P8hja5R8-T_wSy<2k9;1hL6Bn+ zk8>v%`oy{1Ki63!IGQT^tRNhZQOeG9IHyw-({LpEB3sUo%wTFAk)m2P>q3eEiQacv z1jj%HNWBVSrhR7cE_sm|OfEr+_}^To&E>Sd=a|~Z`R$8KxJhROgR79>^s%QMtTK~* z7Sn)1#oVczQ3RjyVX3&t1kb>)>>eW7V6kA?fb&4^fMN~mC98eu=Zk7IMGPqpRBxWo z>4!IrDIFr1q7+d48OfLqVsNGYCa^T`JS4}6&S4~1fd&=DftE<1xFT}JP_~i``vf-0 z8aQ+L4v}!-&5QpzA37e>^&01Jxu`CU2?%2iVm|dg5By^`t#usEDW35#FQH*Hp3XT) z5(av|xoMHyHsB{ZMd@`&&@*w2NuWZ*M}&=nkZWany*&Mr2K2x3g>*pzNf`b+pIaIc z`BJ9~BX}WIvR5$ert?@icw15dx$od;#MtBR2>PRxYH;{XfYX1rh`FD9IA*&~l2wAD zafgHxc1^&kv?tBC>&dZPD+Wkm=LJrVc_{KYThbbIz}Szm+UDHI)d%k|3l@zsfi&E%f!~_lm`~VF~98R5n{qv*p~<^vOo{W z$`XZ=J5#67zlMkio#eL`1(39?e8!aeYqf?!{mYk)Z=ZkN9^khzONTr z6TD_lG+fKkI;Vt30b4KyT4U~IPLp{|XFkF>=FlTVLEk^}_x_^QJ{F12<%wfam}5a% z#ikMjG0^JDv}bI+3R@%`1t?|X&jaMJZ!wY-PEymUuwaHGZeeUvSM9?9bYT*9ulihd zN4k&tgZ=)Cea5tXx#`NoM61dvK^TuQ;K2_Z=8+?uBCKa*o*&m|B zMdggxy#yD$M;8~s-KoqN=VFx1FXjYJ&;=0|Viy!s7~SP1gdXKWnpa#9L@$On6cMe6 z4BB`h@7Nb8O>tU;q>9lL#$*=Kx^fC!0!N<_B^N=8lLQ6zaO*0_E{T5Iona#~8j}k; zO);er3NC~>ToF%Ivh4eqlr%9W7hLI8+I9uRkT0N%af*=h!|IS&egN!=?!g1GKb#GGy15yK}x~(x0VY+lKX8U1 zzxYXSC+!j>VOR``Wbrc-)jT1JykUYdX0SNWqQ*H#;3>Ft1^&GpfS(xaB%95z(Njp3 z9W<9_FwXaqF@~2_AlWtXa=hP5KytT{_+0~KK*6q$^Q%n{|x@J^FROjg#A~} z$Uo{29__B+KBW3wawTeTaZ$#;iw=wn)`Baqcz;?Ljg}bjv)g@zTMPxPiQew_?lno~ z7wo_nk{XMzF8xq_TPx*kCF`1lEi2*Xm>0MOF2Mihe&H9~Qb~^L9h;vE?IUN#l_z-d zD}{7UvhNp}ZJQ{`jzw8y48sTo;&rwKG%7^wPdYw))iLH+`&sxd8ydj`jzW4<{zY7- zFuQb=myxp|M!r}K$HMhSe9CQ-gdIW-Myp>aBw-~}NRYb-H;K|Z?*6VUJuj50=7qFE zscOAh)%ry(fMd?W$f6lgVQ$)>h&?0Kg^N>DQam=hl-F7)Nd{4i&C71?Lw%LyD!QQ-LS7R`Qep`{KXXbxRuO%@n6dHdI9gm?yqb1K~#LB#mgG#7=4&?DT$L45?unC-g}GIiKEY$Q#8 z7)cYKZ%y1(NTiY3Zx)kc?Dfd^B&WJyUEK()Ho~gb9oPt~oCC8FR+R~>TvS*y^U%B) za?ATEjx*L)x48#xh^rjW^^sQY8QG4g79vgnp0<)l8Zl34;d7tjA>(E;E<`apKSXf! zd5FINm9PGLQ04LQQv8(&``3cKsyWtmy^&6IMV_2tzJe2&!kMucW|(o>1MrcZAQ!t| zzI^(fuD%9GdPeT66x0_Nd=M|hTLa<(rc*a$zGKZC!hbUDV@1|!dtvc)_=Odb=FyKBn~nD6vrd3X!I5Wi0N z@c(J^{Aq*Pa^l?v)~SKm+gg zHcRRUwzQL3wxrSwZUG;B{pvGR^i+eKw_qR0)yP*aJlwC&V~~r(pyC1Q!|@|S4$mnO zvcJq1=$W9EVsw5!fAfUw0GJ|%a|fi{-=G9K59$WKe)VKT4~91T$tt2a$o`B7L*DzV zlyny7pz?m5x($GDT4&Pz%S(;*)@_cQU@~R@ofVn}j35 z{g2s1zWeFb>x;9W&Of|-^n`2TXapvRf=(yn=0MpzfDQ(~5*#xoA$g552GX-LtGBPrAueiq(`y^}w_ZgB)gQ>;R@Jd$V( z9%ZAJ&#W;IZ?v#G4d#N8<^edRUve#t%C)pXDZ^7(hTMPN7A_o zT+0YGB53}cutQc`VUP9EBv+$`V|m?f9v^%8M81E0{>$l!V=f!F-l}P1-XGtp>DHqn zscp<=K1{woE=+ok@}MbgELjyS#^y=c>@!Qwda3wfsy7D8i1(W1u*|_C{ z^(^!Kd|B)$C+uIpZk6sNcB$jhnpsJ)cND^n@MOL1jB$Dm(*QhD-3HuQ+NPx9PtSe! zl|>J->G1Zd9|;iv@b}~Mcc<_EI>=+3h`3zdB8xy_j&z8cZnl!Et)6xL{S%(e zq~Yvn&F`#Z9a#*a9u2jeTRxkU>0ebwkOs`M4s{K@vfkXvSY;h(drnyoLRrlyyV_Y) z(5Fq)eXz-{X?>tva`}?@-7(44v+}#)k;`XvJuGs0`}fBo*VEA!405C0`_1`d9m{XX z9`{RlFa0F_QH3N8<1tQWQn?&EqA5NDS0M@Mz;g%o{4Vs%&Go+*QxvhAf=`pET^rT< z-`&0b!I7o^-RQl1refTr_!1P=H3pW*EN zd^`@nfUQmrjP2TvV1T<%y%Qe0U!WwAWEiUua8Sm$9Ny%J3uBjR^m)O&$s`S9ItE++ zK|23Iw#;sbzkiVp-YF9xu=STMuywJuc$em}NcO0wq{=z@JnCk3NAPThW1oA>i4^{# zRhT4$(i1W#?OrOV?Vvz*EdhZ4M)GRKq0UJc#f89f@O~ zm#6ITXGa>zqFfU^LwYcCAutP36bMgI9@RofRk`Em6Uo6y;TktWPta(mnvKb?w~Euy z7`C+M~EJOu0%UIugUBXK=y4*50lO8{$6>RX$m8;iTvUKHEm;PQ? zt?QO?uPb)J2A5l{MbrO>v|B*xcyS030I6}t)AUkgikw_^Yn%A*pC?XR)uLb}B zx3}5({G?V(sM!+jG;1x^^{DDlwc6d1e{3xPa>Wy5U)2|%BpXtri7H46T25AlV5nlk z-13Q~C#@RniYHFLu`WJoI+R8eW?Yn8PF9Hwq++6q*Yc$&sT|~rCrH0ZEj&LOkVey^ z^WrUMr^JM^d~zJdfJ@FzDZ~{|jS7CT=&XqPjV451-&@W_(Tlx&8cfgZC1=0|%rW@i z+T3mPSWk2NPo1;qNUw+#N65c{vucCTYWvS#zu&jx{~YWc?QQHo*YTL%F~VcZ*9eN` zW)_aQMP;R1zWSIB;Yg=n`L$>O_%}GGQ=EqX;wIMlMULMryw71A41lzFKgSXBlv((| z1JVp~An8=6-fAz(j5+Q=9L52PDcBb_@-Yvaw}20=m(C+Z1_eQ4m9HKT$C!kFP4PUD z_;)~liQ_M_z-8*YeIpH#D0qd^VOD5PkWrhP#H){s^zK&kMFQaCr;LzmG@bvc{`%Hy zdGoY?mZ$&2Fb=|aQgIB_(*J`!i~b)T?QQJ;*YbQn^#2F3&K}?~K<2|=(MZHQ?Er!J zdxJmb2v#>xE4}i8kKCK+I-8NMod#8YO!4eJ z8l{Nt>=cfatL)5B;2+>oA+X^({}f{i1}}l12}wi*fk&Uw%`@;wqyb>x9pmw17$G8X zk+Z^TaeuQ3`tp|haBulf|M^e<2L8`1dbFj=igI7S4!|9cyMX@zXOU{`E|>S*e%%6h z!0feoAJAbrAUUd3A7gEiuC3WK|IUS6PV%Ncl;EMhpj)%2ME?IU1=HDUDFH9F%fA4+Wko zV`903s4Q{9)g1asQZjQXq-b&@N~&K2?F^}|R&gMJY%JxFXj4~>RDy$JEzFa=9sx5i zPYs3^j114`Ak%_qn6f7_W^0Kh^*o1J+fOmoM)|sKi7Hj?p*WCl#Nw=605T(Is@%N= z7~}N-Y?a0Vw5o4;g>fxjfS0{2SB_~K;xwc;ClMsX>{H=WMZa8N9DU2ulxpjyQ$tL0 z+R>>AG^nM#31{3lz7${no$Y;0LW)z)zEzi{aKig!wQ)9&BAJe(uC*j9Y5_v=)xb#C z(~b%Dc{ZHa@s&9Q#>h$*)%XlViY@V7v|yDe%%2JO?59^3r)Msh?1D0|J^*3UETu8_ zW8Gki1$gB%o~B1eAWCpxv<_1KCE~2BZc+oAJD|y2TBlNDYssu!t z_uc35dP+Bh9ZPb?b|}N&1yY4-gTWO_X-H5<#?yNF=!qERox$PJ^F7a;o3?A@IGqqz z^Z5dKS+W+KE1`<63?V^3pTBXnc8!L<%CXa#r%~w`I$>y-Xm5EGHGA?iYIBBDIuKz& z^Y1BwK^P-K&Qd%?X5A^J$zKt*7plk-RZauZIQ$|I?smF7L9`9Pg$Mv)9MTX*uTTVU z-irk61F+XKQ+SD-v+mEDrmW^b%u41*e1F#*;VZsi-*S5fdq~B`7ki{53R+#v*7*Qv z+sz3^Zlqc`<)=>7Cfl+AlKHSLI9bI4c3T|{T;wL>(it&^6=d0Qa#?+6g-S_>)+tsl zN7pLFmf}xwbR&wXU-kRS+TfY6^BhGO2BpF19UWcrWY@n}V$p~bsDx0%88oQdl2d2^ zv6ORgA9-Rwb%HQ`S-u519iC$RnUi1{sIR|!ZETM zBUPq#23ngVn`5!{wOwz2$uGF}*c4!7qp(|Y4XZkWV;rFO@|K-rqra^^EesH~cf!hh zleF77!7)W&sD9lsKGa{OEkH|QMR9~u``WC%ti?tLuoNb6JZ4;gMwHc?S{$;f4KD3s zQ#fv4Wt&Fg+(IQ`Zr4o5VeZxJU?>|8r)~s%{pyIgR(g1p!^i~q3rMg^S>aqKpdP{p z#O%3vmtE@@7}5d)%P=I>%t(_C<4mOV0JjA}m!WUksGG89LH&;kY2HBlU#tJ$Jv=(J z_5TOEoBW?^dG68vt2Qf@P=kv@?Va?1ce}4Yk^)~{uwd{I+hyV+S2*qr34Wk3 zCYqGi&$^ix)qOn-hs)!$Qz`l*{@);Rd$me8OG`&qT9VT>Nf`ACMK@7J0Xv!c>{Q^c z>CUPSC)HDEYhc=FUtB;;RgppbSEtEqDMd75tE*WRb^xovaU6#!p`v_tzVeH5cBm$7We;R(4SipTlT{gm zXdm)>ZLcsmIjbbo(cj*(yR<~%4*ZJ4m?LWmc!qHF8O4Dut<-3Rm=c|M6eUUdPB%)c zNc=?(qHae}wK!bHg zDD;EBiMdC4C=1Qv!$|mV7=0{Ga94TEDB{gsg4SX8A<2ny`x$Hc$W9Rp@i=g)#>gG) zH^(IxU3N?bRYz9@ZH)gO!m}X#Pl92yyWgMc>3{F&sBh8#y~EzYhW@YPX;1&l?2TT9 zB%LRWhyP(7OmYi9`zm5akdcJ^tXTg6lk*w;@^hRe(W=mlJ4VHjmnU3Rf~tH4U%A2u)Bh0Am<&pK=&Q`1(wJcuhty;^6WUDf(?5rYLxo z;zXBmDL(Z0%^S~B!gavoOi%S#y>aR?vad?MpS=(&n8yl56#NYnuI0`>=OLY*akafr zd`o)j&~%$+7d3C2VnXGmBp)62^6d1L`Qr2d^gs*0>_i*Cd3;QMCP71P^kI&iL z^! zNfQRh&zSdF7!N>hqd0?K2H^1EVDG>KU`&LQ=~^3A(|C?C1ludxAE@LWu}YijY@Ukody`yD5gt2NY7lykik~8Qrj=3 zBB_K{=~nZw{GLQ+@wYf=V60p0b6(lO!Ze-;X@kL?HMGi4&~H4%bbBB>${#9!B^^e# ztnfLGBF)WlO|-X4kG2*=A$TzvQ-ckxK(p|=Ev_!OmP3pc-iYyzh~z>-+1pkF6#mO> zr#cewh6Bi-1bKpFGW$>JamIylN zY&|Y@=GH=7n~g%NK1Z2h!Xo{Pl)q?c*A`|1GBS~I10$8megNL#7o^x-mm!njn-K zUD3SS>Tu#kjfpVj#mgxU?P=Z|kAJ9Vx$}P|_MdzEh4X)Z|LAaY{;%U%k^XPhN4i{I z%bns5Am9GrmPj=}tIZ1caXfns!aqnXvU6KBsU72`XS1tj!&|GWtGuR9&*U=DUNl|? zI*`&)Y&3Nk20y?E#-n^7%y;#pQG~Gs67TtS`kaf`i|FWIP5aSDqcBKoO`)q>lEH-q zsIpjJ{QXi4p2IA=9Zv^p{q#f&F%B&7>P9Q zpqLSbZj#DqG!hIeRuriHq4?kB_&=E@qlOKvv;R8Sv+chQd;1&t&sv^)l>ao%tyRS@ zs`$y@CZ1dKFjL>HaCy=FFU24PH3$G%z5o0B`@2WB{r`S%bN^e*^N{4fGI6G&0C|lE z9nR5oHdp&pG9yqQIXiVr8E;|kPmE-WIBc!olc2l?t%gp`cg3Y^C@jKGunvyqWkx>JQf zf>8RhC0p=F(t$@Y`1;jfq_P?*S4Z6;d|WR#Q8v}{;G%49cLjm4A#B2IZo+In_%NIL zt4);6KTwp-2#;XIql|2#Y;K}#ZlY|iHp=D#K`#FQK`NIyP47KMWGjn(;|RRU{Zc+C z3BA&-o5HkwLRS%ivS5%Sp4B_Fh%iwl#8HXQvgTLrTVghEc`T@xrr&}@YzglL=X}Uu zE498XMrGThr3nz@9_#dI(dNR6y}45FmXayA?Mf^ZYPo(RI_SnZR6fo1f9$mGpfBu> ziPBC0(G16p)PHsQzux}7t^Ysh?{D(It>szV{*$eT*K#?uj_#E&pR!zTynw0ut3n{p z4p&eQ)f`R@z$|GsYP7JhHqwBy>f~|;@H!1*)jZ6T08;ecNEc_mtDOT2#Hv!q8Eq`6 zMy!IdLN#LTf_YxI9}^r@ni!WAE>#%XOxKbsJiUFl3eUuFVHI92n0r;>8Lc;x9vL-i zq(zRhEu}*a2rZ>S38YhYUW~@%Wp|1RWz56KU5wn2tQ5H+1wCBZ>}x?)$|U}lqNj9} zl;tN6$zquKmT;Y*kutqUk+j^WR{WsR{~l_=5A5lsibWt z8JF?yjk0d~TUkFZx*VCUrV&*ruo~*SQ)Jg1y$U*3jbEKMBUd>%G5o&m_!oT^mH)K~ z09zOT$FrRMzf%UNKK>p8#8wI2RxA9g3J_~cYuW~gZBhS$2Z&W? z%%UM+wUf3s2CR0h7RoMu&KBd$7SGKp{@OTG4gR$3!dl>LGaj_6M#i;ng4Nz{uv#NZ zutW!3|LD}Q zw~hZ;3uG;pd`)`R*f?ud@gM8W2b-YXDE?!8&2k?IXWh2(A8Ua$jsNJLiFWZH8^Txu ziIv5FT%e_;;y;>}MTHQMPIMZFfNZVo*P|u2H~uMFBN;I$a}%W7_AwZnS?5Y-vl#o( z*@Hst!#|YTbMwe&N&c@<0LU8t&lUf1x3}T{*7Drr{ojuNXcWHZ_>Ze`xoB><{@oJL z=KDXHlj#IfbPaD*c$6cJtrPz(rPu@;CC z`+-zMeQ?%VRk#No_=3?MDnP6-*hAfNwL-=VU`vKyC^8pSqqlJIg*qtr8hb%+yiw={ zy+Tdog<{c`fftGZ8pmCzk49in=6i_D+%O!n9^yO-uTYz4$SRH*+XG)z$H11cZnv_& zZGo+8H1tzEr>G<1hi(?8sXftO!avMKGe%o1!|+MJ`CD{cR{BCEyZKVdvc z5g`p70Bhtwy9d2u{`cO-|6?uB{mK80D~?<*x}1oCdz1JS(Lo*<+>Z zZqW{j^dsGDu;i-bvM|h0;EX8uD=({_^)WBm(Jt1y*Smjwb}EHl#Qz&4U@I2Jh+#aj z6d_x-J4|UwPP-)6t5?YN%SK5_`-HUZRN!82o$cyqTjT6H7`fzU5!38-N&TeS-xUJD z)xjwyIb+FJ(majW5+X?y(l;TYV5_SscskqkX#vEDeiZq0y&nOP;bVhb&Ok)=pZduxB`1!=!SLi(LPi_!li7&Z<5(!l=z=+LJBdk35R@9TM1qyJBE@G2zf zJYk&t5A$H6WqG#7mS^$(|9c4UxE{(;9o*3(8f{}cHn0AmLOVLu4GTtf zTtwq&2TwGj@SVOgUu?o3-e34b9#C`RUGlA-1<(Jh(dzjB-QA;u0{_1`|JU=Z-u`zH zy|q>^#&i+=aH%8lnd_i2ScEnRFQfBlmiW|V_WF?YA2qpFt2^vUwdx9)Q*G*FWj?)i z=R9o;V@FvkJ5rvSrexJ=PTL^8ReIz#9|yrwNxvvIr~=8t>z0_hz*>g7mXE5P3D=ne zw|aC`3fy{ai~jao6VKnlv)K9HCi+_g`;S8W&;9-0#{Y9I&;9!UG!OsgGQ?Qsu&oaM zc5em-4SH1-`K_XSIr2*$=?zeB6!opPVzXmz(U@;_Fq(#Zb523Kh;Pk6ERMp;;=Q$R zXsK{-Q%V!%IAljzt24x^4E1J2S`&u)%>t`6Qm>ZARdeB72&?wM|D~6`=jdN6xeGUToBXZ~8Jh2ZVfoQA^cR2X?7xooc5VKD zcmH6s|JU&>xBsOz&_fITCDB@H>ldRWfByl$-2F1xwgSHF)z+2^Q_k4o01@*SqaI&w ztaoOl-;Of(&0nB6NN^ZaqFb!xKcsD&R$-*lgcb&eeVrhh{T+oQ|8dQ@ywZN=Q&ZaG z43jRQkj~3cY>!Wj<8#^E&*yJ+tkmdjl|f#D*Ib7FuPXmbzhB`04vzLV^nV@C_dx#_ z4gGaL$H09B{1UA_yjWkghsJlw_ii5Xw5R{-+-+_EP(%L@_IK_0zk7%K8~VSNXL0$z zMf*FtCU%z48@phZ%=f1&l%}E3OYW4*08Ui-2SWFAwZ$WD`!sk7{H)j20eJ*KZuO*u zrYi8x0NklzL%)faIx07_DD$@ylfz}-90O~7#bhgS?eYu+4#c< zrIc)0JkOIDQ?<0k6z}YqzkO~FN3v))6M4PR76`jT{x4r7?5|(cLNP-xY4NU91-8(9 zegTz?e|8zwA+?%&eH^5PgXS}OB>`5AUU@B*;C1Wv>sIXoC|&oRl10M(S>KORm>@wU zGHqHC)s_^S*Ns!hOjB!s;)`MiV>ro)-i}p9u0y?Oz8d)3FrEyYed1rw5vN&Zr)rC3 zv)*Rf#VRr|btC5LlQrwL#m#6Z#qdlW@OeH&X^bc$7bLh4M}^^$)&Y#w9e@M}*;^VB zSyV4Mf*0eE742TZw42W3uCOL1-MkTY-7s|+-4XOhDb3&v5lm5fLGfo4F9eU*%)pgS zxmr;oq}9*oZ*z@X@DdRjua6 z3>SG1FG9?I4NGQ4gjcIrIc8u>edt2m<$$+zitaz%TH!cmQ3Ed$oYISUJ{zL6*bzr_ zL5hffXVG*I1WT0$4Jy=sig)oq?)bxR};C`&Y$}&hBJ2p`)_}(llzcU13!L zqb1x0V@11buP{t>#S(dLGkwlpi3v1HmUrTfGCC}61I2+6m%60gg=0ro04NyGJC>6x z{Caf&c6UWbi0UO{Zx`hJWplRdau`pecxGh98S@1cE zFbqo0jhrW3B#gK0hK%5?f2nA_QM~Vp`ZeLdYiqWQ23`xVad2=E*IT%7bb>H_*+q2J z74QqiuF-Ic@#oGwjb8G=V%=_k_sH-0J->!UUc__aZs%T`J5wksWVml@a-^<5xb z9Nk>%*?fz0f>7M0=jE}htXN`hft(x>4Jy>zj; zPEbzd1bnfy{c#w%;EAuUby&bHfpqGCP#68cgm{gHtWAO=97r zW2qDoDzicZhQZFepe0x^lP5S6EVy=_j_avb$sR*H8$%te52CycW(>nBHtV>$< z^ozFl?G~%WL`F?lOxF^GN@Q?hfJQKNNv~Li60vTfl2ZnGyW+$?_mSC0?VN>@`nW2$ z%~_*{bcs|xB_I~WWRV0uj;af`-Y#vAU8#X6pQ3aY#vIANrf`JLP#SXYpfZM~vO*5G zG?`D?8J?M1nn!=^NZnIqoGFv_7&$qd5{dHKwJCd?nkxsztKm0Fv=5DPpDmO5sI;N- zq({xGtZeX#7FX=yri-t_v|do6O7b{8Z^BtvV5_qau4P_V-Hjdqx2{8{;}ESm!j2V> zwUUqIZXUx^*v4Yx}Quso(fh7ys+9kpFFO?_d-EYc0=x z*nim?qI*yNR_>x$miH~Y*R)RgW_RlMnC;E#W7{}v71i(APOh<{#hAV~SwuF`cJ7;H z=vi)?2VJYS$E!#oXQ8*r9=C?_hLZrx^eJ z;GnmO|GJjvkDdSRKFLRQ*0-E;v`zTdsOCN8dXw4MTxs4OpZx8ozrTCzNcEP<^|SPD z)ydzKy3mmgj{j7eu%_wZx`>V>eRX&d?NmISUz^;PA6Ylv#Y)Nf_b7SHO(=N51OR|>oraXR;PAz1`GYZkEccH z{|fE@_WON1|Igmu-bVkwmS?5(e>sZ2VAjuy>feTLH^}qpF1lLk>`w1#wcIGPXH}ir z3k+E>pJzq&rl~ybQEr#Tv$pm^4X-SBXR9{uEp2Co9c|kqy4-zHz>aZX0akCSFtTek z^q3TtC+BA;w$GRvl}Vb68jcDFv(V7=doOzZrid;!K+dX;QObVmtki93N+1{0U$$su zQG)2Xh!$y&xmLnAgKj4{=;R(G^`453Fmm?DlQ@-=qG<|7R`FeanCJ z48XERZZmQpxqnxo?x>2``u(YRE1&lJUptFelK*$NzwgTbyV3uy<#{0TUzjAMo0EXN zMk_(^3go|Q6dzQu^%_Ev9=5wt7a}`$_rAr)FRk>oowF7Z89%hJ^a&2$@{}ku6jK%N zv|2Lls3KYEP1O17b-egmUN8>*Dr5iD>+Cl{?;8ZY-^7>S#FyX1m#-MwO?>%HeED|q zBBqHfFr zY+_M^Vl3+Wjy2!V9n{c+T;=Y|ACz=N+47oN$h^19B~&PA+{Lp>zh@C^RL9FyOi7)z zYJhn7IKGeHSV_ivr%~oCupMsrYp2I{#LGr6}d%MkOke~%4)p! z!kwkL0Jr7VTi?GS*Md)L`>(46t~mZj|L~|7|8EojV?ECr?7yy1O2ZM1j^`AU5sWIF z#-J=xhA zMKtObW5MfSUZEtyH!~Dd+uCEXm}&DQfD}np9)}~|uv67_$8#);yaKob0UE=3M8Vci zBt6oeeUG|UqNv`5<4rmBRpXUh}hY=#)Q=eQX z-cx@FKYLGoI!nB#|Igb7zrZxaa{^9Zy(S(zAAdz7>iJ=SU{{n&@volu)8F5{K7ao` zv5s~7|NQmwtGBQHS+GPK)%*YG=|;TneM2A0nE4&d@4GAmZB8>HV;Wi5%IhZ$Xf(`fA24X-2Z?m z1jlEm1W4vacAO85YWIY7+Vei(Y|PkOF%%q%m^Lni=S(ZOoZWQfi_1aP;CHy!FvyFS zO~(h;BA(6Iq7Z{gv>n3+l_8<^Q4L=xz9?2wtyaD{e89kdG~RuBvTgj{0R-_Cz`0Pd zL=%|88KNj{Ra-J{w@UW)D z8vHp9%O+#4K6L{WA&U5CedM)O=bQvtEw51=>J-iJ6(T@Qx<0^omf#r0Y`+tNMUx`+X%YPwYLILIP$m;2?P@1&ReNkn8=Kk~sl^@d&4! zU*hSVd~h;Fqt5`(DMw%yPQ<)|$vg}Y_&7x=D%-aK9vO%5uHWls0J=M#_cLK@0FMF9 ziNkdmMIc6k7Kxh_YdMqzEW?a_W*Eij8jNu|gA@$Wn6Z6yif;ItnkSPK26D81=08|< zPIi+NU2#@Ow0flyn|YqRc!C#x55OQ`G>Wx>c~pGXs@UoPr;PCOKN%j{=)V{D9na)4 zS)n;WV8pg59)olq#|#~)R~1(!w(A%J`T2Ri5&8KtN@2q4pf3z28@w(yZk5 zG>ni&_Xr~qqMKu!0t81>ZE5>9VUj3Znzyz~Fq;!L#DE~mM&Xhj5|_T`9rGDfEAGJW zJ=3Ri&i1CcQhmXGs~UI=@-@PaJbq{(HSPhVP)#r!gOKo;scic|8nV&ndqxA%XHA?^ zR+6pe*$l;jSWbC2+0m_9kelimd&3u;7-11}H777)VPXodar)T@?~$1Ik6O!Y!8hFu zTpCHW{je>!;SQfAhH5I#PEMXv#IE-Yp&L9;0geJbGJI`sgV$f+EQz%3$)<(OXR-j3Z*wWF$F_J!a!2X#NJoW010Pd1XD#k zjH3z+QG~Atp7(Ezj{loZBM08U0d>TyAlXI%9z&a#(%CaWJpf0$y{W2c^@0f8fi{qN zk5v9Y{(~QUeP0UW%zdTSn8xsE#NscKP$d?LI2C-ym5?Caz*!^+&s0vonmfK}$s9(4 z;e`>wjB2}A65s#v2#LMV4rhuwDT0di_B{^(z-PbEX)%nx?~6Y~e(HdE8i_DN z#^z^DcVQBCuln4wHwPr!V*mf7wg;y&Lj>}aD_n}fHt}zBw$#;`XV6U1EpgDjSG(g3 z2S6@2a1}zJ`Bob2I49B2&EhErjhE4wN{ZDqKyU@q5YZbp&p8jC2{(B_7V?Z$z6v=V zX2&xpNMZ-3DH>5-)#`hE^4ZxbS;uR}fRa%f4iT8*YqoncW)UPfAoAWKPzwIj6BJaO z8vKljc|CDXnwTl>Q`Y4pJ%X_pU;rgMspQ9(teJ^ig|4m!h#M2}Tbaj}BV}`!qA^Ml zTXr_7HAY%;+9#RH9!?;eS-Vz%M{}O7fYW)_(~l|QI)DoSu;mG4U}62*HX-luPJPU~ zenEnJXw(IN$M-z_>|xWO4NATq*>ZTsXOS~3j27tncuDyAn6iZfNk;bBUer}EhV~x- zgCc~uE7}`?Eyf6KISR-GqVl%yD!}d5x1RT&_qL?Ug^>kL6aIncfK2f`3IGg#Wj(np zLcatE5&M;&xCs^l31kW!e9s1iQ+lb|%K1AnLMd$m@g3%8H>4WP=3LCB zYsfA+rFLQ=c}x$*qX@H}g)s>5oRLAUHz9(=o#^XD+_*A+0`Lp4cH7Jr7kjN;J>{`< zX0bj%?%OcUD55-sJnu}^26x~UCrIK_z<%+fUPnFP4s<$>U*4s`AY|P29XK6xxyv&k z1Iy^;z@6l`t?G0RW&G@Ds$Y)e znIY_LP{82ZFs1L2f~Y)|7?aQx5g5;-NXWZF0xoZF z4Z~G#aHtfH^$2|ZdMPEgl!|*YyODBNHO_%0DY|0U30?M8f+ZIx3=xAeK`~0X9EZ(b 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 + +`kubectl apply -f https://raw.githubusercontent.com/kubecost/cost-analyzer-helm-chart/master/kubecost.yaml --namespace kubecost` + +
+The following table lists the commonly used configurable parameters of the Kubecost Helm chart and their default values. + +Parameter | Description | Default +--------- | ----------- | ------- +`global.prometheus.enabled` | If false, use an existing Prometheus install. [More info](http://docs.kubecost.com/custom-prom). | `true` +`prometheus.kubeStateMetrics.enabled` | If true, deploy [kube-state-metrics](https://github.com/kubernetes/kube-state-metrics) for Kubernetes metrics | `true` +`prometheus.kube-state-metrics.resources` | Set kube-state-metrics resource requests and limits. | `{}` +`prometheus.server.persistentVolume.enabled` | If true, Prometheus server will create a Persistent Volume Claim. | `true` +`prometheus.server.persistentVolume.size` | Prometheus server data Persistent Volume size. Default set to retain ~6000 samples per second for 15 days. | `32Gi` +`prometheus.server.retention` | Determines when to remove old data. | `15d` +`prometheus.server.resources` | Prometheus server resource requests and limits. | `{}` +`prometheus.nodeExporter.resources` | Node exporter resource requests and limits. | `{}` +`prometheus.nodeExporter.enabled` `prometheus.serviceAccounts.nodeExporter.create` | If false, do not crate NodeExporter daemonset. | `true` +`prometheus.alertmanager.persistentVolume.enabled` | If true, Alertmanager will create a Persistent Volume Claim. | `true` +`prometheus.pushgateway.persistentVolume.enabled` | If true, Prometheus Pushgateway will create a Persistent Volume Claim. | `true` +`persistentVolume.enabled` | If true, Kubecost will create a Persistent Volume Claim for product config data. | `true` +`persistentVolume.size` | Define PVC size for cost-analyzer | `0.2Gi` +`persistentVolume.dbSize` | Define PVC size for cost-analyzer's flat file database | `32.0Gi` +`ingress.enabled` | If true, Ingress will be created | `false` +`ingress.annotations` | Ingress annotations | `{}` +`ingress.paths` | Ingress paths | `["/"]` +`ingress.hosts` | Ingress hostnames | `[cost-analyzer.local]` +`ingress.tls` | Ingress TLS configuration (YAML) | `[]` +`networkPolicy.enabled` | If true, create a NetworkPolicy to deny egress | `false` +`networkCosts.enabled` | If true, collect network allocation metrics [More info](http://docs.kubecost.com/network-allocation) | `false` +`networkCosts.podMonitor.enabled` | If true, a [PodMonitor](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#podmonitor) for the network-cost daemonset is created | `false` +`serviceMonitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` +`serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` +`prometheusRule.enabled` | Set this to `true` to create PrometheusRule for Prometheus operator | `false` +`prometheusRule.additionalLabels` | Additional labels that can be used so PrometheusRule will be discovered by Prometheus | `{}` +`grafana.resources` | Grafana resource requests and limits. | `{}` +`grafana.sidecar.datasources.defaultDatasourceEnabled` | Set this to `false` to disable creation of Prometheus datasource in Grafana | `true` +`serviceAccount.create` | Set this to `false` if you want to create the service account `kubecost-cost-analyzer` on your own | `true` +`tolerations` | node taints to tolerate | `[]` +`affinity` | pod affinity | `{}` diff --git a/charts/kubecost/cost-analyzer/1.83.201/app-readme.md b/charts/kubecost/cost-analyzer/1.83.201/app-readme.md new file mode 100644 index 000000000..90fd50607 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/app-readme.md @@ -0,0 +1,25 @@ +# Kubecost + +[Kubecost](https://kubecost.com/) is an open-source Kubernetes cost monitoring solution. + +Kubecost gives teams visibility into current and historical Kubernetes spend and resource allocation. These models provide cost transparency in Kubernetes environments that support multiple applications, teams, departments, etc. + +To see more on the functionality of the full Kubecost product, please visit the [features page](https://kubecost.com/#features) on our website. + +Here is a summary of features enabled by this cost model: + +- Real-time cost allocation by Kubernetes service, deployment, namespace, label, statefulset, daemonset, pod, and container +- Dynamic asset pricing enabled by integrations with AWS, Azure, and GCP billing APIs +- Supports on-prem k8s clusters with custom pricing sheets +- Allocation for in-cluster resources like CPU, GPU, memory, and persistent volumes. +- Allocation for AWS & GCP out-of-cluster resources like RDS instances and S3 buckets with key (optional) +- Easily export pricing data to Prometheus with /metrics endpoint ([learn more](https://github.com/kubecost/cost-model/blob/develop/PROMETHEUS.md)) +- Free and open source distribution (Apache2 license) + +## Requirements + +- Kubernetes 1.8+ +- kube-state-metrics +- Grafana +- Prometheus +- Node Exporter diff --git a/charts/kubecost/cost-analyzer/1.83.201/attached-disks.json b/charts/kubecost/cost-analyzer/1.83.201/attached-disks.json new file mode 100644 index 000000000..88f60d983 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/attached-disks.json @@ -0,0 +1,444 @@ +{ + "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": 10, + "iteration": 1589748792557, + "links": [], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_fs_limit_bytes{instance=~'$disk', device!=\"tmpfs\", id=\"/\"}) by (instance)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "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": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\"}) by (instance) / sum(container_fs_limit_bytes{instance=~'$disk',device!=\"tmpfs\", id=\"/\"}) by (instance)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk 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": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "1 - sum(container_fs_inodes_free{instance=~'$disk',id=\"/\"}) by (instance) / sum(container_fs_inodes_total{instance=~'$disk',id=\"/\"}) by (instance)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "iNode 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": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_fs_usage_bytes{instance=~'$disk',id=\"/\"}) by (instance)", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decbytes", + "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 + } + } + ], + "schemaVersion": 16, + "style": "dark", + "tags": [ + "cost", + "utilization", + "metrics" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "disk", + "options": [], + "query": "query_result(sum(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance))", + "refresh": 1, + "regex": "/instance=\\\"(.*?)(\\\")/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "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": "", + "title": "Attached disk metrics", + "uid": "nBH7qBgMk", + "version": 2 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/Chart.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/Chart.yaml new file mode 100644 index 000000000..eb46b5995 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +appVersion: 6.0.0 +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 +name: grafana +sources: +- https://github.com/grafana/grafana +version: 1.17.2 diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/README.md b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/README.md new file mode 100644 index 000000000..03c70b520 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/README.md @@ -0,0 +1,162 @@ +# Grafana Helm Chart + +* Installs the web dashboarding system [Grafana](http://grafana.org/) + +## TL;DR; + +```console +$ helm install stable/grafana +``` + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +$ helm install --name my-release stable/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. + + +## Configuration + +| Parameter | Description | Default | +|---------------------------------|-----------------------------------------------|---------------------------------------------------------| +| `replicas` | Number of nodes | `1` | +| `deploymentStrategy` | Deployment strategy | `RollingUpdate` | +| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | +| `readinessProbe` | Rediness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| +| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "fsGroup": 472}` | +| `image.repository` | Image repository | `grafana/grafana` | +| `image.tag` | Image tag. (`Must be >= 5.0.0`) | `5.3.1` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Kubernetes port where service is exposed | `80` | +| `service.annotations` | Service annotations | `{}` | +| `service.labels` | Custom labels | `{}` | +| `ingress.enabled` | Enables Ingress | `false` | +| `ingress.annotations` | Ingress annotations | `{}` | +| `ingress.labels` | Custom labels | `{}` | +| `ingress.hosts` | Ingress accepted hostnames | `[]` | +| `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 | `{}` | +| `persistence.enabled` | Use persistent volume to store data | `false` | +| `persistence.size` | Size of persistent volume claim | `10Gi` | +| `persistence.existingClaim` | Use an existing PVC to persist data | `nil` | +| `persistence.storageClassName` | Type of persistent volume claim | `nil` | +| `persistence.accessModes` | Persistence access modes | `[]` | +| `persistence.subPath` | Mount a sub dir of the persistent volume | `""` | +| `schedulerName` | Alternate scheduler name | `nil` | +| `env` | Extra environment variables passed to pods | `{}` | +| `envFromSecret` | Name of a Kubenretes secret (must be manually created in the same namespace) containing values to be added to the environment | `""` | +| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | +| `plugins` | Plugins to be loaded along with Grafana | `[]` | +| `datasources` | Configure grafana datasources | `{}` | +| `dashboardProviders` | Configure grafana dashboard providers | `{}` | +| `dashboards` | Dashboards to import | `{}` | +| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | +| `grafana.ini` | Grafana's primary configuration | `{}` | +| `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 | `{}` | +| `podAnnotations` | Pod annotations | `{}` | +| `sidecar.dashboards.enabled` | Enabled the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | +| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `false` | +| `sidecar.datasources.enabled` | Enabled 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 | `false` | +| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials, this must have the keys `user` and `password`. | `""` | + +## Sidecar for dashboards + +If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana pod. This container watches all config maps 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 an reduction of multiple dashboards inside one configmap is currently not properly mirrored in grafana. +Example dashboard config: +``` +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-dashboard + labels: + grafana_dashboard: 1 +data: + k8s-dashboard.json: |- + [...] +``` + +## Sidecar for datasources + +If the parameter `sidecar.datasource.enabled` is set, a sidecar container is deployed in the grafana pod. This container watches all config maps in the cluster and filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in those configmaps are written to a folder and accessed by grafana on startup. Using these yaml files, the data sources in grafana can be modified. + +Example datasource config adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): +``` +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-datasource + labels: + grafana_datasource: 1 +data: + datasource.yaml: |- + # config file version + apiVersion: 1 + + # list of datasources that should be deleted from the database + deleteDatasources: + - name: Graphite + orgId: 1 + + # list of datasources to insert/update depending + # whats available in the database + 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 + +``` diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/NOTES.txt b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/NOTES.txt new file mode 100644 index 000000000..57e84cd69 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/NOTES.txt @@ -0,0 +1,37 @@ +1. Get your '{{ .Values.adminUser }}' user password by running: + + kubectl get secret --namespace {{ .Release.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" . }}.{{ .Release.Namespace }}.svc +{{ if .Values.ingress.enabled }} + 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 {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.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 {{ .Release.Namespace }} -w {{ template "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.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 {{ .Release.Namespace }} -l "app={{ template "grafana.fullname" . }},component={{ .Values.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.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/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/_helpers.tpl b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/_helpers.tpl new file mode 100644 index 000000000..3a3ebd3ec --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* 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 -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrole.yaml new file mode 100644 index 000000000..d49193651 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.rbac.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled }} +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps"] + verbs: ["get", "watch", "list"] +{{- else }} +rules: [] +{{- end}} +{{- end}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..99dada9f4 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/clusterrolebinding.yaml @@ -0,0 +1,25 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.rbac.create }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "grafana.fullname" . }}-clusterrolebinding + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ template "grafana.fullname" . }}-clusterrole + apiGroup: rbac.authorization.k8s.io +{{- end}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap-dashboard-provider.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap-dashboard-provider.yaml new file mode 100644 index 000000000..1765e9aff --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap-dashboard-provider.yaml @@ -0,0 +1,28 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.sidecar.dashboards.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-config-dashboards +data: + provider.yaml: |- + apiVersion: 1 + providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + options: + path: {{ .Values.sidecar.dashboards.folder }} +{{- end}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap.yaml new file mode 100644 index 000000000..d283d04c0 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/configmap.yaml @@ -0,0 +1,76 @@ +{{ if .Values.global.grafana.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: +{{- if .Values.plugins }} + plugins: {{ join "," .Values.plugins }} +{{- end }} + grafana.ini: | +{{- range $key, $value := index .Values "grafana.ini" }} + [{{ $key }}] + {{- range $elem, $elemVal := $value }} + {{ $elem }} = {{ $elemVal }} + {{- end }} +{{- end }} + +{{- if .Values.datasources }} + {{- range $key, $value := .Values.datasources }} + {{ $key }}: | +{{ toYaml $value | trim | indent 4 }} + {{- end -}} +{{- end -}} +{{- if .Values.global.prometheus.enabled }} + - access: proxy + isDefault: true + name: Prometheus + type: prometheus + url: http://{{ template "cost-analyzer.prometheus.server.name" . }}.{{ .Release.Namespace }}.svc +{{ else }} + - access: proxy + isDefault: true + name: Prometheus + type: prometheus + url: {{ .Values.global.prometheus.fqdn }} +{{- 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 }} + + {{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} + curl -sk \ + --connect-timeout 60 \ + --max-time 60 \ + -H "Accept: application/json" \ + -H "Content-Type: application/json;charset=UTF-8" \ + {{- 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 }} \ + > /var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/dashboards-json-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/dashboards-json-configmap.yaml new file mode 100644 index 000000000..c1ab8c4ba --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/dashboards-json-configmap.yaml @@ -0,0 +1,24 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.dashboards }} + {{- range $provider, $dashboards := .Values.dashboards }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} + labels: + app: {{ template "grafana.name" $ }} + chart: {{ template "grafana.chart" $ }} + release: {{ $.Release.Name }} + heritage: {{ $.Release.Service }} + dashboard-provider: {{ $provider }} +data: + {{- range $key, $value := $dashboards }} + {{- if hasKey $value "json" }} + {{ $key }}.json: | +{{ $value.json | indent 4 }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/deployment.yaml new file mode 100644 index 000000000..27422364a --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/deployment.yaml @@ -0,0 +1,276 @@ +{{ if .Values.global.grafana.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ template "grafana.name" . }} + release: {{ .Release.Name }} + strategy: + type: {{ .Values.deploymentStrategy }} + {{- if ne .Values.deploymentStrategy "RollingUpdate" }} + rollingUpdate: null + {{- end }} + template: + metadata: + labels: + app: {{ template "grafana.name" . }} + release: {{ .Release.Name }} +{{- with .Values.podAnnotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + spec: + serviceAccountName: {{ template "grafana.serviceAccountName" . }} +{{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" +{{- end }} +{{- if .Values.securityContext }} + securityContext: +{{ toYaml .Values.securityContext | indent 8 }} +{{- end }} +{{- if .Values.dashboards }} + initContainers: + - name: download-dashboards + image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} + command: ["sh", "/etc/grafana/download_dashboards.sh"] + volumeMounts: + - name: config + mountPath: "/etc/grafana/download_dashboards.sh" + subPath: download_dashboards.sh + - name: storage + mountPath: "/var/lib/grafana" + subPath: {{ .Values.persistence.subPath }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} +{{- end }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ . }} + {{- end}} + {{- end }} + containers: +{{- if .Values.sidecar.dashboards.enabled }} + - name: {{ template "grafana.name" . }}-sc-dashboard + image: "{{ .Values.sidecar.image }}" + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: LABEL + value: "{{ .Values.sidecar.dashboards.label }}" + - name: FOLDER + value: "{{ .Values.sidecar.dashboards.folder }}" + - name: ERROR_THROTTLE_SLEEP + value: "{{ .Values.sidecar.dashboards.error_throttle_sleep }}" + resources: +{{ toYaml .Values.sidecar.resources | indent 12 }} + volumeMounts: + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: {{ template "grafana.name" . }}-sc-datasources + image: "{{ .Values.sidecar.image }}" + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: ERROR_THROTTLE_SLEEP + value: "{{ .Values.sidecar.datasources.error_throttle_sleep }}" + resources: +{{ toYaml .Values.sidecar.resources | indent 12 }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/grafana.ini" + subPath: grafana.ini + - name: ldap + mountPath: "/etc/grafana/ldap.toml" + subPath: ldap.toml +{{- if .Values.dashboards }} + {{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if hasKey $value "json" }} + - 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 }} + - name: dashboards-{{ . }} + mountPath: "/var/lib/grafana/dashboards/{{ . }}" + {{- end }} +{{- end }} +{{- if .Values.datasources }} + - name: config + mountPath: "/etc/grafana/provisioning/datasources/datasources.yaml" + subPath: datasources.yaml +{{- end }} +{{- if .Values.dashboardProviders }} + - name: config + mountPath: "/etc/grafana/provisioning/dashboards/dashboardproviders.yaml" + subPath: dashboardproviders.yaml +{{- end }} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + - name: sc-dashboard-provider + mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" + subPath: provider.yaml +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} + - name: storage + mountPath: "/var/lib/grafana" + subPath: {{ .Values.persistence.subPath }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} + ports: + - name: service + containerPort: {{ .Values.service.port }} + protocol: TCP + - name: grafana + containerPort: 3000 + protocol: TCP + env: + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ template "grafana.fullname" . }} + key: admin-user + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "grafana.fullname" . }} + key: admin-password + {{- 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: user + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: password + {{- end }} +{{- range $key, $value := .Values.env }} + - name: "{{ $key }}" + value: "{{ $value }}" +{{- end }} + {{- if .Values.envFromSecret }} + envFrom: + - secretRef: + name: {{ .Values.envFromSecret }} + {{- end }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 12 }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 12 }} + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ template "grafana.fullname" . }} + {{- if .Values.dashboards }} + {{- range keys .Values.dashboards }} + - name: dashboards-{{ . }} + configMap: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsConfigMaps }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} + - name: dashboards-{{ $provider }} + configMap: + name: {{ $name }} + {{- end }} + {{- end }} + - name: ldap + secret: + {{- if .Values.ldap.existingSecret }} + secretName: {{ .Values.ldap.existingSecret }} + {{- else }} + secretName: {{ template "grafana.fullname" . }} + {{- end }} + items: + - key: ldap-toml + path: ldap.toml + - name: storage + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim | default (include "grafana.fullname" .) }} + {{- else }} + emptyDir: {} + {{- end -}} + {{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + emptyDir: {} + - name: sc-dashboard-provider + configMap: + name: {{ template "grafana.fullname" . }}-config-dashboards + {{- end }} + {{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + emptyDir: {} + {{- end -}} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/ingress.yaml new file mode 100644 index 000000000..556f0fab0 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/ingress.yaml @@ -0,0 +1,44 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels | indent 4 }} +{{- end }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..d446e8198 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/podsecuritypolicy.yaml @@ -0,0 +1,45 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.rbac.pspUseAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end}} + +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: false +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/pvc.yaml new file mode 100644 index 000000000..e13c78378 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/pvc.yaml @@ -0,0 +1,26 @@ +{{ if .Values.global.grafana.enabled }} +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- with .Values.persistence.annotations }} + annotations: +{{ toYaml . | indent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + storageClassName: {{ .Values.persistence.storageClassName }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/role.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/role.yaml new file mode 100644 index 000000000..6c9195769 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/role.yaml @@ -0,0 +1,20 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +{{- if .Values.rbac.pspEnabled }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}] +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/rolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/rolebinding.yaml new file mode 100644 index 000000000..e777ddabc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/rolebinding.yaml @@ -0,0 +1,20 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "grafana.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/secret.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/secret.yaml new file mode 100644 index 000000000..cd16c2fc7 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/secret.yaml @@ -0,0 +1,22 @@ +{{ if .Values.global.grafana.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: + admin-user: {{ .Values.adminUser | b64enc | quote }} + {{- if .Values.adminPassword }} + admin-password: {{ .Values.adminPassword | b64enc | quote }} + {{- else }} + admin-password: {{ randAlphaNum 40 | b64enc | quote }} + {{- end }} + {{- if not .Values.ldap.existingSecret }} + ldap-toml: {{ .Values.ldap.config | b64enc | quote }} + {{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/service.yaml new file mode 100644 index 000000000..32d108b90 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/service.yaml @@ -0,0 +1,51 @@ +{{ if .Values.global.grafana.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app: {{ template "grafana.name" . }} + chart: {{ template "grafana.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- with .Values.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- 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: tcp-service + port: {{ .Values.service.port }} + protocol: TCP + targetPort: 3000 +{{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{.Values.service.nodePort}} +{{ end }} + selector: + app: {{ template "grafana.name" . }} + release: {{ .Release.Name }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 000000000..bbcb5055e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{ if .Values.global.grafana.enabled }} +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ template "grafana.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + name: {{ template "grafana.serviceAccountName" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/values.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/values.yaml new file mode 100644 index 000000000..ae7909bb7 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/grafana/values.yaml @@ -0,0 +1,276 @@ +rbac: + create: true + pspEnabled: true + pspUseAppArmor: true +serviceAccount: + create: true + name: + +replicas: 1 + +deploymentStrategy: RollingUpdate + +readinessProbe: + httpGet: + path: /api/health + port: 3000 + +livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 30 + failureThreshold: 10 + +image: + repository: grafana/grafana + tag: 7.5.6 + 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/ + ## + # pullSecrets: + # - myRegistrKeySecretName + +securityContext: + runAsUser: 472 + fsGroup: 472 + +downloadDashboardsImage: + repository: appropriate/curl + tag: latest + pullPolicy: IfNotPresent + +## Pod Annotations +# podAnnotations: {} + +## 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: + type: ClusterIP + port: 80 + annotations: {} + labels: {} + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: / + hosts: + - chart-example.local + 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 +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + enabled: false + # storageClassName: default + # accessModes: + # - ReadWriteOnce + # size: 10Gi + # annotations: {} + # subPath: "" + # existingClaim: + +adminUser: admin +adminPassword: strongpassword + +## 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 +env: {} + +## 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 +envFromSecret: "" + +## 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 + +## 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: Prometheus2 +# type: prometheus +# url: http://prometheus-server.default.svc +# access: proxy +# isDefault: false + +## 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: +# prometheus-stats: +# gnetId: 3662 +# revision: 2 +# datasource: Prometheus + +## Reference to external ConfigMap per provider. Use provider name as key and ConfiMap 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/data + 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 + auth.anonymous: + enabled: true + org_role: Editor + org_name: Main Org. + +## 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: + # `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 in keys `user` and `password`. + existingSecret: "" + +## 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: kiwigrid/k8s-sidecar:1.12.2 + imagePullPolicy: IfNotPresent + resources: +# limits: +# cpu: 100m +# memory: 100Mi +# requests: +# cpu: 50m +# memory: 50Mi + dashboards: + enabled: false + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # folder in the pod that should hold the collected dashboards + folder: /tmp/dashboards + datasources: + enabled: false + # label that the configmaps with datasources are marked with + label: grafana_datasource diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/.helmignore b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/.helmignore new file mode 100644 index 000000000..825c00779 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/.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 +.project +.idea/ +*.tmproj + +OWNERS diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/Chart.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/Chart.yaml new file mode 100644 index 000000000..dd81a9c69 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +appVersion: 2.17.2 +description: Prometheus is a monitoring system and time series database. +home: https://prometheus.io/ +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +maintainers: +- email: gianrubio@gmail.com + name: gianrubio +- email: zanhsieh@gmail.com + name: zanhsieh +name: prometheus +sources: +- https://github.com/prometheus/alertmanager +- https://github.com/prometheus/prometheus +- https://github.com/prometheus/pushgateway +- https://github.com/prometheus/node_exporter +- https://github.com/kubernetes/kube-state-metrics +version: 11.0.2 diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/README.md b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/README.md new file mode 100644 index 000000000..dc32dcd15 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/README.md @@ -0,0 +1,471 @@ +# Prometheus + +[Prometheus](https://prometheus.io/), a [Cloud Native Computing Foundation](https://cncf.io/) project, is a systems and service monitoring system. It collects metrics from configured targets at given intervals, evaluates rule expressions, displays the results, and can trigger alerts if some condition is observed to be true. + +## TL;DR; + +```console +$ helm install stable/prometheus +``` + +## Introduction + +This chart bootstraps a [Prometheus](https://prometheus.io/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.3+ with Beta APIs enabled + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +$ helm install --name my-release stable/prometheus +``` + +The command deploys Prometheus on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## 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. + +## Prometheus 2.x + +Prometheus version 2.x has made changes to alertmanager, storage and recording rules. Check out the migration guide [here](https://prometheus.io/docs/prometheus/2.0/migration/) + +Users of this chart will need to update their alerting rules to the new format before they can upgrade. + +## Upgrading from previous chart versions. + +Version 9.0 adds a new option to enable or disable the Prometheus Server. +This supports the use case of running a Prometheus server in one k8s cluster and scraping exporters in another cluster while using the same chart for each deployment. +To install the server `server.enabled` must be set to `true`. + +As of version 5.0, this chart uses Prometheus 2.x. This version of prometheus introduces a new data format and is not compatible with prometheus 1.x. It is recommended to install this as a new release, as updating existing releases will not work. See the [prometheus docs](https://prometheus.io/docs/prometheus/latest/migration/#storage) for instructions on retaining your old data. + +### Example migration + +Assuming you have an existing release of the prometheus chart, named `prometheus-old`. In order to update to prometheus 2.x while keeping your old data do the following: + +1. Update the `prometheus-old` release. Disable scraping on every component besides the prometheus server, similar to the configuration below: + + ``` + alertmanager: + enabled: false + alertmanagerFiles: + alertmanager.yml: "" + kubeStateMetrics: + enabled: false + nodeExporter: + enabled: false + pushgateway: + enabled: false + server: + extraArgs: + storage.local.retention: 720h + serverFiles: + alerts: "" + prometheus.yml: "" + rules: "" + ``` + +1. Deploy a new release of the chart with version 5.0+ using prometheus 2.x. In the values.yaml set the scrape config as usual, and also add the `prometheus-old` instance as a remote-read target. + + ``` + prometheus.yml: + ... + remote_read: + - url: http://prometheus-old/api/v1/read + ... + ``` + + Old data will be available when you query the new prometheus instance. + +## Scraping Pod Metrics via Annotations + +This chart uses a default configuration that causes prometheus +to scrape a variety of kubernetes resource types, provided they have the correct annotations. +In this section we describe how to configure pods to be scraped; +for information on how other resource types can be scraped you can +do a `helm template` to get the kubernetes resource definitions, +and then reference the prometheus configuration in the ConfigMap against the prometheus documentation +for [relabel_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) +and [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config). + +In order to get prometheus to scrape pods, you must add annotations to the the pods as below: + +``` +metadata: + annotations: + prometheus.io/scrape: "true" + prometheus.io/path: /metrics + prometheus.io/port: "8080" +spec: +... +``` + +You should adjust `prometheus.io/path` based on the URL that your pod serves metrics from. +`prometheus.io/port` should be set to the port that your pod serves metrics from. +Note that the values for `prometheus.io/scrape` and `prometheus.io/port` must be +enclosed in double quotes. + +## Configuration + +The following table lists the configurable parameters of the Prometheus chart and their default values. + +Parameter | Description | Default +--------- | ----------- | ------- +`alertmanager.enabled` | If true, create alertmanager | `true` +`alertmanager.name` | alertmanager container name | `alertmanager` +`alertmanager.image.repository` | alertmanager container image repository | `prom/alertmanager` +`alertmanager.image.tag` | alertmanager container image tag | `v0.20.0` +`alertmanager.image.pullPolicy` | alertmanager container image pull policy | `IfNotPresent` +`alertmanager.prefixURL` | The prefix slug at which the server can be accessed | `` +`alertmanager.baseURL` | The external url at which the server can be accessed | `"http://localhost:9093"` +`alertmanager.extraArgs` | Additional alertmanager container arguments | `{}` +`alertmanager.extraSecretMounts` | Additional alertmanager Secret mounts | `[]` +`alertmanager.configMapOverrideName` | Prometheus alertmanager ConfigMap override where full-name is `{{.Release.Name}}-{{.Values.alertmanager.configMapOverrideName}}` and setting this value will prevent the default alertmanager ConfigMap from being generated | `""` +`alertmanager.configFromSecret` | The name of a secret in the same kubernetes namespace which contains the Alertmanager config, setting this value will prevent the default alertmanager ConfigMap from being generated | `""` +`alertmanager.configFileName` | The configuration file name to be loaded to alertmanager. Must match the key within configuration loaded from ConfigMap/Secret. | `alertmanager.yml` +`alertmanager.ingress.enabled` | If true, alertmanager Ingress will be created | `false` +`alertmanager.ingress.annotations` | alertmanager Ingress annotations | `{}` +`alertmanager.ingress.extraLabels` | alertmanager Ingress additional labels | `{}` +`alertmanager.ingress.hosts` | alertmanager Ingress hostnames | `[]` +`alertmanager.ingress.extraPaths` | Ingress extra paths to prepend to every alertmanager 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) | `[]` +`alertmanager.ingress.tls` | alertmanager Ingress TLS configuration (YAML) | `[]` +`alertmanager.nodeSelector` | node labels for alertmanager pod assignment | `{}` +`alertmanager.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` +`alertmanager.affinity` | pod affinity | `{}` +`alertmanager.podDisruptionBudget.enabled` | If true, create a PodDisruptionBudget | `false` +`alertmanager.podDisruptionBudget.maxUnavailable` | Maximum unavailable instances in PDB | `1` +`alertmanager.schedulerName` | alertmanager alternate scheduler name | `nil` +`alertmanager.persistentVolume.enabled` | If true, alertmanager will create a Persistent Volume Claim | `true` +`alertmanager.persistentVolume.accessModes` | alertmanager data Persistent Volume access modes | `[ReadWriteOnce]` +`alertmanager.persistentVolume.annotations` | Annotations for alertmanager Persistent Volume Claim | `{}` +`alertmanager.persistentVolume.existingClaim` | alertmanager data Persistent Volume existing claim name | `""` +`alertmanager.persistentVolume.mountPath` | alertmanager data Persistent Volume mount root path | `/data` +`alertmanager.persistentVolume.size` | alertmanager data Persistent Volume size | `2Gi` +`alertmanager.persistentVolume.storageClass` | alertmanager data Persistent Volume Storage Class | `unset` +`alertmanager.persistentVolume.volumeBindingMode` | alertmanager data Persistent Volume Binding Mode | `unset` +`alertmanager.persistentVolume.subPath` | Subdirectory of alertmanager data Persistent Volume to mount | `""` +`alertmanager.podAnnotations` | annotations to be added to alertmanager pods | `{}` +`alertmanager.podLabels` | labels to be added to Prometheus AlertManager pods | `{}` +`alertmanager.podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | `{}` | +`alertmanager.replicaCount` | desired number of alertmanager pods | `1` +`alertmanager.statefulSet.enabled` | If true, use a statefulset instead of a deployment for pod management | `false` +`alertmanager.statefulSet.podManagementPolicy` | podManagementPolicy of alertmanager pods | `OrderedReady` +`alertmanager.statefulSet.headless.annotations` | annotations for alertmanager headless service | `{}` +`alertmanager.statefulSet.headless.labels` | labels for alertmanager headless service | `{}` +`alertmanager.statefulSet.headless.enableMeshPeer` | If true, enable the mesh peer endpoint for the headless service | `{}` +`alertmanager.statefulSet.headless.servicePort` | alertmanager headless service port | `80` +`alertmanager.priorityClassName` | alertmanager priorityClassName | `nil` +`alertmanager.resources` | alertmanager pod resource requests & limits | `{}` +`alertmanager.securityContext` | Custom [security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for Alert Manager containers | `{}` +`alertmanager.service.annotations` | annotations for alertmanager service | `{}` +`alertmanager.service.clusterIP` | internal alertmanager cluster service IP | `""` +`alertmanager.service.externalIPs` | alertmanager service external IP addresses | `[]` +`alertmanager.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` +`alertmanager.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` +`alertmanager.service.servicePort` | alertmanager service port | `80` +`alertmanager.service.sessionAffinity` | Session Affinity for alertmanager service, can be `None` or `ClientIP` | `None` +`alertmanager.service.type` | type of alertmanager service to create | `ClusterIP` +`alertmanager.strategy` | Deployment strategy | `{ "type": "RollingUpdate" }` +`alertmanagerFiles.alertmanager.yml` | Prometheus alertmanager configuration | example configuration +`configmapReload.prometheus.enabled` | If false, the configmap-reload container for Prometheus will not be deployed | `true` +`configmapReload.prometheus.name` | configmap-reload container name | `configmap-reload` +`configmapReload.prometheus.image.repository` | configmap-reload container image repository | `jimmidyson/configmap-reload` +`configmapReload.prometheus.image.tag` | configmap-reload container image tag | `v0.3.0` +`configmapReload.prometheus.image.pullPolicy` | configmap-reload container image pull policy | `IfNotPresent` +`configmapReload.prometheus.extraArgs` | Additional configmap-reload container arguments | `{}` +`configmapReload.prometheus.extraVolumeDirs` | Additional configmap-reload volume directories | `{}` +`configmapReload.prometheus.extraConfigmapMounts` | Additional configmap-reload configMap mounts | `[]` +`configmapReload.prometheus.resources` | configmap-reload pod resource requests & limits | `{}` +`configmapReload.alertmanager.enabled` | If false, the configmap-reload container for AlertManager will not be deployed | `true` +`configmapReload.alertmanager.name` | configmap-reload container name | `configmap-reload` +`configmapReload.alertmanager.image.repository` | configmap-reload container image repository | `jimmidyson/configmap-reload` +`configmapReload.alertmanager.image.tag` | configmap-reload container image tag | `v0.3.0` +`configmapReload.alertmanager.image.pullPolicy` | configmap-reload container image pull policy | `IfNotPresent` +`configmapReload.alertmanager.extraArgs` | Additional configmap-reload container arguments | `{}` +`configmapReload.alertmanager.extraVolumeDirs` | Additional configmap-reload volume directories | `{}` +`configmapReload.alertmanager.extraConfigmapMounts` | Additional configmap-reload configMap mounts | `[]` +`configmapReload.alertmanager.resources` | configmap-reload pod resource requests & limits | `{}` +`initChownData.enabled` | If false, don't reset data ownership at startup | true +`initChownData.name` | init-chown-data container name | `init-chown-data` +`initChownData.image.repository` | init-chown-data container image repository | `busybox` +`initChownData.image.tag` | init-chown-data container image tag | `latest` +`initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` +`initChownData.resources` | init-chown-data pod resource requests & limits | `{}` +`kubeStateMetrics.enabled` | If true, create kube-state-metrics sub-chart, see the [kube-state-metrics chart for configuration options](https://github.com/helm/charts/tree/master/stable/kube-state-metrics) | `true` +`nodeExporter.enabled` | If true, create node-exporter | `true` +`nodeExporter.name` | node-exporter container name | `node-exporter` +`nodeExporter.image.repository` | node-exporter container image repository| `prom/node-exporter` +`nodeExporter.image.tag` | node-exporter container image tag | `v0.18.1` +`nodeExporter.image.pullPolicy` | node-exporter container image pull policy | `IfNotPresent` +`nodeExporter.extraArgs` | Additional node-exporter container arguments | `{}` +`nodeExporter.extraHostPathMounts` | Additional node-exporter hostPath mounts | `[]` +`nodeExporter.extraConfigmapMounts` | Additional node-exporter configMap mounts | `[]` +`nodeExporter.hostNetwork` | If true, node-exporter pods share the host network namespace | `true` +`nodeExporter.hostPID` | If true, node-exporter pods share the host PID namespace | `true` +`nodeExporter.nodeSelector` | node labels for node-exporter pod assignment | `{}` +`nodeExporter.podAnnotations` | annotations to be added to node-exporter pods | `{}` +`nodeExporter.pod.labels` | labels to be added to node-exporter pods | `{}` +`nodeExporter.podDisruptionBudget.enabled` | If true, create a PodDisruptionBudget | `false` +`nodeExporter.podDisruptionBudget.maxUnavailable` | Maximum unavailable instances in PDB | `1` +`nodeExporter.podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | `{}` | +`nodeExporter.podSecurityPolicy.enabled` | Specify if a Pod Security Policy for node-exporter must be created | `false` +`nodeExporter.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` +`nodeExporter.priorityClassName` | node-exporter priorityClassName | `nil` +`nodeExporter.resources` | node-exporter resource requests and limits (YAML) | `{}` +`nodeExporter.securityContext` | securityContext for containers in pod | `{}` +`nodeExporter.service.annotations` | annotations for node-exporter service | `{prometheus.io/scrape: "true"}` +`nodeExporter.service.clusterIP` | internal node-exporter cluster service IP | `None` +`nodeExporter.service.externalIPs` | node-exporter service external IP addresses | `[]` +`nodeExporter.service.hostPort` | node-exporter service host port | `9100` +`nodeExporter.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` +`nodeExporter.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` +`nodeExporter.service.servicePort` | node-exporter service port | `9100` +`nodeExporter.service.type` | type of node-exporter service to create | `ClusterIP` +`podSecurityPolicy.enabled` | If true, create & use pod security policies resources | `false` +`pushgateway.enabled` | If true, create pushgateway | `true` +`pushgateway.name` | pushgateway container name | `pushgateway` +`pushgateway.image.repository` | pushgateway container image repository | `prom/pushgateway` +`pushgateway.image.tag` | pushgateway container image tag | `v1.0.1` +`pushgateway.image.pullPolicy` | pushgateway container image pull policy | `IfNotPresent` +`pushgateway.extraArgs` | Additional pushgateway container arguments | `{}` +`pushgateway.ingress.enabled` | If true, pushgateway Ingress will be created | `false` +`pushgateway.ingress.annotations` | pushgateway Ingress annotations | `{}` +`pushgateway.ingress.hosts` | pushgateway Ingress hostnames | `[]` +`pushgateway.ingress.extraPaths` | Ingress extra paths to prepend to every pushgateway 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) | `[]` +`pushgateway.ingress.tls` | pushgateway Ingress TLS configuration (YAML) | `[]` +`pushgateway.nodeSelector` | node labels for pushgateway pod assignment | `{}` +`pushgateway.podAnnotations` | annotations to be added to pushgateway pods | `{}` +`pushgateway.podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | `{}` | +`pushgateway.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` +`pushgateway.replicaCount` | desired number of pushgateway pods | `1` +`pushgateway.podDisruptionBudget.enabled` | If true, create a PodDisruptionBudget | `false` +`pushgateway.podDisruptionBudget.maxUnavailable` | Maximum unavailable instances in PDB | `1` +`pushgateway.schedulerName` | pushgateway alternate scheduler name | `nil` +`pushgateway.persistentVolume.enabled` | If true, Prometheus pushgateway will create a Persistent Volume Claim | `false` +`pushgateway.persistentVolume.accessModes` | Prometheus pushgateway data Persistent Volume access modes | `[ReadWriteOnce]` +`pushgateway.persistentVolume.annotations` | Prometheus pushgateway data Persistent Volume annotations | `{}` +`pushgateway.persistentVolume.existingClaim` | Prometheus pushgateway data Persistent Volume existing claim name | `""` +`pushgateway.persistentVolume.mountPath` | Prometheus pushgateway data Persistent Volume mount root path | `/data` +`pushgateway.persistentVolume.size` | Prometheus pushgateway data Persistent Volume size | `2Gi` +`pushgateway.persistentVolume.storageClass` | Prometheus pushgateway data Persistent Volume Storage Class | `unset` +`pushgateway.persistentVolume.volumeBindingMode` | Prometheus pushgateway data Persistent Volume Binding Mode | `unset` +`pushgateway.persistentVolume.subPath` | Subdirectory of Prometheus server data Persistent Volume to mount | `""` +`pushgateway.priorityClassName` | pushgateway priorityClassName | `nil` +`pushgateway.resources` | pushgateway pod resource requests & limits | `{}` +`pushgateway.service.annotations` | annotations for pushgateway service | `{}` +`pushgateway.service.clusterIP` | internal pushgateway cluster service IP | `""` +`pushgateway.service.externalIPs` | pushgateway service external IP addresses | `[]` +`pushgateway.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` +`pushgateway.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` +`pushgateway.service.servicePort` | pushgateway service port | `9091` +`pushgateway.service.type` | type of pushgateway service to create | `ClusterIP` +`pushgateway.strategy` | Deployment strategy | `{ "type": "RollingUpdate" }` +`rbac.create` | If true, create & use RBAC resources | `true` +`server.enabled` | If false, Prometheus server will not be created | `true` +`server.name` | Prometheus server container name | `server` +`server.image.repository` | Prometheus server container image repository | `prom/prometheus` +`server.image.tag` | Prometheus server container image tag | `v2.16.0` +`server.image.pullPolicy` | Prometheus server container image pull policy | `IfNotPresent` +`server.configPath` | Path to a prometheus server config file on the container FS | `/etc/config/prometheus.yml` +`server.global.scrape_interval` | How frequently to scrape targets by default | `1m` +`server.global.scrape_timeout` | How long until a scrape request times out | `10s` +`server.global.evaluation_interval` | How frequently to evaluate rules | `1m` +`server.remoteWrite` | The remote write feature of Prometheus allow transparently sending samples. | `{}` +`server.remoteRead` | The remote read feature of Prometheus allow transparently receiving samples. | `{}` +`server.extraArgs` | Additional Prometheus server container arguments | `{}` +`server.extraFlags` | Additional Prometheus server container flags | `["web.enable-lifecycle"]` +`server.extraInitContainers` | Init containers to launch alongside the server | `[]` +`server.prefixURL` | The prefix slug at which the server can be accessed | `` +`server.baseURL` | The external url at which the server can be accessed | `` +`server.env` | Prometheus server environment variables | `[]` +`server.extraHostPathMounts` | Additional Prometheus server hostPath mounts | `[]` +`server.extraConfigmapMounts` | Additional Prometheus server configMap mounts | `[]` +`server.extraSecretMounts` | Additional Prometheus server Secret mounts | `[]` +`server.extraVolumeMounts` | Additional Prometheus server Volume mounts | `[]` +`server.extraVolumes` | Additional Prometheus server Volumes | `[]` +`server.configMapOverrideName` | Prometheus server ConfigMap override where full-name is `{{.Release.Name}}-{{.Values.server.configMapOverrideName}}` and setting this value will prevent the default server ConfigMap from being generated | `""` +`server.ingress.enabled` | If true, Prometheus server Ingress will be created | `false` +`server.ingress.annotations` | Prometheus server Ingress annotations | `[]` +`server.ingress.extraLabels` | Prometheus server Ingress additional labels | `{}` +`server.ingress.hosts` | Prometheus server Ingress hostnames | `[]` +`server.ingress.extraPaths` | Ingress extra paths to prepend to every Prometheus server 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) | `[]` +`server.ingress.tls` | Prometheus server Ingress TLS configuration (YAML) | `[]` +`server.nodeSelector` | node labels for Prometheus server pod assignment | `{}` +`server.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` +`server.affinity` | pod affinity | `{}` +`server.podDisruptionBudget.enabled` | If true, create a PodDisruptionBudget | `false` +`server.podDisruptionBudget.maxUnavailable` | Maximum unavailable instances in PDB | `1` +`server.priorityClassName` | Prometheus server priorityClassName | `nil` +`server.schedulerName` | Prometheus server alternate scheduler name | `nil` +`server.persistentVolume.enabled` | If true, Prometheus server will create a Persistent Volume Claim | `true` +`server.persistentVolume.accessModes` | Prometheus server data Persistent Volume access modes | `[ReadWriteOnce]` +`server.persistentVolume.annotations` | Prometheus server data Persistent Volume annotations | `{}` +`server.persistentVolume.existingClaim` | Prometheus server data Persistent Volume existing claim name | `""` +`server.persistentVolume.mountPath` | Prometheus server data Persistent Volume mount root path | `/data` +`server.persistentVolume.size` | Prometheus server data Persistent Volume size | `8Gi` +`server.persistentVolume.storageClass` | Prometheus server data Persistent Volume Storage Class | `unset` +`server.persistentVolume.volumeBindingMode` | Prometheus server data Persistent Volume Binding Mode | `unset` +`server.persistentVolume.subPath` | Subdirectory of Prometheus server data Persistent Volume to mount | `""` +`server.emptyDir.sizeLimit` | emptyDir sizeLimit if a Persistent Volume is not used | `""` +`server.podAnnotations` | annotations to be added to Prometheus server pods | `{}` +`server.podLabels` | labels to be added to Prometheus server pods | `{}` +`server.alertmanagers` | Prometheus AlertManager configuration for the Prometheus server | `{}` +`server.deploymentAnnotations` | annotations to be added to Prometheus server deployment | `{}` +`server.podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | `{}` | +`server.replicaCount` | desired number of Prometheus server pods | `1` +`server.statefulSet.enabled` | If true, use a statefulset instead of a deployment for pod management | `false` +`server.statefulSet.annotations` | annotations to be added to Prometheus server stateful set | `{}` +`server.statefulSet.labels` | labels to be added to Prometheus server stateful set | `{}` +`server.statefulSet.podManagementPolicy` | podManagementPolicy of server pods | `OrderedReady` +`server.statefulSet.headless.annotations` | annotations for Prometheus server headless service | `{}` +`server.statefulSet.headless.labels` | labels for Prometheus server headless service | `{}` +`server.statefulSet.headless.servicePort` | Prometheus server headless service port | `80` +`server.resources` | Prometheus server resource requests and limits | `{}` +`server.verticalAutoscaler.enabled` | If true a VPA object will be created for the controller (either StatefulSet or Deployemnt, based on above configs) | `false` +`server.securityContext` | Custom [security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for server containers | `{}` +`server.service.annotations` | annotations for Prometheus server service | `{}` +`server.service.clusterIP` | internal Prometheus server cluster service IP | `""` +`server.service.externalIPs` | Prometheus server service external IP addresses | `[]` +`server.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` +`server.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` +`server.service.nodePort` | Port to be used as the service NodePort (ignored if `server.service.type` is not `NodePort`) | `0` +`server.service.servicePort` | Prometheus server service port | `80` +`server.service.sessionAffinity` | Session Affinity for server service, can be `None` or `ClientIP` | `None` +`server.service.type` | type of Prometheus server service to create | `ClusterIP` +`server.service.gRPC.enabled` | If true, open a second port on the service for gRPC | `false` +`server.service.gRPC.servicePort` | Prometheus service gRPC port, (ignored if `server.service.gRPC.enabled` is not `true`) | `10901` +`server.service.gRPC.nodePort` | Port to be used as gRPC nodePort in the prometheus service | `0` +`server.service.statefulsetReplica.enabled` | If true, send the traffic from the service to only one replica of the replicaset | `false` +`server.service.statefulsetReplica.replica` | Which replica to send the traffice to | `0` +`server.sidecarContainers` | array of snippets with your sidecar containers for prometheus server | `""` +`server.strategy` | Deployment strategy | `{ "type": "RollingUpdate" }` +`serviceAccounts.alertmanager.create` | If true, create the alertmanager service account | `true` +`serviceAccounts.alertmanager.name` | name of the alertmanager service account to use or create | `{{ prometheus.alertmanager.fullname }}` +`serviceAccounts.kubeStateMetrics.create` | If true, create the kubeStateMetrics service account | `true` +`serviceAccounts.kubeStateMetrics.name` | name of the kubeStateMetrics service account to use or create | `{{ prometheus.kubeStateMetrics.fullname }}` +`serviceAccounts.nodeExporter.create` | If true, create the nodeExporter service account | `true` +`serviceAccounts.nodeExporter.name` | name of the nodeExporter service account to use or create | `{{ prometheus.nodeExporter.fullname }}` +`serviceAccounts.pushgateway.create` | If true, create the pushgateway service account | `true` +`serviceAccounts.pushgateway.name` | name of the pushgateway service account to use or create | `{{ prometheus.pushgateway.fullname }}` +`serviceAccounts.server.create` | If true, create the server service account | `true` +`serviceAccounts.server.name` | name of the server service account to use or create | `{{ prometheus.server.fullname }}` +`server.terminationGracePeriodSeconds` | Prometheus server Pod termination grace period | `300` +`server.retention` | (optional) Prometheus data retention | `"15d"` +`serverFiles.alerts` | (Deprecated) Prometheus server alerts configuration | `{}` +`serverFiles.rules` | (Deprecated) Prometheus server rules configuration | `{}` +`serverFiles.alerting_rules.yml` | Prometheus server alerts configuration | `{}` +`serverFiles.recording_rules.yml` | Prometheus server rules configuration | `{}` +`serverFiles.prometheus.yml` | Prometheus server scrape configuration | example configuration +`extraScrapeConfigs` | Prometheus server additional scrape configuration | "" +`alertRelabelConfigs` | Prometheus server [alert relabeling configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs) for H/A prometheus | "" +`networkPolicy.enabled` | Enable NetworkPolicy | `false` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +$ helm install stable/prometheus --name my-release \ + --set server.terminationGracePeriodSeconds=360 +``` + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +$ helm install stable/prometheus --name my-release -f values.yaml +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +Note that you have multiple yaml files. This is particularly useful when you have alerts belonging to multiple services in the cluster. For example, + +```yaml +# values.yaml +# ... + +# service1-alert.yaml +serverFiles: + alerts: + service1: + - alert: anAlert + # ... + +# service2-alert.yaml +serverFiles: + alerts: + service2: + - alert: anAlert + # ... +``` + +```console +$ helm install stable/prometheus --name my-release -f values.yaml -f service1-alert.yaml -f service2-alert.yaml +``` + +### RBAC Configuration +Roles and RoleBindings resources will be created automatically for `server` and `kubeStateMetrics` services. + +To manually setup RBAC you need to set the parameter `rbac.create=false` and specify the service account to be used for each service by setting the parameters: `serviceAccounts.{{ component }}.create` to `false` and `serviceAccounts.{{ component }}.name` to the name of a pre-existing service account. + +> **Tip**: You can refer to the default `*-clusterrole.yaml` and `*-clusterrolebinding.yaml` files in [templates](templates/) to customize your own. + +### ConfigMap Files +AlertManager is configured through [alertmanager.yml](https://prometheus.io/docs/alerting/configuration/). This file (and any others listed in `alertmanagerFiles`) will be mounted into the `alertmanager` pod. + +Prometheus is configured through [prometheus.yml](https://prometheus.io/docs/operating/configuration/). This file (and any others listed in `serverFiles`) will be mounted into the `server` pod. + +### Ingress TLS +If your cluster allows automatic creation/retrieval of TLS certificates (e.g. [kube-lego](https://github.com/jetstack/kube-lego)), please refer to the documentation for that mechanism. + +To manually configure TLS, first create/retrieve a key & certificate pair for the address(es) you wish to protect. Then create a TLS secret in the namespace: + +```console +kubectl create secret tls prometheus-server-tls --cert=path/to/tls.cert --key=path/to/tls.key +``` + +Include the secret's name, along with the desired hostnames, in the alertmanager/server Ingress TLS section of your custom `values.yaml` file: + +```yaml +server: + ingress: + ## If true, Prometheus server Ingress will be created + ## + enabled: true + + ## Prometheus server Ingress hostnames + ## Must be provided if Ingress is enabled + ## + hosts: + - prometheus.domain.com + + ## Prometheus server Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: + - secretName: prometheus-server-tls + hosts: + - prometheus.domain.com +``` + +### NetworkPolicy + +Enabling Network Policy for Prometheus will secure connections to Alert Manager +and Kube State Metrics by only accepting connections from Prometheus Server. +All inbound connections to Prometheus Server are still allowed. + +To enable network policy for Prometheus, install a networking plugin that +implements the Kubernetes NetworkPolicy spec, and set `networkPolicy.enabled` to true. + +If NetworkPolicy is enabled for Prometheus' scrape targets, you may also need +to manually create a networkpolicy which allows it. diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/.helmignore b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/.helmignore new file mode 100644 index 000000000..f0c131944 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/.helmignore @@ -0,0 +1,21 @@ +# 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 +.project +.idea/ +*.tmproj diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/Chart.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/Chart.yaml new file mode 100644 index 000000000..7752ccb44 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +appVersion: 1.9.5 +description: Install kube-state-metrics to generate and expose cluster-level metrics +home: https://github.com/kubernetes/kube-state-metrics/ +keywords: +- metric +- monitoring +- prometheus +- kubernetes +maintainers: +- email: jose@armesto.net + name: fiunchinho +- email: tariq.ibrahim@mulesoft.com + name: tariq1890 +- email: manuel@rueg.eu + name: mrueg +name: kube-state-metrics +sources: +- https://github.com/kubernetes/kube-state-metrics/ +version: 2.7.2 diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/OWNERS b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/OWNERS new file mode 100644 index 000000000..6ffd97d74 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/OWNERS @@ -0,0 +1,8 @@ +approvers: +- fiunchinho +- tariq1890 +- mrueg +reviewers: +- fiunchinho +- tariq1890 +- mrueg diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/README.md b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/README.md new file mode 100644 index 000000000..5c6456983 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/README.md @@ -0,0 +1,73 @@ +# kube-state-metrics Helm Chart + +* Installs the [kube-state-metrics agent](https://github.com/kubernetes/kube-state-metrics). + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +$ helm install stable/kube-state-metrics +``` + +## Configuration + +| Parameter | Description | Default | +|:---------------------------------------------|:--------------------------------------------------------------------------------------|:-------------------------------------------| +| `image.repository` | The image repository to pull from | quay.io/coreos/kube-state-metrics | +| `image.tag` | The image tag to pull from | `v1.9.5` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `replicas` | Number of replicas | `1` | +| `autosharding.enabled` | Set to `true` to automatically shard data across `replicas` pods. EXPERIMENTAL | `false` | +| `service.port` | The port of the container | `8080` | +| `service.annotations` | Annotations to be added to the service | `{}` | +| `customLabels` | Custom labels to apply to service, deployment and pods | `{}` | +| `hostNetwork` | Whether or not to use the host network | `false` | +| `prometheusScrape` | Whether or not enable prom scrape | `true` | +| `rbac.create` | If true, create & use RBAC resources | `true` | +| `serviceAccount.create` | If true, create & use serviceAccount | `true` | +| `serviceAccount.name` | If not set & create is true, use template fullname | | +| `serviceAccount.imagePullSecrets` | Specify image pull secrets field | `[]` | +| `podSecurityPolicy.enabled` | If true, create & use PodSecurityPolicy resources | `false` | +| `podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | {} | +| `securityContext.enabled` | Enable security context | `true` | +| `securityContext.fsGroup` | Group ID for the container | `65534` | +| `securityContext.runAsUser` | User ID for the container | `65534` | +| `priorityClassName` | Name of Priority Class to assign pods | `nil` | +| `nodeSelector` | Node labels for pod assignment | {} | +| `affinity` | Affinity settings for pod assignment | {} | +| `tolerations` | Tolerations for pod assignment | [] | +| `podAnnotations` | Annotations to be added to the pod | {} | +| `resources` | kube-state-metrics resource requests and limits | {} | +| `collectors.certificatesigningrequests` | Enable the certificatesigningrequests collector. | `true` | +| `collectors.configmaps` | Enable the configmaps collector. | `true` | +| `collectors.cronjobs` | Enable the cronjobs collector. | `true` | +| `collectors.daemonsets` | Enable the daemonsets collector. | `true` | +| `collectors.deployments` | Enable the deployments collector. | `true` | +| `collectors.endpoints` | Enable the endpoints collector. | `true` | +| `collectors.horizontalpodautoscalers` | Enable the horizontalpodautoscalers collector. | `true` | +| `collectors.ingresses` | Enable the ingresses collector. | `true` | +| `collectors.jobs` | Enable the jobs collector. | `true` | +| `collectors.limitranges` | Enable the limitranges collector. | `true` | +| `collectors.mutatingwebhookconfigurations` | Enable the mutatingwebhookconfigurations collector. | `false` | +| `collectors.namespaces` | Enable the namespaces collector. | `true` | +| `collectors.nodes` | Enable the nodes collector. | `true` | +| `collectors.persistentvolumeclaims` | Enable the persistentvolumeclaims collector. | `true` | +| `collectors.persistentvolumes` | Enable the persistentvolumes collector. | `true` | +| `collectors.poddisruptionbudgets` | Enable the poddisruptionbudgets collector. | `true` | +| `collectors.pods` | Enable the pods collector. | `true` | +| `collectors.replicasets` | Enable the replicasets collector. | `true` | +| `collectors.replicationcontrollers` | Enable the replicationcontrollers collector. | `true` | +| `collectors.resourcequotas` | Enable the resourcequotas collector. | `true` | +| `collectors.secrets` | Enable the secrets collector. | `true` | +| `collectors.services` | Enable the services collector. | `true` | +| `collectors.statefulsets` | Enable the statefulsets collector. | `true` | +| `collectors.storageclasses` | Enable the storageclasses collector. | `true` | +| `collectors.validatingwebhookconfigurations` | Enable the validatingwebhookconfigurations collector. | `false` | +| `collectors.verticalpodautoscalers` | Enable the verticalpodautoscalers collector. | `false` | +| `collectors.volumeattachments` | Enable the volumeattachments collector. | `false` | +| `prometheus.monitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` | +| `prometheus.monitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `prometheus.monitor.namespace` | Namespace where servicemonitor resource should be created | `the same namespace as kube-state-metrics` | +| `prometheus.monitor.honorLabels` | Honor metric labels | `false` | +| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt new file mode 100644 index 000000000..5a646e0cc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt @@ -0,0 +1,10 @@ +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. +The exposed metrics can be found here: +https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics + +The metrics are exported on the HTTP endpoint /metrics on the listening port. +In your case, {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc.cluster.local:{{ .Values.service.port }}/metrics + +They are served either as plaintext or protobuf depending on the Accept header. +They are designed to be consumed either by Prometheus itself or by a scraper that is compatible with scraping a Prometheus client endpoint. + diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl new file mode 100644 index 000000000..6ae0e647f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl @@ -0,0 +1,47 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "kube-state-metrics.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 "kube-state-metrics.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 the name of the service account to use +*/}} +{{- define "kube-state-metrics.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "kube-state-metrics.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "kube-state-metrics.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrole.yaml new file mode 100644 index 000000000..9a58fa54d --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrole.yaml @@ -0,0 +1,182 @@ +{{ if not .Values.disabled }} +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: {{ template "kube-state-metrics.fullname" . }} +rules: +{{ if .Values.collectors.certificatesigningrequests }} +- apiGroups: ["certificates.k8s.io"] + resources: + - certificatesigningrequests + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.configmaps }} +- apiGroups: [""] + resources: + - configmaps + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.cronjobs }} +- apiGroups: ["batch"] + resources: + - cronjobs + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.daemonsets }} +- apiGroups: ["extensions", "apps"] + resources: + - daemonsets + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.deployments }} +- apiGroups: ["extensions", "apps"] + resources: + - deployments + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.endpoints }} +- apiGroups: [""] + resources: + - endpoints + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.horizontalpodautoscalers }} +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.ingresses }} +- apiGroups: ["extensions", "networking.k8s.io"] + resources: + - ingresses + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.jobs }} +- apiGroups: ["batch"] + resources: + - jobs + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.limitranges }} +- apiGroups: [""] + resources: + - limitranges + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.mutatingwebhookconfigurations }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - mutatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.namespaces }} +- apiGroups: [""] + resources: + - namespaces + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.networkpolicies }} +- apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.nodes }} +- apiGroups: [""] + resources: + - nodes + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.persistentvolumeclaims }} +- apiGroups: [""] + resources: + - persistentvolumeclaims + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.persistentvolumes }} +- apiGroups: [""] + resources: + - persistentvolumes + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.poddisruptionbudgets }} +- apiGroups: ["policy"] + resources: + - poddisruptionbudgets + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.pods }} +- apiGroups: [""] + resources: + - pods + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.replicasets }} +- apiGroups: ["extensions", "apps"] + resources: + - replicasets + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.replicationcontrollers }} +- apiGroups: [""] + resources: + - replicationcontrollers + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.resourcequotas }} +- apiGroups: [""] + resources: + - resourcequotas + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.secrets }} +- apiGroups: [""] + resources: + - secrets + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.services }} +- apiGroups: [""] + resources: + - services + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.statefulsets }} +- apiGroups: ["apps"] + resources: + - statefulsets + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.storageclasses }} +- apiGroups: ["storage.k8s.io"] + resources: + - storageclasses + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.validatingwebhookconfigurations }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - validatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.volumeattachments }} +- apiGroups: ["storage.k8s.io"] + resources: + - volumeattachments + verbs: ["list", "watch"] +{{ end -}} +{{ if .Values.collectors.verticalpodautoscalers }} +- apiGroups: ["autoscaling.k8s.io"] + resources: + - verticalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..9064522a0 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml @@ -0,0 +1,21 @@ +{{ if (.Values.enabled | default true) }} +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: {{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kube-state-metrics.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml new file mode 100644 index 000000000..f78e48e62 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml @@ -0,0 +1,192 @@ +{{ if not .Values.disabled }} +apiVersion: apps/v1 +{{- if .Values.autosharding.enabled }} +kind: StatefulSet +{{- else }} +kind: Deployment +{{- end }} +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: "{{ .Release.Service }}" +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels | indent 4 }} +{{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + replicas: {{ .Values.replicas }} +{{- if .Values.autosharding.enabled }} + serviceName: {{ template "kube-state-metrics.fullname" . }} + volumeClaimTemplates: [] +{{- end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + app.kubernetes.io/instance: "{{ .Release.Name }}" +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels | indent 8 }} +{{- end }} +{{- if .Values.podAnnotations }} + annotations: +{{ toYaml .Values.podAnnotations | indent 8 }} +{{- end }} + spec: +{{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} +{{- end }} + hostNetwork: {{ .Values.hostNetwork }} + serviceAccountName: {{ template "kube-state-metrics.serviceAccountName" . }} + {{- if .Values.securityContext.enabled }} + securityContext: + fsGroup: {{ .Values.securityContext.fsGroup }} + runAsUser: {{ .Values.securityContext.runAsUser }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + containers: + - name: {{ .Chart.Name }} +{{- if .Values.autosharding.enabled }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +{{- end }} + args: +{{ if .Values.collectors.certificatesigningrequests }} + - --collectors=certificatesigningrequests +{{ end }} +{{ if .Values.collectors.configmaps }} + - --collectors=configmaps +{{ end }} +{{ if .Values.collectors.cronjobs }} + - --collectors=cronjobs +{{ end }} +{{ if .Values.collectors.daemonsets }} + - --collectors=daemonsets +{{ end }} +{{ if .Values.collectors.deployments }} + - --collectors=deployments +{{ end }} +{{ if .Values.collectors.endpoints }} + - --collectors=endpoints +{{ end }} +{{ if .Values.collectors.horizontalpodautoscalers }} + - --collectors=horizontalpodautoscalers +{{ end }} +{{ if .Values.collectors.ingresses }} + - --collectors=ingresses +{{ end }} +{{ if .Values.collectors.jobs }} + - --collectors=jobs +{{ end }} +{{ if .Values.collectors.limitranges }} + - --collectors=limitranges +{{ end }} +{{ if .Values.collectors.mutatingwebhookconfigurations }} + - --collectors=mutatingwebhookconfigurations +{{ end }} +{{ if .Values.collectors.namespaces }} + - --collectors=namespaces +{{ end }} +{{ if .Values.collectors.networkpolicies }} + - --collectors=networkpolicies +{{ end }} +{{ if .Values.collectors.nodes }} + - --collectors=nodes +{{ end }} +{{ if .Values.collectors.persistentvolumeclaims }} + - --collectors=persistentvolumeclaims +{{ end }} +{{ if .Values.collectors.persistentvolumes }} + - --collectors=persistentvolumes +{{ end }} +{{ if .Values.collectors.poddisruptionbudgets }} + - --collectors=poddisruptionbudgets +{{ end }} +{{ if .Values.collectors.pods }} + - --collectors=pods +{{ end }} +{{ if .Values.collectors.replicasets }} + - --collectors=replicasets +{{ end }} +{{ if .Values.collectors.replicationcontrollers }} + - --collectors=replicationcontrollers +{{ end }} +{{ if .Values.collectors.resourcequotas }} + - --collectors=resourcequotas +{{ end }} +{{ if .Values.collectors.secrets }} + - --collectors=secrets +{{ end }} +{{ if .Values.collectors.services }} + - --collectors=services +{{ end }} +{{ if .Values.collectors.statefulsets }} + - --collectors=statefulsets +{{ end }} +{{ if .Values.collectors.storageclasses }} + - --collectors=storageclasses +{{ end }} +{{ if .Values.collectors.validatingwebhookconfigurations }} + - --collectors=validatingwebhookconfigurations +{{ end }} +{{ if .Values.collectors.verticalpodautoscalers }} + - --collectors=verticalpodautoscalers +{{ end }} +{{ if .Values.collectors.volumeattachments }} + - --collectors=volumeattachments +{{ end }} +{{ if .Values.namespace }} + - --namespace={{ .Values.namespace }} +{{ end }} +{{ if .Values.autosharding.enabled }} + - --pod=$(POD_NAME) + - --pod-namespace=$(POD_NAMESPACE) +{{ end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: 8080 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + timeoutSeconds: 5 +{{- if .Values.resources }} + resources: +{{ toYaml .Values.resources | indent 10 }} +{{- end }} +{{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} +{{- end }} +{{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} +{{- end }} +{{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..1267c386c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml @@ -0,0 +1,41 @@ +{{ if not .Values.disabled }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Values.podSecurityPolicy.annotations }} + annotations: +{{ toYaml .Values.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + volumes: + - 'secret' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + 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 }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml new file mode 100644 index 000000000..1edb5afee --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml @@ -0,0 +1,19 @@ +{{ if not .Values.disabled }} +{{- if and .Values.podSecurityPolicy.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml new file mode 100644 index 000000000..6409e3637 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,21 @@ +{{ if (.Values.enabled | default true) }} +{{- if and .Values.podSecurityPolicy.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/service.yaml new file mode 100644 index 000000000..06c7bd484 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/service.yaml @@ -0,0 +1,38 @@ +{{ if not .Values.disabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: "{{ .Release.Service }}" +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels | indent 4 }} +{{- end }} + annotations: + {{- if .Values.prometheusScrape }} + prometheus.io/scrape: '{{ .Values.prometheusScrape }}' + {{- end }} + {{- if .Values.service.annotations }} + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: "{{ .Values.service.type }}" + ports: + - name: "http" + protocol: TCP + port: {{ .Values.service.port }} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: 8080 +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" +{{- end }} + selector: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml new file mode 100644 index 000000000..76bd1d1d6 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{ if not .Values.disabled }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +imagePullSecrets: +{{ toYaml .Values.serviceAccount.imagePullSecrets | indent 2 }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml new file mode 100644 index 000000000..c013f5265 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml @@ -0,0 +1,27 @@ +{{ if not .Values.disabled }} +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/managed-by: "{{ .Release.Service }}" + {{- if .Values.prometheus.monitor.additionalLabels }} +{{ toYaml .Values.prometheus.monitor.additionalLabels | indent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + endpoints: + - port: http + {{- if .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml new file mode 100644 index 000000000..95f237d7e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml @@ -0,0 +1,29 @@ +{{ if not .Values.disabled }} +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - apps + resourceNames: + - kube-state-metrics + resources: + - statefulsets + verbs: + - get +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml new file mode 100644 index 000000000..49119520a --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml @@ -0,0 +1,22 @@ +{{ if not .Values.disabled }} +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/values.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/values.yaml new file mode 100644 index 000000000..fbad46ccd --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/charts/kube-state-metrics/values.yaml @@ -0,0 +1,126 @@ +# Default values for kube-state-metrics. +prometheusScrape: true +image: + repository: quay.io/coreos/kube-state-metrics + tag: v1.9.8 + pullPolicy: IfNotPresent + +# If set to true, this will deploy kube-state-metrics as a StatefulSet and the data +# will be automatically sharded across <.Values.replicas> pods using the built-in +# autodiscovery feature: https://github.com/kubernetes/kube-state-metrics#automated-sharding +# This is an experimental feature and there are no stability guarantees. +autosharding: + enabled: false + +replicas: 1 + +service: + port: 8080 + # Default to clusterIP for backward compatibility + type: ClusterIP + nodePort: 0 + loadBalancerIP: "" + annotations: {} + +customLabels: {} + +hostNetwork: false + +rbac: + # If true, create & use RBAC resources + create: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created, require rbac true + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + # 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: [] + +prometheus: + monitor: + enabled: false + additionalLabels: {} + namespace: "" + honorLabels: false + +## Specify if a Pod Security Policy for kube-state-metrics must be created +## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + enabled: false + annotations: {} + ## 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' + + +securityContext: + enabled: true + runAsUser: 65534 + fsGroup: 65534 + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +## Affinity settings for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +affinity: {} + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# Annotations to be added to the pod +podAnnotations: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +# Available collectors for kube-state-metrics. By default all available +# collectors are enabled. +collectors: + certificatesigningrequests: true + configmaps: true + cronjobs: true + daemonsets: true + deployments: true + endpoints: true + horizontalpodautoscalers: true + ingresses: true + jobs: true + limitranges: true + mutatingwebhookconfigurations: false + namespaces: true + networkpolicies: false + nodes: true + persistentvolumeclaims: true + persistentvolumes: true + poddisruptionbudgets: true + pods: true + replicasets: true + replicationcontrollers: true + resourcequotas: true + secrets: false + services: true + statefulsets: true + storageclasses: true + validatingwebhookconfigurations: false + verticalpodautoscalers: false + volumeattachments: false + +# Namespace to be enabled for collecting resources. By default all namespaces are collected. +# namespace: "" + +## Override the deployment namespace +## +namespaceOverride: "" diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.lock b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.lock new file mode 100644 index 000000000..4a4bde218 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.lock @@ -0,0 +1,6 @@ +dependencies: +- name: kube-state-metrics + repository: https://kubernetes-charts.storage.googleapis.com/ + version: 2.7.2 +digest: sha256:695d0dbc2db8bccf5672145697546891da60ff12fbdb4f1bfc02459f4b755e4c +generated: 2020-03-18T18:57:59.00056179Z diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.yaml new file mode 100644 index 000000000..6e079ae7d --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/requirements.yaml @@ -0,0 +1,7 @@ +dependencies: + + - name: kube-state-metrics + version: "2.7.*" + repository: https://kubernetes-charts.storage.googleapis.com/ + condition: kubeStateMetrics.enabled + diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/NOTES.txt b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/NOTES.txt new file mode 100644 index 000000000..0e8868f0b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/NOTES.txt @@ -0,0 +1,112 @@ +{{- if .Values.server.enabled -}} +The Prometheus server can be accessed via port {{ .Values.server.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.server.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.server.ingress.enabled -}} +From outside the cluster, the server URL(s) are: +{{- range .Values.server.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the Prometheus server URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.server.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.server.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 {{ .Release.Namespace }} -w {{ template "prometheus.server.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.server.service.servicePort }} +{{- else if contains "ClusterIP" .Values.server.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.server.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9090 +{{- end }} +{{- end }} + +{{- if .Values.server.persistentVolume.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Server pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{ if .Values.alertmanager.enabled }} +The Prometheus alertmanager can be accessed via port {{ .Values.alertmanager.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.alertmanager.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.alertmanager.ingress.enabled -}} +From outside the cluster, the alertmanager URL(s) are: +{{- range .Values.alertmanager.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the Alertmanager URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.alertmanager.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.alertmanager.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.alertmanager.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 {{ .Release.Namespace }} -w {{ template "prometheus.alertmanager.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.alertmanager.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.alertmanager.service.servicePort }} +{{- else if contains "ClusterIP" .Values.alertmanager.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.alertmanager.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9093 +{{- end }} +{{- end }} + +{{- if .Values.alertmanager.persistentVolume.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the AlertManager pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{- if .Values.nodeExporter.podSecurityPolicy.enabled }} +{{- else }} +################################################################################# +###### WARNING: Pod Security Policy has been moved to a global property. ##### +###### use .Values.podSecurityPolicy.enabled with pod-based ##### +###### annotations ##### +###### (e.g. .Values.nodeExporter.podSecurityPolicy.annotations) ##### +################################################################################# +{{- end }} + +{{ if .Values.pushgateway.enabled }} +The Prometheus PushGateway can be accessed via port {{ .Values.pushgateway.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.pushgateway.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.pushgateway.ingress.enabled -}} +From outside the cluster, the pushgateway URL(s) are: +{{- range .Values.pushgateway.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the PushGateway URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.pushgateway.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.pushgateway.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.pushgateway.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 {{ .Release.Namespace }} -w {{ template "prometheus.pushgateway.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.pushgateway.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.pushgateway.service.servicePort }} +{{- else if contains "ClusterIP" .Values.pushgateway.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.pushgateway.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9091 +{{- end }} +{{- end }} +{{- end }} + +For more information on running Prometheus, visit: +https://prometheus.io/ diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/_helpers.tpl b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/_helpers.tpl new file mode 100644 index 000000000..295aa01c5 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/_helpers.tpl @@ -0,0 +1,276 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create unified labels for prometheus components +*/}} +{{- define "prometheus.common.matchLabels" -}} +app: {{ template "prometheus.name" . }} +release: {{ .Release.Name }} +{{- end -}} + +{{- define "prometheus.common.metaLabels" -}} +chart: {{ template "prometheus.chart" . }} +heritage: {{ .Release.Service }} +{{- end -}} + +{{- define "prometheus.alertmanager.labels" -}} +{{ include "prometheus.alertmanager.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.alertmanager.matchLabels" -}} +component: {{ .Values.alertmanager.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.kubeStateMetrics.labels" -}} +{{ include "prometheus.kubeStateMetrics.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.kubeStateMetrics.matchLabels" -}} +component: {{ .Values.kubeStateMetrics.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.nodeExporter.labels" -}} +{{ include "prometheus.nodeExporter.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.nodeExporter.matchLabels" -}} +component: {{ .Values.nodeExporter.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.pushgateway.labels" -}} +{{ include "prometheus.pushgateway.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.pushgateway.matchLabels" -}} +component: {{ .Values.pushgateway.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.server.labels" -}} +{{ include "prometheus.server.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.server.matchLabels" -}} +component: {{ .Values.server.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- 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). +*/}} +{{- define "prometheus.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 a fully qualified alertmanager name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} + +{{- define "prometheus.alertmanager.fullname" -}} +{{- if .Values.alertmanager.fullnameOverride -}} +{{- .Values.alertmanager.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.alertmanager.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.alertmanager.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified kube-state-metrics name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.kubeStateMetrics.fullname" -}} +{{- if .Values.kubeStateMetrics.fullnameOverride -}} +{{- .Values.kubeStateMetrics.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.kubeStateMetrics.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.kubeStateMetrics.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified node-exporter name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.nodeExporter.fullname" -}} +{{- if .Values.nodeExporter.fullnameOverride -}} +{{- .Values.nodeExporter.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.nodeExporter.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.nodeExporter.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified Prometheus server name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.server.fullname" -}} +{{- if .Values.server.fullnameOverride -}} +{{- .Values.server.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified pushgateway name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.pushgateway.fullname" -}} +{{- if .Values.pushgateway.fullnameOverride -}} +{{- .Values.pushgateway.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.pushgateway.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.pushgateway.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "prometheus.deployment.apiVersion" -}} +{{- if semverCompare "<1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "prometheus.daemonset.apiVersion" -}} +{{- if semverCompare "<1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "prometheus.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for podsecuritypolicy. +*/}} +{{- define "prometheus.podSecurityPolicy.apiVersion" -}} +{{- if semverCompare ">=1.3-0, <1.10-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.10-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the alertmanager component +*/}} +{{- define "prometheus.serviceAccountName.alertmanager" -}} +{{- if .Values.serviceAccounts.alertmanager.create -}} + {{ default (include "prometheus.alertmanager.fullname" .) .Values.serviceAccounts.alertmanager.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.alertmanager.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the kubeStateMetrics component +*/}} +{{- define "prometheus.serviceAccountName.kubeStateMetrics" -}} +{{- if .Values.serviceAccounts.kubeStateMetrics.create -}} + {{ default (include "prometheus.kubeStateMetrics.fullname" .) .Values.serviceAccounts.kubeStateMetrics.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.kubeStateMetrics.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the nodeExporter component +*/}} +{{- define "prometheus.serviceAccountName.nodeExporter" -}} +{{- if .Values.serviceAccounts.nodeExporter.create -}} + {{ default (include "prometheus.nodeExporter.fullname" .) .Values.serviceAccounts.nodeExporter.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.nodeExporter.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the pushgateway component +*/}} +{{- define "prometheus.serviceAccountName.pushgateway" -}} +{{- if .Values.serviceAccounts.pushgateway.create -}} + {{ default (include "prometheus.pushgateway.fullname" .) .Values.serviceAccounts.pushgateway.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.pushgateway.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the server component +*/}} +{{- define "prometheus.serviceAccountName.server" -}} +{{- if .Values.serviceAccounts.server.create -}} + {{ default (include "prometheus.server.fullname" .) .Values.serviceAccounts.server.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.server.name }} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrole.yaml new file mode 100644 index 000000000..9bec69257 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrole.yaml @@ -0,0 +1,23 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.alertmanager.fullname" . }} +{{- else }} + [] +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrolebinding.yaml new file mode 100644 index 000000000..a058c7121 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.alertmanager" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.alertmanager.fullname" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-configmap.yaml new file mode 100644 index 000000000..09708915c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-configmap.yaml @@ -0,0 +1,20 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled (and (empty .Values.alertmanager.configMapOverrideName) (empty .Values.alertmanager.configFromSecret)) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +data: +{{- $root := . -}} +{{- range $key, $value := .Values.alertmanagerFiles }} + {{- if $key | regexMatch ".*\\.ya?ml$" }} + {{ $key }}: | +{{ toYaml $value | default "{}" | indent 4 }} + {{- else }} + {{ $key }}: {{ toYaml $value | indent 4 }} + {{- end }} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-deployment.yaml new file mode 100644 index 000000000..892204ab2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-deployment.yaml @@ -0,0 +1,141 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled (not .Values.alertmanager.statefulSet.enabled) -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +spec: + selector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + replicas: {{ .Values.alertmanager.replicaCount }} + {{- if .Values.alertmanager.strategy }} + strategy: +{{ toYaml .Values.alertmanager.strategy | indent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.alertmanager.podAnnotations }} + annotations: +{{ toYaml .Values.alertmanager.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 8 }} + {{- if .Values.alertmanager.podLabels}} + {{ toYaml .Values.alertmanager.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.alertmanager.schedulerName }} + schedulerName: "{{ .Values.alertmanager.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{- if .Values.alertmanager.priorityClassName }} + priorityClassName: "{{ .Values.alertmanager.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }} + image: "{{ .Values.alertmanager.image.repository }}:{{ .Values.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.alertmanager.image.pullPolicy }}" + env: + {{- range $key, $value := .Values.alertmanager.extraEnv }} + - name: {{ $key }} + value: {{ $value }} + {{- end }} + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + args: + - --config.file=/etc/config/{{ .Values.alertmanager.configFileName }} + - --storage.path={{ .Values.alertmanager.persistentVolume.mountPath }} + - --cluster.advertise-address=$(POD_IP):6783 + {{- range $key, $value := .Values.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.alertmanager.baseURL }} + - --web.external-url={{ .Values.alertmanager.baseURL }} + {{- end }} + + ports: + - containerPort: 9093 + readinessProbe: + httpGet: + path: {{ .Values.alertmanager.prefixURL }}/-/ready + port: 9093 + initialDelaySeconds: 30 + timeoutSeconds: 30 + resources: +{{ toYaml .Values.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: "{{ .Values.alertmanager.persistentVolume.mountPath }}" + subPath: "{{ .Values.alertmanager.persistentVolume.subPath }}" + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + + {{- if .Values.configmapReload.alertmanager.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }}-{{ .Values.configmapReload.alertmanager.name }} + image: "{{ .Values.configmapReload.alertmanager.image.repository }}:{{ .Values.configmapReload.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.alertmanager.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9093{{ .Values.alertmanager.prefixURL }}/-/reload + resources: +{{ toYaml .Values.configmapReload.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.alertmanager.nodeSelector }} + nodeSelector: +{{ toYaml .Values.alertmanager.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.securityContext | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.tolerations }} + tolerations: +{{ toYaml .Values.alertmanager.tolerations | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.affinity }} + affinity: +{{ toYaml .Values.alertmanager.affinity | indent 8 }} + {{- end }} + volumes: + - name: config-volume + {{- if empty .Values.alertmanager.configFromSecret }} + configMap: + name: {{ if .Values.alertmanager.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.alertmanager.configMapOverrideName }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.alertmanager.configFromSecret }} + {{- end }} + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- end }} + - name: storage-volume + {{- if .Values.alertmanager.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.alertmanager.persistentVolume.existingClaim }}{{ .Values.alertmanager.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- else }} + emptyDir: {} + {{- end -}} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-ingress.yaml new file mode 100644 index 000000000..dc6ba4418 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-ingress.yaml @@ -0,0 +1,44 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.alertmanager.fullname" . }} +{{- $servicePort := .Values.alertmanager.service.servicePort -}} +{{- $extraPaths := .Values.alertmanager.ingress.extraPaths -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{ else }} +apiVersion: extensions/v1beta1 +{{ end -}} +kind: Ingress +metadata: +{{- if .Values.alertmanager.ingress.annotations }} + annotations: +{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- range $key, $value := .Values.alertmanager.ingress.extraLabels }} + {{ $key }}: {{ $value }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }} +spec: + rules: + {{- range .Values.alertmanager.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: /{{ rest $url | join "/" }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end -}} +{{- if .Values.alertmanager.ingress.tls }} + tls: +{{ toYaml .Values.alertmanager.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-networkpolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-networkpolicy.yaml new file mode 100644 index 000000000..62633d0bc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-networkpolicy.yaml @@ -0,0 +1,21 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.networkPolicy.enabled -}} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 12 }} + - ports: + - port: 9093 +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pdb.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pdb.yaml new file mode 100644 index 000000000..bb190f23d --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pdb.yaml @@ -0,0 +1,15 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.alertmanager.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.alertmanager.labels" . | nindent 6 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-podsecuritypolicy.yaml new file mode 100644 index 000000000..da2fbbd1c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-podsecuritypolicy.yaml @@ -0,0 +1,50 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + annotations: +{{- if .Values.alertmanager.podSecurityPolicy.annotations }} +{{ toYaml .Values.alertmanager.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'secret' + allowedHostPaths: + - pathPrefix: /etc + readOnly: true + - pathPrefix: {{ .Values.alertmanager.persistentVolume.mountPath }} + hostNetwork: false + hostPID: false + hostIPC: 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: true +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pvc.yaml new file mode 100644 index 000000000..58de9fd39 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-pvc.yaml @@ -0,0 +1,34 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if not .Values.alertmanager.statefulSet.enabled -}} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.persistentVolume.enabled -}} +{{- if not .Values.alertmanager.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.alertmanager.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.alertmanager.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +spec: + accessModes: +{{ toYaml .Values.alertmanager.persistentVolume.accessModes | indent 4 }} +{{- if .Values.alertmanager.persistentVolume.storageClass }} +{{- if (eq "-" .Values.alertmanager.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.alertmanager.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.alertmanager.persistentVolume.volumeBindingMode }} + volumeBindingModeName: "{{ .Values.alertmanager.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.alertmanager.persistentVolume.size }}" +{{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service-headless.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service-headless.yaml new file mode 100644 index 000000000..1519344ba --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service-headless.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.statefulSet.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.alertmanager.statefulSet.headless.annotations }} + annotations: +{{ toYaml .Values.alertmanager.statefulSet.headless.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- if .Values.alertmanager.statefulSet.headless.labels }} +{{ toYaml .Values.alertmanager.statefulSet.headless.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }}-headless +spec: + clusterIP: None + ports: + - name: http + port: {{ .Values.alertmanager.statefulSet.headless.servicePort }} + protocol: TCP + targetPort: 9093 +{{- if .Values.alertmanager.statefulSet.headless.enableMeshPeer }} + - name: meshpeer + port: 6783 + protocol: TCP + targetPort: 6783 +{{- end }} + selector: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 4 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service.yaml new file mode 100644 index 000000000..9bc45f7c6 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-service.yaml @@ -0,0 +1,54 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.alertmanager.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.alertmanager.service.annotations }} + annotations: +{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- if .Values.alertmanager.service.labels }} +{{ toYaml .Values.alertmanager.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }} +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 }} + ports: + - name: http + port: {{ .Values.alertmanager.service.servicePort }} + protocol: TCP + targetPort: 9093 + {{- if .Values.alertmanager.service.nodePort }} + nodePort: {{ .Values.alertmanager.service.nodePort }} + {{- end }} +{{- if .Values.alertmanager.service.enableMeshPeer }} + - name: meshpeer + port: 6783 + protocol: TCP + targetPort: 6783 +{{- end }} + selector: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 4 }} +{{- if .Values.alertmanager.service.sessionAffinity }} + sessionAffinity: {{ .Values.alertmanager.service.sessionAffinity }} +{{- end }} + type: "{{ .Values.alertmanager.service.type }}" +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-serviceaccount.yaml new file mode 100644 index 000000000..d99c29996 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.serviceAccounts.alertmanager.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-statefulset.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-statefulset.yaml new file mode 100644 index 000000000..25a9b7a9c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/alertmanager-statefulset.yaml @@ -0,0 +1,154 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.statefulSet.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +spec: + serviceName: {{ template "prometheus.alertmanager.fullname" . }}-headless + selector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + replicas: {{ .Values.alertmanager.replicaCount }} + podManagementPolicy: {{ .Values.alertmanager.statefulSet.podManagementPolicy }} + template: + metadata: + {{- if .Values.alertmanager.podAnnotations }} + annotations: +{{ toYaml .Values.alertmanager.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 8 }} + spec: +{{- if .Values.alertmanager.affinity }} + affinity: +{{ toYaml .Values.alertmanager.affinity | indent 8 }} +{{- end }} +{{- if .Values.alertmanager.schedulerName }} + schedulerName: "{{ .Values.alertmanager.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{- if .Values.alertmanager.priorityClassName }} + priorityClassName: "{{ .Values.alertmanager.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }} + image: "{{ .Values.alertmanager.image.repository }}:{{ .Values.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.alertmanager.image.pullPolicy }}" + env: + {{- range $key, $value := .Values.alertmanager.extraEnv }} + - name: {{ $key }} + value: {{ $value }} + {{- end }} + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + args: + - --config.file=/etc/config/alertmanager.yml + - --storage.path={{ .Values.alertmanager.persistentVolume.mountPath }} + - --cluster.advertise-address=$(POD_IP):6783 + {{- if .Values.alertmanager.statefulSet.headless.enableMeshPeer }} + - --cluster.listen-address=0.0.0.0:6783 + {{- range $n := until (.Values.alertmanager.replicaCount | int) }} + - --cluster.peer={{ template "prometheus.alertmanager.fullname" $ }}-{{ $n }}.{{ template "prometheus.alertmanager.fullname" $ }}-headless:6783 + {{- end }} + {{- end }} + {{- range $key, $value := .Values.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.alertmanager.baseURL }} + - --web.external-url={{ .Values.alertmanager.baseURL }} + {{- end }} + + ports: + - containerPort: 9093 + readinessProbe: + httpGet: + path: {{ .Values.alertmanager.prefixURL }}/#/status + port: 9093 + initialDelaySeconds: 30 + timeoutSeconds: 30 + resources: +{{ toYaml .Values.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: "{{ .Values.alertmanager.persistentVolume.mountPath }}" + subPath: "{{ .Values.alertmanager.persistentVolume.subPath }}" + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.configmapReload.alertmanager.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }}-{{ .Values.configmapReload.alertmanager.name }} + image: "{{ .Values.configmapReload.alertmanager.image.repository }}:{{ .Values.configmapReload.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.alertmanager.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://localhost:9093{{ .Values.alertmanager.prefixURL }}/-/reload + resources: +{{ toYaml .Values.configmapReload.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.alertmanager.nodeSelector }} + nodeSelector: +{{ toYaml .Values.alertmanager.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.securityContext | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.tolerations }} + tolerations: +{{ toYaml .Values.alertmanager.tolerations | indent 8 }} + {{- end }} + volumes: + - name: config-volume + configMap: + name: {{ if .Values.alertmanager.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.alertmanager.configMapOverrideName }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- end }} +{{- if .Values.alertmanager.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: storage-volume + {{- if .Values.alertmanager.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.alertmanager.persistentVolume.annotations | indent 10 }} + {{- end }} + spec: + accessModes: +{{ toYaml .Values.alertmanager.persistentVolume.accessModes | indent 10 }} + resources: + requests: + storage: "{{ .Values.alertmanager.persistentVolume.size }}" + {{- if .Values.server.persistentVolume.storageClass }} + {{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.alertmanager.persistentVolume.storageClass }}" + {{- end }} + {{- end }} +{{- else }} + - name: storage-volume + emptyDir: {} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-daemonset.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-daemonset.yaml new file mode 100644 index 000000000..fce0f2714 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-daemonset.yaml @@ -0,0 +1,125 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.nodeExporter.enabled -}} +apiVersion: {{ template "prometheus.daemonset.apiVersion" . }} +kind: DaemonSet +metadata: +{{- if .Values.nodeExporter.deploymentAnnotations }} + annotations: +{{ toYaml .Values.nodeExporter.deploymentAnnotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + name: {{ template "prometheus.nodeExporter.fullname" . }} +spec: + selector: + matchLabels: + {{- include "prometheus.nodeExporter.matchLabels" . | nindent 6 }} + {{- if .Values.nodeExporter.updateStrategy }} + updateStrategy: +{{ toYaml .Values.nodeExporter.updateStrategy | indent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.nodeExporter.podAnnotations }} + annotations: +{{ toYaml .Values.nodeExporter.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 8 }} +{{- if .Values.nodeExporter.pod.labels }} +{{ toYaml .Values.nodeExporter.pod.labels | indent 8 }} +{{- end }} + spec: + serviceAccountName: {{ template "prometheus.serviceAccountName.nodeExporter" . }} +{{- if .Values.nodeExporter.priorityClassName }} + priorityClassName: "{{ .Values.nodeExporter.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.nodeExporter.name }} + image: "{{ .Values.nodeExporter.image.repository }}:{{ .Values.nodeExporter.image.tag }}" + imagePullPolicy: "{{ .Values.nodeExporter.image.pullPolicy }}" + args: + - --path.procfs=/host/proc + - --path.sysfs=/host/sys + {{- if .Values.nodeExporter.hostNetwork }} + - --web.listen-address=:{{ .Values.nodeExporter.service.hostPort }} + {{- end }} + {{- range $key, $value := .Values.nodeExporter.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - name: metrics + {{- if .Values.nodeExporter.hostNetwork }} + containerPort: {{ .Values.nodeExporter.service.hostPort }} + {{- else }} + containerPort: 9100 + {{- end }} + hostPort: {{ .Values.nodeExporter.service.hostPort }} + resources: +{{ toYaml .Values.nodeExporter.resources | indent 12 }} + volumeMounts: + - name: proc + mountPath: /host/proc + readOnly: true + - name: sys + mountPath: /host/sys + readOnly: true + {{- range .Values.nodeExporter.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- if .mountPropagation }} + mountPropagation: {{ .mountPropagation }} + {{- end }} + {{- end }} + {{- range .Values.nodeExporter.extraConfigmapMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.nodeExporter.hostNetwork }} + hostNetwork: true + {{- end }} + {{- if .Values.nodeExporter.hostPID }} + hostPID: true + {{- end }} + {{- if .Values.nodeExporter.tolerations }} + tolerations: +{{ toYaml .Values.nodeExporter.tolerations | indent 8 }} + {{- end }} + {{- if .Values.nodeExporter.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeExporter.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.nodeExporter.securityContext }} + securityContext: +{{ toYaml .Values.nodeExporter.securityContext | indent 8 }} + {{- end }} + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys + {{- range .Values.nodeExporter.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.nodeExporter.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-podsecuritypolicy.yaml new file mode 100644 index 000000000..243667dd1 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-podsecuritypolicy.yaml @@ -0,0 +1,57 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.nodeExporter.enabled .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + annotations: +{{- if .Values.nodeExporter.podSecurityPolicy.annotations }} +{{ toYaml .Values.nodeExporter.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'hostPath' + - 'secret' + allowedHostPaths: + - pathPrefix: /proc + readOnly: true + - pathPrefix: /sys + readOnly: true + {{- range .Values.nodeExporter.extraHostPathMounts }} + - pathPrefix: {{ .hostPath }} + readOnly: {{ .readOnly }} + {{- end }} + hostNetwork: {{ .Values.nodeExporter.hostNetwork }} + hostPID: {{ .Values.nodeExporter.hostPID }} + hostIPC: 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 + hostPorts: + - min: 1 + max: 65535 +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-role.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-role.yaml new file mode 100644 index 000000000..1926db04e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-role.yaml @@ -0,0 +1,19 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.nodeExporter.enabled .Values.rbac.create }} +{{- if or (default .Values.nodeExporter.podSecurityPolicy.enabled false) (.Values.podSecurityPolicy.enabled) }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + namespace: {{ .Release.Namespace }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "prometheus.nodeExporter.fullname" . }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-rolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-rolebinding.yaml new file mode 100644 index 000000000..fb39ab64f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-rolebinding.yaml @@ -0,0 +1,21 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.nodeExporter.enabled .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ template "prometheus.nodeExporter.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.nodeExporter" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-service.yaml new file mode 100644 index 000000000..40cbd8d69 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-service.yaml @@ -0,0 +1,46 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.nodeExporter.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.nodeExporter.service.annotations }} + annotations: +{{ toYaml .Values.nodeExporter.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} +{{- if .Values.nodeExporter.service.labels }} +{{ toYaml .Values.nodeExporter.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.nodeExporter.fullname" . }} +spec: +{{- if .Values.nodeExporter.service.clusterIP }} + clusterIP: {{ .Values.nodeExporter.service.clusterIP }} +{{- end }} +{{- if .Values.nodeExporter.service.externalIPs }} + externalIPs: +{{ toYaml .Values.nodeExporter.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.nodeExporter.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.nodeExporter.service.loadBalancerIP }} +{{- end }} +{{- if .Values.nodeExporter.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.nodeExporter.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: metrics + port: {{ .Values.nodeExporter.service.servicePort }} + protocol: TCP + {{- if .Values.nodeExporter.hostNetwork }} + targetPort: {{ .Values.nodeExporter.service.hostPort }} + {{- else }} + targetPort: 9100 + {{- end }} + selector: + {{- include "prometheus.nodeExporter.matchLabels" . | nindent 4 }} + type: "{{ .Values.nodeExporter.service.type }}" +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-serviceaccount.yaml new file mode 100644 index 000000000..b75c4a4b6 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/node-exporter-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.nodeExporter.enabled .Values.serviceAccounts.nodeExporter.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.nodeExporter" . }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrole.yaml new file mode 100644 index 000000000..9ea81e4a2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrole.yaml @@ -0,0 +1,23 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.pushgateway.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.pushgateway.fullname" . }} +{{- else }} + [] +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrolebinding.yaml new file mode 100644 index 000000000..475d9d63d --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.pushgateway.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.pushgateway" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.pushgateway.fullname" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-deployment.yaml new file mode 100644 index 000000000..9dec641fc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-deployment.yaml @@ -0,0 +1,99 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.pushgateway.enabled -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +spec: + selector: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + matchLabels: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 6 }} + replicas: {{ .Values.pushgateway.replicaCount }} + {{- if .Values.pushgateway.strategy }} + strategy: +{{ toYaml .Values.pushgateway.strategy | indent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.pushgateway.podAnnotations }} + annotations: +{{ toYaml .Values.pushgateway.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 8 }} + spec: + serviceAccountName: {{ template "prometheus.serviceAccountName.pushgateway" . }} +{{- if .Values.pushgateway.priorityClassName }} + priorityClassName: "{{ .Values.pushgateway.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.pushgateway.name }} + image: "{{ .Values.pushgateway.image.repository }}:{{ .Values.pushgateway.image.tag }}" + imagePullPolicy: "{{ .Values.pushgateway.image.pullPolicy }}" + args: + {{- range $key, $value := .Values.pushgateway.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + ports: + - containerPort: 9091 + livenessProbe: + httpGet: + {{- if (index .Values "pushgateway" "extraArgs" "web.route-prefix") }} + path: /{{ index .Values "pushgateway" "extraArgs" "web.route-prefix" }}/-/healthy + {{- else }} + path: /-/healthy + {{- end }} + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + readinessProbe: + httpGet: + {{- if (index .Values "pushgateway" "extraArgs" "web.route-prefix") }} + path: /{{ index .Values "pushgateway" "extraArgs" "web.route-prefix" }}/-/ready + {{- else }} + path: /-/ready + {{- end }} + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + resources: +{{ toYaml .Values.pushgateway.resources | indent 12 }} + {{- if .Values.pushgateway.persistentVolume.enabled }} + volumeMounts: + - name: storage-volume + mountPath: "{{ .Values.pushgateway.persistentVolume.mountPath }}" + subPath: "{{ .Values.pushgateway.persistentVolume.subPath }}" + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.pushgateway.nodeSelector }} + nodeSelector: +{{ toYaml .Values.pushgateway.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.securityContext }} + securityContext: +{{ toYaml .Values.pushgateway.securityContext | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.tolerations }} + tolerations: +{{ toYaml .Values.pushgateway.tolerations | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.affinity }} + affinity: +{{ toYaml .Values.pushgateway.affinity | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.persistentVolume.enabled }} + volumes: + - name: storage-volume + persistentVolumeClaim: + claimName: {{ if .Values.pushgateway.persistentVolume.existingClaim }}{{ .Values.pushgateway.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.pushgateway.fullname" . }}{{- end }} + {{- end -}} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-ingress.yaml new file mode 100644 index 000000000..422129b6f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-ingress.yaml @@ -0,0 +1,41 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.pushgateway.enabled .Values.pushgateway.ingress.enabled -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.pushgateway.fullname" . }} +{{- $servicePort := .Values.pushgateway.service.servicePort -}} +{{- $extraPaths := .Values.pushgateway.ingress.extraPaths -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{ else }} +apiVersion: extensions/v1beta1 +{{ end -}} +kind: Ingress +metadata: +{{- if .Values.pushgateway.ingress.annotations }} + annotations: +{{ toYaml .Values.pushgateway.ingress.annotations | indent 4}} +{{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +spec: + rules: + {{- range .Values.pushgateway.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: /{{ rest $url | join "/" }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end -}} +{{- if .Values.pushgateway.ingress.tls }} + tls: +{{ toYaml .Values.pushgateway.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-networkpolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-networkpolicy.yaml new file mode 100644 index 000000000..70a5ada3b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-networkpolicy.yaml @@ -0,0 +1,21 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.pushgateway.enabled .Values.networkPolicy.enabled -}} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 12 }} + - ports: + - port: 9091 +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pdb.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pdb.yaml new file mode 100644 index 000000000..edf2318fe --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pdb.yaml @@ -0,0 +1,15 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.pushgateway.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.pushgateway.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.pushgateway.labels" . | nindent 6 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-podsecuritypolicy.yaml new file mode 100644 index 000000000..80617cbc7 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-podsecuritypolicy.yaml @@ -0,0 +1,46 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + annotations: +{{- if .Values.pushgateway.podSecurityPolicy.annotations }} +{{ toYaml .Values.pushgateway.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'persistentVolumeClaim' + - 'secret' + allowedHostPaths: + - pathPrefix: {{ .Values.pushgateway.persistentVolume.mountPath }} + hostNetwork: false + hostPID: false + hostIPC: 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: true +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pvc.yaml new file mode 100644 index 000000000..d6cc6cc43 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-pvc.yaml @@ -0,0 +1,34 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.pushgateway.enabled -}} +{{- if .Values.pushgateway.persistentVolume.enabled -}} +{{- if not .Values.pushgateway.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.pushgateway.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.pushgateway.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +spec: + accessModes: +{{ toYaml .Values.pushgateway.persistentVolume.accessModes | indent 4 }} +{{- if .Values.pushgateway.persistentVolume.storageClass }} +{{- if (eq "-" .Values.pushgateway.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.pushgateway.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.pushgateway.persistentVolume.volumeBindingMode }} + volumeBindingModeName: "{{ .Values.pushgateway.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.pushgateway.persistentVolume.size }}" +{{- end -}} +{{- end -}} +{{ end }} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-service.yaml new file mode 100644 index 000000000..ffcc4a20b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-service.yaml @@ -0,0 +1,42 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.pushgateway.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.pushgateway.service.annotations }} + annotations: +{{ toYaml .Values.pushgateway.service.annotations | indent 4}} +{{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +{{- if .Values.pushgateway.service.labels }} +{{ toYaml .Values.pushgateway.service.labels | indent 4}} +{{- end }} + name: {{ template "prometheus.pushgateway.fullname" . }} +spec: +{{- if .Values.pushgateway.service.clusterIP }} + clusterIP: {{ .Values.pushgateway.service.clusterIP }} +{{- end }} +{{- if .Values.pushgateway.service.externalIPs }} + externalIPs: +{{ toYaml .Values.pushgateway.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.pushgateway.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.pushgateway.service.loadBalancerIP }} +{{- end }} +{{- if .Values.pushgateway.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.pushgateway.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: http + port: {{ .Values.pushgateway.service.servicePort }} + protocol: TCP + targetPort: 9091 + selector: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 4 }} + type: "{{ .Values.pushgateway.service.type }}" +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-serviceaccount.yaml new file mode 100644 index 000000000..3b221e43d --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/pushgateway-serviceaccount.yaml @@ -0,0 +1,10 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.pushgateway.enabled .Values.serviceAccounts.pushgateway.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.pushgateway" . }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrole.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrole.yaml new file mode 100644 index 000000000..410685193 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrole.yaml @@ -0,0 +1,49 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.server.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.server.fullname" . }} +{{- end }} + - apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + - ingresses + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + resources: + - ingresses/status + - ingresses + verbs: + - get + - list + - watch + - nonResourceURLs: + - "/metrics" + verbs: + - get +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrolebinding.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrolebinding.yaml new file mode 100644 index 000000000..a89f3bd76 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if and .Values.server.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.server" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.server.fullname" . }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-configmap.yaml new file mode 100644 index 000000000..52a5d5e53 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-configmap.yaml @@ -0,0 +1,83 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if (empty .Values.server.configMapOverrideName) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +data: +{{- $root := . -}} +{{- range $key, $value := .Values.serverFiles }} + {{ $key }}: | +{{- if eq $key "prometheus.yml" }} + global: +{{ $root.Values.server.global | toYaml | trimSuffix "\n" | indent 6 }} +{{- if $root.Values.server.remoteWrite }} + remote_write: +{{ $root.Values.server.remoteWrite | toYaml | indent 4 }} +{{- end }} +{{- if $root.Values.server.remoteRead }} + remote_read: +{{ $root.Values.server.remoteRead | toYaml | indent 4 }} +{{- end }} +{{- end }} +{{- if eq $key "alerts" }} +{{- if and (not (empty $value)) (empty $value.groups) }} + groups: +{{- range $ruleKey, $ruleValue := $value }} + - name: {{ $ruleKey -}}.rules + rules: +{{ $ruleValue | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} +{{- else }} +{{ toYaml $value | indent 4 }} +{{- end }} +{{- else }} +{{ toYaml $value | default "{}" | indent 4 }} +{{- end }} +{{- if eq $key "prometheus.yml" -}} +{{- if $root.Values.extraScrapeConfigs }} +{{ tpl $root.Values.extraScrapeConfigs $root | indent 4 }} +{{- end -}} +{{- if or ($root.Values.alertmanager.enabled) ($root.Values.server.alertmanagers) }} + alerting: +{{- if $root.Values.alertRelabelConfigs }} +{{ $root.Values.alertRelabelConfigs | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} + alertmanagers: +{{- if $root.Values.server.alertmanagers }} +{{ toYaml $root.Values.server.alertmanagers | indent 8 }} +{{- else }} + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + {{- if $root.Values.alertmanager.prefixURL }} + path_prefix: {{ $root.Values.alertmanager.prefixURL }} + {{- end }} + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: {{ $root.Release.Namespace }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_app] + regex: {{ template "prometheus.name" $root }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_component] + regex: alertmanager + action: keep + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_probe] + regex: {{ index $root.Values.alertmanager.podAnnotations "prometheus.io/probe" | default ".*" }} + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: + action: drop +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-deployment.yaml new file mode 100644 index 000000000..4a1c14f08 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-deployment.yaml @@ -0,0 +1,216 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if not .Values.server.statefulSet.enabled -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: +{{- if .Values.server.deploymentAnnotations }} + annotations: +{{ toYaml .Values.server.deploymentAnnotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +spec: + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + replicas: {{ .Values.server.replicaCount }} + {{- if .Values.server.strategy }} + strategy: +{{ toYaml .Values.server.strategy | indent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: +{{ toYaml .Values.server.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 8 }} + {{- if .Values.server.podLabels}} + {{ toYaml .Values.server.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.server.priorityClassName }} + priorityClassName: "{{ .Values.server.priorityClassName }}" +{{- end }} +{{- if .Values.server.schedulerName }} + schedulerName: "{{ .Values.server.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.server" . }} + {{- if .Values.server.extraInitContainers }} + initContainers: +{{ toYaml .Values.server.extraInitContainers | indent 8 }} + {{- end }} + containers: + {{- if .Values.configmapReload.prometheus.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.prometheus.name }} + image: "{{ .Values.configmapReload.prometheus.image.repository }}:{{ .Values.configmapReload.prometheus.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.prometheus.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9090{{ .Values.server.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.prometheus.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraVolumeDirs }} + - --volume-dir={{ . }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.prometheus.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- end }} + + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} + image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag }}" + imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" + {{- if .Values.server.env }} + env: +{{ toYaml .Values.server.env | indent 12}} + {{- end }} + args: + {{- if .Values.server.retention }} + - --storage.tsdb.retention.time={{ .Values.server.retention }} + {{- end }} + - --config.file={{ .Values.server.configPath }} + - --storage.tsdb.path={{ .Values.server.persistentVolume.mountPath }} + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + {{- range .Values.server.extraFlags }} + - --{{ . }} + {{- end }} + {{- if .Values.server.baseURL }} + - --web.external-url={{ .Values.server.baseURL }} + {{- end }} + + {{- range $key, $value := .Values.server.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + ports: + - containerPort: 9090 + readinessProbe: + httpGet: + path: {{ .Values.server.prefixURL }}/-/ready + port: 9090 + initialDelaySeconds: {{ .Values.server.readinessProbeInitialDelay }} + timeoutSeconds: {{ .Values.server.readinessProbeTimeout }} + failureThreshold: {{ .Values.server.readinessProbeFailureThreshold }} + successThreshold: {{ .Values.server.readinessProbeSuccessThreshold }} + livenessProbe: + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: 9090 + initialDelaySeconds: {{ .Values.server.livenessProbeInitialDelay }} + timeoutSeconds: {{ .Values.server.livenessProbeTimeout }} + failureThreshold: {{ .Values.server.livenessProbeFailureThreshold }} + successThreshold: {{ .Values.server.livenessProbeSuccessThreshold }} + resources: +{{ toYaml .Values.server.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: {{ .Values.server.persistentVolume.mountPath }} + subPath: "{{ .Values.server.persistentVolume.subPath }}" + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.server.extraVolumeMounts }} + {{ toYaml .Values.server.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecarContainers }} + {{- toYaml .Values.server.sidecarContainers | nindent 8 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: +{{ toYaml .Values.server.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.server.securityContext }} + securityContext: +{{ toYaml .Values.server.securityContext | indent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: +{{ toYaml .Values.server.tolerations | indent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: +{{ toYaml .Values.server.affinity | indent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + volumes: + - name: config-volume + configMap: + name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + - name: storage-volume + {{- if .Values.server.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.server.persistentVolume.existingClaim }}{{ .Values.server.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else }} + emptyDir: + {{- if .Values.server.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.server.emptyDir.sizeLimit }} + {{- else }} + {} + {{- end -}} + {{- end -}} +{{- if .Values.server.extraVolumes }} +{{ toYaml .Values.server.extraVolumes | indent 8}} +{{- end }} + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-ingress.yaml new file mode 100644 index 000000000..4cdca92a3 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-ingress.yaml @@ -0,0 +1,46 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.server.ingress.enabled -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.server.fullname" . }} +{{- $servicePort := .Values.server.service.servicePort -}} +{{- $extraPaths := .Values.server.ingress.extraPaths -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{ else }} +apiVersion: extensions/v1beta1 +{{ end -}} +kind: Ingress +metadata: +{{- if .Values.server.ingress.annotations }} + annotations: +{{ toYaml .Values.server.ingress.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- range $key, $value := .Values.server.ingress.extraLabels }} + {{ $key }}: {{ $value }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} +spec: + rules: + {{- range .Values.server.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: /{{ rest $url | join "/" }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end -}} +{{- if .Values.server.ingress.tls }} + tls: +{{ toYaml .Values.server.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-networkpolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-networkpolicy.yaml new file mode 100644 index 000000000..152f3a967 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-networkpolicy.yaml @@ -0,0 +1,19 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.networkPolicy.enabled }} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.server.fullname" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + ingress: + - ports: + - port: 9090 +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pdb.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pdb.yaml new file mode 100644 index 000000000..ec90cd5c9 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pdb.yaml @@ -0,0 +1,15 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.server.fullname" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.server.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.server.labels" . | nindent 6 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-podsecuritypolicy.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-podsecuritypolicy.yaml new file mode 100644 index 000000000..73bf065dc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-podsecuritypolicy.yaml @@ -0,0 +1,55 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.server.fullname" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + annotations: +{{- if .Values.server.podSecurityPolicy.annotations }} +{{ toYaml .Values.server.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: + - 'CHOWN' + volumes: + - 'configMap' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'secret' + - 'hostPath' + allowedHostPaths: + - pathPrefix: /etc + readOnly: true + - pathPrefix: {{ .Values.server.persistentVolume.mountPath }} + {{- range .Values.server.extraHostPathMounts }} + - pathPrefix: {{ .hostPath }} + readOnly: {{ .readOnly }} + {{- end }} + hostNetwork: false + hostPID: false + hostIPC: 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 }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pvc.yaml new file mode 100644 index 000000000..22cb51afc --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-pvc.yaml @@ -0,0 +1,36 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if not .Values.server.statefulSet.enabled -}} +{{- if .Values.server.persistentVolume.enabled -}} +{{- if not .Values.server.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.server.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.server.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +spec: + accessModes: +{{ toYaml .Values.server.persistentVolume.accessModes | indent 4 }} +{{- if .Values.server.persistentVolume.storageClass }} +{{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.server.persistentVolume.volumeBindingMode }} + volumeBindingModeName: "{{ .Values.server.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service-headless.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service-headless.yaml new file mode 100644 index 000000000..018a75b79 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service-headless.yaml @@ -0,0 +1,28 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.server.statefulSet.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.statefulSet.headless.annotations }} + annotations: +{{ toYaml .Values.server.statefulSet.headless.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.statefulSet.headless.labels }} +{{ toYaml .Values.server.statefulSet.headless.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }}-headless +spec: + clusterIP: None + ports: + - name: http + port: {{ .Values.server.statefulSet.headless.servicePort }} + protocol: TCP + targetPort: 9090 + selector: + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service.yaml new file mode 100644 index 000000000..e03faf974 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-service.yaml @@ -0,0 +1,61 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.service.annotations }} + annotations: +{{ toYaml .Values.server.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.service.labels }} +{{ toYaml .Values.server.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} +spec: +{{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} +{{- end }} +{{- if .Values.server.service.externalIPs }} + externalIPs: +{{ toYaml .Values.server.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.server.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} +{{- end }} +{{- if .Values.server.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.server.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: http + port: {{ .Values.server.service.servicePort }} + protocol: TCP + targetPort: 9090 + {{- if .Values.server.service.nodePort }} + nodePort: {{ .Values.server.service.nodePort }} + {{- end }} + {{- if .Values.server.service.gRPC.enabled }} + - name: grpc + port: {{ .Values.server.service.gRPC.servicePort }} + protocol: TCP + targetPort: 10901 + {{- if .Values.server.service.gRPC.nodePort }} + nodePort: {{ .Values.server.service.gRPC.nodePort }} + {{- end }} + {{- end }} + selector: + {{- if and .Values.server.statefulSet.enabled .Values.server.service.statefulsetReplica.enabled }} + statefulset.kubernetes.io/pod-name: {{ .Release.Name }}-{{ .Values.server.name }}-{{ .Values.server.service.statefulsetReplica.replica }} + {{- else -}} + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- if .Values.server.service.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.sessionAffinity }} +{{- end }} + {{- end }} + type: "{{ .Values.server.service.type }}" +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-serviceaccount.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-serviceaccount.yaml new file mode 100644 index 000000000..6cf017c20 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-serviceaccount.yaml @@ -0,0 +1,12 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.serviceAccounts.server.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.server" . }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-statefulset.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-statefulset.yaml new file mode 100644 index 000000000..9369ddf38 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-statefulset.yaml @@ -0,0 +1,224 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.server.statefulSet.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: +{{- if .Values.server.statefulSet.annotations }} + annotations: +{{ toYaml .Values.server.statefulSet.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- if .Values.server.statefulSet.labels}} + {{ toYaml .Values.server.statefulSet.labels | nindent 4 }} + {{- end}} + name: {{ template "prometheus.server.fullname" . }} +spec: + serviceName: {{ template "prometheus.server.fullname" . }}-headless + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + replicas: {{ .Values.server.replicaCount }} + podManagementPolicy: {{ .Values.server.statefulSet.podManagementPolicy }} + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: +{{ toYaml .Values.server.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 8 }} + {{- if .Values.server.statefulSet.labels}} + {{ toYaml .Values.server.statefulSet.labels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.server.affinity }} + affinity: +{{ toYaml .Values.server.affinity | indent 8 }} +{{- end }} +{{- if .Values.server.priorityClassName }} + priorityClassName: "{{ .Values.server.priorityClassName }}" +{{- end }} +{{- if .Values.server.schedulerName }} + schedulerName: "{{ .Values.server.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.server" . }} + containers: + {{- if .Values.configmapReload.prometheus.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.prometheus.name }} + image: "{{ .Values.configmapReload.prometheus.image.repository }}:{{ .Values.configmapReload.prometheus.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.prometheus.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9090{{ .Values.server.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.prometheus.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraVolumeDirs }} + - --volume-dir={{ . }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.prometheus.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- end }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} + image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag }}" + imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" + {{- if .Values.server.env }} + env: +{{ toYaml .Values.server.env | indent 12}} + {{- end }} + args: + {{- if .Values.server.retention }} + - --storage.tsdb.retention.time={{ .Values.server.retention }} + {{- end }} + - --config.file={{ .Values.server.configPath }} + - --storage.tsdb.path={{ .Values.server.persistentVolume.mountPath }} + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + {{- range .Values.server.extraFlags }} + - --{{ . }} + {{- end }} + {{- range $key, $value := .Values.server.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.server.baseURL }} + - --web.external-url={{ .Values.server.baseURL }} + {{- end }} + ports: + - containerPort: 9090 + readinessProbe: + httpGet: + path: {{ .Values.server.prefixURL }}/-/ready + port: 9090 + initialDelaySeconds: {{ .Values.server.readinessProbeInitialDelay }} + timeoutSeconds: {{ .Values.server.readinessProbeTimeout }} + livenessProbe: + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: 9090 + initialDelaySeconds: {{ .Values.server.livenessProbeInitialDelay }} + timeoutSeconds: {{ .Values.server.livenessProbeTimeout }} + resources: +{{ toYaml .Values.server.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: {{ .Values.server.persistentVolume.mountPath }} + subPath: "{{ .Values.server.persistentVolume.subPath }}" + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.server.extraVolumeMounts }} + {{ toYaml .Values.server.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecarContainers }} + {{- toYaml .Values.server.sidecarContainers | nindent 8 }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: +{{ toYaml .Values.server.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.server.securityContext }} + securityContext: +{{ toYaml .Values.server.securityContext | indent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: +{{ toYaml .Values.server.tolerations | indent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: +{{ toYaml .Values.server.affinity | indent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + volumes: + - name: config-volume + configMap: + name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} +{{- if .Values.server.extraVolumes }} +{{ toYaml .Values.server.extraVolumes | indent 8}} +{{- end }} +{{- if .Values.server.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: storage-volume + {{- if .Values.server.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.server.persistentVolume.annotations | indent 10 }} + {{- end }} + spec: + accessModes: +{{ toYaml .Values.server.persistentVolume.accessModes | indent 10 }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" + {{- if .Values.server.persistentVolume.storageClass }} + {{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" + {{- end }} + {{- end }} +{{- else }} + - name: storage-volume + emptyDir: {} +{{- end }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-vpa.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-vpa.yaml new file mode 100644 index 000000000..8aec16ad5 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/templates/server-vpa.yaml @@ -0,0 +1,26 @@ +{{ if .Values.global.prometheus.enabled }} +{{- if .Values.server.enabled -}} +{{- if .Values.server.verticalAutoscaler.enabled -}} +apiVersion: autoscaling.k8s.io/v1beta2 +kind: VerticalPodAutoscaler +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }}-vpa +spec: + targetRef: +{{- if .Values.server.statefulSet.enabled }} + apiVersion: "apps/v1" + kind: StatefulSet +{{- else }} + apiVersion: "extensions/v1beta1" + kind: Deployment +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + updatePolicy: + updateMode: {{ .Values.server.verticalAutoscaler.updateMode | default "Off" | quote }} + resourcePolicy: + containerPolicies: {{ .Values.server.verticalAutoscaler.containerPolicies | default list | toYaml | trim | nindent 4 }} +{{- end -}} {{/* if .Values.server.verticalAutoscaler.enabled */}} +{{- end -}} {{/* .Values.server.enabled */}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/values.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/values.yaml new file mode 100644 index 000000000..9e2a2d258 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/prometheus/values.yaml @@ -0,0 +1,1387 @@ +rbac: + create: true + +podSecurityPolicy: + enabled: false + +imagePullSecrets: +# - name: "image-pull-secret" + +## Define serviceAccount names for components. Defaults to component's fully qualified name. +## +serviceAccounts: + alertmanager: + create: true + name: + nodeExporter: + create: true + name: + pushgateway: + create: true + name: + server: + create: true + name: + +alertmanager: + ## If false, alertmanager will not be installed + ## + enabled: true + + strategy: + type: Recreate + rollingUpdate: null + + ## alertmanager container name + ## + name: alertmanager + + ## alertmanager container image + ## + image: + repository: prom/alertmanager + tag: v0.20.0 + pullPolicy: IfNotPresent + + ## alertmanager priorityClassName + ## + priorityClassName: "" + + ## Additional alertmanager container arguments + ## + extraArgs: {} + + ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug + ## so that the various internal URLs are still able to access as they are in the default case. + ## (Optional) + prefixURL: "" + + ## External URL which can access alertmanager + baseURL: "http://localhost:9093" + + ## Additional alertmanager container environment variable + ## For instance to add a http_proxy + ## + extraEnv: {} + + ## Additional alertmanager Secret mounts + # Defines additional mounts with secrets. Secrets must be manually created in the namespace. + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: alertmanager-secret-files + # readOnly: true + + ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.alertmanager.configMapOverrideName}} + ## Defining configMapOverrideName will cause templates/alertmanager-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configMapOverrideName: "" + + ## The name of a secret in the same kubernetes namespace which contains the Alertmanager config + ## Defining configFromSecret will cause templates/alertmanager-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configFromSecret: "" + + ## The configuration file name to be loaded to alertmanager + ## Must match the key within configuration loaded from ConfigMap/Secret + ## + configFileName: alertmanager.yml + + ingress: + ## If true, alertmanager Ingress will be created + ## + enabled: false + + ## alertmanager Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## alertmanager Ingress additional labels + ## + extraLabels: {} + + ## alertmanager Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - alertmanager.domain.com + # - domain.com/alertmanager + + ## 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 + + ## alertmanager Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-alerts-tls + # hosts: + # - alertmanager.domain.com + + ## Alertmanager Deployment Strategy type + # strategy: + # type: Recreate + + ## Node tolerations for alertmanager scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for alertmanager pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Pod affinity + ## + affinity: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + persistentVolume: + ## If true, alertmanager will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: true + + ## alertmanager data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## alertmanager data Persistent Volume Claim annotations + ## + annotations: {} + + ## alertmanager data Persistent Volume existing claim name + ## Requires alertmanager.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## alertmanager data Persistent Volume mount root path + ## + mountPath: /data + + ## alertmanager data Persistent Volume size + ## + size: 2Gi + + ## alertmanager data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## alertmanager data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of alertmanager data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + ## Annotations to be added to alertmanager pods + ## + podAnnotations: {} + ## Tell prometheus to use a specific set of alertmanager pods + ## instead of all alertmanager pods found in the same namespace + ## Useful if you deploy multiple releases within the same namespace + ## + ## prometheus.io/probe: alertmanager-teamA + + ## Labels to be added to Prometheus AlertManager pods + ## + podLabels: {} + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## 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' + + ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) + ## + replicaCount: 1 + + statefulSet: + ## If true, use a statefulset instead of a deployment for pod management. + ## This allows to scale replicas to more than 1 pod + ## + enabled: false + + podManagementPolicy: OrderedReady + + ## Alertmanager headless service to use for the statefulset + ## + headless: + annotations: {} + labels: {} + + ## Enabling peer mesh service end points for enabling the HA alert manager + ## Ref: https://github.com/prometheus/alertmanager/blob/master/README.md + # enableMeshPeer : true + + servicePort: 80 + + ## alertmanager resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 10m + # memory: 32Mi + # requests: + # cpu: 10m + # memory: 32Mi + + ## Security context to be added to alertmanager pods + ## + securityContext: + runAsUser: 1001 + runAsNonRoot: true + runAsGroup: 1001 + fsGroup: 1001 + + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Enabling peer mesh service end points for enabling the HA alert manager + ## Ref: https://github.com/prometheus/alertmanager/blob/master/README.md + # enableMeshPeer : true + + ## List of IP addresses at which the alertmanager service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + # nodePort: 30000 + sessionAffinity: None + type: ClusterIP + +## Monitors ConfigMap changes and POSTs to a URL +## Ref: https://github.com/jimmidyson/configmap-reload +## +configmapReload: + prometheus: + ## If false, the configmap-reload container will not be deployed + ## + enabled: true + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: jimmidyson/configmap-reload + tag: v0.3.0 + pullPolicy: IfNotPresent + + ## Additional configmap-reload container arguments + ## + extraArgs: {} + ## Additional configmap-reload volume directories + ## + extraVolumeDirs: [] + + + ## Additional configmap-reload mounts + ## + extraConfigmapMounts: [] + # - name: prometheus-alerts + # mountPath: /etc/alerts.d + # subPath: "" + # configMap: prometheus-alerts + # readOnly: true + + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + alertmanager: + ## If false, the configmap-reload container will not be deployed + ## + enabled: true + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: jimmidyson/configmap-reload + tag: v0.3.0 + pullPolicy: IfNotPresent + + ## Additional configmap-reload container arguments + ## + extraArgs: {} + ## Additional configmap-reload volume directories + ## + extraVolumeDirs: [] + + + ## Additional configmap-reload mounts + ## + extraConfigmapMounts: [] + # - name: prometheus-alerts + # mountPath: /etc/alerts.d + # subPath: "" + # configMap: prometheus-alerts + # readOnly: true + + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + +kube-state-metrics: + ## If false, kube-state-metrics sub-chart will not be installed + ## Please see https://github.com/helm/charts/tree/master/stable/kube-state-metrics for configurable values + ## + enabled: true + +nodeExporter: + ## If false, node-exporter will not be installed + ## + enabled: true + + ## If true, node-exporter pods share the host network namespace + ## + hostNetwork: true + + ## If true, node-exporter pods share the host PID namespace + ## + hostPID: true + + ## node-exporter container name + ## + name: node-exporter + + ## node-exporter container image + ## + image: + repository: prom/node-exporter + tag: v0.18.1 + pullPolicy: IfNotPresent + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## 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' + + ## node-exporter priorityClassName + ## + priorityClassName: "" + + ## Custom Update Strategy + ## + updateStrategy: + type: RollingUpdate + + ## Additional node-exporter container arguments + ## + extraArgs: {} + + ## Additional node-exporter hostPath mounts + ## + extraHostPathMounts: [] + # - name: textfile-dir + # mountPath: /srv/txt_collector + # hostPath: /var/lib/node-exporter + # readOnly: true + # mountPropagation: HostToContainer + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /prometheus + # configMap: certs-configmap + # readOnly: true + + ## Node tolerations for node-exporter scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for node-exporter pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Annotations to be added to node-exporter pods + ## + podAnnotations: {} + + ## Labels to be added to node-exporter pods + ## + pod: + labels: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## node-exporter resource limits & requests + ## Ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 200m + # memory: 50Mi + # requests: + # cpu: 100m + # memory: 30Mi + + ## Security context to be added to node-exporter pods + ## + securityContext: {} + # runAsUser: 0 + + service: + annotations: + prometheus.io/scrape: "true" + labels: {} + + # Exposed as a headless service: + # https://kubernetes.io/docs/concepts/services-networking/service/#headless-services + clusterIP: None + + ## List of IP addresses at which the node-exporter service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + hostPort: 9100 + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 9100 + type: ClusterIP + +server: + ## Prometheus server container name + ## + enabled: true + name: server + sidecarContainers: + strategy: + type: Recreate + rollingUpdate: null + + ## Prometheus server container image + ## + image: + repository: prom/prometheus + tag: v2.22.2 + pullPolicy: IfNotPresent + + ## prometheus server priorityClassName + ## + priorityClassName: "" + + ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug + ## so that the various internal URLs are still able to access as they are in the default case. + ## (Optional) + prefixURL: "" + + ## External URL which can access alertmanager + ## Maybe same with Ingress host name + baseURL: "" + + ## Additional server container environment variables + ## + ## You specify this manually like you would a raw deployment manifest. + ## This means you can bind in environment variables from secrets. + ## + ## e.g. static environment variable: + ## - name: DEMO_GREETING + ## value: "Hello from the environment" + ## + ## e.g. secret environment variable: + ## - name: USERNAME + ## valueFrom: + ## secretKeyRef: + ## name: mysecret + ## key: username + env: [] + + extraFlags: + - web.enable-lifecycle + ## web.enable-admin-api flag controls access to the administrative HTTP API which includes functionality such as + ## deleting time series. This is disabled by default. + # - web.enable-admin-api + ## + ## storage.tsdb.no-lockfile flag controls BD locking + # - storage.tsdb.no-lockfile + ## + ## storage.tsdb.wal-compression flag enables compression of the write-ahead log (WAL) + # - storage.tsdb.wal-compression + + ## Path to a configuration file on prometheus server container FS + configPath: /etc/config/prometheus.yml + + global: + ## How frequently to scrape targets by default + ## + scrape_interval: 1m + ## How long until a scrape request times out + ## + scrape_timeout: 10s + ## How frequently to evaluate rules + ## + evaluation_interval: 1m + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write + ## + remoteWrite: {} + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read + ## + remoteRead: {} + + ## Additional Prometheus server container arguments + ## + extraArgs: {} + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ## Additional Prometheus server Volume mounts + ## + extraVolumeMounts: [] + + ## Additional Prometheus server Volumes + ## + extraVolumes: [] + + ## Additional Prometheus server hostPath mounts + ## + extraHostPathMounts: [] + # - name: certs-dir + # mountPath: /etc/kubernetes/certs + # subPath: "" + # hostPath: /etc/kubernetes/certs + # readOnly: true + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /prometheus + # subPath: "" + # configMap: certs-configmap + # readOnly: true + + ## Additional Prometheus server Secret mounts + # Defines additional mounts with secrets. Secrets must be manually created in the namespace. + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: prom-secret-files + # readOnly: true + + ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.server.configMapOverrideName}} + ## Defining configMapOverrideName will cause templates/server-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configMapOverrideName: "" + + ingress: + ## If true, Prometheus server Ingress will be created + ## + enabled: false + + ## Prometheus server Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## Prometheus server Ingress additional labels + ## + extraLabels: {} + + ## Prometheus server Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - prometheus.domain.com + # - domain.com/prometheus + + ## 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 + + ## Prometheus server Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-server-tls + # hosts: + # - prometheus.domain.com + + ## Server Deployment Strategy type + # strategy: + # type: Recreate + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for Prometheus server pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Pod affinity + ## + affinity: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + persistentVolume: + ## If true, Prometheus server will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: true + + ## Prometheus server data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## Prometheus server data Persistent Volume annotations + ## + annotations: {} + + ## Prometheus server data Persistent Volume existing claim name + ## Requires server.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## Prometheus server data Persistent Volume mount root path + ## + mountPath: /data + + ## Prometheus server data Persistent Volume size + ## + size: 8Gi + + ## Prometheus server data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## Prometheus server data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of Prometheus server data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + emptyDir: + sizeLimit: "" + + ## Annotations to be added to Prometheus server pods + ## + podAnnotations: {} + # iam.amazonaws.com/role: prometheus + + ## Labels to be added to Prometheus server pods + ## + podLabels: {} + + ## Prometheus AlertManager configuration + ## + alertmanagers: [] + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## 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' + + ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) + ## + replicaCount: 1 + + statefulSet: + ## If true, use a statefulset instead of a deployment for pod management. + ## This allows to scale replicas to more than 1 pod + ## + enabled: false + + annotations: {} + labels: {} + podManagementPolicy: OrderedReady + + ## Alertmanager headless service to use for the statefulset + ## + headless: + annotations: {} + labels: {} + servicePort: 80 + + ## Prometheus server readiness and liveness probe initial delay and timeout + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## + readinessProbeInitialDelay: 30 + readinessProbeTimeout: 30 + readinessProbeFailureThreshold: 3 + readinessProbeSuccessThreshold: 1 + livenessProbeInitialDelay: 30 + livenessProbeTimeout: 30 + livenessProbeFailureThreshold: 3 + livenessProbeSuccessThreshold: 1 + + ## Prometheus server resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 500m + # memory: 512Mi + + ## Vertical Pod Autoscaler config + ## Ref: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler + verticalAutoscaler: + ## If true a VPA object will be created for the controller (either StatefulSet or Deployemnt, based on above configs) + enabled: false + # updateMode: "Auto" + # containerPolicies: + # - containerName: 'prometheus-server' + + ## Security context to be added to server pods + ## + securityContext: + runAsUser: 1001 + runAsNonRoot: true + runAsGroup: 1001 + fsGroup: 1001 + + service: + annotations: {} + labels: {} + clusterIP: "" + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + sessionAffinity: None + type: ClusterIP + + ## Enable gRPC port on service to allow auto discovery with thanos-querier + gRPC: + enabled: false + servicePort: 10901 + # nodePort: 10901 + + ## If using a statefulSet (statefulSet.enabled=true), configure the + ## service to connect to a specific replica to have a consistent view + ## of the data. + statefulsetReplica: + enabled: false + replica: 0 + + ## Prometheus server pod termination grace period + ## + terminationGracePeriodSeconds: 300 + + ## Prometheus data retention period (default if not specified is 15 days) + ## + retention: "15d" + +pushgateway: + ## If false, pushgateway will not be installed + ## + enabled: true + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + ## pushgateway container name + ## + name: pushgateway + + ## pushgateway container image + ## + image: + repository: prom/pushgateway + tag: v1.0.1 + pullPolicy: IfNotPresent + + ## pushgateway priorityClassName + ## + priorityClassName: "" + + ## Additional pushgateway container arguments + ## + ## for example: persistence.file: /data/pushgateway.data + extraArgs: {} + + ingress: + ## If true, pushgateway Ingress will be created + ## + enabled: false + + ## pushgateway Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## pushgateway Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - pushgateway.domain.com + # - domain.com/pushgateway + + ## 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 + + ## pushgateway Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-alerts-tls + # hosts: + # - pushgateway.domain.com + + ## Node tolerations for pushgateway scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for pushgateway pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Annotations to be added to pushgateway pods + ## + podAnnotations: {} + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## 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' + + replicaCount: 1 + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## pushgateway resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: {} + # limits: + # cpu: 10m + # memory: 32Mi + # requests: + # cpu: 10m + # memory: 32Mi + + ## Security context to be added to push-gateway pods + ## + securityContext: + runAsUser: 1001 + runAsNonRoot: true + + service: + annotations: + prometheus.io/probe: pushgateway + labels: {} + clusterIP: "" + + ## List of IP addresses at which the pushgateway service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 9091 + type: ClusterIP + + strategy: + type: Recreate + rollingUpdate: null + + + persistentVolume: + ## If true, pushgateway will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: false + + ## pushgateway data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## pushgateway data Persistent Volume Claim annotations + ## + annotations: {} + + ## pushgateway data Persistent Volume existing claim name + ## Requires pushgateway.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## pushgateway data Persistent Volume mount root path + ## + mountPath: /data + + ## pushgateway data Persistent Volume size + ## + size: 2Gi + + ## pushgateway data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## pushgateway data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of pushgateway data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + +## alertmanager ConfigMap entries +## +alertmanagerFiles: + alertmanager.yml: + global: {} + # slack_api_url: '' + + receivers: + - name: default-receiver + # slack_configs: + # - channel: '@you' + # send_resolved: true + + route: + group_wait: 10s + group_interval: 5m + receiver: default-receiver + repeat_interval: 3h + +## Prometheus server ConfigMap entries +## +serverFiles: + + ## Alerts configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + alerting_rules.yml: {} + # groups: + # - name: Instances + # rules: + # - alert: InstanceDown + # expr: up == 0 + # for: 5m + # labels: + # severity: page + # annotations: + # description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.' + # summary: 'Instance {{ $labels.instance }} down' + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use alerting_rules.yml + alerts: {} + + ## Records configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/ + recording_rules.yml: {} + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use recording_rules.yml + rules: {} + + prometheus.yml: + rule_files: + - /etc/config/recording_rules.yml + - /etc/config/alerting_rules.yml + ## Below two files are DEPRECATED will be removed from this default values file + - /etc/config/rules + - /etc/config/alerts + + scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - localhost:9090 + + # A scrape configuration for running Prometheus on a Kubernetes cluster. + # This uses separate scrape configs for cluster components (i.e. API server, node) + # and services to allow each to use different authentication configs. + # + # Kubernetes labels will be added as Prometheus labels on metrics via the + # `labelmap` relabeling action. + + - job_name: 'kubernetes-nodes-cadvisor' + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + + # This configuration will work only on kubelet 1.7.3+ + # As the scrape endpoints for cAdvisor have changed + # if you are using older version you need to change the replacement to + # replacement: /api/v1/nodes/$1:4194/proxy/metrics + # more info here https://github.com/coreos/prometheus-operator/issues/633 + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + + metric_relabel_configs: + - source_labels: [ __name__ ] + regex: (container_cpu_usage_seconds_total|container_memory_working_set_bytes|container_network_receive_errors_total|container_network_transmit_errors_total|container_network_receive_packets_dropped_total|container_network_transmit_packets_dropped_total|container_memory_usage_bytes|container_cpu_cfs_throttled_periods_total|container_cpu_cfs_periods_total|container_fs_usage_bytes|container_fs_limit_bytes|container_cpu_cfs_periods_total|container_fs_inodes_free|container_fs_inodes_total|container_fs_usage_bytes|container_fs_limit_bytes|container_cpu_cfs_throttled_periods_total|container_cpu_cfs_periods_total|container_network_receive_bytes_total|container_network_transmit_bytes_total|container_fs_inodes_free|container_fs_inodes_total|container_fs_usage_bytes|container_fs_limit_bytes|container_spec_cpu_shares|container_spec_memory_limit_bytes|container_network_receive_bytes_total|container_network_transmit_bytes_total|container_fs_reads_bytes_total|container_network_receive_bytes_total|container_fs_writes_bytes_total|container_fs_reads_bytes_total|cadvisor_version_info) + action: keep + - source_labels: [ container ] + target_label: container_name + regex: (.+) + action: replace + - source_labels: [ pod ] + target_label: pod_name + regex: (.+) + action: replace + + # Scrape config for service endpoints. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape`: Only scrape services that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + - job_name: 'kubernetes-service-endpoints' + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: kubernetes_node + metric_relabel_configs: + - source_labels: [ __name__ ] + regex: (container_gpu_allocation|container_cpu_allocation|container_cpu_usage_seconds_total|container_fs_limit_bytes|container_memory_allocation_bytes|container_memory_usage_bytes|container_memory_working_set_bytes|container_network_receive_bytes_total|container_network_transmit_bytes_total|deployment_match_labels|kube_deployment_spec_replicas|kube_deployment_status_replicas_available|kube_job_status_failed|kube_namespace_annotations|kube_namespace_labels|kube_node_info|kube_node_labels|kube_node_status_capacity|kube_node_status_capacity_cpu_cores|kube_node_status_capacity_memory_bytes|kube_node_status_condition|kube_persistentvolume_capacity_bytes|kube_persistentvolume_status_phase|kube_persistentvolumeclaim_info|kube_persistentvolumeclaim_resource_requests_storage_bytes|kube_persistentvolumeclaim_resource_requests_storage_bytes|container_memory_allocation_bytes|kube_pod_container_resource_limits|kube_pod_container_resource_limits_cpu_cores|kube_pod_container_resource_limits_memory_bytes|kube_pod_container_resource_requests_cpu_cores|kube_pod_container_resource_requests_cpu_cores|container_cpu_usage_seconds_total|kube_pod_container_resource_requests_memory_bytes|kube_pod_container_resource_requests_memory_bytes|kube_pod_container_resource_requests|kube_pod_container_status_restarts_total|kube_pod_container_status_running|kube_pod_container_status_terminated_reason|kube_pod_labels|kube_pod_owner|kube_pod_status_phase|kubecost_cluster_memory_working_set_bytes|kubecost_pod_network_egress_bytes_total|node_cpu_hourly_cost|node_cpu_seconds_total|node_disk_reads_completed|node_disk_reads_completed_total|node_disk_writes_completed|node_disk_writes_completed_total|node_filesystem_device_error|node_gpu_hourly_cost|node_memory_Buffers_bytes|node_memory_Cached_bytes|node_memory_MemAvailable_bytes|node_memory_MemFree_bytes|node_memory_MemTotal_bytes|node_network_transmit_bytes_total|node_ram_hourly_cost|pod_pvc_allocation|pv_hourly_cost|service_selector_labels|statefulSet_match_labels|up|kube_node_status_allocatable|kube_node_status_allocatable_cpu_cores|kube_node_status_allocatable_memory_bytes|container_fs_writes_bytes_total|kube_deployment_status_replicas|kube_statefulset_replicas|kube_daemonset_status_desired_number_scheduled|kube_deployment_status_replicas_available|kube_statefulset_status_replicas|kube_daemonset_status_number_ready|kube_deployment_status_replicas|kube_statefulset_replicas|kube_daemonset_status_desired_number_scheduled|kube_replicaset_owner|kube_pod_container_info) + action: keep + + # Scrape config for slow service endpoints; same as above, but with a larger + # timeout and a larger interval + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape-slow`: Only scrape services that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + - job_name: 'kubernetes-service-endpoints-slow' + + scrape_interval: 5m + scrape_timeout: 30s + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: kubernetes_node + + - job_name: 'prometheus-pushgateway' + honor_labels: true + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: pushgateway + + # Example scrape config for probing services via the Blackbox Exporter. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/probe`: Only probe services that have a value of `true` + - job_name: 'kubernetes-services' + + metrics_path: /probe + params: + module: [http_2xx] + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: true + - source_labels: [__address__] + target_label: __param_target + - target_label: __address__ + replacement: blackbox + - source_labels: [__param_target] + target_label: instance + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + target_label: kubernetes_name + +# adds additional scrape configs to prometheus.yml +# must be a string so you have to add a | after extraScrapeConfigs: +# example adds prometheus-blackbox-exporter scrape config +extraScrapeConfigs: + # - job_name: 'prometheus-blackbox-exporter' + # metrics_path: /probe + # params: + # module: [http_2xx] + # static_configs: + # - targets: + # - https://example.com + # relabel_configs: + # - source_labels: [__address__] + # target_label: __param_target + # - source_labels: [__param_target] + # target_label: instance + # - target_label: __address__ + # replacement: prometheus-blackbox-exporter:9115 + +# Adds option to add alert_relabel_configs to avoid duplicate alerts in alertmanager +# useful in H/A prometheus with different external labels but the same alerts +alertRelabelConfigs: + # alert_relabel_configs: + # - source_labels: [dc] + # regex: (.+)\d+ + # target_label: dc + +networkPolicy: + ## Enable creation of NetworkPolicy resources. + ## + enabled: false diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/.helmignore b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/.helmignore new file mode 100644 index 000000000..f0c131944 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/.helmignore @@ -0,0 +1,21 @@ +# 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 +.project +.idea/ +*.tmproj diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/Chart.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/Chart.yaml new file mode 100644 index 000000000..e77679d6b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +appVersion: 0.19.0 +description: Thanos is a set of components that can be composed into a highly available + metric system with unlimited storage capacity, which can be added seamlessly on + top of existing Prometheus deployments. +icon: https://raw.githubusercontent.com/thanos-io/thanos/master/website/static/Thanos-logo_full.svg +keywords: +- thanos +- prometheus +- metrics +maintainers: +- email: info@banzaicloud.com + name: Banzai Cloud +name: thanos +sources: +- https://github.com/thanos-io/thanos +- https://github.com/banzaicloud/banzai-charts/tree/master/thanos +version: 0.19.0 diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/requirements.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/requirements.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/NOTES.txt b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/NOTES.txt new file mode 100644 index 000000000..e69de29bb diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/_helpers.tpl b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/_helpers.tpl new file mode 100644 index 000000000..7b5fb57d8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "thanos.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 "thanos.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 "thanos.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Create a default fully qualified component name from the full app name and a component name. +We truncate the full name at 63 - 1 (last dash) - len(component name) chars because some Kubernetes name fields are limited to this (by the DNS naming spec) +and we want to make sure that the component is included in the name. +*/}} +{{- define "thanos.componentname" -}} +{{- $global := index . 0 -}} +{{- $component := index . 1 | trimPrefix "-" -}} +{{- printf "%s-%s" (include "thanos.fullname" $global | trunc (sub 62 (len $component) | int) | trimSuffix "-" ) $component | trimSuffix "-" -}} +{{- end -}} + +{{/* + +*/}} +{{- define "thanos.secretname" }} +{{- default (include "thanos.name" .) .Values.storeSecretName }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-deployment.yaml new file mode 100644 index 000000000..a0c167772 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-deployment.yaml @@ -0,0 +1,91 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.bucket.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "thanos.componentname" (list $ "bucket") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end -}} + {{- with .Values.bucket.deploymentAnnotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.bucket.replicaCount | default 1 }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.deploymentMatchLabels }}{{ toYaml . | indent 6 }}{{ end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.labels }}{{ toYaml . | indent 8 }}{{ end }} + {{- with .Values.bucket.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + containers: + - name: thanos-bucket + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: {{- with .Values.bucket.extraEnv }}{{ toYaml . | nindent 8 }}{{- end }} + args: + - "tools" + - "bucket" + - "web" + - "--log.level={{ .Values.bucket.logLevel }}" + - "--http-address=0.0.0.0:{{ .Values.bucket.http.port }}" + - "--objstore.config-file=/etc/config/object-store.yaml" + {{- if .Values.bucket.refresh }} + - "--refresh={{ .Values.bucket.refresh }}" + {{- end }} + {{- if .Values.bucket.timeout }} + - "--timeout={{ .Values.bucket.timeout }}" + {{- end }} + {{- if .Values.bucket.label }} + - "--label={{ .Values.bucket.label }}" + {{- end }} + {{ with .Values.bucket.extraArgs }}{{ toYaml . | nindent 8 }}{{- end }} + ports: + - name: http + containerPort: {{ .Values.bucket.http.port }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + resources: {{ toYaml .Values.bucket.resources | nindent 10 }} + volumes: + - name: config-volume + secret: + secretName: {{ include "thanos.secretname" . }} + {{- with .Values.bucket.securityContext }} + securityContext: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bucket.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bucket.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bucket.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.bucket.serviceAccount }} + serviceAccountName: "{{ . }}" + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-ingress.yaml new file mode 100644 index 000000000..28b037bda --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-ingress.yaml @@ -0,0 +1,42 @@ +{{ if .Values.global.thanos.enabled }} +{{ if and .Values.bucket.enabled .Values.bucket.http.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "bucket") }} + {{- with .Values.bucket.http.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: bucket + {{- if .Values.bucket.http.ingress.labels }} +{{ toYaml .Values.bucket.http.ingress.labels | indent 4 }} + {{- end }} +spec: + {{- if .Values.bucket.http.ingress.tls }} + tls: + {{- range .Values.bucket.http.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.bucket.http.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.bucket.http.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "bucket") }} + servicePort: {{ $.Values.bucket.http.port }} + {{- end }} +{{ end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-poddisruptionbudget.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-poddisruptionbudget.yaml new file mode 100644 index 000000000..fb3fd1cb7 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-poddisruptionbudget.yaml @@ -0,0 +1,27 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.bucket.enabled .Values.bucket.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ include "thanos.componentname" (list $ "bucket") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + {{- if .Values.bucket.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.bucket.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.bucket.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.bucket.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/component: bucket +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-service.yaml new file mode 100644 index 000000000..0d56d8a2b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/bucket-service.yaml @@ -0,0 +1,30 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.bucket.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "bucket") }} + {{- with .Values.bucket.http.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + ports: + - port: {{ .Values.bucket.http.port }} + protocol: TCP + targetPort: http + name: http + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: bucket +{{ with .Values.bucket.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{ end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-deployment.yaml new file mode 100644 index 000000000..3ac2bafd8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-deployment.yaml @@ -0,0 +1,112 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.compact.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "thanos.componentname" (list $ "compact") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: compact +{{ with .Values.compact.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end -}} + {{- with .Values.compact.deploymentAnnotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.compact.replicaCount | default 1 }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: compact +{{ with .Values.compact.deploymentMatchLabels }}{{ toYaml . | indent 6 }}{{ end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: compact +{{ with .Values.compact.labels }}{{ toYaml . | indent 8 }}{{ end }} + {{- with .Values.compact.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.compact.metrics.annotations.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.compact.http.port }}" + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + containers: + - name: thanos-compact + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: {{- with .Values.compact.extraEnv }}{{ toYaml . | nindent 8 }}{{- end }} + args: + - "compact" + - "--log.level={{ .Values.compact.logLevel }}" + - "--http-address=0.0.0.0:{{ .Values.compact.http.port }}" + - "--objstore.config-file=/etc/config/object-store.yaml" + - "--data-dir=/var/thanos/compact" + - "--consistency-delay={{ .Values.compact.consistencyDelay }}" + - "--retention.resolution-raw={{ .Values.compact.retentionResolutionRaw }}" + - "--retention.resolution-5m={{ .Values.compact.retentionResolution5m }}" + - "--retention.resolution-1h={{ .Values.compact.retentionResolution1h }}" + - "--block-sync-concurrency={{ .Values.compact.blockSyncConcurrency }}" + - "--compact.concurrency={{ .Values.compact.compactConcurrency }}" +{{- if .Values.compact.disableDownsampling }} + - "--downsampling.disable" +{{- end }} + - "--wait" +{{ with .Values.compact.extraArgs }}{{ toYaml . | indent 8 }}{{- end }} + ports: + - name: http + containerPort: {{ .Values.compact.http.port }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + - name: data-volume + mountPath: /var/thanos/compact + resources: {{ toYaml .Values.compact.resources | nindent 10 }} + volumes: + - name: data-volume + {{- if .Values.compact.dataVolume }} + {{- if .Values.compact.dataVolume.persistentVolumeClaim }} + {{- if .Values.compact.dataVolume.persistentVolumeClaim.claimName }} + persistentVolumeClaim: + claimName: {{ .Values.compact.dataVolume.persistentVolumeClaim.claimName }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: config-volume + secret: + secretName: {{ include "thanos.secretname" . }} + {{- with .Values.compact.securityContext }} + securityContext: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compact.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compact.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compact.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.compact.serviceAccount }} + serviceAccountName: "{{ . }}" + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-pvc.yaml new file mode 100644 index 000000000..f6b33e491 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-pvc.yaml @@ -0,0 +1,27 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.compact.enabled }} +{{- if .Values.compact.dataVolume -}} +{{- if .Values.compact.dataVolume.persistentVolumeClaim -}} +{{- if .Values.compact.dataVolume.persistentVolumeClaim.claimName -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .Values.compact.dataVolume.persistentVolumeClaim.claimName }} +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.compact.dataVolume.persistentVolumeClaim.storageClass }} + storageClassName: {{ .Values.compact.dataVolume.persistentVolumeClaim.storageClass }} + {{- end }} + resources: + requests: + {{- if .Values.compact.dataVolume.persistentVolumeClaim.storage }} + storage: {{ .Values.compact.dataVolume.persistentVolumeClaim.storage }} + {{- else }} + storage: 100Gi + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-service.yaml new file mode 100644 index 000000000..080821849 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-service.yaml @@ -0,0 +1,30 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.compact.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "compact") }} + {{- with .Values.compact.http.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: compact +{{ with .Values.compact.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + ports: + - port: {{ .Values.compact.http.port }} + protocol: TCP + targetPort: http + name: http + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: compact +{{ with .Values.compact.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{ end}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-servicemonitor.yaml new file mode 100644 index 000000000..bc224d802 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/compact-servicemonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.compact.enabled .Values.compact.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "thanos.componentname" (list $ "compact") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: compact +{{ with .Values.compact.metrics.serviceMonitor.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + jobLabel: thanos-compact + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: compact + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + interval: {{ .Values.compact.metrics.serviceMonitor.interval | default "15s" }} + {{- with .Values.compact.metrics.serviceMonitor.relabellings }} + metricRelabelings: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-deployment.yaml new file mode 100644 index 000000000..14d027a9e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-deployment.yaml @@ -0,0 +1,152 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.query.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "thanos.componentname" (list $ "query") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +{{ with .Values.query.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} + {{- with .Values.query.deploymentAnnotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.query.autoscaling.enabled }} + replicas: {{ .Values.query.replicaCount | default 1 }} +{{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query +{{ with .Values.query.deploymentMatchLabels }}{{ toYaml . | indent 6 }}{{ end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query +{{ with .Values.query.labels }}{{ toYaml . | indent 8 }}{{ end }} + {{- with .Values.query.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.query.metrics.annotations.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.query.http.port }}" + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + containers: + - name: thanos-query + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "query" + - "--log.level={{ .Values.query.logLevel }}" + - "--grpc-address=0.0.0.0:{{ .Values.query.grpc.port }}" + - "--http-address=0.0.0.0:{{ .Values.query.http.port }}" + - "--query.timeout={{ .Values.query.timeout }}" + - "--query.max-concurrent={{ .Values.query.maxConcurrent }}" + {{- if .Values.query.autoDownsampling }} + - "--query.auto-downsampling" + {{- end }} + {{- if .Values.query.replicaLabel }} + - "--query.replica-label={{ .Values.query.replicaLabel }}" + {{- end }} + {{- if .Values.query.webRoutePrefix }} + - "--web.route-prefix={{ .Values.query.webRoutePrefix }}" + {{- end }} + {{- if .Values.query.webExternalPrefix }} + - "--web.external-prefix={{ .Values.query.webExternalPrefix }}" + {{- end }} + {{- if .Values.query.webPrefixHeader }} + - "--web.prefix-header={{ .Values.query.webPrefixHeader }}" + {{- end }} + {{- if .Values.query.storeDNSResolver }} + - "--store.sd-dns-resolver={{ .Values.query.storeDNSResolver }}" + {{- end }} + {{- if .Values.query.storeDNSDiscovery }} + - "--store=dnssrv+_grpc._tcp.{{ include "thanos.componentname" (list $ "store") }}-grpc.{{ .Release.Namespace }}.svc" + {{- end }} + {{- if .Values.query.sidecarDNSDiscovery }} + - "--store=dnssrv+_grpc._tcp.{{ include "thanos.componentname" (list $ "sidecar") }}-grpc.{{ .Release.Namespace }}.svc" + {{- end }} + {{- range .Values.query.stores }} + - "--store={{ . }}" + {{- end }} + {{- range .Values.query.serviceDiscoveryFiles }} + - "--store.sd-files={{ . }}" + {{- end }} + {{- range .Values.query.serviceDiscoveryFileConfigMaps }} + - "--store.sd-files=/etc/query/{{ . }}/*.yaml" + - "--store.sd-files=/etc/query/{{ . }}/*.yml" + - "--store.sd-files=/etc/query/{{ . }}/*.json" + {{- end }} + {{- if .Values.query.serviceDiscoveryInterval }} + - "--store.sd-interval={{ .Values.query.serviceDiscoveryInterval }}" + {{- end }} + + {{- if .Values.query.extraArgs }} + {{ toYaml .Values.query.extraArgs | nindent 8 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.query.http.port }} + - name: grpc + containerPort: {{ .Values.query.grpc.port }} + resources: + {{ toYaml .Values.query.resources | nindent 10 }} + env: + {{- toYaml .Values.query.extraEnv | nindent 10 }} + volumeMounts: + {{- range .Values.query.serviceDiscoveryFileConfigMaps }} + - mountPath: /etc/query/{{ . }} + name: {{ . }} + {{- end }} + {{- if .Values.query.certSecretName }} + - mountPath: /etc/certs + name: {{ .Values.query.certSecretName }} + readOnly: true + {{- end }} + livenessProbe: + httpGet: + path: /-/healthy + port: http + volumes: + {{- range .Values.query.serviceDiscoveryFileConfigMaps }} + - name: {{ . }} + configMap: + defaultMode: 420 + name: {{ . }} + {{- end }} + {{- if .Values.query.certSecretName }} + - name: {{ .Values.query.certSecretName }} + secret: + defaultMode: 420 + secretName: {{ .Values.query.certSecretName }} + {{- end }} + {{- with .Values.query.securityContext }} + securityContext: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.query.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.query.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.query.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.query.serviceAccount }} + serviceAccountName: "{{ . }}" + {{- end }} +{{ end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-deployment.yaml new file mode 100644 index 000000000..e710ea3ed --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-deployment.yaml @@ -0,0 +1,126 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.queryFrontend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} + {{- with .Values.queryFrontend.deploymentAnnotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if not .Values.queryFrontend.autoscaling.enabled }} + replicas: {{ .Values.queryFrontend.replicaCount | default 1 }} +{{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.deploymentMatchLabels }}{{ toYaml . | indent 6 }}{{ end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.labels }}{{ toYaml . | indent 8 }}{{ end }} + {{- with .Values.queryFrontend.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.queryFrontend.metrics.annotations.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.queryFrontend.http.port }}" + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + containers: + - name: thanos-query-frontend + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "query-frontend" + - "--log.level={{ .Values.queryFrontend.logLevel }}" + - "--http-address=0.0.0.0:{{ .Values.queryFrontend.http.port }}" + - "--query-frontend.downstream-url=http://{{ include "thanos.componentname" (list $ "query") }}-http.{{ .Release.Namespace }}:{{ .Values.query.http.port }}" + - "--query-range.split-interval={{ .Values.queryFrontend.splitInterval }}" + - "--query-range.max-retries-per-request={{ .Values.queryFrontend.maxRetriesPerRequest }}" + - "--query-range.max-query-length={{ .Values.queryFrontend.maxQueryLength }}" + - "--query-range.max-query-parallelism={{ .Values.queryFrontend.maxQueryParallelism }}" + - "--query-range.response-cache-max-freshness={{ .Values.queryFrontend.responseCacheMaxFreshness }}" + {{- if .Values.queryFrontend.responseCache.enabled }} + {{- with .Values.queryFrontend.responseCache }} + - |- + --query-range.response-cache-config= + config: + max_size: {{ quote .maxSize }} + max_size_items: {{ .maxSizeItems }} + validity: {{ quote .validity }} + type: "in-memory" + {{- end }} + {{- else if .Values.queryFrontend.responseCacheConfigFile }} + - "--query-range.response-cache-config-file={{ .Values.queryFrontend.responseCacheConfigFile }}" + {{- else if .Values.queryFrontend.responseCacheConfig }} + - |- + --query-range.response-cache-config={{ toYaml .Values.queryFrontend.responseCacheConfig | nindent 12 }} + {{- end }} + {{- if .Values.queryFrontend.compressResponses }} + - "--query-frontend.compress-responses" + {{- end }} + {{- if .Values.queryFrontend.partialResponse }} + - "--query-range.partial-response" + {{- end }} + {{- if .Values.queryFrontend.extraArgs }} + {{ toYaml .Values.queryFrontend.extraArgs | nindent 8 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.queryFrontend.http.port }} + resources: + {{ toYaml .Values.queryFrontend.resources | nindent 10 }} + env: + {{- toYaml .Values.queryFrontend.extraEnv | nindent 10 }} + volumeMounts: + {{- if .Values.queryFrontend.certSecretName }} + - mountPath: /etc/certs + name: {{ .Values.queryFrontend.certSecretName }} + readOnly: true + {{- end }} + livenessProbe: + httpGet: + path: /-/healthy + port: http + volumes: + {{- if .Values.queryFrontend.certSecretName }} + - name: {{ .Values.queryFrontend.certSecretName }} + secret: + defaultMode: 420 + secretName: {{ .Values.queryFrontend.certSecretName }} + {{- end }} + {{- with .Values.queryFrontend.securityContext }} + securityContext: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.queryFrontend.serviceAccount }} + serviceAccountName: "{{ . }}" + {{- end }} +{{ end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-horizontalpodautoscaler.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-horizontalpodautoscaler.yaml new file mode 100644 index 000000000..3d08e459b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-horizontalpodautoscaler.yaml @@ -0,0 +1,37 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.queryFrontend.enabled }} +{{- if .Values.queryFrontend.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "thanos.componentname" (list $ "query-frontend") }} + minReplicas: {{ .Values.queryFrontend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.queryFrontend.autoscaling.maxReplicas }} + metrics: +{{- with .Values.queryFrontend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ . }} +{{- end }} +{{- with .Values.queryFrontend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ . }} +{{- end }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-ingress.yml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-ingress.yml new file mode 100644 index 000000000..5423cecf2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-ingress.yml @@ -0,0 +1,45 @@ +--- +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.queryFrontend.enabled .Values.queryFrontend.http.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }}-http + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend + {{- if .Values.queryFrontend.http.ingress.labels }} + {{ toYaml .Values.queryFrontend.http.ingress.labels | indent 4 }} + {{- end }} + {{- with .Values.queryFrontend.http.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.queryFrontend.http.ingress.tls }} + tls: + {{- range .Values.queryFrontend.http.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + {{- if .secretName }} + secretName: {{ .secretName }} + {{- end}} + {{- end }} + {{- end }} + rules: + {{- range .Values.queryFrontend.http.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.queryFrontend.http.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "query-frontend") }}-http + servicePort: {{ $.Values.queryFrontend.http.port }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-poddisruptionbudget.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-poddisruptionbudget.yaml new file mode 100644 index 000000000..5cfef4756 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-poddisruptionbudget.yaml @@ -0,0 +1,27 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.queryFrontend.enabled .Values.queryFrontend.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + {{- if .Values.queryFrontend.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.queryFrontend.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.queryFrontend.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.queryFrontend.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/component: query-frontend +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-service.yaml new file mode 100644 index 000000000..2521e898a --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-service.yaml @@ -0,0 +1,34 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.queryFrontend.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }}-http + {{- with .Values.queryFrontend.http.service.annotations }} + annotations: {{ toYaml .| nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: {{ .Values.queryFrontend.http.service.type }} + {{- if .Values.queryFrontend.http.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.queryFrontend.http.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.queryFrontend.http.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-servicemonitor.yaml new file mode 100644 index 000000000..004367519 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-frontend-servicemonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.queryFrontend.enabled .Values.queryFrontend.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "thanos.componentname" (list $ "query-frontend") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query-frontend +{{ with .Values.queryFrontend.metrics.serviceMonitor.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + jobLabel: thanos-query + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query-frontend + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + interval: {{ .Values.queryFrontend.metrics.serviceMonitor.interval | default "15s" }} + {{- with .Values.queryFrontend.metrics.serviceMonitor.relabellings }} + metricRelabelings: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-horizontalpodautoscaler.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-horizontalpodautoscaler.yaml new file mode 100644 index 000000000..9b38473d8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-horizontalpodautoscaler.yaml @@ -0,0 +1,37 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.query.enabled }} +{{- if .Values.query.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "thanos.componentname" (list $ "query") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "thanos.componentname" (list $ "query") }} + minReplicas: {{ .Values.query.autoscaling.minReplicas }} + maxReplicas: {{ .Values.query.autoscaling.maxReplicas }} + metrics: +{{- with .Values.query.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ . }} +{{- end }} +{{- with .Values.query.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ . }} +{{- end }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-ingress.yml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-ingress.yml new file mode 100644 index 000000000..cfda4a0e3 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-ingress.yml @@ -0,0 +1,89 @@ +--- +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.query.enabled .Values.query.http.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "query") }}-http + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query + {{- if .Values.query.http.ingress.labels }} + {{ toYaml .Values.query.http.ingress.labels | indent 4 }} + {{- end }} + {{- with .Values.query.http.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.query.http.ingress.tls }} + tls: + {{- range .Values.query.http.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + {{- if .secretName }} + secretName: {{ .secretName }} + {{- end}} + {{- end }} + {{- end }} + rules: + {{- range .Values.query.http.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.query.http.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "query") }}-http + servicePort: {{ $.Values.query.http.port }} + {{- end }} +{{- end }} + +{{- if and .Values.query.enabled .Values.query.grpc.ingress.enabled }} +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "query") }}-grpc + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query + {{- if .Values.query.grpc.ingress.labels }} + {{ toYaml .Values.grpc.ingress.labels | indent 4 }} + {{- end }} + {{- with .Values.query.grpc.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.query.grpc.ingress.tls }} + tls: + {{- range .Values.query.grpc.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + {{- if .secretName }} + secretName: {{ .secretName }} + {{- end}} + {{- end }} + {{- end }} + rules: + {{- range .Values.query.grpc.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.query.grpc.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "query") }}-grpc + servicePort: {{ $.Values.query.http.port }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-poddisruptionbudget.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-poddisruptionbudget.yaml new file mode 100644 index 000000000..efc2c817c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-poddisruptionbudget.yaml @@ -0,0 +1,27 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.query.enabled .Values.query.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ include "thanos.componentname" (list $ "query") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +{{ with .Values.query.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + {{- if .Values.query.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.query.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.query.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.query.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/component: query +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-service.yaml new file mode 100644 index 000000000..89178a4e1 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-service.yaml @@ -0,0 +1,65 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.query.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "query") }}-grpc + {{- with .Values.query.grpc.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +{{ with .Values.query.grpc.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ .Values.query.grpc.port }} + targetPort: grpc + protocol: TCP + name: grpc + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query +{{ with .Values.query.grpc.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "query") }}-http + {{- with .Values.query.http.service.annotations }} + annotations: {{ toYaml .| nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +{{ with .Values.query.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: {{ .Values.query.http.service.type }} + {{- if .Values.query.http.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.query.http.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.query.http.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query +{{ with .Values.query.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-servicemonitor.yaml new file mode 100644 index 000000000..673445428 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/query-servicemonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.query.enabled .Values.query.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "thanos.componentname" (list $ "query") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: query +{{ with .Values.query.metrics.serviceMonitor.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + jobLabel: thanos-query + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: query + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + interval: {{ .Values.query.metrics.serviceMonitor.interval | default "15s" }} + {{- with .Values.query.metrics.serviceMonitor.relabellings }} + metricRelabelings: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-service.yaml new file mode 100644 index 000000000..021bdfaf9 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-service.yaml @@ -0,0 +1,61 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.sidecar.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "sidecar") }}-grpc + {{- with .Values.sidecar.grpc.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: sidecar +{{ with .Values.sidecar.grpc.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ .Values.sidecar.grpc.port }} + protocol: TCP + targetPort: grpc + name: grpc + selector: + app: prometheus +{{ with .Values.sidecar.grpc.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "sidecar") }}-http + {{- with .Values.sidecar.http.service.annotations }} + annotations: {{ toYaml .| nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: sidecar +{{ with .Values.store.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: {{ .Values.sidecar.http.service.type }} + {{- if .Values.sidecar.http.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.sidecar.http.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.sidecar.http.port }} + targetPort: http + protocol: TCP + name: http + selector: + app: prometheus +{{ with .Values.sidecar.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-servicemonitor.yaml new file mode 100644 index 000000000..6271a23ca --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/sidecar-servicemonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.sidecar.enabled .Values.sidecar.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "thanos.componentname" (list $ "sidecar") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: sidecar +{{ with .Values.sidecar.metrics.serviceMonitor.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + jobLabel: thanos-sidecar + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: sidecar + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + interval: {{ .Values.sidecar.metrics.serviceMonitor.interval | default "15s" }} + {{- with .Values.sidecar.metrics.serviceMonitor.relabellings }} + metricRelabelings: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-deployment.yaml new file mode 100644 index 000000000..e6a9c8bd8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-deployment.yaml @@ -0,0 +1,138 @@ +{{ if .Values.global.thanos.enabled }} +{{ if .Values.store.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "thanos.componentname" (list $ "store") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store +{{ with .Values.store.deploymentLabels }}{{ toYaml . | indent 4 }}{{ end }} + {{- with .Values.store.deploymentAnnotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.store.replicaCount | default 1 }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: store +{{ with .Values.store.deploymentMatchLabels }}{{ toYaml . | indent 6 }}{{ end }} + template: + metadata: + labels: +{{ with .Values.store.labels }}{{ toYaml . | indent 8 }}{{ end }} + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: store + {{- with .Values.store.annotations }} + annotations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.store.metrics.annotations.enabled }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.store.http.port }}" + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + containers: + - name: thanos-store + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "store" + - "--data-dir=/var/thanos/store" + - "--log.level={{ .Values.store.logLevel }}" + - "--http-address=0.0.0.0:{{ .Values.store.http.port }}" + - "--grpc-address=0.0.0.0:{{ .Values.store.grpc.port }}" + - "--objstore.config-file=/etc/config/object-store.yaml" + {{- if .Values.store.indexCacheSize }} + - "--index-cache-size={{ .Values.store.indexCacheSize }}" + {{- end }} + {{- if .Values.store.chunkPoolSize }} + - "--chunk-pool-size={{ .Values.store.chunkPoolSize }}" + {{- end }} + {{- if .Values.store.grpcSeriesSampleLimit }} + - "--store.grpc.series-sample-limit={{ .Values.store.grpcSeriesSampleLimit }}" + {{- end }} + {{- if .Values.store.grpcSeriesMaxConcurrency }} + - "--store.grpc.series-max-concurrency={{ .Values.store.grpcSeriesMaxConcurrency }}" + {{- end }} + {{- if .Values.store.syncBlockDuration }} + - "--sync-block-duration={{ .Values.store.syncBlockDuration }}" + {{- end }} + {{- if .Values.store.blockSyncConcurrency }} + - "--block-sync-concurrency={{ .Values.store.blockSyncConcurrency }}" + {{- end }} + {{- if .Values.store.extraArgs }} + {{ toYaml .Values.store.extraArgs | nindent 8 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.store.http.port }} + - name: grpc + containerPort: {{ .Values.store.grpc.port }} + env: + {{- toYaml .Values.store.extraEnv | nindent 10 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + - name: data + mountPath: /var/thanos/store + {{- if .Values.store.certSecretName }} + - mountPath: /etc/certs + name: {{ .Values.store.certSecretName }} + readOnly: true + {{- end }} + resources: + {{ toYaml .Values.store.resources | nindent 10 }} + volumes: + - name: data + {{- if .Values.store.dataVolume }} + {{- if .Values.store.dataVolume.persistentVolumeClaim }} + {{- if .Values.store.dataVolume.persistentVolumeClaim.claimName }} + persistentVolumeClaim: + claimName: {{ .Values.store.dataVolume.persistentVolumeClaim.claimName }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + {{- else }} + emptyDir: {} + {{- end }} + - name: config-volume + secret: + secretName: {{ include "thanos.secretname" . }} + {{- if .Values.store.certSecretName }} + - name: {{ .Values.store.certSecretName }} + secret: + defaultMode: 420 + secretName: {{ .Values.store.certSecretName }} + {{- end }} + {{- with .Values.store.securityContext }} + securityContext: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.store.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.store.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.store.tolerations }} + tolerations: {{ toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.store.serviceAccount }} + serviceAccountName: "{{ . }}" + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-ingress.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-ingress.yaml new file mode 100644 index 000000000..4d18c019e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-ingress.yaml @@ -0,0 +1,85 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.store.enabled .Values.store.http.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "store") }}-http + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store + {{- if .Values.store.http.ingress.labels }} + {{ toYaml .Values.store.http.ingress.labels | indent 4 }} + {{- end }} + {{- with .Values.store.http.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.store.http.ingress.tls }} + tls: + {{- range .Values.store.http.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.store.http.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.store.http.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "store") }}-http + servicePort: {{ $.Values.store.http.port }} + {{- end }} +{{- end }} + +--- + + {{- if and .Values.store.enabled .Values.store.grpc.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ include "thanos.componentname" (list $ "store") }}-grpc + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store + {{- if .Values.store.grpc.ingress.labels }} + {{ toYaml .Values.grpc.ingress.labels | indent 4 }} + {{- end }} + {{- with .Values.store.grpc.ingress.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.store.grpc.ingress.tls }} + tls: + {{- range .Values.store.grpc.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.store.grpc.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $.Values.store.grpc.ingress.path }} + backend: + serviceName: {{ include "thanos.componentname" (list $ "store") }}-grpc + servicePort: {{ $.Values.store.http.port }} + {{- end }} +{{- end }} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-pvc.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-pvc.yaml new file mode 100644 index 000000000..a778e067b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-pvc.yaml @@ -0,0 +1,27 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.store.enabled }} +{{- if .Values.store.dataVolume -}} +{{- if .Values.store.dataVolume.persistentVolumeClaim -}} +{{- if .Values.store.dataVolume.persistentVolumeClaim.claimName -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .Values.store.dataVolume.persistentVolumeClaim.claimName }} +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.store.dataVolume.persistentVolumeClaim.storageClass }} + storageClassName: {{ .Values.store.dataVolume.persistentVolumeClaim.storageClass }} + {{- end }} + resources: + requests: + {{- if .Values.store.dataVolume.persistentVolumeClaim.storage }} + storage: {{ .Values.store.dataVolume.persistentVolumeClaim.storage }} + {{- else }} + storage: 100Gi + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-service.yaml new file mode 100644 index 000000000..ce5894fa3 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-service.yaml @@ -0,0 +1,65 @@ +{{ if .Values.global.thanos.enabled }} +{{- if .Values.store.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "store") }}-grpc + {{- with .Values.store.grpc.service.annotations }} + annotations: {{ toYaml . | nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store +{{ with .Values.store.grpc.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ .Values.store.grpc.port }} + targetPort: grpc + protocol: TCP + name: grpc + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: store +{{ with .Values.store.grpc.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "thanos.componentname" (list $ "store") }}-http + {{- with .Values.store.http.service.annotations }} + annotations: {{ toYaml .| nindent 4 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ $.Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store +{{ with .Values.store.http.service.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + type: {{ .Values.store.http.service.type }} + {{- if .Values.store.http.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.store.http.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.store.http.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: store +{{ with .Values.store.http.service.matchLabels }}{{ toYaml . | indent 4 }}{{ end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-servicemonitor.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-servicemonitor.yaml new file mode 100644 index 000000000..c181c6416 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/templates/store-servicemonitor.yaml @@ -0,0 +1,32 @@ +{{ if .Values.global.thanos.enabled }} +{{- if and .Values.store.enabled .Values.store.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "thanos.componentname" (list $ "store") }} + labels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + helm.sh/chart: {{ include "thanos.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/version: {{ .Chart.AppVersion | replace "+" "_" }} + app.kubernetes.io/component: store +{{ with .Values.store.metrics.serviceMonitor.labels }}{{ toYaml . | indent 4 }}{{ end }} +spec: + jobLabel: thanos-store + selector: + matchLabels: + app.kubernetes.io/name: {{ include "thanos.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: store + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + interval: {{ .Values.store.metrics.serviceMonitor.interval | default "15s" }} + {{- with .Values.store.metrics.serviceMonitor.relabellings }} + metricRelabelings: {{ toYaml . | nindent 8 }} + {{- end }} +{{- end -}} +{{ end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/values.yaml b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/values.yaml new file mode 100644 index 000000000..7dfab45fe --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/charts/thanos/values.yaml @@ -0,0 +1,764 @@ +image: + repository: thanosio/thanos + tag: v0.19.0 + pullPolicy: IfNotPresent + +store: + enabled: true + # Maximum size of items held in the index cache. + indexCacheSize: 250MB + # Maximum size of concurrently allocatable bytes for chunks. + chunkPoolSize: 2GB + # Maximum amount of samples returned via a single series call. 0 means no limit. + # NOTE: for efficiency we take 120 as the number of samples in chunk (it cannot be bigger than that), + # so the actual number of samples might be lower, even though the maximum could be hit. + grpcSeriesSampleLimit: 0 + # Maximum number of concurrent Series calls. + grpcSeriesMaxConcurrency: 20 + # Repeat interval for syncing the blocks between local and remote view. + syncBlockDuration: 3m + # Number of goroutines to use when syncing blocks from object storage. + blockSyncConcurrency: 20 + # Log filtering level. + logLevel: info + # Add extra environment variables to store + extraEnv: [] + # - name: ENV + # value: value + # + # Add extra arguments to the store service + extraArgs: [] + # - "--extraargs=extravalue" + # + # Data volume for the store to store temporary data defaults to emptyDir + # dataVolume: + # persistentVolumeClaim: + # claimName: store-data-volume + # storage: 100Gi + # Number of replicas running from store component + replicaCount: 1 + # Extra labels for store pod template + labels: {} + # cluster: example + # + # Extra annotations for store pod template + annotations: {} + # example.com: default + # + # Add extra labels to store deployment + deploymentLabels: {} + # extraLabel: extraLabelValue + # + # Add extra annotations to store deployment + deploymentAnnotations: {} + # extraAnnotation: extraAnnotationValue + # + # Add extra selector matchLabels to store deployment + deploymentMatchLabels: {} + # Enable metrics collecting for store service + metrics: + # This is the Prometheus annotation type scraping configuration + annotations: + enabled: false + # Enable ServiceMonitor https://github.com/coreos/prometheus-operator + serviceMonitor: + enabled: false + # Labels for prometheus-operator to find servicemonitor + labels: {} + # The grpc endpoint to communicate with other components + grpc: + # grpc listen port number + port: 10901 + # Service definition for query grpc service + service: + # Annotations to query grpc service + annotations: {} + # Labels to query grpc service + labels: {} + matchLabels: {} + # Set up ingress for the grpc service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + # The http endpoint to communicate with other components + http: + # http listen port number + port: 10902 + # Service definition for query http service + service: + type: ClusterIP + # Annotations to query http service + annotations: {} + # Labels to query http service + labels: {} + matchLabels: {} + # Set up ingress for the http service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # Optional securityContext + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + + resources: {} + # limits: + # cpu: 2000m + # memory: 16Gi + # requests: + # cpu: 1000m + # memory: 4Gi + # + # Node tolerations for server scheduling to nodes with taints + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + # + # Node labels for store pod assignment + # Ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + # + # Pod affinity + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + serviceAccount: "" + +# Query Frontend Component +queryFrontend: + enabled: true + + # Split queries by an interval and execute in parallel, 0 disables it. + splitInterval: 24h + + # Maximum number of retries for a single request; beyond this, the downstream error is returned. + maxRetriesPerRequest: 5 + + # Limit the query time range (end - start time) in the query-frontend, 0 disables it. + maxQueryLength: 0 + + # Maximum number of queries will be scheduled in parallel by the frontend.\ + maxQueryParallelism: 14 + + # Most recent allowed cacheable result, to prevent caching very recent results that might still be in flux. + responseCacheMaxFreshness: 1m + + # Path to YAML file that contains response cache configuration. + # responseCacheConfigFile: + + # Response Cache Configuration + responseCache: + enabled: false + maxSize: 512MB + maxSizeItems: 0 + validity: 10m + + # Response cache configuration content + # responseCacheConfig: + + # Enable partial response for queries if no partial_response param is specified. --no-query-range.partial-response for disabling. + # partialResponse: false + + # Compress HTTP responses. + compressResponses: true + + logLevel: info + # Add extra environment variables to query + extraEnv: [] + # - name: ENV + # value: value + # + # Add extra arguments to the query service + extraArgs: [] + # - "--extraargs=extravalue" + # + # Number of replicas running from query component + replicaCount: 1 + # Enable HPA for query component + autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 3 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + # Enable podDisruptionBudget for query component + podDisruptionBudget: + enabled: false + # minAvailable and maxUnavailable can't be used simultaneous. Choose one. + minAvailable: 1 + # maxUnavailable: 50% + + serviceAccount: "" + + # The http endpoint to communicate with other components + http: + # http listen port number + port: 10902 + # Service definition for query http service + service: + type: ClusterIP + # Annotations to query http service + annotations: {} + # Labels to query http service + labels: {} + matchLabels: {} + # Set up ingress for the http service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + certSecretName: "" + # Extra labels for query pod template + labels: {} + # cluster: example + # + # Extra annotations for query pod template + annotations: {} + # example.com: default + # + # Add extra labels to query deployment + deploymentLabels: {} + # extraLabel: extraLabelValue + # + # Add extra annotations to query deployment + deploymentAnnotations: {} + # extraAnnotation: extraAnnotationValue + # + # Add extra selector matchLabels to query deployment + deploymentMatchLabels: {} + + # Enable metrics collecting for query service + metrics: + # This is the Prometheus annotation type scraping configuration + annotations: + enabled: false + # Enable ServiceMonitor https://github.com/coreos/prometheus-operator + serviceMonitor: + enabled: false + # Labels for prometheus-operator to find servicemonitor + labels: {} + + # Optional securityContext + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + + resources: {} + # limits: + # cpu: 2000m + # memory: 16Gi + # requests: + # cpu: 1000m + # memory: 4Gi + # + # Node tolerations for server scheduling to nodes with taints + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + # + # Node labels for compact pod assignment + # Ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + # + # Pod affinity + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + +query: + enabled: true + # Label to treat as a replica indicator along which data is deduplicated. + # Still you will be able to query without deduplication using 'dedup=false' parameter. + replicaLabel: "" + # Prefix for API and UI endpoints. This allows thanos UI to be served on a sub-path. + # This option is analogous to --web.route-prefix of Promethus. + webRoutePrefix: "" + # Static prefix for all HTML links and redirect + # URLs in the UI query web interface. Actual + # endpoints are still served on / or the + # web.route-prefix. This allows thanos UI to be + # served behind a reverse proxy that strips a URL + # sub-path. + webExternalPrefix: "" + # Name of HTTP request header used for dynamic prefixing of UI links and redirects. + # This option is ignored if web.external-prefix argument is set. Security risk: enable this + # option only if a reverse proxy in front of thanos is resetting the header. The --web.prefix-header=X-Forwarded-Prefix option + # can be useful, for example, if Thanos UI is served via Traefik reverse proxy with PathPrefixStrip option enabled, which sends the + # stripped prefix value in X-Forwarded-Prefix header. This allows thanos UI to be served on a sub-path + webPrefixHeader: "" + # Maximum time to process query by query node. + timeout: 2m + # Maximum number of queries processed concurrently by query node. + maxConcurrent: 16 + # Maximum number of select requests made concurrently per a query. + maxConcurrentSelect: 4 + # Enable automatic adjustment (step / 5) to what source of data should be used in store gateways + # if no max_source_resolution param is specified. + autoDownsampling: false + # https://github.com/improbable-eng/thanos/issues/1015 + storeDNSResolver: miekgdns + # Enable DNS discovery for stores + storeDNSDiscovery: true + # Enable DNS discovery for sidecars (this is for the chart built-in sidecar service) + sidecarDNSDiscovery: true + # Addresses of statically configured store API servers (repeatable). + # The scheme may be prefixed with 'dns+' or 'dnssrv+' to detect store API servers through respective DNS lookups. + stores: [] + # - "dnssrv+_grpc._tcp...svc" + # + # Path to files that contains addresses of store API servers. The path can be a glob pattern (repeatable). + serviceDiscoveryFiles: [] + # Names of configmaps that contain addresses of store API servers, used for file service discovery. + serviceDiscoveryFileConfigMaps: [] + # Refresh interval to re-read file SD files. It is used as a resync fallback. + serviceDiscoveryInterval: 5m + # Log filtering level. + logLevel: info + # Add extra environment variables to query + extraEnv: [] + # - name: ENV + # value: value + # + # Add extra arguments to the query service + extraArgs: [] + # - "--extraargs=extravalue" + # + # Number of replicas running from query component + replicaCount: 1 + # Enable HPA for query component + autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 3 + targetCPUUtilizationPercentage: 50 + targetMemoryUtilizationPercentage: 50 + # Enable podDisruptionBudget for query component + podDisruptionBudget: + enabled: false + # minAvailable and maxUnavailable can't be used simultaneous. Choose one. + minAvailable: 1 + # maxUnavailable: 50% + + # The http endpoint to communicate with other components + http: + # http listen port number + port: 10902 + # Service definition for query http service + service: + type: ClusterIP + # Annotations to query http service + annotations: {} + # Labels to query http service + labels: {} + matchLabels: {} + # Set up ingress for the http service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + certSecretName: "" + # Extra labels for query pod template + labels: {} + # cluster: example + # + # Extra annotations for query pod template + annotations: {} + # example.com: default + # + # Add extra labels to query deployment + deploymentLabels: {} + # extraLabel: extraLabelValue + # + # Add extra annotations to query deployment + deploymentAnnotations: {} + # extraAnnotation: extraAnnotationValue + # + # Add extra selector matchLabels to query deployment + deploymentMatchLabels: {} + + # Enable metrics collecting for query service + metrics: + # This is the Prometheus annotation type scraping configuration + annotations: + enabled: false + # Enable ServiceMonitor https://github.com/coreos/prometheus-operator + serviceMonitor: + enabled: false + # Labels for prometheus-operator to find servicemonitor + labels: {} + + # Optional securityContext + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + + resources: {} + # limits: + # cpu: 2000m + # memory: 16Gi + # requests: + # cpu: 1000m + # memory: 4Gi + # + # Node tolerations for server scheduling to nodes with taints + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + # + # Node labels for compact pod assignment + # Ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + # + # Pod affinity + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + + # The grpc endpoint to communicate with other components + grpc: + # grpc listen port number + port: 10901 + # Service definition for query grpc service + service: + # Annotations to query grpc service + annotations: {} + # labels to query grpc service + labels: {} + matchLabels: {} + # Set up ingress for the grpc service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + serviceAccount: "" + +compact: + enabled: true + # Minimum age of fresh (non-compacted) blocks before they are being processed. + # Malformed blocks older than the maximum of consistency-delay and 30m0s will be removed. + consistencyDelay: 30m + # How long to retain raw samples in bucket. Setting this to 0d will retain samples of this resolution forever + retentionResolutionRaw: 1825d + # How long to retain samples of resolution 1 (5 minutes) in bucket. Setting this to 0d will retain samples of this resolution forever + retentionResolution5m: 1825d + # How long to retain samples of resolution 2 (1 hour) in bucket. Setting this to 0d will retain samples of this resolution forever + retentionResolution1h: 1825d + # Number of goroutines to use when compacting groups. + compactConcurrency: 1 + # Number of goroutines to use when syncing block metadata from object storage. + blockSyncConcurrency: 20 + # Disables Downsampling data + disableDownsampling: false + # Log filtering level. + logLevel: info + # Compact service listening http port + http: + port: 10902 + service: + labels: {} + # Add extra environment variables to compact + extraEnv: + # - name: ENV + # value: value + # + # Add extra arguments to the compact service + extraArgs: + # - "--extraargs=extravalue" + # + # Data volume for the compactor to store temporary data defaults to emptyDir + # dataVolume: + # persistentVolumeClaim: + # claimName: compact-data-volume + # storage: 100Gi + # Extra labels for compact pod template + labels: {} + # cluster: example + # + # Extra annotations for compact pod template + annotations: {} + # example.com: default + # + # Add extra labels to compact deployment + deploymentLabels: {} + # extraLabel: extraLabelValue + # + # Add extra annotations to compact deployment + deploymentAnnotations: {} + # extraAnnotation: extraAnnotationValue + # + # Add extra selector matchLabels to compact deployment + deploymentMatchLabels: {} + # + # Enable metrics collecting for compact service + metrics: + # This is the Prometheus annotation type scraping configuration + annotations: + enabled: false + # Enable ServiceMonitor https://github.com/coreos/prometheus-operator + serviceMonitor: + enabled: false + # Labels for prometheus-operator to find servicemonitor + labels: {} + serviceAccount: "" + + # Optional securityContext + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + + resources: {} + # limits: + # cpu: 2000m + # memory: 16Gi + # requests: + # cpu: 1000m + # memory: 4Gi + # + # Node tolerations for server scheduling to nodes with taints + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + # + # Node labels for compact pod assignment + # Ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + # + # Pod affinity + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + +bucket: + enabled: true + # Number of replicas running from bucket component + replicaCount: 1 + # Log filtering level. + logLevel: info + # Refresh interval to download metadata from remote storage + refresh: 30m + # Timeout to download metadata from remote storage + timeout: 5m + # Prometheus label to use as timeline title + label: "" + # The http endpoint to communicate with other components + http: + # http listen port number + port: 8080 + # Service definition for bucket http service + service: + type: ClusterIP + # Annotations to bucket http service + annotations: {} + # Labels to bucket http service + labels: {} + matchLabels: {} + # Set up ingress for the http service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # Add extra environment variables to bucket + extraEnv: + # - name: ENV + # value: value + # + # Add extra arguments to the bucket service + extraArgs: + # - "--extraargs=extravalue" + # + # Extra labels for bucket pod template + labels: {} + # cluster: example + # + # Extra annotations for bucket pod template + annotations: {} + # example.com: default + # + # Add extra labels to bucket deployment + deploymentLabels: {} + # extraLabel: extraLabelValue + # + # Add extra annotations to bucket deployment + deploymentAnnotations: {} + # + # Add extra selector matchLabels to bucket deployment + deploymentMatchLabels: {} + + # Enable podDisruptionBudget for bucket component + podDisruptionBudget: + enabled: false + # minAvailable and maxUnavailable can't be used simultaneous. Choose one. + minAvailable: 1 + # maxUnavailable: 50% + + # Optional securityContext + securityContext: + fsGroup: 1001 + runAsNonRoot: true + runAsUser: 1001 + + resources: {} + # limits: + # cpu: 2000m + # memory: 16Gi + # requests: + # cpu: 1000m + # memory: 4Gi + # + # Node tolerations for server scheduling to nodes with taints + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + # + # Node labels for bucket pod assignment + # Ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + # + # Pod affinity + # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + serviceAccount: "" + +sidecar: + # NOTE: This is only the service references for the sidecar + enabled: true + # Enable metrics collecting for sidecar service + metrics: + # Enable ServiceMonitor https://github.com/coreos/prometheus-operator + serviceMonitor: + enabled: false + # Labels for prometheus-operator to find servicemonitor + labels: {} + # The grpc endpoint to communicate with other components + grpc: + # grpc listen port number + port: 10901 + # Service definition for sidecar grpc service + service: + # Annotations to sidecar grpc service + annotations: {} + # Labels to sidecar grpc service + labels: {} + matchLabels: {} + # Set up ingress for the grpc service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + # The http endpoint to communicate with other components + http: + # http listen port number + port: 10902 + # Service definition for sidecar http service + service: + type: ClusterIP + # Annotations to sidecar http service + annotations: {} + # Labels to sidecar http service + labels: {} + matchLabels: {} + # Set up ingress for the http service + ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: "/" + hosts: + - "/" + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +storeSecretName: diff --git a/charts/kubecost/cost-analyzer/1.83.201/cluster-metrics.json b/charts/kubecost/cost-analyzer/1.83.201/cluster-metrics.json new file mode 100644 index 000000000..3ef328208 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/cluster-metrics.json @@ -0,0 +1,1682 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Cost metrics from the Kubecost product", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 7, + "iteration": 1558062099204, + "links": [], + "panels": [ + { + "content": "Note: this dashboard requires Kubecost metrics to be available in your Prometheus deployment. [Learn more](https://github.com/kubecost/cost-model/blob/master/PROMETHEUS.md)", + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 27, + "links": [], + "mode": "markdown", + "title": "", + "transparent": true, + "type": "text" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${datasource}", + "decimals": 2, + "description": "Monthly run rate of CPU + GPU costs based on currently provisioned resources.", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 2 + }, + "hideTimeOverride": true, + "id": 2, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100) +\n avg(node_gpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n)", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "CPU Cost", + "type": "singlestat", + "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": 2, + "description": "Monthly run rate of memory costs based on currently provisioned expenses.", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 2 + }, + "hideTimeOverride": true, + "id": 3, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n)", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Memory Cost", + "type": "singlestat", + "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": 2, + "description": "Monthly run rate of attached storage and PV costs based on currently provisioned resources.", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 2 + }, + "hideTimeOverride": true, + "id": 4, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(avg(pv_hourly_cost) by (persistentvolume) * 730 * avg(kube_persistentvolume_capacity_bytes) by (persistentvolume) / 1024 / 1024 / 1024) \n+\nsum(sum(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance) / 1024 / 1024 / 1024) * $localStorageGBCost", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Storage Cost", + "type": "singlestat", + "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": 2, + "description": "Sum of compute, memory, storage and network costs.", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 2 + }, + "hideTimeOverride": true, + "id": 11, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "# Compute\nsum(\n avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100) +\n avg(node_gpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n) +\n\n\n# Memory\nsum(\n avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n) +\n\n# Storage \n\nsum(avg(pv_hourly_cost) by (persistentvolume) * 730 * avg(kube_persistentvolume_capacity_bytes) by (persistentvolume) / 1024 / 1024 / 1024) \n+\nsum(sum(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance) / 1024 / 1024 / 1024) * $localStorageGBCost", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Total Cost", + "type": "singlestat", + "valueFontSize": "120%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource": "${datasource}", + "decimals": 2, + "description": "Current CPU use from applications divided by allocatable CPUs", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 5 + }, + "height": "180px", + "hideTimeOverride": true, + "id": 13, + "interval": null, + "isNew": 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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "(\n sum(\n count(irate(container_cpu_usage_seconds_total{id=\"/\"}[10m])) by (instance)\n * on (instance) \n sum(irate(container_cpu_usage_seconds_total{id=\"/\"}[10m])) by (instance)\n ) \n / \n (sum (kube_node_status_allocatable{resource=\"cpu\", unit=\"core\"}))\n) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "thresholds": "30, 80", + "timeFrom": "", + "title": "CPU Utilization", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource": "${datasource}", + "decimals": 2, + "description": "Current CPU reservation requests from applications vs allocatable CPU", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 5 + }, + "height": "180px", + "id": 15, + "interval": null, + "isNew": 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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "SUM(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"}) / SUM(kube_node_status_allocatable{resource=\"cpu\", unit=\"core\"}) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "thresholds": "30, 80", + "title": "CPU Requests", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource": "${datasource}", + "description": "Current RAM use vs RAM available", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 5 + }, + "height": "180px", + "hideTimeOverride": true, + "id": 17, + "interval": null, + "isNew": 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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "SUM(container_memory_usage_bytes{namespace!=\"\"}) / SUM(kube_node_status_allocatable{resource=\"memory\", unit=\"byte\"}) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "refId": "A", + "step": 10 + }, + { + "expr": "", + "format": "time_series", + "intervalFactor": 1, + "refId": "B" + } + ], + "thresholds": "30,80", + "timeFrom": "", + "title": "RAM Utilization", + "transparent": false, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource": "${datasource}", + "description": "Current RAM requests vs RAM available", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 5 + }, + "height": "180px", + "id": 19, + "interval": null, + "isNew": 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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\"})\n /\n sum(kube_node_status_allocatable{resource=\"memory\", unit=\"byte\"})\n) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "thresholds": "30,80", + "title": "RAM Requests", + "transparent": false, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource": "${datasource}", + "decimals": 2, + "description": "This gauge shows the current standard storage use, including cluster storage, vs storage available", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 12, + "y": 5 + }, + "height": "180px", + "hideTimeOverride": true, + "id": 21, + "interval": null, + "isNew": 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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (\n sum(kube_persistentvolumeclaim_info) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kubelet_volume_stats_used_bytes) by (persistentvolumeclaim, namespace) or up * 0\n + sum(container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"})\n) /\nsum (\n sum(kube_persistentvolumeclaim_info) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n + sum(container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"})\n) * 100", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "thresholds": "30, 80", + "timeFrom": "", + "title": "Storage Utilization", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Monthly run rate of CPU + GPU costs", + "fill": 1, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 9 + }, + "id": 6, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost) by (node) * 730 +\n avg(node_gpu_hourly_cost) by (node) * 730\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "compute cost", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Compute Cost", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "currencyUSD", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Monthly run rate of memory costs", + "fill": 1, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 9 + }, + "id": 9, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "memory cost", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Memory Cost", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "currencyUSD", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Monthly run rate of attached disk + PV storage costs", + "fill": 1, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 9 + }, + "id": 10, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n avg(avg_over_time(pv_hourly_cost[$timeRange] offset 1m)) by (persistentvolume) * 730 \n * avg(avg_over_time(kube_persistentvolume_capacity_bytes[$timeRange] offset 1m)) by (persistentvolume) / 1024 / 1024 / 1024\n) +\nsum(avg(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance) / 1024 / 1024 / 1024) * $localStorageGBCost", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "storage cost", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Storage Cost", + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Sum of compute, memory, and storage costs", + "fill": 1, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 9 + }, + "id": 22, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "# Compute\nsum(\n avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100) +\n avg(node_gpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n) +\n\n\n# Memory\nsum(\n avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n) +\n\n# Storage \n\nsum(avg(pv_hourly_cost) by (persistentvolume) * 730 * avg(kube_persistentvolume_capacity_bytes) by (persistentvolume) / 1024 / 1024 / 1024) \n+\nsum(sum(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance) / 1024 / 1024 / 1024) * $localStorageGBCost", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "total cost", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Total Cost", + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "${datasource}", + "description": "Cost of by resource class of currently provisioned nodes", + "fontSize": "100%", + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 8, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 4, + "desc": false + }, + "styles": [ + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Time", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Compute Cost", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "CPU Cost", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "Mem Cost", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "Total", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "instance", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "GPU", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost or up * 0) by (node) * 730 * (1-$useDiscount/100)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + }, + { + "expr": "avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730 * (1-$useDiscount/100)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + }, + { + "expr": "avg(node_gpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "D" + }, + { + "expr": "# CPU \navg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost or up * 0) by (node) * 730 * (1-$useDiscount/100) +\n# GPU\navg(node_gpu_hourly_cost) by (node) * 730 * (1-$useDiscount/100) +\n# Memory\navg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730 * (1-$useDiscount/100)\n", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + } + ], + "title": "Cost by node", + "transform": "table", + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Monthly run rate of attached disk + PV storage costs based on currently provisioned resources.", + "fill": 1, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 25, + "interval": "1m", + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node) * avg(node_cpu_hourly_cost) by (node) * 730 +\n avg(node_gpu_hourly_cost) by (node) * 730\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "cpu", + "refId": "B" + }, + { + "expr": "sum(\n avg(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node) / 1024 / 1024 / 1024 * avg(node_ram_hourly_cost) by (node) * 730\n)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "memory", + "refId": "A" + }, + { + "expr": "sum(\n avg(avg_over_time(pv_hourly_cost[$timeRange] offset 1m)) by (persistentvolume) * 730 \n * avg(avg_over_time(kube_persistentvolume_capacity_bytes[$timeRange] offset 1m)) by (persistentvolume) / 1024 / 1024 / 1024\n) +\nsum(avg(container_fs_limit_bytes{device!=\"tmpfs\", id=\"/\"}) by (instance) / 1024 / 1024 / 1024) * $localStorageGBCost", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "storage", + "refId": "C" + }, + { + "expr": "SUM(rate(node_network_transmit_bytes_total{device=\"eth0\"}[60m]) / 1024 / 1024 / 1024 ) * (60 * 60 * 24 * 30) * $percentEgress * $egressCost ", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "network", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Cost by Resource", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "currencyUSD", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [ + "cost", + "utilization", + "metrics" + ], + "templating": { + "list": [ + { + "auto": true, + "auto_count": 1, + "auto_min": "1m", + "current": { + "text": "auto", + "value": "$__auto_interval_timeRange" + }, + "hide": 2, + "label": null, + "name": "timeRange", + "options": [ + { + "selected": true, + "text": "auto", + "value": "$__auto_interval_timeRange" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + }, + { + "selected": false, + "text": "90d", + "value": "90d" + } + ], + "query": "1h,6h,12h,1d,7d,14d,30d,90d", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + }, + { + "current": { + "text": ".04", + "value": ".04" + }, + "hide": 2, + "label": "Cost per Gb hour for attached disks", + "name": "localStorageGBCost", + "options": [ + { + "selected": true, + "text": ".04", + "value": ".04" + } + ], + "query": ".04", + "skipUrlSync": false, + "type": "constant" + }, + { + "current": { + "tags": [], + "text": "0", + "value": "0" + }, + "hide": 0, + "label": "Sustained Use Discount %", + "name": "useDiscount", + "options": [ + { + "selected": true, + "text": "0", + "value": "0" + } + ], + "query": "0", + "skipUrlSync": false, + "type": "constant" + }, + { + "current": { + "text": ".1", + "value": ".1" + }, + "hide": 2, + "label": null, + "name": "percentEgress", + "options": [ + { + "selected": true, + "text": ".1", + "value": ".1" + } + ], + "query": ".1", + "skipUrlSync": false, + "type": "constant" + }, + { + "current": { + "text": ".12", + "value": ".12" + }, + "hide": 2, + "label": null, + "name": "egressCost", + "options": [ + { + "selected": true, + "text": ".12", + "value": ".12" + } + ], + "query": ".12", + "skipUrlSync": false, + "type": "constant" + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "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": "", + "title": "Kubecost cluster metrics", + "uid": "JOUdHGZZz", + "version": 20 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/cluster-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/cluster-utilization.json new file mode 100644 index 000000000..388d46fe8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/cluster-utilization.json @@ -0,0 +1,3492 @@ +{ + "annotations":{ + "list":[ + { + "builtIn":1, + "datasource":"-- Grafana --", + "enable":true, + "hide":true, + "iconColor":"rgba(0, 211, 255, 1)", + "name":"Annotations & Alerts", + "type":"dashboard" + } + ] + }, + "description":"A dashboard to help manage Kubernetes cluster costs and resources", + "editable":true, + "gnetId":6873, + "graphTooltip":0, + "id":4, + "iteration":1556759633456, + "links":[ + + ], + "panels":[ + { + "content":"This dashboard shows monthly cost estimates for the cluster, based on **current** CPU, RAM and storage provisioned.", + "gridPos":{ + "h":2, + "w":24, + "x":0, + "y":0 + }, + "id":86, + "links":[ + + ], + "mode":"markdown", + "title":"", + "transparent":true, + "type":"text" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "decimals":2, + "format":"currencyUSD", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":6, + "x":0, + "y":2 + }, + "hideTimeOverride":true, + "id":75, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"label_cloud_google_com_gke_preemptible", + "targets":[ + { + "expr":"sum(\n (\n (\n sum(kube_node_status_capacity_cpu_cores) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) * $costpcpu\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) * ($costcpu - ($costcpu / 100 * $costDiscount))\n )\n) ", + "format":"time_series", + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":" {{ node }}", + "refId":"A" + } + ], + "thresholds":"", + "timeFrom":"15m", + "timeShift":null, + "title":"CPU Cost", + "type":"singlestat", + "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":2, + "format":"currencyUSD", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":6, + "x":6, + "y":2 + }, + "hideTimeOverride":true, + "id":77, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"label_cloud_google_com_gke_preemptible", + "targets":[ + { + "expr":"sum(\n (\n (\n sum(kube_node_status_capacity_memory_bytes) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) /1024/1024/1024 * $costpram\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) /1024/1024/1024 * ($costram - ($costram / 100 * $costDiscount))\n)\n) ", + "format":"time_series", + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":" {{ node }}", + "refId":"A" + } + ], + "thresholds":"", + "timeFrom":"15m", + "timeShift":null, + "title":"RAM Cost", + "type":"singlestat", + "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":2, + "format":"currencyUSD", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":6, + "x":12, + "y":2 + }, + "hideTimeOverride":true, + "id":78, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"label_cloud_google_com_gke_preemptible", + "targets":[ + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageSSD\n\n+\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageStandard\n\n+ \n\nsum(container_fs_limit_bytes{id=\"/\"}) / 1024 / 1024 / 1024 * 1.03 * $costStorageStandard", + "format":"time_series", + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":" {{ node }}", + "refId":"A" + } + ], + "thresholds":"", + "timeFrom":"15m", + "timeShift":null, + "title":"Storage Cost (Cluster and PVC)", + "type":"singlestat", + "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":2, + "description":"Represents a near worst-case approximation of network costs.", + "format":"currencyUSD", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":6, + "x":18, + "y":2 + }, + "hideTimeOverride":true, + "id":129, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"label_cloud_google_com_gke_preemptible", + "targets":[ + { + "expr":"SUM(rate(node_network_transmit_bytes_total{device=\"eth0\"}[60m]) / 1024 / 1024 / 1024 ) * (60 * 60 * 24 * 30) * $costEgress", + "format":"time_series", + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":" {{ node }}", + "refId":"A" + } + ], + "thresholds":"", + "timeFrom":"15m", + "timeShift":null, + "title":"Network Egress Cost", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "decimals":2, + "description":"Current CPU use from applications divided by allocatable CPUs", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":0, + "y":6 + }, + "height":"180px", + "hideTimeOverride":true, + "id":82, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"(\n sum(\n count(irate(container_cpu_usage_seconds_total{id=\"/\"}[10m])) by (instance)\n * on (instance) \n sum(irate(container_cpu_usage_seconds_total{id=\"/\"}[10m])) by (instance)\n ) \n / \n (sum (kube_node_status_allocatable{resource=\"cpu\", unit=\"core\"}))\n) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + } + ], + "thresholds":"30, 80", + "timeFrom":"", + "title":"CPU Utilization", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "decimals":2, + "description":"Current CPU reservation requests from applications vs allocatable CPU", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":3, + "y":6 + }, + "height":"180px", + "id":91, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"SUM(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"}) / SUM(kube_node_status_allocatable{resource=\"cpu\", unit=\"core\"}) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + } + ], + "thresholds":"30, 80", + "title":"CPU Requests", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "description":"Current RAM use vs RAM available", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":6, + "y":6 + }, + "height":"180px", + "hideTimeOverride":true, + "id":80, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"SUM(container_memory_usage_bytes{namespace!=\"\"}) / SUM(kube_node_status_allocatable{resource=\"memory\", unit=\"byte\"}) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + }, + { + "expr":"", + "format":"time_series", + "intervalFactor":1, + "refId":"B" + } + ], + "thresholds":"30,80", + "timeFrom":"", + "title":"RAM Utilization", + "transparent":false, + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "description":"Current RAM requests vs RAM available", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":9, + "y":6 + }, + "height":"180px", + "id":92, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\"})\n /\n sum(kube_node_status_allocatable{resource=\"memory\", unit=\"byte\"})\n) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + } + ], + "thresholds":"30,80", + "title":"RAM Requests", + "transparent":false, + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "decimals":2, + "description":"This gauge shows the current standard storage use, including cluster storage, vs storage available", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":12, + "y":6 + }, + "height":"180px", + "hideTimeOverride":true, + "id":95, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kubelet_volume_stats_used_bytes) by (persistentvolumeclaim, namespace) or up * 0\n + sum(container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"})\n) /\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n + sum(container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"})\n) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + } + ], + "thresholds":"30, 80", + "timeFrom":"", + "title":"Storage Utilization", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":true, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "datasource":"${datasource}", + "decimals":2, + "description":"This gauge shows the current SSD use vs SSD available", + "editable":true, + "error":false, + "format":"percent", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":3, + "x":15, + "y":6 + }, + "height":"180px", + "hideTimeOverride":true, + "id":96, + "interval":null, + "isNew":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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kubelet_volume_stats_used_bytes) by (persistentvolumeclaim, namespace)\n) /\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace)\n) * 100", + "format":"time_series", + "interval":"", + "intervalFactor":1, + "refId":"A", + "step":10 + } + ], + "thresholds":"30, 80", + "timeFrom":"", + "title":"SSD Utilization", + "type":"singlestat", + "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":2, + "description":"Expected monthly cost given current CPU, memory storage, and network resource consumption", + "format":"currencyUSD", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":6, + "x":18, + "y":6 + }, + "hideTimeOverride":true, + "id":93, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"label_cloud_google_com_gke_preemptible", + "targets":[ + { + "expr":"# CPU\nsum(\n (\n (\n sum(kube_node_status_capacity_cpu_cores) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) * $costpcpu\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) * ($costcpu - ($costcpu / 100 * $costDiscount))\n )\n) \n\n+ \n\n# Storage\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageSSD\n\n+\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageStandard\n\n+ \n\nsum(container_fs_limit_bytes{id=\"/\"}) / 1024 / 1024 / 1024 * 1.03 * $costStorageStandard \n\n+\n\n# END STORAGE\n# RAM \nsum(\n (\n (\n sum(kube_node_status_capacity_memory_bytes) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) /1024/1024/1024 * $costpram\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) /1024/1024/1024 * ($costram - ($costram / 100 * $costDiscount))\n)\n)\n\n+\n\n#Network \nSUM(rate(node_network_transmit_bytes_total{device=\"eth0\"}[60m]) / 1024 / 1024 / 1024 ) * (60 * 60 * 24 * 30) * $costEgress", + "format":"time_series", + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":" {{ node }}", + "refId":"A" + } + ], + "thresholds":"", + "timeFrom":"15m", + "timeShift":null, + "title":"Total Monthly Cost", + "type":"singlestat", + "valueFontSize":"120%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "description":"Expected monthly CPU, memory and storage costs given provisioned resources", + "fill":1, + "gridPos":{ + "h":8, + "w":12, + "x":0, + "y":10 + }, + "id":120, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":false, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"# CPU\nsum(\n (\n (\n sum(kube_node_status_capacity_cpu_cores) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) * $costpcpu\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) * ($costcpu - ($costcpu / 100 * $costDiscount))\n )\n) \n\n+ \n\n# Storage\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageSSD\n\n+\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) or up * 0\n) / 1024 / 1024 /1024 * $costStorageStandard\n\n+ \n\nsum(container_fs_limit_bytes{id=\"/\"}) / 1024 / 1024 / 1024 * 1.03 * $costStorageStandard \n\n+\n\n# END STORAGE\n# RAM \nsum(\n (\n (\n sum(kube_node_status_capacity_memory_bytes) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible=\"true\"}) by (node)\n ) /1024/1024/1024 * $costpram\n )\n or\n (\n (\n sum(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node)\n * on (node) group_left (label_cloud_google_com_gke_preemptible)\n avg(kube_node_labels{label_cloud_google_com_gke_preemptible!=\"true\"}) by (node)\n ) /1024/1024/1024 * ($costram - ($costram / 100 * $costDiscount))\n)\n) \n\n+\n\n#Network \nSUM(rate(node_network_transmit_bytes_total{device=\"eth0\"}[60m]) / 1024 / 1024 / 1024 ) * (60 * 60 * 24 * 30) * $costEgress", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"cluster cost", + "refId":"A" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Total monthly cost", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"currencyUSD", + "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 + } + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "description":"Resources allocated to namespace based on container requests", + "fontSize":"100%", + "gridPos":{ + "h":8, + "w":12, + "x":12, + "y":10 + }, + "hideTimeOverride":false, + "id":73, + "links":[ + + ], + "pageSize":10, + "repeat":null, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":7, + "desc":true + }, + "styles":[ + { + "alias":"Namespace", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":true, + "linkTooltip":"View namespace cost metrics", + "linkUrl":"d/at-cost-analysis-namespace2/namespace-cost-metrics?&var-namespace=$__cell", + "pattern":"namespace", + "thresholds":[ + "30", + "80" + ], + "type":"string", + "unit":"currencyUSD" + }, + { + "alias":"RAM", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "pattern":"Value #B", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"CPU", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"PV Storage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"Total", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #D", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"CPU Utilization", + "colorMode":"value", + "colors":[ + "#bf1b00", + "rgba(50, 172, 45, 0.97)", + "#ef843c" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #E", + "thresholds":[ + "30", + "80" + ], + "type":"number", + "unit":"percent" + }, + { + "alias":"RAM Utilization", + "colorMode":"value", + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#ef843c" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #F", + "thresholds":[ + "30", + "80" + ], + "type":"number", + "unit":"percent" + } + ], + "targets":[ + { + "expr":"(\n sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible!=\"true\"}*($costcpu - ($costcpu / 100 * $costDiscount))) by(namespace)\n or\n count(\n count(container_spec_cpu_shares{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n(\n sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible=\"true\"}*$costpcpu) by(namespace)\n or\n count(\n count(container_spec_cpu_shares{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"{{ namespace }}", + "refId":"A" + }, + { + "expr":"(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible!=\"true\"} / 1024 / 1024 / 1024*($costram- ($costram / 100 * $costDiscount))) by (namespace) \n or\n count(\n count(container_spec_memory_limit_bytes{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible=\"true\"} / 1024 / 1024 / 1024 * $costpram ) by (namespace) \n or\n count(\n count(container_spec_memory_limit_bytes{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)", + "format":"table", + "instant":true, + "intervalFactor":1, + "legendFormat":"{{ namespace }}", + "refId":"B" + }, + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) \n) by (namespace) / 1024 / 1024 /1024 * $costStorageSSD \n\nor\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) \n) by (namespace) / 1024 / 1024 /1024 * $costStorageStandard", + "format":"table", + "instant":true, + "intervalFactor":1, + "legendFormat":"{{ namespace }}", + "refId":"C" + }, + { + "expr":"# CPU \n(\n sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible!=\"true\"}*($costcpu - ($costcpu / 100 * $costDiscount))) by(namespace)\n or\n count(\n count(container_spec_cpu_shares{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n(\n sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible=\"true\"}*$costpcpu) by(namespace)\n or\n count(\n count(container_spec_cpu_shares{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n#END CPU \n# Memory \n\n(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible!=\"true\"} / 1024 / 1024 / 1024*($costram- ($costram / 100 * $costDiscount))) by (namespace) \n or\n count(\n count(container_spec_memory_limit_bytes{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n(\n sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\",namespace!=\"kube-system\",cloud_google_com_gke_preemptible=\"true\"} / 1024 / 1024 / 1024 * $costpram ) by (namespace) \n or\n count(\n count(container_spec_memory_limit_bytes{namespace!=\"\",namespace!=\"kube-system\"}) by(namespace)\n ) by(namespace) -1\n)\n\n+\n\n# PV storage\n\n(\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) \n) by (namespace) / 1024 / 1024 /1024 * $costStorageSSD \n\nor\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim, namespace) \n) by (namespace) / 1024 / 1024 /1024 * $costStorageStandard \n)", + "format":"table", + "instant":true, + "intervalFactor":1, + "legendFormat":"Total", + "refId":"D" + } + ], + "timeFrom":"", + "timeShift":null, + "title":"Namespace cost allocation", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "collapsed":false, + "gridPos":{ + "h":1, + "w":24, + "x":0, + "y":18 + }, + "id":108, + "panels":[ + + ], + "title":"CPU Metrics", + "type":"row" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":8, + "w":24, + "x":0, + "y":19 + }, + "id":116, + "legend":{ + "alignAsTable":false, + "avg":false, + "current":false, + "max":false, + "min":false, + "rightSide":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"SUM(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"})", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"capacity", + "refId":"A" + }, + { + "expr":"SUM(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"})", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"requests", + "refId":"C" + }, + { + "expr":"SUM(irate(container_cpu_usage_seconds_total{id=\"/\"}[5m]))", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"usage", + "refId":"B" + }, + { + "expr":"SUM(kube_pod_container_resource_limits{resource=\"cpu\", unit=\"core\"}) ", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"limits", + "refId":"D" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Cluster CPUs", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "decimals":1, + "format":"short", + "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":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":8, + "w":24, + "x":0, + "y":27 + }, + "id":130, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"avg(irate(node_cpu_seconds_total{mode!=\"idle\"}[5m])) by (mode) * 100", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"{{mode}}", + "refId":"A" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"CPU Mode", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"percent", + "label":null, + "logBase":1, + "max":null, + "min":null, + "show":true + }, + { + "format":"percent", + "label":null, + "logBase":1, + "max":null, + "min":null, + "show":false + } + ], + "yaxis":{ + "align":false, + "alignLevel":null + } + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "description":"This table shows the comparison of CPU requests and usage by namespace", + "fontSize":"100%", + "gridPos":{ + "h":10, + "w":12, + "x":0, + "y":35 + }, + "hideTimeOverride":true, + "id":104, + "links":[ + + ], + "pageSize":8, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":1, + "desc":true + }, + "styles":[ + { + "alias":"CPU Requests", + "colorMode":null, + "colors":[ + "#fceaca", + "#fce2de", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + "" + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Node", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"node", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"CPU Requests", + "colorMode":"value", + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#cffaff" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + "" + ], + "type":"number", + "unit":"short" + }, + { + "alias":"24h CPU Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + "30" + ], + "type":"number", + "unit":"none" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":true, + "linkTooltip":"View namespace cost metrics", + "linkUrl":"d/at-cost-analysis-namespace2/namespace-cost-metrics?&var-namespace=$__cell", + "mappingType":1, + "pattern":"namespace", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + } + ], + "targets":[ + { + "expr":"sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace!=\"\"}) by (namespace) ", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"", + "refId":"A" + }, + { + "expr":"sum (rate (container_cpu_usage_seconds_total{image!=\"\",namespace!=\"\"}[24h])) by (namespace)", + "format":"table", + "instant":true, + "intervalFactor":1, + "legendFormat":"{{ namespace }}", + "refId":"C" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"CPU request utilization by namespace", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "description":"This table shows the comparison of application CPU usage vs the capacity of the node (measured over last 60 minutes)", + "fontSize":"100%", + "gridPos":{ + "h":10, + "w":12, + "x":12, + "y":35 + }, + "hideTimeOverride":true, + "id":90, + "links":[ + + ], + "pageSize":8, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":2, + "desc":true + }, + "styles":[ + { + "alias":"CPU Request Utilization", + "colorMode":"value", + "colors":[ + "#ef843c", + "rgba(50, 172, 45, 0.97)", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + ".30", + " .80" + ], + "type":"number", + "unit":"percentunit" + }, + { + "alias":"Node", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"node", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"CPU Utilization", + "colorMode":"value", + "colors":[ + "#ef843c", + "rgba(50, 172, 45, 0.97)", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + ".20", + " .80" + ], + "type":"number", + "unit":"percentunit" + }, + { + "alias":"24h Utilization ", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value", + "thresholds":[ + + ], + "type":"number", + "unit":"percentunit" + } + ], + "targets":[ + { + "expr":"SUM(\nSUM(rate(container_cpu_usage_seconds_total[24h])) by (pod_name)\n* on (pod_name) group_left (node) \nlabel_replace(\n avg(kube_pod_info{}),\n \"pod_name\", \n \"$1\", \n \"pod\", \n \"(.+)\"\n)\n) by (node) \n/ \nsum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"B" + }, + { + "expr":"sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"}) by (node) / sum(kube_node_status_capacity{resource=\"cpu\", unit=\"core\"}) by (node)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"A" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Cluster cost & utilization by node", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "collapsed":false, + "gridPos":{ + "h":1, + "w":24, + "x":0, + "y":45 + }, + "id":113, + "panels":[ + + ], + "title":"Memory Metrics", + "type":"row" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":8, + "w":24, + "x":0, + "y":46 + }, + "id":117, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":false, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"SUM(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"} / 1024 / 1024 / 1024)", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"capacity", + "refId":"A" + }, + { + "expr":"SUM(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\"} / 1024 / 1024 / 1024)", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"requests", + "refId":"C" + }, + { + "expr":"SUM(container_memory_usage_bytes{image!=\"\"} / 1024 / 1024 / 1024)", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"usage", + "refId":"B" + }, + { + "expr":"SUM(kube_pod_container_resource_limits{resource=\"memory\", unit=\"byte\", namespace!=\"\"} / 1024 / 1024 / 1024)", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"limits", + "refId":"D" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Cluster memory (GB)", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"decgbytes", + "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":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":8, + "w":24, + "x":0, + "y":54 + }, + "id":131, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":false, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"1 - sum(node_memory_MemAvailable_bytes) by (node) / sum(node_memory_MemTotal_bytes) by (node)", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"usage", + "refId":"A" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Cluster Memory Utilization", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"percentunit", + "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 + } + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "description":"Comparison of memory requests and current usage by namespace", + "fontSize":"100%", + "gridPos":{ + "h":10, + "w":12, + "x":0, + "y":62 + }, + "hideTimeOverride":true, + "id":109, + "links":[ + + ], + "pageSize":7, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":1, + "desc":true + }, + "styles":[ + { + "alias":"Mem Requests (GB)", + "colorMode":null, + "colors":[ + "#fceaca", + "#fce2de", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + "" + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Node", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"node", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"CPU Requests", + "colorMode":"value", + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#cffaff" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + "" + ], + "type":"number", + "unit":"short" + }, + { + "alias":"24h Mem Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "#508642", + "#e5ac0e" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + ".30", + ".75" + ], + "type":"number", + "unit":"none" + }, + { + "alias":"Namespace", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":true, + "linkTooltip":"View namespace cost metrics", + "linkUrl":"d/at-cost-analysis-namespace2/namespace-cost-metrics?&var-namespace=$__cell", + "mappingType":1, + "pattern":"namespace", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + } + ], + "targets":[ + { + "expr":"sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\"} / 1024 / 1024 / 1024) by (namespace) ", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"", + "refId":"A" + }, + { + "expr":"SUM(container_memory_usage_bytes{image!=\"\",namespace!=\"\"} / 1024 / 1024 / 1024) by (namespace)", + "format":"table", + "instant":true, + "intervalFactor":1, + "legendFormat":"", + "refId":"C" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Memory requests & utilization by namespace", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "description":"Container RAM usage vs node capacity", + "fontSize":"100%", + "gridPos":{ + "h":10, + "w":12, + "x":12, + "y":62 + }, + "hideTimeOverride":true, + "id":114, + "links":[ + + ], + "pageSize":8, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":1, + "desc":true + }, + "styles":[ + { + "alias":"RAM Requests", + "colorMode":"value", + "colors":[ + "#ef843c", + "rgba(50, 172, 45, 0.97)", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + "30", + " 80" + ], + "type":"number", + "unit":"percentunit" + }, + { + "alias":"Node", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"node", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"RAM Usage", + "colorMode":"value", + "colors":[ + "#ef843c", + "rgba(50, 172, 45, 0.97)", + "rgba(245, 54, 54, 0.9)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + "25", + " 80" + ], + "type":"number", + "unit":"percent" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + } + ], + "targets":[ + { + "expr":"SUM(label_replace(container_memory_usage_bytes{namespace!=\"\"}, \"node\", \"$1\", \"instance\",\"(.+)\")) by (node) * 100\n/\nSUM(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"B" + }, + { + "expr":"sum(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", namespace!=\"\"}) by (node) / SUM(kube_node_status_capacity{resource=\"memory\", unit=\"byte\"}) by (node)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"A" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Node utilization of allocatable RAM", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "collapsed":false, + "gridPos":{ + "h":1, + "w":24, + "x":0, + "y":72 + }, + "id":101, + "panels":[ + + ], + "title":"Storage Metrics", + "type":"row" + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "fontSize":"100%", + "gridPos":{ + "h":9, + "w":12, + "x":0, + "y":73 + }, + "hideTimeOverride":true, + "id":97, + "links":[ + + ], + "pageSize":8, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":4, + "desc":true + }, + "styles":[ + { + "alias":"Node", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"instance", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"PVC Name", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"persistentvolumeclaim", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Storage Class", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"storageclass", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Cost", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"Cost", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"Size (GB)", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + + ], + "type":"number", + "unit":"percentunit" + } + ], + "targets":[ + { + "expr":"SUM(container_fs_limit_bytes{id=\"/\"}) by (instance) / 1024 / 1024 / 1024 * 1.03", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"B" + }, + { + "expr":"SUM(container_fs_limit_bytes{id=\"/\"}) by (instance) / 1024 / 1024 / 1024 * 1.03 * $costStorageStandard\n", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"{{ persistentvolumeclaim }}", + "refId":"A" + }, + { + "expr":"sum(container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"} / container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\"}) by (instance) \n", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"C" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Local Storage", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":9, + "w":12, + "x":12, + "y":73 + }, + "id":128, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"SUM(container_fs_usage_bytes{id=\"/\"}) / SUM(container_fs_limit_bytes{id=\"/\"})", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"reads", + "refId":"D" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Local storage utilization", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"percent", + "label":"IOPS", + "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 + } + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "fontSize":"100%", + "gridPos":{ + "h":10, + "w":12, + "x":0, + "y":82 + }, + "hideTimeOverride":true, + "id":94, + "links":[ + + ], + "pageSize":10, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":2, + "desc":true + }, + "styles":[ + { + "alias":"Namespace", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":true, + "linkTooltip":"View namespace cost metrics", + "linkUrl":"d/at-cost-analysis-namespace2/namespace-cost-metrics?&var-namespace=$__cell", + "mappingType":1, + "pattern":"namespace", + "thresholds":[ + + ], + "type":"string", + "unit":"short" + }, + { + "alias":"PVC Name", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"persistentvolumeclaim", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Storage Class", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"storageclass", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Cost", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"Cost", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + + ], + "type":"number", + "unit":"percentunit" + }, + { + "alias":"Size (GB)", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + } + ], + "targets":[ + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n * on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim,storageclass) / 1024 / 1024 /1024\n\nor\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n * on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim,storageclass) / 1024 / 1024 /1024\n\n\n", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"C" + }, + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n * on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim,storageclass) / 1024 / 1024 /1024 * $costStorageSSD\n\nor\n\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n * on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim,storageclass) / 1024 / 1024 /1024 * $costStorageStandard\n", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"{{ persistentvolumeclaim }}", + "refId":"A" + }, + { + "expr":"sum(kubelet_volume_stats_used_bytes) by (persistentvolumeclaim, namespace) \n/\nsum (\n sum(kube_persistentvolumeclaim_info{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace, storageclass)\n * on (persistentvolumeclaim, namespace) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{storageclass!~\".*ssd.*\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"B" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Persistent Volume Claims", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":10, + "w":12, + "x":12, + "y":82 + }, + "id":132, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"SUM(rate(node_disk_reads_completed_total[10m])) or SUM(rate(node_disk_reads_completed[10m]))\n", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"reads", + "refId":"D" + }, + { + "expr":"SUM(rate(node_disk_writes_completed_total[10m])) or SUM(rate(node_disk_writes_completed[10m]))", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"writes", + "refId":"A" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Disk IOPS", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"none", + "label":"IOPS", + "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":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":9, + "w":24, + "x":0, + "y":92 + }, + "id":122, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"SUM( kubelet_volume_stats_inodes_used / kubelet_volume_stats_inodes) by (persistentvolumeclaim) * 100", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"", + "refId":"D" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Inode usage", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"percent", + "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 + } + }, + { + "collapsed":false, + "gridPos":{ + "h":1, + "w":24, + "x":0, + "y":101 + }, + "id":127, + "panels":[ + + ], + "title":"Network", + "type":"row" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "fill":1, + "gridPos":{ + "h":9, + "w":24, + "x":0, + "y":102 + }, + "id":123, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"sum (rate (node_network_transmit_bytes_total{}[60m]))\n", + "format":"time_series", + "intervalFactor":1, + "legendFormat":"node_out", + "refId":"B" + }, + { + "expr":"SUM ( rate(node_network_transmit_bytes_total{device=\"eth0\"}[60m]))", + "format":"time_series", + "instant":false, + "intervalFactor":1, + "legendFormat":"eth0 out", + "refId":"C" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Node network transmit", + "tooltip":{ + "shared":true, + "sort":0, + "value_type":"individual" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"decbytes", + "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":"15m", + "schemaVersion":16, + "style":"dark", + "tags":[ + "cost", + "utilization", + "metrics" + ], + "templating":{ + "list":[ + { + "current":{ + "text":"23.076", + "value":"23.076" + }, + "hide":0, + "label":"CPU", + "name":"costcpu", + "options":[ + { + "text":"23.076", + "value":"23.076" + } + ], + "query":"23.076", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"5.10", + "value":"5.10" + }, + "hide":0, + "label":"PE CPU", + "name":"costpcpu", + "options":[ + { + "text":"5.10", + "value":"5.10" + } + ], + "query":"5.10", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"3.25", + "value":"3.25" + }, + "hide":0, + "label":"RAM", + "name":"costram", + "options":[ + { + "text":"3.25", + "value":"3.25" + } + ], + "query":"3.25", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"0.6862", + "value":"0.6862" + }, + "hide":0, + "label":"PE RAM", + "name":"costpram", + "options":[ + { + "text":"0.6862", + "value":"0.6862" + } + ], + "query":"0.6862", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"0.040", + "value":"0.040" + }, + "hide":0, + "label":"Storage", + "name":"costStorageStandard", + "options":[ + { + "text":"0.040", + "value":"0.040" + } + ], + "query":"0.040", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":".17", + "value":".17" + }, + "hide":0, + "label":"SSD", + "name":"costStorageSSD", + "options":[ + { + "text":".17", + "value":".17" + } + ], + "query":".17", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":".12", + "value":".12" + }, + "hide":0, + "label":"Egress", + "name":"costEgress", + "options":[ + { + "selected":true, + "text":".12", + "value":".12" + } + ], + "query":".12", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"30", + "value":"30" + }, + "hide":0, + "label":"Discount", + "name":"costDiscount", + "options":[ + { + "text":"30", + "value":"30" + } + ], + "query":"30", + "skipUrlSync":false, + "type":"constant" + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time":{ + "from":"now-24h", + "to":"now" + }, + "timepicker":{ + "hidden":false, + "refresh_intervals":[ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options":[ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone":"browser", + "title":"Cluster cost & utilization metrics", + "uid":"cluster-costs", + "version":1 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/deployment-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/deployment-utilization.json new file mode 100644 index 000000000..087132873 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/deployment-utilization.json @@ -0,0 +1,1385 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Monitors Kubernetes deployments in cluster using Prometheus and kube-state-metrics. Shows resource utilization of deployments, daemonsets, and statefulsets.", + "editable": true, + "gnetId": 8588, + "graphTooltip": 0, + "id": 2, + "iteration": 1586200623748, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 0 + }, + "height": "180px", + "id": 1, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (container_memory_working_set_bytes{container!=\"\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\", kubernetes_io_hostname=~\"^$Node$\", pod_name!=\"\"}) / sum (kube_node_status_allocatable{resource=\"memory\", unit=\"byte\", node=~\"^$Node.*$\"}) * 100", + "format": "time_series", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "65, 90", + "title": "Deployment memory usage", + "transparent": false, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "${datasource}", + "decimals": 2, + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 0 + }, + "height": "180px", + "id": 2, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (rate (container_cpu_usage_seconds_total{pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\", kubernetes_io_hostname=~\"^$Node$\"}[2m])) / sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "format": "time_series", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 900 + } + ], + "thresholds": "65, 90", + "title": "Deployment CPU usage", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": true, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 0 + }, + "height": "180px", + "id": 3, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "(((sum(kube_deployment_status_replicas{deployment=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_statefulset_replicas{statefulset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_daemonset_status_desired_number_scheduled{daemonset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0))) - ((sum(kube_deployment_status_replicas_available{deployment=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_statefulset_status_replicas{statefulset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_daemonset_status_number_ready{daemonset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)))) / ((sum(kube_deployment_status_replicas{deployment=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_statefulset_replicas{statefulset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_daemonset_status_desired_number_scheduled{daemonset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0))) * 100", + "format": "time_series", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "1,30", + "title": "Unavailable Replicas", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 5 + }, + "height": "100px", + "id": 4, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(container_memory_working_set_bytes{container!=\"\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\", kubernetes_io_hostname=~\"^$Node$\", pod_name!=\"\"})", + "format": "time_series", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Used", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 5 + }, + "height": "100px", + "id": 5, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (kube_node_status_allocatable{resource=\"memory\", unit=\"byte\", node=~\"^$Node.*$\"})", + "format": "time_series", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 8, + "y": 5 + }, + "height": "100px", + "id": 6, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": " cores", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (rate (container_cpu_usage_seconds_total{pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\", kubernetes_io_hostname=~\"^$Node$\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Used", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 5 + }, + "height": "100px", + "id": 7, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": " cores", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"})", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Total", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 5 + }, + "height": "100px", + "id": 8, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "(sum(kube_deployment_status_replicas_available{deployment=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_statefulset_status_replicas{statefulset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_daemonset_status_number_ready{daemonset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0))", + "format": "time_series", + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Available (cluster)", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${datasource}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 5 + }, + "height": "100px", + "id": 9, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "(sum(kube_deployment_status_replicas{deployment=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_statefulset_replicas{statefulset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0)) + (sum(kube_daemonset_status_desired_number_scheduled{daemonset=~\".*$Deployment$Statefulset$Daemonset\"}) or vector(0))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ $Daemonset }}", + "refId": "A", + "step": 1800 + } + ], + "thresholds": "", + "title": "Total (cluster)", + "type": "singlestat", + "valueFontSize": "50%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 3, + "editable": true, + "error": false, + "fill": 0, + "grid": {}, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 8 + }, + "height": "", + "id": 10, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/avlbl.*/", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum (irate (container_cpu_usage_seconds_total{container!=\"\",image!=\"\",name=~\"^k8s_.*\",io_kubernetes_container_name!=\"POD\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\",kubernetes_io_hostname=~\"^$Node$\"}[5m])) by (pod_name,kubernetes_io_hostname)", + "format": "time_series", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "usage: {{ kubernetes_io_hostname }} | {{ pod_name }} ", + "metric": "container_cpu", + "refId": "A", + "step": 60 + }, + { + "expr": "sum (kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", pod=~\"^$Deployment$Statefulset$Daemonset.*$\",node=~\"^$Node$\"}) by (pod,node)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "rqst: {{ node }} | {{ pod }}", + "refId": "B", + "step": 120 + }, + { + "expr": "sum ((kube_node_status_allocatable{resource=\"cpu\", unit=\"core\", node=~\"^$Node$\"})) by (node)", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "avlbl: {{ node }}", + "refId": "C", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "CPU usage & requests", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": "cores", + "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": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 2, + "editable": true, + "error": false, + "fill": 0, + "grid": {}, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 11, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/^avlbl.*$/", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max (container_memory_working_set_bytes{container!=\"POD\",container!=\"\",id!=\"/\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\",kubernetes_io_hostname=~\"^$Node$\"}) by (pod_name,kubernetes_io_hostname)", + "format": "time_series", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "usage: {{kubernetes_io_hostname }} | {{ pod_name }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 60 + }, + { + "expr": "sum ((kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", pod=~\"^$Deployment$Statefulset$Daemonset.*$\",node=~\"^$Node$\"})) by (pod,node)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "rqst: {{ node }} | {{ pod }}", + "refId": "B", + "step": 120 + }, + { + "expr": "sum ((kube_node_status_allocatable{resource=\"memory\", unit=\"byte\", node=~\"^$Node$\"})) by (node)", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "avlbl: {{ node }}", + "refId": "C", + "step": 30 + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Memory usage & requests", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "100 * (kubelet_volume_stats_used_bytes{kubernetes_io_hostname=~\"^$Node$\", persistentvolumeclaim=~\".*$Deployment$Statefulset$Daemonset.*$\"} / kubelet_volume_stats_capacity_bytes{kubernetes_io_hostname=~\"^$Node$\", persistentvolumeclaim=~\".*$Deployment$Statefulset$Daemonset.*$\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{ persistentvolumeclaim }} | {{ kubernetes_io_hostname }}", + "refId": "A", + "step": 120 + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "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}", + "decimals": 2, + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 13, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum (rate (container_network_receive_bytes_total{id!=\"/\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\",kubernetes_io_hostname=~\"^$Node$\"}[2m])) by (pod_name, kubernetes_io_hostname)", + "format": "time_series", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> {{ kubernetes_io_hostname }} | {{ pod_name }}", + "metric": "network", + "refId": "A", + "step": 60 + }, + { + "expr": "- sum( rate (container_network_transmit_bytes_total{id!=\"/\",pod_name=~\"^$Deployment$Statefulset$Daemonset.*$\",kubernetes_io_hostname=~\"^$Node$\"}[2m])) by (pod_name, kubernetes_io_hostname)", + "format": "time_series", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- {{ kubernetes_io_hostname }} | {{ pod_name }}", + "metric": "network", + "refId": "B", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "All processes network I/O", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [ + "kubernetes", + "deployment" + ], + "templating": { + "list": [ + { + "allValue": "()", + "current": { + "selected": false, + "tags": [], + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "Deployment", + "options": [], + "query": "label_values(deployment)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "()", + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "Statefulset", + "options": [], + "query": "label_values(statefulset)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "()", + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "Daemonset", + "options": [], + "query": "label_values(daemonset)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "Node", + "options": [], + "query": "label_values(kubernetes_io_hostname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-24h", + "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": "browser", + "title": "Deployment/Statefulset/Daemonset utilization metrics", + "uid": "deployment-metrics", + "version": 1 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/label-cost-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/label-cost-utilization.json new file mode 100644 index 000000000..c13ade6cb --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/label-cost-utilization.json @@ -0,0 +1,1212 @@ +{ + "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": 7, + "iteration": 1586214000479, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${datasource}", + "decimals": 2, + "description": "Monthly projected CPU cost given last 10m", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 0 + }, + "hideTimeOverride": true, + "id": 15, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(\n avg(container_cpu_allocation) by (pod,node)\n\n * on (node) group_left()\n avg(avg_over_time(node_cpu_hourly_cost[10m])) by (node)\n\n * on (pod) group_left()\n label_replace(\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod),\n \"pod_name\",\n \"$1\", \n \"pod\", \n \"(.+)\"\n )\n) * 730", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "CPU Cost", + "type": "singlestat", + "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": 2, + "description": "Based on CPU usage over last 24 hours", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 0 + }, + "hideTimeOverride": true, + "id": 16, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(\n avg(container_memory_allocation_bytes) by (pod,node) / 1024 / 1024 / 1024\n\n * on (node) group_left()\n avg(avg_over_time(node_ram_hourly_cost[10m])) by (node)\n\n * on (pod) group_left()\n label_replace(\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod),\n \"pod_name\",\n \"$1\", \n \"pod\", \n \"(.+)\"\n )\n) * 730", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Memory Cost", + "type": "singlestat", + "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": 2, + "description": "", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 0 + }, + "hideTimeOverride": true, + "id": 21, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "sum(\n sum(kube_persistentvolumeclaim_info{storageclass!=\".*ssd.*\"}) by (persistentvolumeclaim, storageclass)\n * on (persistentvolumeclaim) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim)\n * on (persistentvolumeclaim) group_left(label_app)\n max(kube_persistentvolumeclaim_labels{label_$label=~\"$label_value\"}) by (persistentvolumeclaim) or up * 0\n) / 1024 / 1024 /1024 * .04 \n\n+\n\nsum(\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, storageclass)\n * on (persistentvolumeclaim) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim)\n * on (persistentvolumeclaim) group_left(label_app)\n max(kube_persistentvolumeclaim_labels{label_$label=~\"$label_value\"}) by (persistentvolumeclaim) or up * 0\n) / 1024 / 1024 /1024 * .17 \n", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Storage Cost", + "type": "singlestat", + "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": 2, + "description": "Cost of memory + CPU usage", + "format": "currencyUSD", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 0 + }, + "hideTimeOverride": true, + "id": 20, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "label_cloud_google_com_gke_preemptible", + "targets": [ + { + "expr": "# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CPU ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nsum(\n avg(container_cpu_allocation) by (pod,node)\n\n * on (node) group_left()\n avg(avg_over_time(node_cpu_hourly_cost[10m])) by (node)\n\n * on (pod) group_left()\n label_replace(\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod),\n \"pod_name\",\n \"$1\", \n \"pod\", \n \"(.+)\"\n )\n) * 730\n\n#END CPU\n+\n\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Memory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nsum(\n avg(container_memory_allocation_bytes) by (pod,node) / 1024 / 1024 / 1024\n\n * on (node) group_left()\n avg(avg_over_time(node_ram_hourly_cost[10m])) by (node)\n\n * on (pod) group_left()\n label_replace(\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod),\n \"pod_name\",\n \"$1\", \n \"pod\", \n \"(.+)\"\n )\n) * 730\n\n# END MEMORY\n\n+\n\n# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ STORAGE ~~~~~~~~~~~~~~~~~~~~~~~~~\n\nsum(\n sum(kube_persistentvolumeclaim_info{storageclass!=\".*ssd.*\"}) by (persistentvolumeclaim, storageclass)\n * on (persistentvolumeclaim) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim)\n * on (persistentvolumeclaim) group_left(label_app)\n max(kube_persistentvolumeclaim_labels{label_$label=~\"$label_value\"}) by (persistentvolumeclaim) or up * 0\n) / 1024 / 1024 /1024 * .04 \n\n+\n\nsum(\n sum(kube_persistentvolumeclaim_info{storageclass=~\".*ssd.*\"}) by (persistentvolumeclaim, storageclass)\n * on (persistentvolumeclaim) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim)\n * on (persistentvolumeclaim) group_left(label_app)\n max(kube_persistentvolumeclaim_labels{label_$label=~\"$label_value\"}) by (persistentvolumeclaim) or up * 0\n) / 1024 / 1024 /1024 * .17 \n\n\n# END STORAGE\n", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{ node }}", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": "15m", + "timeShift": null, + "title": "Total Cost", + "type": "singlestat", + "valueFontSize": "110%", + "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}", + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 5 + }, + "id": 10, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": " cores", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(\n sum (kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"}) by (pod)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod)\n or up * 0\n) ", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "CPU Request", + "type": "singlestat", + "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": 2, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 5 + }, + "id": 17, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": " cores", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(\n label_replace(\n sum(rate(container_cpu_usage_seconds_total{image!=\"\",container_name!=\"POD\"}[1h])) by (kubernetes_io_hostname,pod_name),\n \"node\",\n \"$1\", \n \"kubernetes_io_hostname\", \n \"(.+)\"\n ) \n * on (pod_name) group_left()\n label_replace(\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod),\n \"pod_name\",\n \"$1\", \n \"pod\", \n \"(.+)\"\n ) or up * 0\n) ", + "format": "time_series", + "intervalFactor": 2, + "refId": "A" + } + ], + "thresholds": "", + "title": "CPU Used", + "type": "singlestat", + "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": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 5 + }, + "id": 11, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(\n sum (kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\"}) by (pod)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod)\n or up * 0\n) ", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Memory Request", + "type": "singlestat", + "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}", + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 5 + }, + "id": 18, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(\n label_replace(\n sum (container_memory_working_set_bytes{pod_name!=\"\",container!=\"POD\",container!=\"\"}) by (pod_name),\n \"pod\",\n \"$1\", \n \"pod_name\", \n \"(.+)\")\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod)\n or up * 0\n)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Memory Usage", + "type": "singlestat", + "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": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 12, + "y": 5 + }, + "id": 22, + "interval": null, + "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" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(\n max(kube_persistentvolumeclaim_info) by (persistentvolumeclaim, storageclass)\n * on (persistentvolumeclaim) group_right(storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes) by (persistentvolumeclaim)\n * on (persistentvolumeclaim) group_left(label_app)\n max(kube_persistentvolumeclaim_labels{label_$label=~\"$label_value\"}) by (persistentvolumeclaim) or up * 0\n) \n", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Storage Request", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n label_replace(\n sum (kube_pod_container_resource_limits{resource=\"cpu\", unit=\"core\"}) by (pod, container)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container),\n \"container_name\",\n \"$1\", \n \"container\", \n \"(.+)\"\n )\n) \n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "limit", + "refId": "C" + }, + { + "expr": "sum(\n label_replace(\n sum (kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\"}) by (pod, container)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container),\n \"container_name\",\n \"$1\", \n \"container\", \n \"(.+)\"\n )\n) \n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "request", + "refId": "B" + }, + { + "expr": "sum(\n label_replace(\n sum (rate (container_cpu_usage_seconds_total{image!=\"\",container!=\"POD\",container!=\"\"}[10m])) by (container,pod),\n \"pod\", \n \"$1\", \n \"pod_name\", \n \"(.+)\"\n )\n * on (pod) group_left (label_$label)\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container)\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "usage", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage vs Requests vs Limits", + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fill": 1, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 23, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n label_replace(\n sum (kube_pod_container_resource_limits{resource=\"memory\", unit=\"byte\"}) by (pod, container)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container),\n \"container_name\",\n \"$1\", \n \"container\", \n \"(.+)\"\n )\n) \n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "limit", + "refId": "C" + }, + { + "expr": "sum(\n label_replace(\n sum (kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\"}) by (pod, container)\n * on (pod) group_left()\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container),\n \"container_name\",\n \"$1\", \n \"container\", \n \"(.+)\"\n )\n) \n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "request", + "refId": "B" + }, + { + "expr": "sum(\n label_replace(\n sum (container_memory_working_set_bytes{container!=\"\",container!=\"POD\"}) by (container,pod),\n \"pod\", \n \"$1\", \n \"pod_name\", \n \"(.+)\"\n )\n * on (pod) group_left (label_$label)\n max(kube_pod_labels{label_$label=~\"$label_value\"}) by (pod,container)\n)\n", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "usage", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage vs Requests vs Limits", + "tooltip": { + "shared": true, + "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": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [ + "cost", + "utilization", + "metrics" + ], + "templating": { + "list": [ + { + "datasource": "${datasource}", + "filters": [], + "hide": 0, + "label": "", + "name": "Filters", + "skipUrlSync": false, + "type": "adhoc" + }, + { + "allValue": null, + "current": { + "tags": [], + "text": "app", + "value": "app" + }, + "hide": 0, + "includeAll": false, + "label": "Label", + "multi": false, + "name": "label", + "options": [ + { + "selected": false, + "text": "app", + "value": "app" + }, + { + "selected": false, + "text": "tier", + "value": "tier" + }, + { + "selected": false, + "text": "component", + "value": "component" + }, + { + "selected": true, + "text": "release", + "value": "release" + }, + { + "selected": false, + "text": "name", + "value": "name" + }, + { + "selected": false, + "text": "team", + "value": "team" + }, + { + "selected": false, + "text": "department", + "value": "department" + }, + { + "selected": false, + "text": "owner", + "value": "owner" + }, + { + "selected": false, + "text": "contact", + "value": "contact" + } + ], + "query": "app, tier, component, release, name, team, department, owner, contact", + "skipUrlSync": false, + "type": "custom" + }, + { + "allValue": ".*", + "current": { + "tags": [], + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": "Value", + "multi": false, + "name": "label_value", + "options": [], + "query": "query_result(SUM(kube_pod_labels{label_$label!=\"\",namespace!=\"kube-system\"}) by (label_$label))", + "refresh": 1, + "regex": "/label_$label=\\\"(.*?)(\\\")/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "()", + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": "", + "multi": false, + "name": "Deployments", + "options": [], + "query": "label_values(deployment)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "tags": [], + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "Secondary", + "options": [ + { + "selected": true, + "text": "All", + "value": "$__all" + }, + { + "selected": false, + "text": "app", + "value": "app" + }, + { + "selected": false, + "text": "component", + "value": "component" + }, + { + "selected": false, + "text": "controller_revision_hash", + "value": "controller_revision_hash" + }, + { + "selected": false, + "text": "k8s_app", + "value": "k8s_app" + } + ], + "query": "query_result(kube_pod_labels)", + "refresh": 0, + "regex": "/.+?label_([^=]*).*/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-24h", + "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": "", + "title": "Label costs & utilization", + "uid": "lWMhIA-ik", + "version": 2 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/namespace-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/namespace-utilization.json new file mode 100644 index 000000000..a2e60c1f2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/namespace-utilization.json @@ -0,0 +1,1175 @@ +{ + "annotations":{ + "list":[ + { + "builtIn":1, + "datasource":"-- Grafana --", + "enable":true, + "hide":true, + "iconColor":"rgba(0, 211, 255, 1)", + "name":"Annotations & Alerts", + "type":"dashboard" + } + ] + }, + "description":"A dashboard to help with utilization and resource allocation", + "editable":true, + "gnetId":8673, + "graphTooltip":0, + "id":9, + "iteration":1553150922105, + "links":[ + + ], + "panels":[ + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "fontSize":"100%", + "gridPos":{ + "h":9, + "w":16, + "x":0, + "y":0 + }, + "hideTimeOverride":true, + "id":73, + "links":[ + + ], + "pageSize":8, + "repeat":null, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":2, + "desc":false + }, + "styles":[ + { + "alias":"Pod", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":false, + "linkTooltip":"", + "linkUrl":"", + "pattern":"pod_name", + "thresholds":[ + "30", + "80" + ], + "type":"string", + "unit":"currencyUSD" + }, + { + "alias":"RAM", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "pattern":"Value #B", + "thresholds":[ + + ], + "type":"number", + "unit":"decbytes" + }, + { + "alias":"CPU %", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + + ], + "type":"number", + "unit":"percent" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"Storage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"Total", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #D", + "thresholds":[ + + ], + "type":"number", + "unit":"currencyUSD" + }, + { + "alias":"CPU Utilization", + "colorMode":"value", + "colors":[ + "#bf1b00", + "rgba(50, 172, 45, 0.97)", + "#ef843c" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #E", + "thresholds":[ + "30", + "80" + ], + "type":"number", + "unit":"percent" + }, + { + "alias":"RAM Utilization", + "colorMode":"value", + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#ef843c" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #F", + "thresholds":[ + "30", + "80" + ], + "type":"number", + "unit":"percent" + } + ], + "targets":[ + { + "expr":"sum (rate (container_cpu_usage_seconds_total{namespace=\"$namespace\"}[10m])) by (pod_name) * 100", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"{{ pod_name }}", + "refId":"A" + }, + { + "expr":"sum (avg_over_time (container_memory_working_set_bytes{namespace=\"$namespace\", container_name!=\"POD\"}[10m])) by (pod_name)", + "format":"table", + "hide":false, + "instant":true, + "intervalFactor":1, + "legendFormat":"{{ pod_name }}", + "refId":"B" + } + ], + "timeFrom":"1M", + "timeShift":null, + "title":"Pod utilization analysis", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "fontSize":"100%", + "gridPos":{ + "h":9, + "w":8, + "x":16, + "y":0 + }, + "hideTimeOverride":true, + "id":90, + "links":[ + + ], + "pageSize":8, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":4, + "desc":true + }, + "styles":[ + { + "alias":"Namespace", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"namespace", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"PVC Name", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"persistentvolumeclaim", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Storage Class", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"storageclass", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Size", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":1, + "mappingType":1, + "pattern":"Value", + "thresholds":[ + + ], + "type":"number", + "unit":"gbytes" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + } + ], + "targets":[ + { + "expr":"sum (\n sum(kube_persistentvolumeclaim_info) by (persistentvolumeclaim, namespace, storageclass)\n + on (persistentvolumeclaim, namespace) group_right (storageclass)\n sum(kube_persistentvolumeclaim_resource_requests_storage_bytes{namespace=~\"$namespace\"}) by (persistentvolumeclaim, namespace)\n) by (namespace,persistentvolumeclaim,storageclass) / 1024 / 1024 /1024 ", + "format":"table", + "hide":false, + "instant":true, + "interval":"", + "intervalFactor":1, + "legendFormat":"{{ persistentvolumeclaim }}", + "refId":"A" + } + ], + "timeFrom":null, + "timeShift":null, + "title":"Persistent Volume Claims", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "description":"CPU requests by pod divided by the rate of CPU usage over the last hour", + "fill":1, + "gridPos":{ + "h":9, + "w":24, + "x":0, + "y":9 + }, + "id":100, + "legend":{ + "avg":false, + "current":false, + "max":false, + "min":false, + "show":true, + "total":false, + "values":false + }, + "lines":true, + "linewidth":1, + "links":[ + + ], + "nullPointMode":"null", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"topk(10,\n label_replace(\n sum(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace=\"$namespace\"}) by (pod),\n \"pod_name\", \n \"$1\", \n \"pod\", \n \"(.+)\"\n ) \n/ on (pod_name) sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",pod_name=~\".+\"}[1h])) by (pod_name))", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":[ + + ], + "timeFrom":null, + "timeShift":null, + "title":"Ratio of CPU requests to usage (Top 10 pods)", + "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 + } + ], + "yaxis":{ + "align":false, + "alignLevel":null + } + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "decimals":3, + "description":"This panel shows historical utilization as an average across all pods in this namespace. It only accounts for currently deployed pods", + "editable":true, + "error":false, + "fill":0, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":0, + "y":18 + }, + "height":"", + "id":94, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":false, + "current":false, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":false, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":true, + "targets":[ + { + "expr":"sum (rate (container_cpu_usage_seconds_total{namespace=\"$namespace\"}[10m])) by (namespace)\n", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"10s", + "intervalFactor":1, + "legendFormat":"cpu utilization", + "metric":"container_cpu", + "refId":"A", + "step":10 + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Overall CPU Utilization", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "decimals":null, + "format":"percent", + "label":"", + "logBase":1, + "max":"110", + "min":"0", + "show":true + }, + { + "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}", + "decimals":2, + "description":"This panel shows historical utilization as an average across all pods in this namespace. It only accounts for currently deployed pods", + "editable":true, + "error":false, + "fill":0, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":12, + "y":18 + }, + "id":92, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":false, + "current":false, + "max":false, + "min":false, + "rightSide":false, + "show":false, + "sideWidth":200, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":true, + "targets":[ + { + "expr":"sum (container_memory_working_set_bytes{namespace=\"$namespace\"})\n/\nsum(node_memory_MemTotal_bytes)", + "format":"time_series", + "instant":false, + "intervalFactor":1, + "legendFormat":"mem utilization", + "refId":"B" + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Overall RAM Utilization", + "tooltip":{ + "msResolution":false, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "decimals":null, + "format":"percent", + "label":null, + "logBase":1, + "max":"110", + "min":"0", + "show":true + }, + { + "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}", + "decimals":2, + "description":"Traffic in and out of this namespace, as a sum of the pods within it", + "editable":true, + "error":false, + "fill":1, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":0, + "y":24 + }, + "height":"", + "id":96, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":true, + "current":true, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":true, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"sum (rate (container_network_receive_bytes_total{namespace=\"$namespace\"}[10m])) by (namespace)", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"<- in", + "metric":"container_cpu", + "refId":"A", + "step":10 + }, + { + "expr":"- sum (rate (container_network_transmit_bytes_total{namespace=\"$namespace\"}[10m])) by (namespace)", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"-> out", + "refId":"B" + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Network IO", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"Bps", + "label":"", + "logBase":1, + "max":null, + "min":null, + "show":true + }, + { + "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}", + "decimals":2, + "description":"Disk reads and writes for the namespace, as a sum of the pods within it", + "editable":true, + "error":false, + "fill":1, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":12, + "y":24 + }, + "height":"", + "id":98, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":true, + "current":true, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":true, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"sum (rate (container_fs_writes_bytes_total{namespace=\"$namespace\"}[10m])) by (namespace)", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"<- write", + "metric":"container_cpu", + "refId":"A", + "step":10 + }, + { + "expr":"- sum (rate (container_fs_reads_bytes_total{namespace=\"$namespace\"}[10m])) by (namespace)", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"-> read", + "refId":"B" + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Disk IO", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"Bps", + "label":"", + "logBase":1, + "max":null, + "min":null, + "show":true + }, + { + "format":"short", + "label":null, + "logBase":1, + "max":null, + "min":null, + "show":false + } + ], + "yaxis":{ + "align":false, + "alignLevel":null + } + } + ], + "refresh":"10s", + "schemaVersion":16, + "style":"dark", + "tags":[ + "cost", + "utilization", + "metrics" + ], + "templating":{ + "list":[ + { + "current":{ + "text":"23.06", + "value":"23.06" + }, + "hide":0, + "label":"CPU", + "name":"costcpu", + "options":[ + { + "text":"23.06", + "value":"23.06" + } + ], + "query":"23.06", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"7.28", + "value":"7.28" + }, + "hide":0, + "label":"PE CPU", + "name":"costpcpu", + "options":[ + { + "text":"7.28", + "value":"7.28" + } + ], + "query":"7.28", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"3.25", + "value":"3.25" + }, + "hide":0, + "label":"RAM", + "name":"costram", + "options":[ + { + "text":"3.25", + "value":"3.25" + } + ], + "query":"3.25", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"0.6862", + "value":"0.6862" + }, + "hide":0, + "label":"PE RAM", + "name":"costpram", + "options":[ + { + "text":"0.6862", + "value":"0.6862" + } + ], + "query":"0.6862", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"0.04", + "value":"0.04" + }, + "hide":0, + "label":"Storage", + "name":"costStorageStandard", + "options":[ + { + "text":"0.04", + "value":"0.04" + } + ], + "query":"0.04", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":".17", + "value":".17" + }, + "hide":0, + "label":"SSD", + "name":"costStorageSSD", + "options":[ + { + "text":".17", + "value":".17" + } + ], + "query":".17", + "skipUrlSync":false, + "type":"constant" + }, + { + "current":{ + "text":"30", + "value":"30" + }, + "hide":0, + "label":"Disc.", + "name":"costDiscount", + "options":[ + { + "text":"30", + "value":"30" + } + ], + "query":"30", + "skipUrlSync":false, + "type":"constant" + }, + { + "allValue":null, + "current":{ + "text":"kube-system", + "value":"kube-system" + }, + "datasource":"${datasource}", + "hide":0, + "includeAll":false, + "label":"NS", + "multi":false, + "name":"namespace", + "options":[ + + ], + "query":"query_result(sum(kube_namespace_created{namespace!=\"\"}) by (namespace))", + "refresh":1, + "regex":"/namespace=\\\"(.*?)(\\\")/", + "skipUrlSync":false, + "sort":0, + "tagValuesQuery":"", + "tags":[ + + ], + "tagsQuery":"", + "type":"query", + "useTags":false + }, + { + "datasource":"${datasource}", + "filters":[ + + ], + "hide":0, + "label":"", + "name":"Filters", + "skipUrlSync":false, + "type":"adhoc" + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time":{ + "from":"now-15m", + "to":"now" + }, + "timepicker":{ + "hidden":false, + "refresh_intervals":[ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options":[ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone":"browser", + "title":"Namespace utilization metrics", + "uid":"at-cost-analysis-namespace2", + "version":1 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/node-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/node-utilization.json new file mode 100644 index 000000000..dc03cc074 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/node-utilization.json @@ -0,0 +1,1389 @@ +{ + "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":6, + "iteration":1557245882378, + "links":[ + + ], + "panels":[ + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "format":"percentunit", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":7, + "w":8, + "x":0, + "y":0 + }, + "id":2, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum(irate(container_cpu_usage_seconds_total{id=\"/\",instance=\"$node\"}[10m]))", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"CPU Usage", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"avg" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "format":"percentunit", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":7, + "w":8, + "x":8, + "y":0 + }, + "id":3, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"SUM(container_memory_usage_bytes{namespace!=\"\",instance=\"$node\"}) / SUM(kube_node_status_capacity{resource=\"memory\", unit=\"byte\", node=\"$node\"})", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"Memory Usage", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"avg" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "format":"percentunit", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":true, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":7, + "w":8, + "x":16, + "y":0 + }, + "id":4, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum(container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",instance=\"$node\"}) /\nsum(container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",instance=\"$node\"})", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"Storage Usage", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"avg" + }, + { + "columns":[ + { + "text":"Avg", + "value":"avg" + } + ], + "datasource":"${datasource}", + "fontSize":"100%", + "gridPos":{ + "h":8, + "w":16, + "x":0, + "y":7 + }, + "hideTimeOverride":true, + "id":21, + "links":[ + + ], + "pageSize":8, + "repeat":null, + "repeatDirection":"v", + "scroll":true, + "showHeader":true, + "sort":{ + "col":4, + "desc":true + }, + "styles":[ + { + "alias":"Pod", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "link":false, + "linkTooltip":"", + "linkUrl":"", + "pattern":"pod_name", + "thresholds":[ + "30", + "80" + ], + "type":"string", + "unit":"currencyUSD" + }, + { + "alias":"", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Time", + "thresholds":[ + + ], + "type":"hidden", + "unit":"short" + }, + { + "alias":"CPU Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #C", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"CPU Request", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #A", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"CPU Limit", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #B", + "thresholds":[ + + ], + "type":"number", + "unit":"short" + }, + { + "alias":"Mem Usage", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #D", + "thresholds":[ + + ], + "type":"number", + "unit":"bytes" + }, + { + "alias":"Mem Request", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #E", + "thresholds":[ + + ], + "type":"number", + "unit":"bytes" + }, + { + "alias":"Mem Limit", + "colorMode":null, + "colors":[ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat":"YYYY-MM-DD HH:mm:ss", + "decimals":2, + "mappingType":1, + "pattern":"Value #F", + "thresholds":[ + + ], + "type":"number", + "unit":"bytes" + } + ], + "targets":[ + { + "expr":"sum(rate(container_cpu_usage_seconds_total{container_name!=\"\",container_name!=\"POD\",pod_name!=\"\",instance=\"$node\"}[24h])) by (pod_name)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"C" + }, + { + "expr":"sum(label_replace(\nsum(avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", container!=\"\",container!=\"POD\",node=\"$node\"}[24h])) by (pod), \n\"pod_name\",\"$1\",\"pod\",\"(.+)\")\nor up * 0\n) by (pod_name)", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"A" + }, + { + "expr":"sum(avg_over_time(container_memory_usage_bytes{container_name!=\"\",container_name!=\"POD\",pod_name!=\"\",instance=\"$node\"}[24h])) by (pod_name)\n", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"D" + }, + { + "expr":"sum(label_replace(label_replace(\nsum(avg_over_time(kube_pod_container_resource_requests{resource=\"memory\", unit=\"byte\", container!=\"\",container!=\"POD\",node=\"$node\"}[24h])) by (pod),\n\"container_name\",\"$1\",\"container\",\"(.+)\"), \"pod_name\",\"$1\",\"pod\",\"(.+)\")\nor up * 0\n) by (pod_name)\n", + "format":"table", + "instant":true, + "intervalFactor":1, + "refId":"E" + } + ], + "timeFrom":"1M", + "timeShift":null, + "title":"Current pods", + "transform":"table", + "transparent":false, + "type":"table" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "decimals":0, + "format":"none", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":4, + "x":16, + "y":7 + }, + "id":8, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum(\n count(avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", container!=\"\",container!=\"POD\",node=\"$node\"}[24h])) by (pod)\n * on (pod) group_right()\n sum(kube_pod_container_status_running) by (pod)\n)", + "format":"time_series", + "instant":true, + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"Pods Running", + "type":"singlestat", + "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}", + "format":"bytes", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":4, + "x":20, + "y":7 + }, + "id":18, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"sum(container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",instance=\"$node\"})", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"Storage Capacity", + "type":"singlestat", + "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}", + "format":"none", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":4, + "x":16, + "y":11 + }, + "id":9, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"kube_node_status_capacity{resource=\"cpu\", unit=\"core\", node=\"$node\"}", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"CPU Capacity", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"avg" + }, + { + "cacheTimeout":null, + "colorBackground":false, + "colorValue":false, + "colors":[ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource":"${datasource}", + "format":"bytes", + "gauge":{ + "maxValue":100, + "minValue":0, + "show":false, + "thresholdLabels":false, + "thresholdMarkers":true + }, + "gridPos":{ + "h":4, + "w":4, + "x":20, + "y":11 + }, + "id":19, + "interval":null, + "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" + } + ], + "sparkline":{ + "fillColor":"rgba(31, 118, 189, 0.18)", + "full":false, + "lineColor":"rgb(31, 120, 193)", + "show":false + }, + "tableColumn":"", + "targets":[ + { + "expr":"kube_node_status_capacity{resource=\"memory\", unit=\"byte\", node=\"$node\"}", + "format":"time_series", + "intervalFactor":1, + "refId":"A" + } + ], + "thresholds":"", + "title":"RAM Capacity", + "type":"singlestat", + "valueFontSize":"80%", + "valueMaps":[ + { + "op":"=", + "text":"N/A", + "value":"null" + } + ], + "valueName":"current" + }, + { + "aliasColors":{ + + }, + "bars":false, + "dashLength":10, + "dashes":false, + "datasource":"${datasource}", + "decimals":3, + "description":"This panel shows historical utilization for the node.", + "editable":true, + "error":false, + "fill":0, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":0, + "y":15 + }, + "height":"", + "id":11, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":false, + "current":false, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":false, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":true, + "targets":[ + { + "expr":"sum(irate(container_cpu_usage_seconds_total{id=\"/\",instance=\"$node\"}[10m]))", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"10s", + "intervalFactor":1, + "legendFormat":"cpu utilization", + "metric":"container_cpu", + "refId":"A", + "step":10 + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"CPU Utilization", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "decimals":null, + "format":"percentunit", + "label":"", + "logBase":1, + "max":"1.1", + "min":"0", + "show":true + }, + { + "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}", + "decimals":2, + "description":"This panel shows historical utilization for the node.", + "editable":true, + "error":false, + "fill":0, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":12, + "y":15 + }, + "id":13, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":false, + "current":false, + "max":false, + "min":false, + "rightSide":false, + "show":false, + "sideWidth":200, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":true, + "targets":[ + { + "expr":"SUM(container_memory_usage_bytes{namespace!=\"\",instance=\"$node\"}) / SUM(kube_node_status_capacity{resource=\"memory\", unit=\"byte\", node=\"$node\"})", + "format":"time_series", + "instant":false, + "interval":"10s", + "intervalFactor":1, + "legendFormat":"ram utilization", + "metric":"container_memory_usage:sort_desc", + "refId":"A", + "step":10 + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"RAM Utilization", + "tooltip":{ + "msResolution":false, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "decimals":null, + "format":"percentunit", + "label":null, + "logBase":1, + "max":"1.1", + "min":"0", + "show":true + }, + { + "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}", + "decimals":2, + "description":"Traffic in and out of this namespace, as a sum of the pods within it", + "editable":true, + "error":false, + "fill":1, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":0, + "y":21 + }, + "height":"", + "id":15, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":true, + "current":true, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":true, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"sum (rate (container_network_receive_bytes_total{instance=\"$node\"}[10m]))", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"<- in", + "metric":"container_cpu", + "refId":"A", + "step":10 + }, + { + "expr":"- sum (rate (container_network_transmit_bytes_total{instance=\"$node\"}[10m]))", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"-> out", + "refId":"B" + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Network IO", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"Bps", + "label":"", + "logBase":1, + "max":null, + "min":null, + "show":true + }, + { + "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}", + "decimals":2, + "description":"Disk reads and writes for the namespace, as a sum of the pods within it", + "editable":true, + "error":false, + "fill":1, + "grid":{ + + }, + "gridPos":{ + "h":6, + "w":12, + "x":12, + "y":21 + }, + "height":"", + "id":17, + "isNew":true, + "legend":{ + "alignAsTable":false, + "avg":true, + "current":true, + "hideEmpty":false, + "hideZero":false, + "max":false, + "min":false, + "rightSide":false, + "show":true, + "sideWidth":null, + "sort":"current", + "sortDesc":true, + "total":false, + "values":true + }, + "lines":true, + "linewidth":2, + "links":[ + + ], + "nullPointMode":"connected", + "percentage":false, + "pointradius":5, + "points":false, + "renderer":"flot", + "seriesOverrides":[ + + ], + "spaceLength":10, + "stack":false, + "steppedLine":false, + "targets":[ + { + "expr":"sum (rate (container_fs_writes_bytes_total{instance=\"$node\"}[10m]))", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"<- write", + "metric":"container_cpu", + "refId":"A", + "step":10 + }, + { + "expr":"- sum (rate (container_fs_reads_bytes_total{instance=\"$node\"}[10m]))", + "format":"time_series", + "hide":false, + "instant":false, + "interval":"", + "intervalFactor":1, + "legendFormat":"-> read", + "refId":"B" + } + ], + "thresholds":[ + + ], + "timeFrom":"", + "timeShift":null, + "title":"Disk IO", + "tooltip":{ + "msResolution":true, + "shared":true, + "sort":2, + "value_type":"cumulative" + }, + "type":"graph", + "xaxis":{ + "buckets":null, + "mode":"time", + "name":null, + "show":true, + "values":[ + + ] + }, + "yaxes":[ + { + "format":"Bps", + "label":"", + "logBase":1, + "max":null, + "min":null, + "show":true + }, + { + "format":"short", + "label":null, + "logBase":1, + "max":null, + "min":null, + "show":false + } + ], + "yaxis":{ + "align":false, + "alignLevel":null + } + } + ], + "schemaVersion":16, + "style":"dark", + "tags":[ + "cost", + "utilization", + "metrics" + ], + "templating":{ + "list":[ + { + "allValue":null, + "current":{ + "text":"ip-172-20-44-170.us-east-2.compute.internal", + "value":"ip-172-20-44-170.us-east-2.compute.internal" + }, + "datasource":"${datasource}", + "hide":0, + "includeAll":false, + "label":null, + "multi":false, + "name":"node", + "options":[ + + ], + "query":"query_result(kube_node_labels)", + "refresh":1, + "regex":"/node=\\\"(.*?)(\\\")/", + "skipUrlSync":false, + "sort":0, + "tagValuesQuery":"", + "tags":[ + + ], + "tagsQuery":"", + "type":"query", + "useTags":false + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "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":"", + "title":"Node utilization metrics", + "uid":"NUQW37Lmk", + "version":1 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/pod-utilization.json b/charts/kubecost/cost-analyzer/1.83.201/pod-utilization.json new file mode 100644 index 000000000..efab1f3aa --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/pod-utilization.json @@ -0,0 +1,950 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Visualize your kubernetes costs at the pod level.", + "editable": true, + "gnetId": 9063, + "graphTooltip": 0, + "iteration": 1616382275479, + "links": [], + "panels": [ + { + "columns": [ + { + "text": "Avg", + "value": "avg" + } + ], + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 0 + }, + "hideTimeOverride": true, + "id": 98, + "links": [], + "pageSize": 5, + "repeatDirection": "v", + "scroll": true, + "showHeader": true, + "sort": { + "col": 6, + "desc": true + }, + "styles": [ + { + "alias": "Container", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(50, 172, 45, 0.97)", + "#c15c17" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": false, + "pattern": "container_name", + "thresholds": [ + "30", + "80" + ], + "type": "string", + "unit": "currencyUSD" + }, + { + "alias": "Memory Allocation", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "CPU Allocation", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "none" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Time", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Memory ($/hour)", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "Spot/PE RAM", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #D", + "thresholds": [], + "type": "number", + "unit": "currencyUSD" + }, + { + "alias": "Total", + "align": "auto", + "colorMode": null, + "colors": [ + "#bf1b00", + "rgba(50, 172, 45, 0.97)", + "#ef843c" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #E", + "thresholds": [ + "" + ], + "type": "number", + "unit": "currencyUSD" + } + ], + "targets": [ + { + "expr": "sum(\n avg_over_time(container_memory_allocation_bytes{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__range])\n) by (container,node)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "sum(\n avg_over_time(container_cpu_allocation{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}[$__range])\n or up * 0 \n) by (container,node)", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": "1M", + "timeShift": null, + "title": "Container cost & allocation analysis", + "transform": "table", + "type": "table-old" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 3, + "description": "This graph attempts to show you CPU use of your application vs its requests", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 5 + }, + "height": "", + "hiddenSeries": false, + "id": 94, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "avg (rate (container_cpu_usage_seconds_total{namespace=~\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\",container_name!=\"\"}[10m])) by (container_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ container_name }} (usage)", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "exemplar": true, + "expr": "avg(kube_pod_container_resource_requests{resource=\"cpu\", unit=\"core\", namespace=~\"$namespace\", pod=~\"$pod\", container=~\"$container\", container!=\"POD\"}) by (container)", + "legendFormat": "{{ container}} (request)", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": "", + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage vs Requested", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "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}", + "decimals": 3, + "description": "This graph attempts to show you RAM use of your application vs its requests", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 5 + }, + "height": "", + "hiddenSeries": false, + "id": 96, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "avg (avg_over_time (container_memory_working_set_bytes{namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\",container_name!=\"\"}[1m])) by (container_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ container_name }} (usage)", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "expr": "avg(kube_pod_container_resource_requests_memory_bytes{namespace=~\"$namespace\", pod=\"$pod\", container!=\"POD\"}) by (container)", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{ container }} (requested)", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": "", + "timeRegions": [], + "timeShift": null, + "title": "RAM Usage vs Requested", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "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}", + "decimals": 2, + "description": "Traffic in and out of this pod, as a sum of its containers", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 12 + }, + "height": "", + "hiddenSeries": false, + "id": 95, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg (rate (container_network_receive_bytes_total{namespace=\"$namespace\",pod_name=\"$pod\"}[10m])) by (pod_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "<- in", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "expr": "- avg (rate (container_network_transmit_bytes_total{namespace=\"$namespace\",pod_name=\"$pod\"}[10m])) by (pod_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "-> out", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": "", + "timeRegions": [], + "timeShift": null, + "title": "Network IO", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "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}", + "decimals": 2, + "description": "Disk read writes", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 12 + }, + "height": "", + "hiddenSeries": false, + "id": 97, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg (rate (container_fs_writes_bytes_total{namespace=\"$namespace\",pod_name=\"$pod\"}[10m])) by (pod_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "<- write", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "expr": "- avg (rate (container_fs_reads_bytes_total{namespace=\"$namespace\",pod_name=\"$pod\"}[10m])) by (pod_name)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "-> read", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": "", + "timeRegions": [], + "timeShift": null, + "title": "Disk IO", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "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}", + "decimals": 3, + "description": "This graph shows the % of periods where a pod is being throttled. Values range from 0-100", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 19 + }, + "height": "", + "hiddenSeries": false, + "id": 99, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "expr": "100\n * sum by(container_name, pod_name, namespace) (increase(container_cpu_cfs_throttled_periods_total{container_name!=\"\",namespace=~\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\"}[5m]))\n / sum by(container_name, pod_name, namespace) (increase(container_cpu_cfs_periods_total{container_name!=\"\",namespace=~\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\"}[5m]))", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{container_name}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": "", + "timeRegions": [], + "timeShift": null, + "title": "CPU throttle percent", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [ + "cost", + "utilization", + "metrics" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": { + "selected": true, + "text": "kube-system", + "value": "kube-system" + }, + "datasource": "${datasource}", + "definition": "query_result(sum(container_memory_working_set_bytes{namespace!=\"\"}) by (namespace))", + "hide": 0, + "includeAll": false, + "label": "ns", + "multi": false, + "name": "namespace", + "options": [], + "query": "query_result(sum(container_memory_working_set_bytes{namespace!=\"\"}) by (namespace))", + "refresh": 1, + "regex": "/namespace=\\\"(.*?)(\\\")/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": true, + "text": "heapster-gke-5759dc947d-ctckh", + "value": "heapster-gke-5759dc947d-ctckh" + }, + "datasource": "${datasource}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "pod", + "multi": false, + "name": "pod", + "options": [], + "query": "query_result(sum(container_memory_working_set_bytes{namespace=\"$namespace\"}) by (pod_name))", + "refresh": 1, + "regex": "/pod_name=\\\"(.*?)(\\\")/", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": "-- Dashboard --", + "definition": "query_result(sum(container_memory_working_set_bytes{namespace!=\"\"}) by (cluster_id))", + "hide": 0, + "includeAll": false, + "label": "", + "multi": false, + "name": "cluster", + "options": [], + "query": "query_result(sum(container_memory_working_set_bytes{namespace!=\"\"}) by (cluster_id))", + "refresh": 1, + "regex": "/cluster_id=\\\"(.*?)(\\\")/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "hidden": false, + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Pod cost & utilization metrics", + "uid": "at-cost-analysis-pod", + "version": 1 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/prom-benchmark.json b/charts/kubecost/cost-analyzer/1.83.201/prom-benchmark.json new file mode 100644 index 000000000..0c5eae7e5 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/prom-benchmark.json @@ -0,0 +1,5689 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Metrics useful for benchmarking and loadtesting Prometheus itself. Designed primarily for Prometheus 2.17.x.", + "editable": true, + "gnetId": 12054, + "graphTooltip": 1, + "id": 9, + "iteration": 1603144824023, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 49, + "panels": [], + "title": "Basics", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_build_info{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{version}} - {{revision}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Prometheus Version", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 1 + }, + "hiddenSeries": false, + "id": 72, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "time() - process_start_time_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Age", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Uptime", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "dtdurations", + "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": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 1 + }, + "hiddenSeries": false, + "id": 107, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "time() - prometheus_config_last_reload_success_timestamp_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Age", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Last Successful Config Reload", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "dtdurations", + "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 + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 46, + "panels": [], + "title": "Ingestion", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "Time series": "#70dbed" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 9 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_series{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Time series", + "metric": "prometheus_local_storage_memory_series", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head Time series", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 9 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_active_appenders{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Head Appenders", + "metric": "prometheus_local_storage_memory_series", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head Active Appenders", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "samples/s": "#e5a8e2" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 9 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_head_samples_appended_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "samples/s", + "metric": "prometheus_local_storage_ingested_samples_total", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Samples Appended/s", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "To persist": "#9AC48A" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Max.*/", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_chunks{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Chunks", + "metric": "prometheus_local_storage_memory_chunks", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head Chunks", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 16 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_head_chunks_created_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Created", + "metric": "prometheus_local_storage_chunk_ops_total", + "refId": "A", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_head_chunks_removed_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Removed", + "metric": "prometheus_local_storage_chunk_ops_total", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head Chunks/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "Removed": "#e5ac0e" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 16 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_isolation_high_watermark{job=\"prometheus\",instance=\"$Prometheus:9090\"} - prometheus_tsdb_isolation_low_watermark{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Difference", + "metric": "prometheus_local_storage_chunk_ops_total", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Isolation Watermarks", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 52, + "panels": [], + "title": "Compaction", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max": "#447ebc", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "Min": "#447ebc", + "Now": "#7eb26d" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Max", + "fillBelowTo": "Min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_head_min_time{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Min", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + }, + { + "expr": "time() * 1000", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Now", + "refId": "C" + }, + { + "expr": "prometheus_tsdb_head_max_time{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Max", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head Time Range", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "dateTimeAsIso", + "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": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 24 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_head_gc_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "GC Time/s", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Head GC Time/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 24 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Queue length", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_blocks_loaded{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Blocks Loaded", + "metric": "prometheus_local_storage_indexing_batch_sizes_sum", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Blocks Loaded", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Failed Compactions": "#bf1b00", + "Failed Reloads": "#bf1b00", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_reloads_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Reloads", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TSDB Reloads/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Failed Compactions": "#bf1b00", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 31 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_wal_fsync_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m]) / rate(prometheus_tsdb_wal_fsync_duration_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Fsync Latency", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_wal_truncate_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m]) / rate(prometheus_tsdb_wal_trunacte_duration_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Truncate Latency", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "WAL Fsync&Truncate Latency", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Failed Compactions": "#bf1b00", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "{instance=\"demo.robustperception.io:9090\",job=\"prometheus\"}": "#bf1b00" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 31 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_wal_corruptions_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "WAL Corruptions", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_reloads_failures_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Reload Failures", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "B", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_head_series_not_found{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Head Series Not Found", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "C", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_compactions_failed_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Compaction Failures", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "D", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_retention_cutoffs_failures_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Retention Cutoff Failures", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "E", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_checkpoint_creations_failed_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "WAL Checkpoint Creation Failures", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "F", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_checkpoint_deletions_failed_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "WAL Checkpoint Deletion Failures", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "G", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TSDB Problems/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Failed Compactions": "#bf1b00", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 38 + }, + "hiddenSeries": false, + "id": 19, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_compactions_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Compactions", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compactions/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 38 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_compaction_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compaction Time/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Allocated bytes": "#F9BA8F", + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "RSS": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 38 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_time_retentions_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Time Cutoffs", + "metric": "last", + "refId": "A", + "step": 10 + }, + { + "expr": "rate(prometheus_tsdb_size_retentions_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Size Cutoffs", + "metric": "last", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Retention Cutoffs/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 45 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_compaction_chunk_range_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m]) / rate(prometheus_tsdb_compaction_chunk_range_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Chunk Time Range", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "First Compaction, Avg Chunk Time Range", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "dtdurationms", + "label": "", + "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": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 45 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_compaction_chunk_size_bytes_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m]) / rate(prometheus_tsdb_compaction_chunk_samples_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Bytes/Sample", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "First Compaction, Avg Bytes/Sample", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "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": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 45 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_tsdb_compaction_chunk_samples_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m]) / rate(prometheus_tsdb_compaction_chunk_samples_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[10m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Chunk Samples", + "metric": "prometheus_local_storage_series_chunks_persisted_count", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "First Compaction, Avg Chunk Samples", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "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 + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 55, + "panels": [], + "title": "Resource Usage", + "type": "row" + }, + { + "aliasColors": { + "Allocated bytes": "#7EB26D", + "Allocated bytes - 1m max": "#BF1B00", + "Allocated bytes - 1m min": "#BF1B00", + "Allocated bytes - 5m max": "#BF1B00", + "Allocated bytes - 5m min": "#BF1B00", + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "RSS": "#447EBC" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 53 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/-/", + "fill": 0 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_resident_memory_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "intervalFactor": 2, + "legendFormat": "RSS", + "metric": "process_resident_memory_bytes", + "refId": "B", + "step": 10 + }, + { + "expr": "prometheus_local_storage_target_heap_size_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "intervalFactor": 2, + "legendFormat": "Target heap size", + "metric": "go_memstats_alloc_bytes", + "refId": "D", + "step": 10 + }, + { + "expr": "go_memstats_next_gc_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "intervalFactor": 2, + "legendFormat": "Next GC", + "metric": "go_memstats_next_gc_bytes", + "refId": "C", + "step": 10 + }, + { + "expr": "go_memstats_alloc_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "intervalFactor": 2, + "legendFormat": "Allocated", + "metric": "go_memstats_alloc_bytes", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "msResolution": false, + "shared": true, + "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": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Allocated bytes": "#F9BA8F", + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833", + "RSS": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 53 + }, + "hiddenSeries": false, + "id": 7, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(go_memstats_alloc_bytes_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Allocated Bytes/s", + "metric": "go_memstats_alloc_bytes", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Allocations", + "tooltip": { + "msResolution": false, + "shared": true, + "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": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 53 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(process_cpu_seconds_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "intervalFactor": 2, + "legendFormat": "Irate", + "metric": "prometheus_local_storage_ingested_samples_total", + "refId": "A", + "step": 10 + }, + { + "expr": "rate(process_cpu_seconds_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[5m])", + "intervalFactor": 2, + "legendFormat": "5m rate", + "metric": "prometheus_local_storage_ingested_samples_total", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "avg" + ] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 70, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_symbol_table_size_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "RAM Used", + "metric": "prometheus_local_storage_ingested_samples_total", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Symbol Tables Size", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "avg" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 60 + }, + "hiddenSeries": false, + "id": 71, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_tsdb_storage_blocks_bytes_total{job=\"prometheus\",instance=\"$Prometheus:9090\"} or prometheus_tsdb_storage_blocks_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Disk Used", + "metric": "prometheus_local_storage_ingested_samples_total", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Block Size", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [ + "avg" + ] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Max": "#e24d42", + "Open": "#508642" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 60 + }, + "hiddenSeries": false, + "id": 41, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_max_fds{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max", + "refId": "A" + }, + { + "expr": "process_open_fds{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Open", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "File Descriptors", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 67 + }, + "id": 91, + "panels": [], + "title": "Service Discovery", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 68 + }, + "hiddenSeries": false, + "id": 42, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_sd_discovered_targets{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}}-{{config}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Discovered Targets", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 68 + }, + "hiddenSeries": false, + "id": 96, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_sd_updates_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent Updates/s", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 68 + }, + "hiddenSeries": false, + "id": 97, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_sd_received_updates_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[5m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Updates/s", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 75 + }, + "id": 99, + "panels": [], + "title": "Scraping", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 76 + }, + "hiddenSeries": false, + "id": 105, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_target_interval_length_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m]) / rate(prometheus_target_interval_length_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{interval}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Scrape Interval", + "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": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 76 + }, + "hiddenSeries": false, + "id": 104, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_target_scrapes_exceeded_sample_limit_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Exceeded Sample Limit", + "refId": "A" + }, + { + "expr": "rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Duplicate Timestamp", + "refId": "C" + }, + { + "expr": "rate(prometheus_target_scrapes_sample_out_of_bounds_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Out Of Bounds ", + "refId": "D" + }, + { + "expr": "rate(prometheus_target_scrapes_sample_out_of_order_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Out of Order", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Scrape Problems/s", + "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 + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 76 + }, + "hiddenSeries": false, + "id": 95, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_target_metadata_cache_bytes{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{scrape_job}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Metadata Cache Size", + "tooltip": { + "shared": true, + "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": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 83 + }, + "id": 63, + "panels": [], + "title": "Query Engine", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "Time spent in each mode, per second", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 84 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_engine_query_duration_seconds_sum{job=\"prometheus\",}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{slice}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Query engine timings/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 84 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_rule_group_iterations_missed_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m]) ", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Rule group missed", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "B", + "step": 10 + }, + { + "expr": "rate(prometheus_rule_evaluation_failures_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Rule evals failed", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Rule group evaulation problems/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 84 + }, + "hiddenSeries": false, + "id": 23, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_rule_group_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Rule evaluation duration", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Evaluation time of rule groups/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 91 + }, + "id": 77, + "panels": [ + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 92 + }, + "hiddenSeries": false, + "id": 86, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_notifications_sent_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{alertmanager}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Notification Sent/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 92 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_notifications_errors_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m]) / rate(prometheus_notifications_sent_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{alertmanager}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Notification Error Ratio", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 92 + }, + "hiddenSeries": false, + "id": 81, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_notifications_latency_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m]) / rate(prometheus_notifications_latency_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{alertmanager}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Notification Latency", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 99 + }, + "hiddenSeries": false, + "id": 85, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_notifications_alertmanagers_discovered{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Alertmanagers", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Alertmanagers Discovered", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 99 + }, + "hiddenSeries": false, + "id": 89, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_notifications_dropped_total{job=\"prometheus\",instance=\"$Prometheus:9090\"}[1m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Dropped", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Notifications Dropped/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 99 + }, + "hiddenSeries": false, + "id": 88, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_notifications_queue_length{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Pending", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + }, + { + "expr": "prometheus_notifications_queue_capacity{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Max", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Notification Queue", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Notification", + "type": "row" + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 92 + }, + "id": 58, + "panels": [], + "title": "HTTP Server", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 93 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_http_request_duration_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{handler}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP requests/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 93 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_http_request_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m]) / rate(prometheus_http_request_duration_seconds_count{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{handler}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP request latency", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "description": "", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 93 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(prometheus_http_request_duration_seconds_sum{job=\"prometheus\",instance=\"$Prometheus:9090\"}[2m])", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{handler}}", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time spent in HTTP requests/s", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 100 + }, + "id": 61, + "panels": [], + "repeat": "RuleGroup", + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;CPU", + "value": "/etc/config/rules;CPU" + } + }, + "title": "Rule Group: $RuleGroup", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Interval": "#890f02", + "Last Duration": "#f9934e", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 101 + }, + "hiddenSeries": false, + "id": 43, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;CPU", + "value": "/etc/config/rules;CPU" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_rule_group_interval_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Interval", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + }, + { + "expr": "prometheus_rule_group_last_duration_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Last Duration", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$RuleGroup: Duration", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Interval": "#890f02", + "Last Duration": "#f9934e", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 101 + }, + "hiddenSeries": false, + "id": 66, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;CPU", + "value": "/etc/config/rules;CPU" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_rule_group_rules{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Rules", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$RuleGroup: Rules", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${datasource}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 108 + }, + "id": 108, + "panels": [], + "repeat": null, + "repeatIteration": 1603144824023, + "repeatPanelId": 61, + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;Savings", + "value": "/etc/config/rules;Savings" + } + }, + "title": "Rule Group: $RuleGroup", + "type": "row" + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Interval": "#890f02", + "Last Duration": "#f9934e", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 109 + }, + "hiddenSeries": false, + "id": 109, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1603144824023, + "repeatPanelId": 43, + "repeatedByRow": true, + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;Savings", + "value": "/etc/config/rules;Savings" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_rule_group_interval_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Interval", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + }, + { + "expr": "prometheus_rule_group_last_duration_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Last Duration", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$RuleGroup: Duration", + "tooltip": { + "msResolution": false, + "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": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Chunks": "#1F78C1", + "Chunks to persist": "#508642", + "Interval": "#890f02", + "Last Duration": "#f9934e", + "Max chunks": "#052B51", + "Max to persist": "#3F6833" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${datasource}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 109 + }, + "hiddenSeries": false, + "id": 110, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "repeatIteration": 1603144824023, + "repeatPanelId": 66, + "repeatedByRow": true, + "scopedVars": { + "RuleGroup": { + "selected": false, + "text": "/etc/config/rules;Savings", + "value": "/etc/config/rules;Savings" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "prometheus_rule_group_rules{job=\"prometheus\",instance=\"$Prometheus:9090\",rule_group=~\"$RuleGroup\"}\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Rules", + "metric": "prometheus_local_storage_memory_chunkdescs", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$RuleGroup: Rules", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "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": [ + { + "allValue": null, + "current": { + "selected": false, + "text": "localhost", + "value": "localhost" + }, + "datasource": "${datasource}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "Prometheus", + "options": [], + "query": "query_result(up{job=\"prometheus\"} == 1)", + "refresh": 2, + "regex": ".*instance=\"([^\"]+):9090\".*", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": null, + "tags": [], + "tagsQuery": null, + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "${datasource}", + "definition": "", + "hide": 2, + "includeAll": true, + "label": null, + "multi": false, + "name": "RuleGroup", + "options": [], + "query": "prometheus_rule_group_last_duration_seconds{job=\"prometheus\",instance=\"$Prometheus:9090\"}", + "refresh": 2, + "regex": ".*rule_group=\"(.*?)\".*", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "default-kubecost", + "value": "default-kubecost" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "utc", + "title": "Prometheus Benchmark - 2.17.x", + "uid": "L0HBvojWz", + "version": 4 +} diff --git a/charts/kubecost/cost-analyzer/1.83.201/questions.yaml b/charts/kubecost/cost-analyzer/1.83.201/questions.yaml new file mode 100644 index 000000000..3569a25e0 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/questions.yaml @@ -0,0 +1,160 @@ +questions: + # General Settings + - variable: kubecostProductConfigs.clusterName + label: Cluster Name + description: "Used for display in the cost-analyzer UI (Can be renamed in the UI)" + type: string + required: true + default: "" + group: General Settings + - variable: persistentVolume.enabled + label: Enable Persistent Volume for CostAnalyzer + description: "If true, Kubecost will create a Persistent Volume Claim for product config data" + type: boolean + default: false + show_subquestion_if: true + group: "General Settings" + subquestions: + - variable: persistentVolume.size + label: CostAnalyzer Persistent Volume Size + type: string + default: "0.2Gi" + + # Prometheus Server + - variable: global.prometheus.enabled + label: Enable Prometheus + description: If false, use an existing Prometheus install + type: boolean + default: true + group: "Prometheus" + - variable: prometheus.kubeStateMetrics.enabled + label: Enable KubeStateMetrics + description: "If true, deploy kube-state-metrics for Kubernetes metrics" + type: boolean + default: true + show_if: "global.prometheus.enabled=true" + group: "Prometheus" + - variable: prometheus.server.retention + label: Prometheus Server Retention + description: "Determines when to remove old data" + type: string + default: "15d" + show_if: "global.prometheus.enabled=true" + group: "Prometheus" + - variable: prometheus.server.persistentVolume.enabled + label: Create Persistent Volume for Prometheus + description: "If true, prometheus will create a persistent volume claim" + type: boolean + required: true + default: false + group: "Prometheus" + show_if: "global.prometheus.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.server.persistentVolume.size + label: Prometheus Persistent Volume Size + type: string + default: "8Gi" + - variable: prometheus.server.persistentVolume.storageClass + label: Prometheus Persistent Volume StorageClass + description: "Prometheus data persistent volume storageClass, if not set use default StorageClass" + default: "" + type: storageclass + - variable: prometheus.server.persistentVolume.existingClaim + label: Existing Persistent Volume Claim for Prometheus + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + default: "" + + # Prometheus Node Exporter + - variable: prometheus.nodeExporter.enabled + label: Enable NodeExporter + description: "If false, do not create NodeExporter daemonset" + type: boolean + default: true + group: "NodeExporter" + - variable: prometheus.serviceAccounts.nodeExporter.create + label: Enable Service Accounts NodeExporter + description: "If false, do not create NodeExporter daemonset" + type: boolean + default: true + group: "NodeExporter" + + # Prometheus AlertManager + - variable: prometheus.alertmanager.enabled + label: Enable AlertManager + type: boolean + default: true + group: "AlertManager" + - variable: prometheus.alertmanager.persistentVolume.enabled + label: Create Persistent Volume for AlertManager + description: "If true, alertmanager will create a persistent volume claim" + type: boolean + required: true + default: false + group: "AlertManager" + show_if: "prometheus.alertmanager.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.alertmanager.persistentVolume.size + default: "2Gi" + description: "AlertManager data persistent volume size" + type: string + label: AlertManager Persistent Volume Size + - variable: prometheus.alertmanager.persistentVolume.storageClass + default: "" + description: "Alertmanager data persistent volume storageClass, if not set use default StorageClass" + type: storageclass + label: AlertManager Persistent Volume StorageClass + - variable: prometheus.alertmanager.persistentVolume.existingClaim + default: "" + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + label: Existing Persistent Volume Claim for AlertManager + + # PushGateway + - variable: prometheus.pushgateway.enabled + label: Enable PushGateway + type: boolean + default: true + group: "PushGateway" + - variable: prometheus.pushgateway.persistentVolume.enabled + label: Create Persistent Volume for PushGateway + description: "If true, PushGateway will create a persistent volume claim" + required: true + type: boolean + default: false + group: "PushGateway" + show_if: "prometheus.pushgateway.enabled=true" + show_subquestion_if: true + subquestions: + - variable: prometheus.prometheus.pushgateway.persistentVolume.size + label: PushGateway Persistent Volume Size + type: string + default: "2Gi" + - variable: prometheus.pushgateway.persistentVolume.storageClass + label: PushGateway Persistent Volume StorageClass + description: "PushGateway data persistent volume storageClass, if not set use default StorageClass" + type: storageclass + default: "" + - variable: prometheus.pushgateway.persistentVolume.existingClaim + label: Existing Persistent Volume Claim for PushGateway + description: "If not empty, uses the specified existing PVC instead of creating new one" + type: pvc + default: "" + + # Services and Load Balancing + - variable: ingress.enabled + label: Enable Ingress + description: "Expose app using Ingress (Layer 7 Load Balancer)" + default: true + type: boolean + show_subquestion_if: true + group: "Services and Load Balancing" + subquestions: + - variable: ingress.hosts[0] + default: "xip.io" + description: "Hostname to your CostAnalyzer installation" + type: hostname + required: true + label: Hostname diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/NOTES.txt b/charts/kubecost/cost-analyzer/1.83.201/templates/NOTES.txt new file mode 100644 index 000000000..bbc2594e9 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/NOTES.txt @@ -0,0 +1,10 @@ + + +-------------------------------------------------- +{{- $servicePort := .Values.service.port | default 9090 -}} +Kubecost has been successfully installed. When pods are Ready, you can enable port-forwarding with the following command: + + kubectl port-forward --namespace {{ .Release.Namespace }} deployment/{{ template "cost-analyzer.fullname" . }} {{ $servicePort }} + +Next, navigate to http://localhost:{{ $servicePort }} in a web browser. + diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/_helpers.tpl b/charts/kubecost/cost-analyzer/1.83.201/templates/_helpers.tpl new file mode 100644 index 000000000..6293e51c7 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/_helpers.tpl @@ -0,0 +1,211 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cost-analyzer.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 "cost-analyzer.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 the fully qualified name for Prometheus server service. +*/}} +{{- define "cost-analyzer.prometheus.server.name" -}} +{{- if .Values.prometheus -}} +{{- if .Values.prometheus.server -}} +{{- if .Values.prometheus.server.fullnameOverride -}} +{{- .Values.prometheus.server.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-prometheus-server" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- else -}} +{{- printf "%s-prometheus-server" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- else -}} +{{- printf "%s-prometheus-server" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create the fully qualified name for Prometheus alertmanager service. +*/}} +{{- define "cost-analyzer.prometheus.alertmanager.name" -}} +{{- if .Values.prometheus -}} +{{- if .Values.prometheus.alertmanager -}} +{{- if .Values.prometheus.alertmanager.fullnameOverride -}} +{{- .Values.prometheus.alertmanager.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-prometheus-alertmanager" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- else -}} +{{- printf "%s-prometheus-alertmanager" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- else -}} +{{- printf "%s-prometheus-alertmanager" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{- define "cost-analyzer.serviceName" -}} +{{- printf "%s-%s" .Release.Name "cost-analyzer" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Network Costs name used to tie autodiscovery of metrics to daemon set pods +*/}} +{{- define "cost-analyzer.networkCostsName" -}} +{{- printf "%s-%s" .Release.Name "network-costs" -}} +{{- end -}} + +{{- define "kubecost.clusterControllerName" -}} +{{- printf "%s-%s" .Release.Name "cluster-controller" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cost-analyzer.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "cost-analyzer.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "cost-analyzer.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the common labels. +*/}} +{{- define "cost-analyzer.commonLabels" -}} +app.kubernetes.io/name: {{ include "cost-analyzer.name" . }} +helm.sh/chart: {{ include "cost-analyzer.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app: cost-analyzer +{{- end -}} + +{{/* +Create the selector labels. +*/}} +{{- define "cost-analyzer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cost-analyzer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app: cost-analyzer +{{- end -}} + +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "cost-analyzer.daemonset.apiVersion" -}} +{{- if semverCompare "<1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.9-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for priorityClass. +*/}} +{{- define "cost-analyzer.priorityClass.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "scheduling.k8s.io/v1beta1" -}} +{{- else if semverCompare "^1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "scheduling.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "cost-analyzer.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for Ingress. +*/}} +{{- define "cost-analyzer.ingress.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podsecuritypolicy. +*/}} +{{- define "cost-analyzer.podSecurityPolicy.apiVersion" -}} +{{- if semverCompare ">=1.3-0, <1.10-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.10-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Recursive filter which accepts a map containing an input map (.v) and an output map (.r). The template +will traverse all values inside .v recursively writing non-map values to the output .r. If a nested map +is discovered, we look for an 'enabled' key. If it doesn't exist, we continue traversing the +map. If it does exist, we omit the inner map traversal iff enabled is false. This filter writes the +enabled only version to the output .r +*/}} +{{- define "cost-analyzer.filter" -}} +{{- $v := .v }} +{{- $r := .r }} +{{- range $key, $value := .v }} + {{- $tp := kindOf $value -}} + {{- if eq $tp "map" -}} + {{- $isEnabled := true -}} + {{- if (hasKey $value "enabled") -}} + {{- $isEnabled = $value.enabled -}} + {{- end -}} + {{- if $isEnabled -}} + {{- $rr := "{}" | fromYaml }} + {{- template "cost-analyzer.filter" (dict "v" $value "r" $rr) }} + {{- $_ := set $r $key $rr -}} + {{- end -}} + {{- else -}} + {{- $_ := set $r $key $value -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +This template accepts a map and returns a base64 encoded json version of the map where all disabled +leaf nodes are omitted. + +The implied use case is {{ template "cost-analyzer.filterEnabled" .Values }} +*/}} +{{- define "cost-analyzer.filterEnabled" -}} +{{- $result := "{}" | fromYaml }} +{{- template "cost-analyzer.filter" (dict "v" . "r" $result) }} +{{- $result | toJson | b64enc }} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/aws-service-key-secret.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/aws-service-key-secret.yaml new file mode 100644 index 000000000..6b8de4d5e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/aws-service-key-secret.yaml @@ -0,0 +1,17 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if .Values.kubecostProductConfigs.createServiceKeySecret }} +{{- if .Values.kubecostProductConfigs.awsServiceKeyName }} +apiVersion: v1 +kind: Secret +metadata: + name: cloud-service-key +type: Opaque +stringData: + service-key.json: |- + { + "aws_access_key_id": "{{ .Values.kubecostProductConfigs.awsServiceKeyName }}", + "aws_secret_access_key": "{{ .Values.kubecostProductConfigs.awsServiceKeyPassword }}" + } +{{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-deployment-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-deployment-template.yaml new file mode 100644 index 000000000..35f5b9991 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-deployment-template.yaml @@ -0,0 +1,26 @@ +{{- if .Values.awsstore }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "cost-analyzer.fullname" . }}-awsstore + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: awsstore + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app: awsstore + spec: + serviceAccountName: awsstore-serviceaccount + containers: + - image: {{ .Values.awsstore.imageNameAndVersion }} + name: awsstore +{{- end }} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-service-account-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-service-account-template.yaml new file mode 100644 index 000000000..65f37e652 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/awsstore-service-account-template.yaml @@ -0,0 +1,12 @@ +{{- if .Values.awsstore }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: awsstore-serviceaccount + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +{{- with .Values.awsstore.annotations }} + annotations: + {{- toYaml . | nindent 4 }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/azure-service-key-secret.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/azure-service-key-secret.yaml new file mode 100644 index 000000000..bb71e064b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/azure-service-key-secret.yaml @@ -0,0 +1,21 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if .Values.kubecostProductConfigs.createServiceKeySecret }} +{{- if .Values.kubecostProductConfigs.azureSubscriptionID }} +apiVersion: v1 +kind: Secret +metadata: + name: cloud-service-key +type: Opaque +stringData: + service-key.json: |- + { + "subscriptionId": "{{ .Values.kubecostProductConfigs.azureSubscriptionID }}", + "serviceKey": { + "appId": "{{ .Values.kubecostProductConfigs.azureClientID }}", + "password": "{{ .Values.kubecostProductConfigs.azureClientPassword }}", + "tenant": "{{ .Values.kubecostProductConfigs.azureTenantID }}" + } + } +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/azure-storage-config-secret.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/azure-storage-config-secret.yaml new file mode 100644 index 000000000..ae9e0a234 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/azure-storage-config-secret.yaml @@ -0,0 +1,22 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if .Values.kubecostProductConfigs.azureStorageCreateSecret }} +{{- if .Values.kubecostProductConfigs.azureStorageAccessKey }} +{{- if .Values.kubecostProductConfigs.azureStorageAccount }} +{{- if .Values.kubecostProductConfigs.azureStorageContainer }} +apiVersion: v1 +kind: Secret +metadata: + name: azure-storage-config +type: Opaque +stringData: + azure-storage-config.json: |- + { + "azureStorageAccount": "{{ .Values.kubecostProductConfigs.azureStorageAccount }}", + "azureStorageAccessKey": "{{ .Values.kubecostProductConfigs.azureStorageAccessKey }}", + "azureStorageContainer": "{{ .Values.kubecostProductConfigs.azureStorageContainer }}" + } +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-alerts-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-alerts-configmap.yaml new file mode 100644 index 000000000..e2d0edf73 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-alerts-configmap.yaml @@ -0,0 +1,10 @@ +{{- if .Values.global.notifications.alertConfigs }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: alert-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + alerts.json: '{{ toJson .Values.global.notifications.alertConfigs }}' +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-asset-reports-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-asset-reports-configmap.yaml new file mode 100644 index 000000000..2d3f1725f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-asset-reports-configmap.yaml @@ -0,0 +1,13 @@ +{{- if .Values.global.assetReports }} +{{- if .Values.global.assetReports.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: asset-report-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + asset-reports.json: '{{ toJson .Values.global.assetReports.reports }}' +{{- end -}} +{{- end -}} + diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluser-role-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluser-role-template.yaml new file mode 100644 index 000000000..16f926e8a --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluser-role-template.yaml @@ -0,0 +1,105 @@ +{{- if and .Values.reporting .Values.reporting.logCollection -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cost-analyzer.serviceAccountName" . }} +rules: +- apiGroups: + - '' + resources: + - "pods/log" + verbs: + - get + - list + - watch +--- +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cost-analyzer.serviceAccountName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +rules: + - apiGroups: + - '' + resources: + - configmaps + - deployments + - nodes + - pods + - events + - services + - resourcequotas + - replicationcontrollers + - limitranges + - persistentvolumeclaims + - persistentvolumes + - namespaces + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - daemonsets + - deployments + - replicasets + verbs: + - get + - list + - watch + - apiGroups: + - apps + resources: + - statefulsets + - deployments + - daemonsets + - replicasets + verbs: + - list + - watch + - apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - get + - list + - watch + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - get + - list + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - get + - list + - watch diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluster-role-binding-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluster-role-binding-template.yaml new file mode 100644 index 000000000..f2952b923 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-cluster-role-binding-template.yaml @@ -0,0 +1,33 @@ +{{- if .Values.reporting }} +{{- if .Values.reporting.logCollection }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "cost-analyzer.serviceAccountName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cost-analyzer.serviceAccountName" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cost-analyzer.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +--- +{{- end }} +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cost-analyzer.serviceAccountName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cost-analyzer.serviceAccountName" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cost-analyzer.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-config-map-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-config-map-template.yaml new file mode 100644 index 000000000..86aa0ee51 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-config-map-template.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "cost-analyzer.fullname" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + {{- if .Values.global.prometheus.enabled }} + {{- if .Values.global.zone }} + prometheus-alertmanager-endpoint: http://{{ template "cost-analyzer.prometheus.alertmanager.name" . }}.{{ .Release.Namespace }}.svc.{{ .Values.global.zone }} + {{ else }} + prometheus-alertmanager-endpoint: http://{{ template "cost-analyzer.prometheus.alertmanager.name" . }}.{{ .Release.Namespace }} + {{- end -}} + {{ else }} + prometheus-alertmanager-endpoint: {{ .Values.global.notifications.alertmanager.fqdn }} + {{- end -}} + {{- if .Values.global.prometheus.enabled }} + {{- if .Values.global.zone }} + prometheus-server-endpoint: http://{{ template "cost-analyzer.prometheus.server.name" . }}.{{ .Release.Namespace }}.svc.{{ .Values.global.zone }} + {{ else }} + prometheus-server-endpoint: http://{{ template "cost-analyzer.prometheus.server.name" . }}.{{ .Release.Namespace }} + {{- end -}} + {{ else }} + prometheus-server-endpoint: {{ .Values.global.prometheus.fqdn }} + {{- end -}} + {{- if .Values.kubecostToken }} + kubecost-token: {{ .Values.kubecostToken }} + {{ else }} + kubecost-token: not-applied + {{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-db-pvc-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-db-pvc-template.yaml new file mode 100644 index 000000000..38b7e92f8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-db-pvc-template.yaml @@ -0,0 +1,29 @@ +{{- if (.Values.kubecostModel.etlToDisk | default true) -}} +{{- if .Values.persistentVolume -}} +{{- if not .Values.persistentVolume.dbExistingClaim -}} +{{- if .Values.persistentVolume.enabled -}} +{{- if .Values.persistentVolume.dbPVEnabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "cost-analyzer.fullname" . }}-db + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.persistentVolume.dbStorageClass }} + storageClassName: {{ .Values.persistentVolume.dbStorageClass }} + {{ end }} + resources: + requests: + {{- if .Values.persistentVolume }} + storage: {{ .Values.persistentVolume.dbSize }} + {{- else }} + storage: 32.0Gi + {{ end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-deployment-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-deployment-template.yaml new file mode 100644 index 000000000..286a983df --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-deployment-template.yaml @@ -0,0 +1,784 @@ +{{- $nginxPort := int .Values.service.port | default 9090 -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "cost-analyzer.fullname" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +{{- if .Values.kubecostDeployment }} +{{- with .Values.kubecostDeployment.labels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- end }} +spec: +{{- if .Values.kubecostDeployment }} + replicas: {{ .Values.kubecostDeployment.replicas | default 1 }} +{{- end }} + selector: + matchLabels: +{{ include "cost-analyzer.selectorLabels" . | nindent 8}} + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + {{ include "cost-analyzer.selectorLabels" . | nindent 8 }} + {{- if .Values.global.additionalLabels }} + {{ toYaml .Values.global.additionalLabels | nindent 8 }} + {{- end }} +{{- if .Values.kubecostDeployment }} +{{- with .Values.kubecostDeployment.labels }} +{{ toYaml . | indent 8 }} +{{- end }} +{{- end }} +{{- if .Values.global.podAnnotations}} + annotations: +{{- with .Values.global.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} +{{- end }} + spec: + {{- if .Values.kubecostFrontend.tls }} + {{- if .Values.kubecostFrontend.tls.enabled }} + securityContext: + runAsUser: 0 + {{- else }} + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + {{- end }} + {{- else if lt $nginxPort 1025 }} + securityContext: + runAsUser: 0 + {{- else }} + securityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + {{- end }} + restartPolicy: Always + serviceAccountName: {{ template "cost-analyzer.serviceAccountName" . }} + volumes: + - name: nginx-conf + configMap: + name: nginx-conf + items: + - key: nginx.conf + path: default.conf + {{- if .Values.kubecostModel.etlBucketConfigSecret }} + - name: etl-bucket-config + secret: + defaultMode: 420 + secretName: {{ .Values.kubecostModel.etlBucketConfigSecret }} + {{- end }} + {{- if .Values.kubecostProductConfigs }} + {{- if .Values.kubecostProductConfigs.productKey }} + {{- if .Values.kubecostProductConfigs.productKey.secretname }} + - name: productkey-secret + secret: + secretName: {{ .Values.kubecostProductConfigs.productKey.secretname }} + items: + - key: productkey.json + path: productkey.json + {{- end }} + {{- end -}} + {{- if .Values.kubecostProductConfigs }} + {{- if .Values.kubecostProductConfigs.gcpSecretName }} + - name: gcp-key-secret + secret: + secretName: {{ .Values.kubecostProductConfigs.gcpSecretName }} + items: + - key: compute-viewer-kubecost-key.json + path: key.json + {{- end }} + {{- end -}} + {{- if .Values.kubecostProductConfigs.serviceKeySecretName }} + - name: service-key-secret + secret: + secretName: {{ .Values.kubecostProductConfigs.serviceKeySecretName }} + {{- else if .Values.kubecostProductConfigs.createServiceKeySecret }} + - name: service-key-secret + secret: + secretName: cloud-service-key + {{- end }} + {{- if .Values.kubecostProductConfigs.azureStorageSecretName }} + - name: azure-storage-config + secret: + secretName: {{ .Values.kubecostProductConfigs.azureStorageSecretName }} + items: + - key: azure-storage-config.json + path: azure-storage-config.json + {{- else if .Values.kubecostProductConfigs.azureStorageCreateSecret }} + - name: azure-storage-config + secret: + secretName: azure-storage-config + {{- end }} + {{- if .Values.kubecostProductConfigs.cloudIntegrationSecret }} + - name: cloud-integration + secret: + secretName: {{ .Values.kubecostProductConfigs.cloudIntegrationSecret }} + items: + - key: cloud-integration.json + path: cloud-integration.json + {{- end }} + {{- if .Values.kubecostProductConfigs.clusters }} + - name: kubecost-clusters + configMap: + name: kubecost-clusters + {{- range .Values.kubecostProductConfigs.clusters }} + {{- if .auth }} + {{- if .auth.secretName }} + - name: {{ .auth.secretName }} + secret: + secretName: {{ .auth.secretName }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.kubecostFrontend.tls }} + {{- if .Values.kubecostFrontend.tls.enabled }} + - name: tls + secret: + secretName : {{ .Values.kubecostFrontend.tls.secretName }} + items: + - key: tls.crt + path: kc.crt + - key: tls.key + path: kc.key + {{- end }} + {{- end }} + {{- if .Values.saml }} + {{- if .Values.saml.enabled }} + {{- if .Values.saml.secretName }} + - name: secret-volume + secret: + secretName: {{ .Values.saml.secretName }} + {{- end }} + {{- if .Values.saml.metadataSecretName }} + - name: metadata-secret-volume + secret: + secretName: {{ .Values.saml.metadataSecretName }} + {{- end }} + {{- if .Values.saml.rbac.enabled }} + - name: saml-roles + configMap: + name: {{ template "cost-analyzer.fullname" . }}-saml + {{- end }} + {{- end }} + {{- end }} + - name: persistent-configs +{{- if .Values.persistentVolume }} +{{- if .Values.persistentVolume.enabled }} + persistentVolumeClaim: +{{- if .Values.persistentVolume.existingClaim }} + claimName: {{ .Values.persistentVolume.existingClaim }} +{{- else }} + claimName: {{ template "cost-analyzer.fullname" . }} +{{- end -}} +{{- else }} + emptyDir: {} +{{- end -}} +{{- else }} + persistentVolumeClaim: + claimName: {{ template "cost-analyzer.fullname" . }} +{{- end }} +{{- if and (.Values.kubecostModel.etlToDisk | default true) .Values.persistentVolume.dbPVEnabled }} + - name: persistent-db +{{- if .Values.persistentVolume }} +{{- if .Values.persistentVolume.enabled }} + persistentVolumeClaim: +{{- if .Values.persistentVolume.dbExistingClaim }} + claimName: {{ .Values.persistentVolume.dbExistingClaim }} +{{- else }} + claimName: {{ template "cost-analyzer.fullname" . }}-db +{{- end -}} +{{- else }} + emptyDir: {} +{{- end -}} +{{- else }} + persistentVolumeClaim: + claimName: {{ template "cost-analyzer.fullname" . }}-db +{{- end }} +{{- end }} + initContainers: +{{- if .Values.supportNFS }} + - name: config-db-perms-fix + {{- if .Values.initChownDataImage }} + image: {{ .Values.initChownDataImage }} + {{- else }} + image: busybox + {{- end }} + resources: +{{ toYaml .Values.initChownData.resources | indent 12 }} + {{- if and (.Values.kubecostModel.etlToDisk | default true) .Values.persistentVolume.dbPVEnabled }} + command: ["sh", "-c", "/bin/chmod -R 777 /var/configs && /bin/chmod -R 777 /var/db"] + {{- else }} + command: ["sh", "-c", "/bin/chmod -R 777 /var/configs"] + {{- end}} + volumeMounts: + - name: persistent-configs + mountPath: /var/configs + {{- if and (.Values.kubecostModel.etlToDisk | default true) .Values.persistentVolume.dbPVEnabled }} + - name: persistent-db + mountPath: /var/db + {{- end }} + securityContext: + runAsUser: 0 +{{ end }} + containers: + {{- if .Values.kubecostModel }} + {{- if .Values.kubecostModel.fullImageName }} + - image: {{ .Values.kubecostModel.fullImageName }} + {{- else if .Values.imageVersion }} + - image: {{ .Values.kubecostModel.image }}:{{ .Values.imageVersion }} + {{- else }} + - image: {{ .Values.kubecostModel.image }}:prod-{{ $.Chart.AppVersion }} + {{ end }} + {{- else }} + - image: gcr.io/kubecost1/cost-model:prod-{{ $.Chart.AppVersion }} + {{ end }} + name: cost-model + {{- if .Values.kubecostModel.imagePullPolicy }} + imagePullPolicy: {{ .Values.kubecostModel.imagePullPolicy }} + {{- else }} + imagePullPolicy: Always + {{- end }} + resources: +{{ toYaml .Values.kubecostModel.resources | indent 12 }} + readinessProbe: + httpGet: + path: /healthz + port: 9003 + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 200 + volumeMounts: + - name: persistent-configs + mountPath: /var/configs + {{- if .Values.kubecostModel.etlBucketConfigSecret }} + - name: etl-bucket-config + mountPath: /var/configs/etl + readOnly: true + {{- else if and (.Values.kubecostModel.etlToDisk | default true) .Values.persistentVolume.dbPVEnabled }} + - name: persistent-db + mountPath: /var/db + {{- end }} + {{- if .Values.kubecostProductConfigs }} + {{- if .Values.kubecostProductConfigs.productKey }} + {{- if .Values.kubecostProductConfigs.productKey.secretname }} + - name: productkey-secret + mountPath: /var/configs/productkey + {{- end }} + {{- end }} + {{- if .Values.kubecostProductConfigs.gcpSecretName }} + - name: gcp-key-secret + mountPath: /models + {{- end }} + {{- if or .Values.kubecostProductConfigs.azureStorageSecretName .Values.kubecostProductConfigs.azureStorageCreateSecret}} + - name: azure-storage-config + mountPath: /var/azure-storage-config + {{- end }} + {{- if .Values.kubecostProductConfigs.cloudIntegrationSecret}} + - name: cloud-integration + mountPath: /var/cloud-integration + {{- end }} + {{- if or .Values.kubecostProductConfigs.serviceKeySecretName .Values.kubecostProductConfigs.createServiceKeySecret }} + - name: service-key-secret + mountPath: /var/secrets + {{- end }} + {{- if .Values.kubecostProductConfigs.clusters }} + - name: kubecost-clusters + mountPath: /var/configs/clusters + {{- range .Values.kubecostProductConfigs.clusters }} + {{- if .auth }} + {{- if .auth.secretName }} + - name: {{ .auth.secretName }} + mountPath: /var/secrets/{{ .auth.secretName }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.saml }} + {{- if .Values.saml.enabled }} + {{- if .Values.saml.secretName }} + - name: secret-volume + mountPath: /var/configs/secret-volume + {{- end }} + {{- if .Values.saml.metadataSecretName }} + - name: metadata-secret-volume + mountPath: /var/configs/metadata-secret-volume + {{- end }} + {{- if .Values.saml.rbac.enabled }} + - name: saml-roles + mountPath: /var/configs/saml + {{- end }} + {{- end }} + {{- end }} + env: + - name: READ_ONLY + value: {{ (quote .Values.readonly) | default (quote false) }} + - name: PROMETHEUS_SERVER_ENDPOINT + valueFrom: + configMapKeyRef: + name: {{ template "cost-analyzer.fullname" . }} + key: prometheus-server-endpoint + - name: CLOUD_PROVIDER_API_KEY + value: "AIzaSyDXQPG_MHUEy9neR7stolq6l0ujXmjJlvk" # The GCP Pricing API requires a key. + - name: GOOGLE_APPLICATION_CREDENTIALS + {{- if .Values.kubecostProductConfigs }} + {{- if .Values.kubecostProductConfigs.gcpSecretName }} + value: /models/key.json + {{- else }} + value: /var/configs/key.json + {{- end }} + {{- else }} + value: /var/configs/key.json + {{- end }} + - name: CONFIG_PATH + value: /var/configs/ + - name: DB_PATH + value: /var/db/ + - name: CLUSTER_PROFILE + {{- if .Values.kubecostProductConfigs }} + value: {{ .Values.kubecostProductConfigs.clusterProfile | default "production" }} + {{- else }} + value: production + {{- end }} + - name: REMOTE_WRITE_PASSWORD + value: {{ .Values.remoteWrite.postgres.auth.password }} + {{- if .Values.remoteWrite.postgres.enabled }} + - name: REMOTE_WRITE_ENABLED + value: "true" + {{- end }} + - name: GOGC + value: "60" + - name: GODEBUG + value: "madvdontneed=1" + {{- if .Values.global.thanos.queryServiceBasicAuthSecretName}} + - name: MC_BASIC_AUTH_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBasicAuthSecretName }} + key: USERNAME + - name: MC_BASIC_AUTH_PW + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBasicAuthSecretName }} + key: PASSWORD + {{- end }} + {{- if .Values.global.prometheus.queryServiceBasicAuthSecretName}} + - name: DB_BASIC_AUTH_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBasicAuthSecretName }} + key: USERNAME + - name: DB_BASIC_AUTH_PW + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBasicAuthSecretName }} + key: PASSWORD + {{- end }} + {{- if .Values.global.prometheus.queryServiceBearerTokenSecretName }} + - name: DB_BEARER_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBearerTokenSecretName }} + key: TOKEN + {{- end }} + {{- if .Values.global.thanos.queryServiceBearerTokenSecretName }} + - name: MC_BEARER_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBearerTokenSecretName }} + key: TOKEN + {{- end }} + {{- if .Values.global.prometheus.insecureSkipVerify }} + - name: INSECURE_SKIP_VERIFY + value: {{ (quote .Values.global.prometheus.insecureSkipVerify) }} + {{- end }} + {{- if .Values.pricingCsv }} + {{- if .Values.pricingCsv.enabled }} + - name: USE_CSV_PROVIDER + value: "true" + - name: CSV_PATH + value: {{ .Values.pricingCsv.location.URI }} + - name: CSV_REGION + value: {{ .Values.pricingCsv.location.region }} + {{- if eq .Values.pricingCsv.location.provider "AWS"}} + {{- if .Values.pricingCsv.location.csvAccessCredentials }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Values.pricingCsv.location.csvAccessCredentials }} + key: AWS_ACCESS_KEY_ID + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.pricingCsv.location.csvAccessCredentials }} + key: AWS_SECRET_ACCESS_KEY + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.kubecostMetrics }} + - name: EMIT_POD_ANNOTATIONS_METRIC + value: {{ (quote .Values.kubecostMetrics.emitPodAnnotations) | default (quote false) }} + - name: EMIT_NAMESPACE_ANNOTATIONS_METRIC + value: {{ (quote .Values.kubecostMetrics.emitNamespaceAnnotations) | default (quote false) }} + {{- end }} + {{- if .Values.kubecostMetrics }} + - name: EMIT_KSM_V1_METRICS + value: {{ (quote .Values.kubecostMetrics.emitKsmV1Metrics) | default (quote true) }} + {{- end }} + {{- if .Values.reporting }} + - name: LOG_COLLECTION_ENABLED + value: {{ (quote .Values.reporting.logCollection) | default (quote true) }} + - name: PRODUCT_ANALYTICS_ENABLED + value: {{ (quote .Values.reporting.productAnalytics) | default (quote true) }} + - name: ERROR_REPORTING_ENABLED + value: {{ (quote .Values.reporting.errorReporting ) | default (quote true) }} + - name: VALUES_REPORTING_ENABLED + value: {{ (quote .Values.reporting.valuesReporting) | default (quote true) }} + {{- if .Values.reporting.errorReporting }} + - name: SENTRY_DSN + value: "https://71964476292e4087af8d5072afe43abd@o394722.ingest.sentry.io/5245431" + {{- end }} + {{- end }} + - name: LEGACY_EXTERNAL_API_DISABLED + value: {{ (quote .Values.kubecostModel.legacyOutOfClusterAPIDisabled) | default (quote false) }} + - name: OUT_OF_CLUSTER_PROM_METRICS_ENABLED + value: {{ (quote .Values.kubecostModel.outOfClusterPromMetricsEnabled) | default (quote false) }} + - name: CACHE_WARMING_ENABLED + value: {{ (quote .Values.kubecostModel.warmCache) | default (quote true) }} + - name: SAVINGS_CACHE_WARMING_ENABLED + value: {{ (quote .Values.kubecostModel.warmSavingsCache) | default (quote true) }} + - name: ETL_ENABLED + value: {{ (quote .Values.kubecostModel.etl) | default (quote true) }} + {{- if .Values.kubecostModel.etlBucketConfigSecret }} + - name: ETL_TO_DISK_ENABLED + value: "false" + - name: ETL_BUCKET_CONFIG + value: "/var/configs/etl/object-store.yaml" + {{- else }} + - name: ETL_TO_DISK_ENABLED + value: {{ (quote .Values.kubecostModel.etlToDisk) | default (quote true) }} + {{- end }} + - name : ETL_CLOUD_ASSETS_ENABLED + value: {{ (quote .Values.kubecostModel.etlCloudAssets) | default (quote true) }} + {{- if .Values.persistentVolume.dbPVEnabled }} + - name: ETL_PATH_PREFIX + value: "/var/db" + {{- end }} + - name: ETL_RESOLUTION_SECONDS + value: {{ (quote .Values.kubecostModel.etlResolutionSeconds) | default (quote 300) }} + - name: ETL_MAX_BATCH_HOURS + value: {{ (quote .Values.kubecostModel.etlMaxBatchHours) | default (quote 6) }} + - name: ETL_DAILY_STORE_DURATION_DAYS + value: {{ (quote .Values.kubecostModel.etlDailyStoreDurationDays) | default (quote 91) }} + - name: ETL_HOURLY_STORE_DURATION_HOURS + value: {{ (quote .Values.kubecostModel.etlHourlyStoreDurationHours) | default (quote 49) }} + - name: ETL_FILE_STORE_ENABLED + value: {{ (quote .Values.kubecostModel.etlFileStoreEnabled) | default (quote false) }} + - name: ETL_ASSET_RECONCILIATION_ENABLED + value: {{ (quote .Values.kubecostModel.etlAssetReconciliationEnabled) | default (quote true) }} + {{- if .Values.systemProxy.enabled }} + - name: HTTP_PROXY + value: {{ .Values.systemProxy.httpProxyUrl }} + - name: http_proxy + value: {{ .Values.systemProxy.httpProxyUrl }} + - name: HTTPS_PROXY + value: {{ .Values.systemProxy.httpsProxyUrl }} + - name: https_proxy + value: {{ .Values.systemProxy.httpsProxyUrl }} + - name: NO_PROXY + value: {{ .Values.systemProxy.noProxy }} + - name: no_proxy + value: {{ .Values.systemProxy.noProxy }} + {{- end }} + - name: PV_ENABLED + value: {{ (quote .Values.persistentVolume.enabled) | default (quote true) }} + - name: MAX_QUERY_CONCURRENCY + value: {{ (quote .Values.kubecostModel.maxQueryConcurrency) | default (quote 5) }} + - name: UTC_OFFSET + value: {{ (quote .Values.kubecostModel.utcOffset) | default (quote ) }} + {{- if .Values.networkCosts }} + {{- if .Values.networkCosts.enabled }} + - name: NETWORK_COSTS_PORT + value: {{ quote .Values.networkCosts.port | default (quote 3001) }} + {{- end }} + {{- end }} + {{- /* + If queryService is set, the cost-analyzer will always pass THANOS_ENABLED as true + to ensure that the custom query service target is used. The global.thanos.enabled + flag does not have any affect on this behavior. + */}} + {{- if .Values.global.thanos.queryService }} + - name: THANOS_ENABLED + value: "true" + - name: THANOS_QUERY_URL + value: {{ .Values.global.thanos.queryService }} + - name: THANOS_QUERY_OFFSET + value: {{ .Values.global.thanos.queryOffset | default "3h" }} + - name: THANOS_MAX_SOURCE_RESOLUTION + value: {{ .Values.kubecostModel.maxSourceResolution | default "raw" }} + {{- else if and .Values.global.thanos.enabled .Values.thanos }} + {{- if .Values.thanos.query }} + {{- if .Values.thanos.query.enabled }} + - name: THANOS_ENABLED + value: "true" + - name: THANOS_QUERY_URL + value: http://{{ .Release.Name }}-thanos-query-frontend-http.{{ .Release.Namespace }}:{{ .Values.thanos.queryFrontend.http.port }} + - name: THANOS_QUERY_OFFSET + value: {{ .Values.global.thanos.queryOffset | default "3h" }} + - name: THANOS_MAX_SOURCE_RESOLUTION + value: {{ .Values.kubecostModel.maxSourceResolution | default "raw" }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.saml }} + {{- if .Values.saml.enabled }} + - name: SAML_ENABLED + value: "true" + - name: IDP_URL + value: {{ .Values.saml.idpMetadataURL }} + - name: SP_HOST + value: {{ .Values.saml.appRootURL }} + {{- if .Values.saml.audienceURI }} + - name: AUDIENCE_URI + value: {{ .Values.saml.audienceURI }} + {{- end }} + {{- if .Values.saml.nameIDFormat }} + - name: NAME_ID_FORMAT + value: {{ .Values.saml.nameIDFormat }} + {{- end}} + {{- if .Values.saml.rbac.enabled }} + - name: SAML_RBAC_ENABLED + value: "true" + {{- end }} + {{- end }} + {{- end }} + {{- if and (.Values.prometheus.server.global.external_labels.cluster_id) (not .Values.prometheus.server.clusterIDConfigmap) }} + - name: CLUSTER_ID + value: {{ .Values.prometheus.server.global.external_labels.cluster_id }} + {{- end }} + {{- if .Values.prometheus.server.clusterIDConfigmap }} + - name: CLUSTER_ID + valueFrom: + configMapKeyRef: + name: {{ .Values.prometheus.server.clusterIDConfigmap }} + key: CLUSTER_ID + {{- end }} + {{- if .Values.remoteWrite.postgres.installLocal }} + - name: SQL_ADDRESS + value: pgprometheus + {{- else }} + - name: SQL_ADDRESS + value: {{ .Values.remoteWrite.postgres.remotePostgresAddress }} + {{- end }} + {{- if .Values.kubecostModel.promClusterIDLabel }} + - name: PROM_CLUSTER_ID_LABEL + value: {{ .Values.kubecostModel.promClusterIDLabel }} + {{- end }} + - name: RELEASE_NAME + value: {{ .Release.Name }} + - name: KUBECOST_NAMESPACE + value: {{ .Release.Namespace }} + - name: KUBECOST_TOKEN + valueFrom: + configMapKeyRef: + name: {{ template "cost-analyzer.fullname" . }} + key: kubecost-token + {{- if .Values.kubecostFrontend }} + {{- if .Values.kubecostFrontend.fullImageName }} + - image: {{ .Values.kubecostFrontend.fullImageName }} + {{- else if .Values.imageVersion }} + - image: {{ .Values.kubecostFrontend.image }}:{{ .Values.imageVersion }} + {{- else }} + - image: {{ .Values.kubecostFrontend.image }}:prod-{{ $.Chart.AppVersion }} + {{ end }} + {{- else }} + - image: gcr.io/kubecost1/frontend:prod-{{ $.Chart.AppVersion }} + {{ end }} + {{- if .Values.kubecostFrontend.tls }} + {{- if .Values.kubecostFrontend.tls.enabled }} + command: ["nginx", "-g", "daemon off;"] + ports: + - containerPort: 443 + {{- end }} + {{- end }} + env: + - name: GET_HOSTS_FROM + value: dns + name: cost-analyzer-frontend + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/ + {{- if .Values.kubecostFrontend.tls }} + {{- if .Values.kubecostFrontend.tls.enabled }} + - name: tls + mountPath: /etc/ssl/certs + {{- end }} + {{- end }} + resources: +{{ toYaml .Values.kubecostFrontend.resources | indent 12 }} + {{- if .Values.kubecostFrontend.imagePullPolicy }} + imagePullPolicy: {{ .Values.kubecostFrontend.imagePullPolicy }} + {{- else }} + imagePullPolicy: Always + {{- end }} + readinessProbe: + httpGet: + path: /healthz + port: 9003 + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 200 + {{- if .Values.kubecost }} + {{- if .Values.kubecost.fullImageName }} + - image: {{ .Values.kubecost.fullImageName }} + {{- else if .Values.imageVersion}} + - image: {{ .Values.kubecost.image }}:{{ .Values.imageVersion }} + {{- else }} + - image: {{ .Values.kubecost.image }}:prod-{{ $.Chart.AppVersion }} + {{ end }} + {{- else }} + - image: gcr.io/kubecost1/server:prod-{{ $.Chart.AppVersion }} + {{ end }} + resources: +{{ toYaml .Values.kubecost.resources | indent 12 }} + name: cost-analyzer-server + readinessProbe: + httpGet: + path: /healthz + port: 9003 + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 200 + volumeMounts: + - name: persistent-configs + mountPath: /var/configs + env: + - name: PROMETHEUS_SERVER_ENDPOINT + valueFrom: + configMapKeyRef: + name: {{ template "cost-analyzer.fullname" . }} + key: prometheus-server-endpoint + {{- if .Values.reporting }} + {{- if .Values.reporting.valuesReporting }} + - name: HELM_VALUES + value: {{ template "cost-analyzer.filterEnabled" .Values }} + {{- end }} + {{- end }} + {{- if .Values.global.prometheus.insecureSkipVerify }} + - name: INSECURE_SKIP_VERIFY + value: {{ (quote .Values.global.prometheus.insecureSkipVerify) }} + {{- end }} + {{- /* + If queryService is set, the cost-analyzer will always pass THANOS_ENABLED as true + to ensure that the custom query service target is used. The global.thanos.enabled + flag does not have any affect on this behavior. + */}} + {{- if .Values.global.thanos.queryService }} + - name: THANOS_ENABLED + value: "true" + - name: THANOS_QUERY_URL + value: {{ .Values.global.thanos.queryService }} + - name: THANOS_QUERY_OFFSET + value: {{ .Values.global.thanos.queryOffset | default "3h" }} + - name: THANOS_MAX_SOURCE_RESOLUTION + value: {{ .Values.kubecostModel.maxSourceResolution | default "raw" }} + {{- else if and .Values.global.thanos.enabled .Values.thanos }} + {{- if .Values.thanos.query }} + {{- if .Values.thanos.query.enabled }} + - name: THANOS_ENABLED + value: "true" + - name: THANOS_QUERY_URL + value: http://{{ .Release.Name }}-thanos-query-frontend-http.{{ .Release.Namespace }}:{{ .Values.thanos.queryFrontend.http.port }} + - name: THANOS_QUERY_OFFSET + value: {{ .Values.global.thanos.queryOffset | default "3h" }} + - name: THANOS_MAX_SOURCE_RESOLUTION + value: {{ .Values.kubecostModel.maxSourceResolution | default "raw" }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.global.thanos.queryServiceBasicAuthSecretName}} + - name: MC_BASIC_AUTH_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBasicAuthSecretName }} + key: USERNAME + - name: MC_BASIC_AUTH_PW + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBasicAuthSecretName }} + key: PASSWORD + {{- end }} + {{- if .Values.global.prometheus.queryServiceBasicAuthSecretName}} + - name: DB_BASIC_AUTH_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBasicAuthSecretName }} + key: USERNAME + - name: DB_BASIC_AUTH_PW + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBasicAuthSecretName }} + key: PASSWORD + {{- end }} + {{- if .Values.global.prometheus.queryServiceBearerTokenSecretName }} + - name: DB_BEARER_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.global.prometheus.queryServiceBearerTokenSecretName }} + key: TOKEN + {{- end }} + {{- if .Values.global.thanos.queryServiceBearerTokenSecretName }} + - name: MC_BEARER_TOKEN + valueFrom: + secretKeyRef: + name: {{ .Values.global.thanos.queryServiceBearerTokenSecretName }} + key: TOKEN + {{- end }} + - name: KUBECOST_NAMESPACE + value: {{ .Release.Namespace }} + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /var/configs/key.json + - name: KUBECOST_TOKEN + valueFrom: + configMapKeyRef: + name: {{ template "cost-analyzer.fullname" . }} + key: kubecost-token + {{- if eq .Values.global.grafana.proxy false }} + - name: GRAFANA_URL + valueFrom: + configMapKeyRef: + name: external-grafana-config-map + key: grafanaURL + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + {{- if .Values.priority }} + {{- if .Values.priority.enabled }} + priorityClassName: {{ template "cost-analyzer.fullname" . }}-priority + {{- end }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-frontend-config-map-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-frontend-config-map-template.yaml new file mode 100644 index 000000000..a4b6d9fd6 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-frontend-config-map-template.yaml @@ -0,0 +1,195 @@ +{{- $serviceName := include "cost-analyzer.serviceName" . -}} +{{- $nginxPort := .Values.service.targetPort | default 9090 -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-conf + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + nginx.conf: | + gzip_static on; + + # Enable gzip encoding for content of the provided types of 50kb and higher. + gzip on; + gzip_min_length 50000; + gzip_proxied expired no-cache no-store private auth; + gzip_types + application/atom+xml + application/geo+json + application/javascript + application/x-javascript + application/json + application/ld+json + application/manifest+json + application/rdf+xml + application/rss+xml + application/vnd.ms-fontobject + application/wasm + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/eot + font/otf + font/ttf + image/bmp + image/svg+xml + text/cache-manifest + text/calendar + text/css + text/javascript + text/markdown + text/plain + text/xml + text/x-component + text/x-cross-domain-policy; + + upstream api { + server {{ $serviceName }}.{{ .Release.Namespace }}:9001; + } + + upstream model { + server {{ $serviceName }}.{{ .Release.Namespace }}:9003; + } + +{{- if .Values.clusterController }} +{{- if .Values.clusterController.enabled }} + upstream clustercontroller { + server {{ template "kubecost.clusterControllerName" . }}-service.{{ .Release.Namespace }}:9731; + } +{{- end }} +{{- end }} + +{{- if .Values.global.grafana.proxy }} + upstream grafana { +{{- if .Values.global.grafana.enabled }} + server {{ .Release.Name }}-grafana.{{ .Release.Namespace }}; +{{ else }} + server {{.Values.global.grafana.domainName}}; +{{ end }} + } +{{ end }} + + server { + server_name _; + root /var/www; + index index.html; + add_header Cache-Control "max-age=300"; + add_header Cache-Control "must-revalidate"; +{{- if .Values.imageVersion }} + add_header ETag "{{ $.Values.imageVersion }}"; +{{- else }} + add_header ETag "{{ $.Chart.Version }}"; +{{- end }} +{{- if .Values.kubecostFrontend.tls }} +{{- if .Values.kubecostFrontend.tls.enabled }} + ssl_certificate /etc/ssl/certs/kc.crt; + ssl_certificate_key /etc/ssl/certs/kc.key; + listen 443 ssl; +{{- else }} + listen {{ $nginxPort }}; +{{- end }} +{{- else }} + listen {{ $nginxPort }}; +{{- end }} + location /api/ { + {{- if .Values.saml.enabled }} + auth_request /auth; + {{- end }} + proxy_pass http://api/; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location /model/ { + proxy_connect_timeout 180; + proxy_send_timeout 180; + proxy_read_timeout 180; + proxy_pass http://model/; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location ~ ^/(turndown|cluster)/ { + + add_header 'Access-Control-Allow-Origin' '*' always; +{{- if .Values.clusterController }} +{{- if .Values.clusterController.enabled }} + {{- if .Values.saml }} + {{- if .Values.saml.enabled }} + auth_request /auth; + {{- else if .Values.saml.rbac.enabled}} + auth_request /authrbac; + {{- end }} + {{- end }} + + rewrite ^/(?:turndown|cluster)/(.*)$ /$1 break; + proxy_pass http://clustercontroller; + proxy_connect_timeout 180; + proxy_send_timeout 180; + proxy_read_timeout 180; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + +{{- else }} + return 404; +{{- end }} +{{- else }} + return 404; +{{- end }} + } + location /saml/ { + proxy_connect_timeout 180; + proxy_send_timeout 180; + proxy_read_timeout 180; + proxy_pass http://model/saml/; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location /login { + proxy_connect_timeout 180; + proxy_send_timeout 180; + proxy_read_timeout 180; + proxy_pass http://model/login; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + {{- if .Values.global.grafana.proxy }} + location /grafana/ { + {{- if .Values.saml.enabled }} + auth_request /auth; + {{- end }} + proxy_pass http://grafana/; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + {{ end }} + {{- if .Values.saml.enabled }} + location /auth { + proxy_pass http://model/isAuthenticated; + } + {{- end }} + {{- if .Values.saml.rbac.enabled }} + location /authrbac { + proxy_pass http://model/isAdminAuthenticated; + } + {{- end }} + } diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-ingress-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-ingress-template.yaml new file mode 100644 index 000000000..8754d8548 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-ingress-template.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ingress -}} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "cost-analyzer.fullname" . -}} +{{- $serviceName := include "cost-analyzer.serviceName" . -}} +{{- $ingressPaths := .Values.ingress.paths -}} +apiVersion: {{ include "cost-analyzer.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . | quote }} + http: + paths: + {{- range $ingressPaths }} + - path: {{ . }} + backend: + serviceName: {{ $serviceName }} + servicePort: tcp-frontend + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-config-map-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-config-map-template.yaml new file mode 100644 index 000000000..37276f297 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-config-map-template.yaml @@ -0,0 +1,15 @@ +{{- if .Values.networkCosts -}} +{{- if .Values.networkCosts.enabled -}} +{{- if .Values.networkCosts.config -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: network-costs-config + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + config.yaml: | +{{- toYaml .Values.networkCosts.config | nindent 4 }} +{{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-podmonitor-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-podmonitor-template.yaml new file mode 100644 index 000000000..d45567616 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-podmonitor-template.yaml @@ -0,0 +1,31 @@ +{{- if .Values.networkCosts }} +{{- if .Values.networkCosts.enabled }} +{{- if .Values.networkCosts.podMonitor }} +{{- if .Values.networkCosts.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ include "cost-analyzer.networkCostsName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if .Values.networkCosts.podMonitor.additionalLabels }} + {{ toYaml .Values.networkCosts.podMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - port: http-server + honorLabels: true + interval: 1m + scrapeTimeout: 10s + path: /metrics + scheme: http + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app: {{ template "cost-analyzer.networkCostsName" . }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-service-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-service-template.yaml new file mode 100644 index 000000000..2ce22c0b2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-service-template.yaml @@ -0,0 +1,26 @@ +{{- if .Values.networkCosts }} +{{- if .Values.networkCosts.enabled }} +{{- if .Values.networkCosts.prometheusScrape }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "cost-analyzer.networkCostsName" . }} + annotations: + prometheus.io/scrape: "{{ .Values.networkCosts.prometheusScrape }}" + prometheus.io/port: {{ (quote .Values.networkCosts.port) | default (quote 3001) }} + labels: + app: {{ template "cost-analyzer.networkCostsName" . -}} + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + clusterIP: None + ports: + - name: metrics + port: {{ .Values.networkCosts.port | default 3001 }} + protocol: TCP + targetPort: {{ .Values.networkCosts.port | default 3001 }} + selector: + app: {{ template "cost-analyzer.networkCostsName" . }} + type: ClusterIP +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-template.yaml new file mode 100644 index 000000000..3db9fb67f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-costs-template.yaml @@ -0,0 +1,114 @@ +{{- if .Values.networkCosts -}} +{{- if .Values.networkCosts.enabled -}} +apiVersion: {{ include "cost-analyzer.daemonset.apiVersion" . }} +kind: DaemonSet +metadata: + name: {{ template "cost-analyzer.networkCostsName" . }} + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + app: {{ template "cost-analyzer.networkCostsName" . }} + template: + metadata: + {{- with .Values.networkCosts.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app: {{ template "cost-analyzer.networkCostsName" . }} + {{- if .Values.networkCosts.additionalLabels }} + {{ toYaml .Values.networkCosts.additionalLabels | nindent 8 }} + {{- end }} + spec: + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 2 }} + {{- end }} + hostNetwork: true + serviceAccountName: {{ template "cost-analyzer.serviceAccountName" . }} + containers: + - name: {{ template "cost-analyzer.networkCostsName" . }} + image: {{ .Values.networkCosts.image }} +{{- if .Values.networkCosts.imagePullPolicy }} + imagePullPolicy: {{ .Values.networkCosts.imagePullPolicy }} +{{- else }} + imagePullPolicy: Always +{{- end }} +{{- if .Values.networkCosts.resources }} + resources: +{{ toYaml .Values.networkCosts.resources | indent 10 }} +{{- end }} + env: + {{- if .Values.networkCosts.hostProc }} + - name: HOST_PROC + value: {{ .Values.networkCosts.hostProc.mountPath }} + {{- end }} + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: HOST_PORT + value: {{ (quote .Values.networkCosts.port) | default (quote 3001) }} + - name: TRAFFIC_LOGGING_ENABLED + value: {{ (quote .Values.networkCosts.trafficLogging) | default (quote true) }} + - name: GODEBUG + value: "madvdontneed=1" + volumeMounts: + {{- if .Values.networkCosts.hostProc }} + - mountPath: {{ .Values.networkCosts.hostProc.mountPath }} + name: host-proc + {{- else }} + - mountPath: /net + name: nf-conntrack + - mountPath: /netfilter + name: netfilter + {{- end }} + {{- if .Values.networkCosts.config }} + - mountPath: /network-costs/config + name: network-costs-config + {{- end }} + securityContext: + privileged: true + ports: + - name: http-server + containerPort: {{ .Values.networkCosts.port | default 3001 }} + hostPort: {{ .Values.networkCosts.port | default 3001 }} +{{- if .Values.networkCosts.priorityClassName }} + priorityClassName: "{{ .Values.networkCosts.priorityClassName }}" +{{- end }} + {{- with .Values.networkCosts.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 10 }} + {{- end }} +{{- if .Values.networkCosts.tolerations }} + tolerations: +{{ toYaml .Values.networkCosts.tolerations | indent 8 }} + {{- end }} + {{- with .Values.networkCosts.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.networkCosts.config }} + - name: network-costs-config + configMap: + name: network-costs-config + {{- end }} + {{- if .Values.networkCosts.hostProc }} + - name: host-proc + hostPath: + path: {{ default "/proc" .Values.networkCosts.hostProc.hostPath }} + {{- else }} + - name: nf-conntrack + hostPath: + path: /proc/net + - name: netfilter + hostPath: + path: /proc/sys/net/netfilter + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-policy.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-policy.yaml new file mode 100644 index 000000000..c806c3d51 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-network-policy.yaml @@ -0,0 +1,50 @@ +{{- if .Values.networkPolicy -}} +{{- if .Values.networkPolicy.enabled -}} +apiVersion: {{ include "cost-analyzer.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +{{- if .Values.networkPolicy.denyEgress }} +metadata: + name: deny-egress + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "cost-analyzer.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - to: + - namespaceSelector: {} +{{- else }} +{{- if .Values.networkPolicy.sameNamespace}} +metadata: + name: shared-namespace + namespace: {{ default "kubecost" .Values.networkPolicy.namespace}} +spec: + podSelector: + matchLabels: + app: prometheus + component: server +{{- else }} +metadata: + name: closed-traffic + namespace: {{ default "kubecost" .Values.networkPolicy.namespace}} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: cost-analyzer +{{- end }} + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: cost-analyzer + - namespaceSelector: + matchLabels: + name: k8s-kubecost +{{- end }} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pkey-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pkey-configmap.yaml new file mode 100644 index 000000000..5ce22f52b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pkey-configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if .Values.kubecostProductConfigs.productKey }} +{{- if .Values.kubecostProductConfigs.productKey.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: product-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + {{- if .Values.kubecostProductConfigs.productKey.key }} + key: {{ .Values.kubecostProductConfigs.productKey.key | quote }} + {{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pricing-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pricing-configmap.yaml new file mode 100644 index 000000000..c186ec020 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pricing-configmap.yaml @@ -0,0 +1,128 @@ +{{- if .Values.kubecostProductConfigs }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: pricing-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + {{- if .Values.kubecostProductConfigs.defaultModelPricing }} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.enabled }} + {{- if .Values.kubecostProductConfigs.customPricesEnabled }} + customPricesEnabled: "{{ .Values.kubecostProductConfigs.customPricesEnabled }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.CPU }} + CPU: "{{ .Values.kubecostProductConfigs.defaultModelPricing.CPU | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.spotCPU }} + spotCPU: "{{ .Values.kubecostProductConfigs.defaultModelPricing.spotCPU | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.RAM }} + RAM: "{{ .Values.kubecostProductConfigs.defaultModelPricing.RAM | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.spotRAM }} + spotRAM: "{{ .Values.kubecostProductConfigs.defaultModelPricing.spotRAM | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.GPU }} + GPU: "{{ .Values.kubecostProductConfigs.defaultModelPricing.GPU | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.spotGPU }} + spotGPU: "{{ .Values.kubecostProductConfigs.defaultModelPricing.spotGPU | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.storage }} + storage: "{{ .Values.kubecostProductConfigs.defaultModelPricing.storage | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.zoneNetworkEgress }} + zoneNetworkEgress: "{{ .Values.kubecostProductConfigs.defaultModelPricing.zoneNetworkEgress | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.regionNetworkEgress }} + regionNetworkEgress: "{{ .Values.kubecostProductConfigs.defaultModelPricing.regionNetworkEgress | toString }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultModelPricing.internetNetworkEgress }} + internetNetworkEgress: "{{ .Values.kubecostProductConfigs.defaultModelPricing.internetNetworkEgress | toString }}" + {{- end -}} + {{- end -}} + {{- end -}} + {{- if .Values.kubecostProductConfigs.clusterName }} + clusterName: "{{ .Values.kubecostProductConfigs.clusterName }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.currencyCode }} + currencyCode: "{{ .Values.kubecostProductConfigs.currencyCode }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.azureBillingRegion }} + azureBillingRegion: "{{ .Values.kubecostProductConfigs.azureBillingRegion }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.azureSubscriptionID }} + azureSubscriptionID: "{{ .Values.kubecostProductConfigs.azureSubscriptionID }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.azureClientID }} + azureClientID: "{{ .Values.kubecostProductConfigs.azureClientID }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.azureTenantID }} + azureTenantID: "{{ .Values.kubecostProductConfigs.azureTenantID }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.discount }} + discount: "{{ .Values.kubecostProductConfigs.discount }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.negotiatedDiscount }} + negotiatedDiscount: "{{ .Values.kubecostProductConfigs.negotiatedDiscount }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.defaultIdle }} + defaultIdle: "{{ .Values.kubecostProductConfigs.defaultIdle }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.sharedNamespaces }} + sharedNamespaces: "{{ .Values.kubecostProductConfigs.sharedNamespaces }}" + {{- end -}} + {{- if gt (len (toString .Values.kubecostProductConfigs.shareTenancyCosts)) 0 }} + {{- if eq (toString .Values.kubecostProductConfigs.shareTenancyCosts) "false" }} + shareTenancyCosts: "false" + {{- else if eq (toString .Values.kubecostProductConfigs.shareTenancyCosts) "true" }} + shareTenancyCosts: "true" + {{- end -}} + {{- end -}} + {{- if .Values.kubecostProductConfigs.spotLabel }} + spotLabel: "{{ .Values.kubecostProductConfigs.spotLabel }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.spotLabelValue }} + spotLabelValue: "{{ .Values.kubecostProductConfigs.spotLabelValue }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.awsSpotDataRegion }} + spotDataRegion: "{{ .Values.kubecostProductConfigs.awsSpotDataRegion }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.awsSpotDataBucket }} + spotDataBucket: "{{ .Values.kubecostProductConfigs.awsSpotDataBucket }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.awsSpotDataPrefix }} + spotDataPrefix: "{{ .Values.kubecostProductConfigs.awsSpotDataPrefix }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.projectID }} + projectID: "{{ .Values.kubecostProductConfigs.projectID }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.bigQueryBillingDataDataset }} + billingDataDataset: "{{ .Values.kubecostProductConfigs.bigQueryBillingDataDataset }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.athenaProjectID }} + athenaProjectID: "{{ .Values.kubecostProductConfigs.athenaProjectID }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.athenaBucketName }} + athenaBucketName: "{{ .Values.kubecostProductConfigs.athenaBucketName }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.athenaRegion }} + athenaRegion: "{{ .Values.kubecostProductConfigs.athenaRegion }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.athenaDatabase }} + athenaDatabase: "{{ .Values.kubecostProductConfigs.athenaDatabase }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.athenaTable }} + athenaTable: "{{ .Values.kubecostProductConfigs.athenaTable }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.masterPayerARN}} + masterPayerARN: "{{ .Values.kubecostProductConfigs.masterPayerARN }}" + {{- end }} + {{- if .Values.kubecostProductConfigs.gpuLabel }} + gpuLabel: "{{ .Values.kubecostProductConfigs.gpuLabel }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.gpuLabelValue }} + gpuLabelValue: "{{ .Values.kubecostProductConfigs.gpuLabelValue }}" + {{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-deployment.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-deployment.yaml new file mode 100644 index 000000000..2d6cfc387 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-deployment.yaml @@ -0,0 +1,57 @@ +{{- if .Values.remoteWrite -}} +{{- if .Values.remoteWrite.postgres -}} +{{- if .Values.remoteWrite.postgres.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "cost-analyzer.fullname" . }}-adapter + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: adapter + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app: adapter + spec: + initContainers: + - name: kubecost-sql-init + image: {{ .Values.remoteWrite.postgres.initImage }}:prod-{{ $.Chart.AppVersion }} + {{- if .Values.remoteWrite.postgres.initImagePullPolicy }} + imagePullPolicy: {{ .Values.remoteWrite.postgres.initImagePullPolicy }} + {{- else }} + imagePullPolicy: Always + {{- end }} + env: + - name: PROMETHEUS_SERVER_ENDPOINT + valueFrom: + configMapKeyRef: + name: {{ template "cost-analyzer.fullname" . }} + key: prometheus-server-endpoint + containers: + - image: timescale/prometheus-postgresql-adapter:latest + name: pgprometheusadapter + ports: + - containerPort: 9201 + args: + {{- if .Values.remoteWrite.postgres.installLocal }} + - "-pg-host=pgprometheus" + {{- else }} + - "-pg-host={{ .Values.remoteWrite.postgres.remotePostgresAddress }}" + {{- end }} + - "-pg-prometheus-log-samples=true" + - "-pg-password={{ .Values.remoteWrite.postgres.auth.password }}" + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 10 }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-service.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-service.yaml new file mode 100644 index 000000000..d36479439 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheus-postgres-adapter-service.yaml @@ -0,0 +1,20 @@ +{{- if .Values.remoteWrite -}} +{{- if .Values.remoteWrite.postgres -}} +{{- if .Values.remoteWrite.postgres.enabled -}} +kind: Service +apiVersion: v1 +metadata: + name: pgprometheus-adapter + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + selector: + app: adapter + type: ClusterIP + ports: + - name: server + port: 9201 + targetPort: 9201 +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheusrule-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheusrule-template.yaml new file mode 100644 index 000000000..61380b424 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-prometheusrule-template.yaml @@ -0,0 +1,21 @@ +{{- if .Values.prometheus }} +{{- if .Values.prometheus.serverFiles }} +{{- if .Values.prometheus.serverFiles.rules }} +{{- if .Values.prometheusRule }} +{{- if .Values.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "cost-analyzer.fullname" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if .Values.prometheusRule.additionalLabels }} + {{ toYaml .Values.prometheusRule.additionalLabels | nindent 4 }} + {{- end }} +spec: + {{ toYaml .Values.prometheus.serverFiles.rules | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-role.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-role.template.yaml new file mode 100644 index 000000000..95ca43ee8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-role.template.yaml @@ -0,0 +1,18 @@ +{{- if .Values.podSecurityPolicy }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "cost-analyzer.fullname" . }}-psp + annotations: +{{- if .Values.podSecurityPolicy.annotations }} +{{ toYaml .Values.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "cost-analyzer.fullname" . }}-psp +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-rolebinding.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-rolebinding.template.yaml new file mode 100644 index 000000000..1739f91b6 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp-rolebinding.template.yaml @@ -0,0 +1,16 @@ +{{- if .Values.podSecurityPolicy }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "cost-analyzer.fullname" . }}-psp +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cost-analyzer.fullname" . }}-psp +subjects: +- kind: ServiceAccount + name: {{ template "cost-analyzer.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp.template.yaml new file mode 100644 index 000000000..68887771f --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-psp.template.yaml @@ -0,0 +1,20 @@ +{{- if .Values.podSecurityPolicy }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ include "cost-analyzer.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "cost-analyzer.fullname" . }}-psp +spec: + privileged: false + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + fsGroup: + rule: RunAsAny + volumes: + - '*' +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pvc-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pvc-template.yaml new file mode 100644 index 000000000..d3e257668 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-pvc-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.persistentVolume -}} +{{- if not .Values.persistentVolume.existingClaim -}} +{{- if .Values.persistentVolume.enabled -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "cost-analyzer.fullname" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.persistentVolume.storageClass }} + storageClassName: {{ .Values.persistentVolume.storageClass }} + {{ end }} + resources: + requests: + {{- if .Values.persistentVolume }} + storage: {{ .Values.persistentVolume.size }} + {{- else }} + storage: 0.2Gi + {{ end }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saml-config-map-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saml-config-map-template.yaml new file mode 100644 index 000000000..71ac8659c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saml-config-map-template.yaml @@ -0,0 +1,13 @@ +{{- if .Values.saml }} +{{- if .Values.saml.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "cost-analyzer.fullname" . }}-saml + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: +{{- $root := . }} + saml.json: '{{ toJson .Values.saml }}' +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saved-reports-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saved-reports-configmap.yaml new file mode 100644 index 000000000..64425dd92 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-saved-reports-configmap.yaml @@ -0,0 +1,12 @@ +{{- if .Values.global.savedReports }} +{{- if .Values.global.savedReports.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: saved-report-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + saved-reports.json: '{{ toJson .Values.global.savedReports.reports }}' +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-server-configmap.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-server-configmap.yaml new file mode 100644 index 000000000..edf5ca6fa --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-server-configmap.yaml @@ -0,0 +1,69 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if or .Values.kubecostProductConfigs.grafanaURL .Values.kubecostProductConfigs.labelMappingConfigs }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-configs + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: +{{- if .Values.kubecostProductConfigs.labelMappingConfigs }} +{{- if .Values.kubecostProductConfigs.labelMappingConfigs.enabled }} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.owner_label }} + owner_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.owner_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.team_label }} + team_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.team_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.department_label }} + department_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.department_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.product_label }} + product_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.product_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.environment_label }} + environment_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.environment_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.namespace_external_label }} + namespace_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.namespace_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.cluster_external_label }} + cluster_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.cluster_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.controller_external_label }} + controller_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.controller_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.product_external_label }} + product_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.product_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.service_external_label }} + service_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.service_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.deployment_external_label }} + deployment_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.deployment_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.team_external_label }} + team_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.team_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.environment_external_label }} + environment_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.environment_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.department_external_label }} + department_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.department_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.statefulset_external_label }} + statefulset_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.statefulset_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.daemonset_external_label }} + daemonset_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.daemonset_external_label }}" + {{- end -}} + {{- if .Values.kubecostProductConfigs.labelMappingConfigs.pod_external_label }} + pod_external_label: "{{ .Values.kubecostProductConfigs.labelMappingConfigs.pod_external_label }}" + {{- end -}} +{{- end -}} +{{- end -}} + {{- if .Values.kubecostProductConfigs.grafanaURL }} + grafanaURL: "{{ .Values.kubecostProductConfigs.grafanaURL }}" + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-account-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-account-template.yaml new file mode 100644 index 000000000..d5e3be3b9 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-account-template.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "cost-analyzer.serviceAccountName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +{{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-template.yaml new file mode 100644 index 000000000..ed8c8a4bd --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-service-template.yaml @@ -0,0 +1,69 @@ +{{- $nginxPort := .Values.service.targetPort | default 9090 -}} +{{- $servicePort := .Values.service.port | default 9090 -}} +kind: Service +apiVersion: v1 +metadata: + name: {{ template "cost-analyzer.serviceName" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} +spec: + selector: + {{ include "cost-analyzer.selectorLabels" . | nindent 4 }} +{{- if .Values.service -}} +{{- if .Values.service.type }} + type: "{{ .Values.service.type }}" +{{- else }} + type: ClusterIP +{{- end }} +{{- else }} + type: ClusterIP +{{- end }} + ports: + - name: tcp-server + port: 9001 + targetPort: 9001 + - name: tcp-model + port: 9003 + targetPort: 9003 + - name: tcp-frontend + {{- if .Values.kubecostFrontend.tls }} + {{- if .Values.kubecostFrontend.tls.enabled }} + port: 443 + targetPort: 443 + {{- if (eq .Values.service.type "NodePort") }} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- end }} + {{- else }} + port: {{ $servicePort }} + targetPort: {{ $nginxPort }} + {{- if (eq .Values.service.type "NodePort") }} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- end }} + {{- end}} + {{- else }} + port: {{ $servicePort }} + targetPort: {{ $nginxPort }} + {{- if (eq .Values.service.type "NodePort") }} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.saml }} + {{- if .Values.saml.enabled }} + - name: apiserver + port: 9004 + targetPort: 9004 + {{- end }} + {{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-servicemonitor-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-servicemonitor-template.yaml new file mode 100644 index 000000000..648c6b272 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/cost-analyzer-servicemonitor-template.yaml @@ -0,0 +1,27 @@ +{{- if .Values.serviceMonitor }} +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "cost-analyzer.fullname" . }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if .Values.serviceMonitor.additionalLabels }} + {{ toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: tcp-model + honorLabels: true + interval: 1m + scrapeTimeout: 10s + path: /metrics + scheme: http + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{ include "cost-analyzer.selectorLabels" . | nindent 6 }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/external-grafana-config-map-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/external-grafana-config-map-template.yaml new file mode 100644 index 000000000..5e81ed359 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/external-grafana-config-map-template.yaml @@ -0,0 +1,10 @@ +{{- if eq .Values.global.grafana.proxy false -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: external-grafana-config-map + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + grafanaURL: {{ .Values.global.grafana.scheme | default "http" }}://{{- .Values.global.grafana.domainName }} +{{- end -}} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-attached-disk-metrics-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-attached-disk-metrics-template.yaml new file mode 100644 index 000000000..6d896a34c --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-attached-disk-metrics-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: attached-disk-metrics-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + attached-disks.json: |- +{{ .Files.Get "attached-disks.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-metrics-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-metrics-template.yaml new file mode 100644 index 000000000..91650c74b --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-metrics-template.yaml @@ -0,0 +1,27 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-metrics-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + cluster-metrics.json: |- +{{ .Files.Get "cluster-metrics.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + + diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-utilization-template.yaml new file mode 100644 index 000000000..8fe764c3e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-cluster-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-utilization-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + cluster-utilization.json: |- +{{ .Files.Get "cluster-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-deployment-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-deployment-utilization-template.yaml new file mode 100644 index 000000000..d16c70bcd --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-deployment-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: deployment-utilization-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + deployment-utilization.json: |- +{{ .Files.Get "deployment-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-label-cost-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-label-cost-utilization-template.yaml new file mode 100644 index 000000000..2372514d4 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-label-cost-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: label-cost-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + label-cost-utilization.json: |- +{{ .Files.Get "label-cost-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-namespace-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-namespace-utilization-template.yaml new file mode 100644 index 000000000..17393dd16 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-namespace-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: namespace-utilization-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + namespace-utilization.json: |- +{{ .Files.Get "namespace-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-node-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-node-utilization-template.yaml new file mode 100644 index 000000000..586a3dfca --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-node-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: node-utilization-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + node-utilization.json: |- +{{ .Files.Get "node-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-pod-utilization-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-pod-utilization-template.yaml new file mode 100644 index 000000000..92017afb8 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-pod-utilization-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: pod-utilization-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + pod-utilization.json: |- +{{ .Files.Get "pod-utilization.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-prometheus-metrics-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-prometheus-metrics-template.yaml new file mode 100644 index 000000000..9b02ea9b1 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-dashboard-prometheus-metrics-template.yaml @@ -0,0 +1,25 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.dashboards -}} +{{- if .Values.grafana.sidecar.dashboards.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: prom-benchmark-dashboard + {{- if $.Values.grafana.namespace_dashboards }} + namespace: {{ $.Values.grafana.namespace_dashboards }} + {{- end }} + labels: + {{ include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.dashboards.label }} + {{ $.Values.grafana.sidecar.dashboards.label }}: "1" + {{- else }} + grafana_dashboard: "1" + {{- end }} +data: + prom-benchmark.json: |- +{{ .Files.Get "prom-benchmark.json" | indent 8 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-datasource-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-datasource-template.yaml new file mode 100644 index 000000000..d92a95023 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/grafana-datasource-template.yaml @@ -0,0 +1,56 @@ +{{- if .Values.grafana -}} +{{- if .Values.grafana.sidecar -}} +{{- if .Values.grafana.sidecar.datasources -}} +{{- if .Values.grafana.sidecar.datasources.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-datasource + {{- if $.Values.grafana.namespace_datasources }} + namespace: {{ $.Values.grafana.namespace_datasources }} + {{- end }} + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} + {{- if $.Values.grafana.sidecar.datasources.label }} + {{ $.Values.grafana.sidecar.datasources.label }}: "1" + {{- else }} + {{- if .Values.global.grafana.enabled }} + kubecost_grafana_datasource: "1" + {{- else }} + grafana_datasource: "1" + {{- end }} + {{- end }} +data: + {{ default "datasource.yaml" .Values.grafana.sidecar.datasources.dataSourceFilename }}: |- + apiVersion: 1 + datasources: + - access: proxy + name: default-kubecost + type: prometheus +{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }} + isDefault: true +{{- else }} + isDefault: false +{{- end }} +{{- if .Values.global.thanos }} +{{- if .Values.global.thanos.enabled }} +{{- if .Values.global.prometheus.enabled }} + url: http://{{ .Release.Name }}-thanos-query-http.{{ .Release.Namespace }}:{{ .Values.thanos.query.http.port }} +{{- else }} + url: {{ .Values.global.thanos.queryService }} +{{- end }} + - access: proxy + name: {{ default "Prometheus" .Values.grafana.sidecar.datasources.dataSourceName}} + isDefault: false + type: prometheus +{{- end }} +{{- if .Values.global.prometheus.enabled }} + url: http://{{ template "cost-analyzer.prometheus.server.name" . }}.{{ .Release.Namespace }} +{{- else }} + url: {{ .Values.global.prometheus.fqdn }} +{{- end }} +{{- end }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-controller-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-controller-template.yaml new file mode 100644 index 000000000..1a947e696 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-controller-template.yaml @@ -0,0 +1,282 @@ +{{- if .Values.clusterController }} +{{- if .Values.clusterController.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "kubecost.clusterControllerName" . }} + labels: + app: {{ template "kubecost.clusterControllerName" . }} +--- +# +# NOTE: +# The following ClusterRole permissions are only created and assigned for the +# cluster controller feature. They will not be added to any clusters by default. +# +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "kubecost.clusterControllerName" . }} + labels: + app: {{ template "kubecost.clusterControllerName" . }} +rules: + - apiGroups: + - kubecost.k8s.io + resources: + - turndownschedules + - turndownschedules/status + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - "" + - events.k8s.io + resources: + - events + verbs: + - create + - patch + - update + - apiGroups: + - '' + resources: + - deployments + - nodes + - pods + - resourcequotas + - replicationcontrollers + - limitranges + - pods/eviction + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - '' + resources: + - configmaps + - namespaces + - persistentvolumeclaims + - persistentvolumes + - endpoints + - events + - services + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - daemonsets + - deployments + - replicasets + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - apps + resources: + - statefulsets + - deployments + - daemonsets + - replicasets + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - get + - list + - watch + - create + - patch + - update + - delete + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - get + - list + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "kubecost.clusterControllerName" . }} + labels: + app: {{ template "kubecost.clusterControllerName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "kubecost.clusterControllerName" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kubecost.clusterControllerName" . }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "kubecost.clusterControllerName" . }} +spec: + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + app: {{ template "kubecost.clusterControllerName" . }} + template: + metadata: + labels: + app: {{ template "kubecost.clusterControllerName" . }} + spec: + containers: + - name: {{ template "kubecost.clusterControllerName" . }} + image: {{ .Values.clusterController.image }} + imagePullPolicy: {{ .Values.clusterController.imagePullPolicy }} + volumeMounts: + - name: cluster-controller-keys + mountPath: /var/keys + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: TURNDOWN_NAMESPACE + value: {{ .Release.Namespace }} + - name: TURNDOWN_DEPLOYMENT + value: {{ template "kubecost.clusterControllerName" . }} + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /var/keys/service-key.json + ports: + - name: http-server + containerPort: 9731 + hostPort: 9731 + serviceAccount: {{ template "kubecost.clusterControllerName" . }} + serviceAccountName: {{ template "kubecost.clusterControllerName" . }} + volumes: + - name: cluster-controller-keys + secret: + secretName: {{ .Values.clusterController.secretName | default "cluster-controller-service-key" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kubecost.clusterControllerName" . }}-service +spec: + type: ClusterIP + ports: + - name: http + protocol: TCP + port: 9731 + targetPort: 9731 + selector: + app: {{ template "kubecost.clusterControllerName" . }} +--- +# TurndownSchedule Custom Resource Definition for persistence +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: turndownschedules.kubecost.k8s.io +spec: + group: kubecost.k8s.io + version: v1alpha1 + names: + kind: TurndownSchedule + singular: turndownschedule + plural: turndownschedules + shortNames: + - td + - tds + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + type: object + properties: + start: + type: string + format: date-time + end: + type: string + format: date-time + repeat: + type: string + enum: [none, daily, weekly] + additionalPrinterColumns: + - name: State + type: string + description: The state of the turndownschedule + JSONPath: .status.state + - name: Next Turndown + type: string + description: The next turndown date-time + JSONPath: .status.nextScaleDownTime + - name: Next Turn Up + type: string + description: The next turn up date-time + JSONPath: .status.nextScaleUpTime +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-manager-configmap-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-manager-configmap-template.yaml new file mode 100644 index 000000000..907252f93 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-cluster-manager-configmap-template.yaml @@ -0,0 +1,13 @@ +{{- if .Values.kubecostProductConfigs }} +{{- if .Values.kubecostProductConfigs.clusters }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubecost-clusters + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + default-clusters.yaml: | +{{- toYaml .Values.kubecostProductConfigs.clusters | nindent 4 }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-priority-class-template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-priority-class-template.yaml new file mode 100644 index 000000000..a098a766e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/kubecost-priority-class-template.yaml @@ -0,0 +1,11 @@ +{{- if .Values.priority }} +{{- if .Values.priority.enabled }} +apiVersion: {{ include "cost-analyzer.priorityClass.apiVersion" . }} +kind: PriorityClass +metadata: + name: {{ template "cost-analyzer.fullname" . }}-priority +value: {{ .Values.priority.value | default "1000000" }} +globalDefault: false +description: "Priority class for scheduling the cost-analyzer pod" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-psp.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-psp.template.yaml new file mode 100644 index 000000000..e983c2702 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-psp.template.yaml @@ -0,0 +1,36 @@ +{{- if .Values.networkCosts }} +{{- if .Values.networkCosts.enabled }} +{{- if .Values.networkCosts.podSecurityPolicy }} +{{- if .Values.networkCosts.podSecurityPolicy.enabled }} +apiVersion: {{ include "cost-analyzer.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: kubecost-network-costs +spec: + privileged: true + hostNetwork: true + allowedHostPaths: + {{- if .Values.networkCosts.hostProc }} + - pathPrefix: {{ default "/proc" .Values.networkCosts.hostProc.hostPath }} + readOnly: false + {{- else }} + - pathPrefix: /proc + readOnly: false + {{- end }} + hostPorts: + - min: 1 + max: 65535 + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + fsGroup: + rule: RunAsAny + volumes: + - '*' +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-role.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-role.template.yaml new file mode 100644 index 000000000..04424a44e --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-role.template.yaml @@ -0,0 +1,22 @@ +{{- if .Values.networkCosts }} +{{- if .Values.networkCosts.enabled }} +{{- if .Values.networkCosts.podSecurityPolicy }} +{{- if .Values.networkCosts.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kubecost-network-costs + annotations: +{{- if .Values.networkCosts.podSecurityPolicy.annotations }} +{{ toYaml .Values.networkCosts.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - kubecost-network-costs +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-rolebinding.template.yaml b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-rolebinding.template.yaml new file mode 100644 index 000000000..84ab0d1c2 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/templates/network-costs-rolebinding.template.yaml @@ -0,0 +1,20 @@ +{{- if .Values.networkCosts }} +{{- if .Values.networkCosts.enabled }} +{{- if .Values.networkCosts.podSecurityPolicy }} +{{- if .Values.networkCosts.podSecurityPolicy.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kubecost-network-costs +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubecost-network-costs +subjects: +- kind: ServiceAccount + name: {{ template "cost-analyzer.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/kubecost/cost-analyzer/1.83.201/values-thanos.yaml b/charts/kubecost/cost-analyzer/1.83.201/values-thanos.yaml new file mode 100644 index 000000000..8d5a75844 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/values-thanos.yaml @@ -0,0 +1,134 @@ +global: + thanos: + enabled: true + +# For Thanos Installs, Allow Higher Concurrency from Cost-Model +# Still may require tweaking for some installs, but the thanos-query-frontend +# will greatly assist in reduction memory bloat in query. +kubecostModel: + maxQueryConcurrency: 5 + # This configuration is applied to thanos only. Expresses the resolution to + # use for longer query ranges. Options: raw, 5m, 1h - Default: raw + maxSourceResolution: 5m + +prometheus: + server: + extraArgs: + storage.tsdb.min-block-duration: 2h + storage.tsdb.max-block-duration: 2h + storage.tsdb.retention: 2w + securityContext: + runAsNonRoot: true + runAsUser: 1001 + extraVolumes: + - name: object-store-volume + secret: + # Ensure this secret name matches thanos.storeSecretName + secretName: kubecost-thanos + enableAdminApi: true + sidecarContainers: + - name: thanos-sidecar + image: thanosio/thanos:v0.19.0 + securityContext: + runAsNonRoot: true + runAsUser: 1001 + args: + - sidecar + - --log.level=debug + - --tsdb.path=/data/ + - --prometheus.url=http://127.0.0.1:9090 + - --objstore.config-file=/etc/config/object-store.yaml + # Start of time range limit to serve. Thanos sidecar will serve only metrics, which happened + # later than this value. Option can be a constant time in RFC3339 format or time duration + # relative to current time, such as -1d or 2h45m. Valid duration units are ms, s, m, h, d, w, y. + - --min-time=-3h + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + ports: + - name: sidecar-http + containerPort: 10902 + - name: grpc + containerPort: 10901 + - name: cluster + containerPort: 10900 + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus + - name: storage-volume + mountPath: /data + subPath: "" + - name: object-store-volume + mountPath: /etc/config + +thanos: + store: + enabled: true + grpcSeriesMaxConcurrency: 20 + blockSyncConcurrency: 20 + extraEnv: + - name: GOGC + value: "100" + - name: GODEBUG + value: "madvdontneed=1" + resources: + requests: + memory: "2.5Gi" + query: + enabled: true + timeout: 3m + # Maximum number of queries processed concurrently by query node. + maxConcurrent: 8 + # Maximum number of select requests made concurrently per a query. + maxConcurrentSelect: 2 + resources: + requests: + memory: "2.5Gi" + autoDownsampling: false + extraEnv: + - name: GOGC + value: "100" + - name: GODEBUG + value: "madvdontneed=1" + + # Thanos Query Frontend + queryFrontend: + enabled: true + compressResponses: true + # Response Cache Configuration + # Configure either a max size constraint or max items. + responseCache: + enabled: true + # Maximum memory size of the cache in bytes. A unit suffix (KB, MB, GB) may be applied. + maxSize: 1.25GB + # Maximum number of entries in the cache. + maxSizeItems: 0 + # The expiry duration for the cache. + validity: 2m + extraEnv: + - name: GOGC + value: "100" + - name: GODEBUG + value: "madvdontneed=1" + resources: + requests: + memory: "1.5Gi" + + # Thanos Sidecar Service Discovery + # Disabling removes the prometheus sidecar from querier store discovery. This ensures + # that all clusters read from the same data in remote store. + sidecar: + enabled: true + bucket: + enabled: false + compact: + enabled: true + dataVolume: + persistentVolumeClaim: + claimName: compact-data-volume + storage: 100Gi + # This secret name should match the sidecar configured secret name volume + # in the prometheus.server.extraVolumes entry + storeSecretName: kubecost-thanos diff --git a/charts/kubecost/cost-analyzer/1.83.201/values.yaml b/charts/kubecost/cost-analyzer/1.83.201/values.yaml new file mode 100644 index 000000000..af7438598 --- /dev/null +++ b/charts/kubecost/cost-analyzer/1.83.201/values.yaml @@ -0,0 +1,675 @@ +global: + # zone: cluster.local (use only if your DNS server doesn't live in the same zone as kubecost) + prometheus: + enabled: true # If false, Prometheus will not be installed -- only actively supported on paid Kubecost plans + fqdn: http://cost-analyzer-prometheus-server.default.svc #example fqdn. Ignored if enabled: true + # insecureSkipVerify : false # If true, kubecost will not check the TLS cert of prometheus + # queryServiceBasicAuthSecretName: dbsecret # kubectl create secret generic dbsecret -n kubecost --from-file=USERNAME --from-file=PASSWORD + # queryServiceBearerTokenSecretName: dbsecret # kubectl create secret generic mcdbsecret -n kubecost --from-file=TOKEN + + # Durable storage option, product key required + thanos: + enabled: false + # queryService: http://kubecost-thanos-query-frontend-http.kubecost:{{ .Values.thanos.queryFrontend.http.port }} # an address of the thanos query-frontend endpoint, if different from installed thanos + # queryServiceBasicAuthSecretName: mcdbsecret # kubectl create secret generic mcdbsecret -n kubecost --from-file=USERNAME --from-file=PASSWORD <---enter basic auth credentials like that + # queryServiceBearerTokenSecretName mcdbsecret # kubectl create secret generic mcdbsecret -n kubecost --from-file=TOKEN + # queryOffset: 3h # The offset to apply to all thanos queries in order to achieve syncronization on all cluster block stores + + grafana: + enabled: true # If false, Grafana will not be installed + domainName: cost-analyzer-grafana.default.svc #example grafana domain Ignored if enabled: true + scheme: "http" # http or https, for the domain name above. + proxy: true # If true, the kubecost frontend will route to your grafana through its service endpoint + + notifications: + # Kubecost alerting configuration + # Ref: http://docs.kubecost.com/alerts + # alertConfigs: + # frontendUrl: http://localhost:9090 # optional, used for linkbacks + # globalSlackWebhookUrl: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX # optional, used for Slack alerts + # globalAlertEmails: + # - recipient@example.com + # - additionalRecipient@example.com + # Alerts generated by kubecost, about cluster data + # alerts: + # Daily namespace budget alert on namespace `kubecost` + # - type: budget # supported: budget, recurringUpdate + # threshold: 50 # optional, required for budget alerts + # window: daily # or 1d + # aggregation: namespace + # filter: kubecost + # ownerContact: # optional, overrides globalAlertEmails default + # - owner@example.com + # - owner2@example.com + # # optional, used for alert-specific Slack alerts + # slackWebhookUrl: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX + + # Daily cluster budget alert on cluster `cluster-one` + # - type: budget + # threshold: 200.8 # optional, required for budget alerts + # window: daily # or 1d + # aggregation: cluster + # filter: cluster-one # does not accept csv + + # Recurring weekly update (weeklyUpdate alert) + # - type: recurringUpdate + # window: weekly # or 7d + # aggregation: namespace + # filter: '*' + + # Recurring weekly namespace update on kubecost namespace + # - type: recurringUpdate + # window: weekly # or 7d + # aggregation: namespace + # filter: kubecost + + # Spend Change Alert + # - type: spendChange # change relative to moving avg + # relativeThreshold: 0.20 # Proportional change relative to baseline. Must be greater than -1 (can be negative) + # window: 1d # accepts ‘d’, ‘h’ + # baselineWindow: 30d # previous window, offset by window + # aggregation: namespace + # filter: kubecost, default # accepts csv + + # Health Score Alert + # - type: health # Alerts when health score changes by a threshold + # window: 10m + # threshold: 5 # Send Alert if health scores changes by 5 or more + + # Kubecost Health Diagnostic + # - type: diagnostic # Alerts when kubecost is is unable to compute costs - ie: Prometheus unreachable + # window: 10m + + alertmanager: # Supply an alertmanager FQDN to receive notifications from the app. + enabled: false # If true, allow kubecost to write to your alertmanager + fqdn: http://cost-analyzer-prometheus-server.default.svc #example fqdn. Ignored if prometheus.enabled: true + + # Set saved report(s) accessible from reports.html + # Ref: http://docs.kubecost.com/saved-reports + savedReports: + enabled: false # If true, overwrites report parameters set through UI + reports: + - title: "Example Saved Report 0" + window: "today" + aggregateBy: "namespace" + idle: "separate" + accumulate: false # daily resolution + filters: + - property: "cluster" + value: "cluster-one,cluster*" # supports wildcard filtering and multiple comma separated values + - property: "namespace" + value: "kubecost" + - title: "Example Saved Report 1" + window: "month" + aggregateBy: "controllerKind" + idle: "share" + accumulate: false + filters: + - property: "label" + value: "app:cost*,environment:kube*" + - property: "namespace" + value: "kubecost" + - title: "Example Saved Report 2" + window: "2020-11-11T00:00:00Z,2020-12-09T23:59:59Z" + aggregateBy: "service" + idle: "hide" + accumulate: true # entire window resolution + filters: [] # if no filters, specify empty array + + # Set saved report(s) accessible from reports.html + # Ref: http://docs.kubecost.com/saved-reports + assetReports: + enabled: false # If true, overwrites report parameters set through UI + reports: + - title: "Example Asset Report 0" + window: "today" + aggregateBy: "type" + accumulate: false # daily resolution + filters: + - property: "cluster" + value: "cluster-one" + + podAnnotations: {} + # iam.amazonaws.com/role: role-arn + additionalLabels: {} + +# generated at http://kubecost.com/install, used for alerts tracking and free trials +kubecostToken: # "" + +# Advanced pipeline for custom prices, enterprise key required +pricingCsv: + enabled: false + location: + provider: "AWS" + region: "us-east-1" + URI: s3://kc-csv-test/pricing_schema.csv # a valid file URI + csvAccessCredentials: pricing-schema-access-secret + +# SAML integration for user management and RBAC, enterprise key required +# Ref: https://github.com/kubecost/docs/blob/master/user-management.md +saml: + enabled: false + secretName: "kubecost-authzero" + #metadataSecretName: "kubecost-authzero-metadata" # One of metadataSecretName or idpMetadataURL must be set. defaults to metadataURL if set + idpMetadataURL: "https://dev-elu2z98r.auth0.com/samlp/metadata/c6nY4M37rBP0qSO1IYIqBPPyIPxLS8v2" + appRootURL: "http://localhost:9090" # sample URL + # audienceURI: "http://localhost:9090" # by convention, the same as the appRootURL, but any string uniquely identifying kubecost to your samp IDP. Optional if you follow the convention + # nameIDFormat: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" If your SAML provider requires a specific nameid format + rbac: + enabled: false + groups: + - name: admin + enabled: false # if admin is disabled, all SAML users will be able to make configuration changes to the kubecost frontend + assertionName: "http://schemas.auth0.com/userType" # a SAML Assertion, one of whose elements has a value that matches on of the values in assertionValues + assertionValues: + - "admin" + - "superusers" + - name: readonly + enabled: false # if readonly is disabled, all users authorized on SAML will default to readonly + assertionName: "http://schemas.auth0.com/userType" + assertionvalues: + - "readonly" + +# Adds an httpProxy as an environment variable. systemProxy.enabled must be `true`to have any effect. +# Ref: https://www.oreilly.com/library/view/security-with-go/9781788627917/5ea6a02b-3d96-44b1-ad3c-6ab60fcbbe4f.xhtml +systemProxy: + enabled: false + httpProxyUrl: "" + httpsProxyUrl: "" + noProxy: "" + +# imagePullSecrets: +# - name: "image-pull-secret" + +kubecostFrontend: + image: "gcr.io/kubecost1/frontend" + imagePullPolicy: Always + resources: + requests: + cpu: "10m" + memory: "55Mi" + #limits: + # cpu: "100m" + # memory: "256Mi" + +kubecost: + image: "gcr.io/kubecost1/server" + resources: + requests: + cpu: "100m" + memory: "55Mi" + #limits: + # cpu: "100m" + # memory: "256Mi" + +kubecostModel: + image: "gcr.io/kubecost1/cost-model" + imagePullPolicy: Always + # Enables the emission of the kubecost_cloud_credit_total and + # kubecost_cloud_expense_total metrics + outOfClusterPromMetricsEnabled: false + # Build local cost allocation cache + warmCache: false + # Build local savings cache + warmSavingsCache: true + # Run allocation ETL pipelines + etl: true + # The total number of days the ETL pipelines will build + # Set to 0 to disable daily ETL (not recommended) + etlDailyStoreDurationDays: 91 + # The total number of hours the ETL pipelines will build + # Set to 0 to disable hourly ETL (not recommended) + etlHourlyStoreDurationHours: 49 + # max number of concurrent Prometheus queries + maxQueryConcurrency: 5 + # utcOffset represents a timezone in hours and minutes east (+) or west (-) + # of UTC, itself, which is defined as +00:00. + # See the tz database of timezones to look up your local UTC offset: + # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + utcOffset: "+00:00" + resources: + requests: + cpu: "200m" + memory: "55Mi" + #limits: + # cpu: "800m" + # memory: "256Mi" + +# Basic Kubecost ingress, more examples available at https://github.com/kubecost/docs/blob/master/ingress-examples.md +ingress: + enabled: false + annotations: + kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + paths: ["/"] # There's no need to route specifically to the pods-- we have an nginx deployed that handles routing + hosts: + - cost-analyzer.local + tls: [] + # - secretName: cost-analyzer-tls + # hosts: + # - cost-analyzer.local + +nodeSelector: {} + +tolerations: [] +# - key: "key" +# operator: "Equal|Exists" +# value: "value" +# effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + +affinity: {} + +# If true, creates a PriorityClass to be used by the cost-analyzer pod +priority: + enabled: false + # value: 1000000 + +# If true, enable creation of NetworkPolicy resources. +networkPolicy: + enabled: false + denyEgress: true # create a network policy that denies egress from kubecost + sameNamespace: true # Set to true if cost analyser and prometheus are on the same namespace +# namespace: kubecost # Namespace where prometheus is installed + +podSecurityPolicy: + enabled: true + +# Define persistence volume for cost-analyzer, more information at https://github.com/kubecost/docs/blob/master/storage.md +persistentVolume: + size: 32Gi + dbSize: 32.0Gi + enabled: true # Note that setting this to false means configurations will be wiped out on pod restart. + # storageClass: "-" # + # existingClaim: kubecost-cost-analyzer # a claim in the same namespace as kubecost + +service: + type: ClusterIP + port: 9090 + targetPort: 9090 + # nodePort: + labels: {} + annotations: {} + +# Enabling long-term durable storage with Postgres requires an enterprise license +remoteWrite: + postgres: + enabled: false + initImage: "gcr.io/kubecost1/sql-init" + initImagePullPolicy: Always + installLocal: true + remotePostgresAddress: "" # ignored if installing locally + persistentVolume: + size: 200Gi + auth: + password: admin # change me + +prometheus: + extraScrapeConfigs: | + - job_name: kubecost + honor_labels: true + scrape_interval: 1m + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + dns_sd_configs: + - names: + - {{ template "cost-analyzer.serviceName" . }} + type: 'A' + port: 9003 + - job_name: kubecost-networking + kubernetes_sd_configs: + - role: pod + relabel_configs: + # Scrape only the the targets matching the following metadata + - source_labels: [__meta_kubernetes_pod_label_app] + action: keep + regex: {{ template "cost-analyzer.networkCostsName" . }} + server: + # If clusterIDConfigmap is defined, instead use user-generated configmap with key CLUSTER_ID + # to use as unique cluster ID in kubecost cost-analyzer deployment. + # This overrides the cluster_id set in prometheus.server.global.external_labels. + # NOTE: This does not affect the external_labels set in prometheus config. + # clusterIDConfigmap: cluster-id-configmap + + resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 500m + # memory: 512Mi + global: + scrape_interval: 1m + scrape_timeout: 10s + evaluation_interval: 1m + external_labels: + cluster_id: cluster-one # Each cluster should have a unique ID + persistentVolume: + size: 32Gi + enabled: true + extraArgs: + query.max-concurrency: 1 + query.max-samples: 100000000 + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + alertmanager: + enabled: false + persistentVolume: + enabled: true + nodeExporter: + enabled: true + pushgateway: + enabled: false + persistentVolume: + enabled: true + serverFiles: + # prometheus.yml: # Sample block -- enable if using an in cluster durable store. + # remote_write: + # - url: "http://pgprometheus-adapter:9201/write" + # write_relabel_configs: + # - source_labels: [__name__] + # regex: 'container_.*_allocation|container_.*_allocation_bytes|.*_hourly_cost|kube_pod_container_resource_requests{resource="memory", unit="byte"}|container_memory_working_set_bytes|kube_pod_container_resource_requests{resource="cpu", unit="core"}|kube_pod_container_resource_requests|pod_pvc_allocation|kube_namespace_labels|kube_pod_labels' + # action: keep + # queue_config: + # max_samples_per_send: 1000 + #remote_read: + # - url: "http://pgprometheus-adapter:9201/read" + rules: + groups: + - name: CPU + rules: + - expr: sum(rate(container_cpu_usage_seconds_total{container_name!=""}[5m])) + record: cluster:cpu_usage:rate5m + - expr: rate(container_cpu_usage_seconds_total{container_name!=""}[5m]) + record: cluster:cpu_usage_nosum:rate5m + - expr: avg(irate(container_cpu_usage_seconds_total{container_name!="POD", container_name!=""}[5m])) by (container_name,pod_name,namespace) + record: kubecost_container_cpu_usage_irate + - expr: sum(container_memory_working_set_bytes{container_name!="POD",container_name!=""}) by (container_name,pod_name,namespace) + record: kubecost_container_memory_working_set_bytes + - expr: sum(container_memory_working_set_bytes{container_name!="POD",container_name!=""}) + record: kubecost_cluster_memory_working_set_bytes + - name: Savings + rules: + - expr: sum(avg(kube_pod_owner{owner_kind!="DaemonSet"}) by (pod) * sum(container_cpu_allocation) by (pod)) + record: kubecost_savings_cpu_allocation + labels: + daemonset: "false" + - expr: sum(avg(kube_pod_owner{owner_kind="DaemonSet"}) by (pod) * sum(container_cpu_allocation) by (pod)) / sum(kube_node_info) + record: kubecost_savings_cpu_allocation + labels: + daemonset: "true" + - expr: sum(avg(kube_pod_owner{owner_kind!="DaemonSet"}) by (pod) * sum(container_memory_allocation_bytes) by (pod)) + record: kubecost_savings_memory_allocation_bytes + labels: + daemonset: "false" + - expr: sum(avg(kube_pod_owner{owner_kind="DaemonSet"}) by (pod) * sum(container_memory_allocation_bytes) by (pod)) / sum(kube_node_info) + record: kubecost_savings_memory_allocation_bytes + labels: + daemonset: "true" + - expr: label_replace(sum(kube_pod_status_phase{phase="Running",namespace!="kube-system"} > 0) by (pod, namespace), "pod_name", "$1", "pod", "(.+)") + record: kubecost_savings_running_pods + - expr: sum(rate(container_cpu_usage_seconds_total{container_name!="",container_name!="POD",instance!=""}[5m])) by (namespace, pod_name, container_name, instance) + record: kubecost_savings_container_cpu_usage_seconds + - expr: sum(container_memory_working_set_bytes{container_name!="",container_name!="POD",instance!=""}) by (namespace, pod_name, container_name, instance) + record: kubecost_savings_container_memory_usage_bytes + - expr: avg(sum(kube_pod_container_resource_requests{resource="cpu", unit="core", namespace!="kube-system"}) by (pod, namespace, instance)) by (pod, namespace) + record: kubecost_savings_pod_requests_cpu_cores + - expr: avg(sum(kube_pod_container_resource_requests{resource="memory", unit="byte", namespace!="kube-system"}) by (pod, namespace, instance)) by (pod, namespace) + record: kubecost_savings_pod_requests_memory_bytes + +## Module for measuring network costs +## Ref: https://github.com/kubecost/docs/blob/master/network-allocation.md +networkCosts: + enabled: false + podSecurityPolicy: + enabled: false + image: gcr.io/kubecost1/kubecost-network-costs:v15.4 + imagePullPolicy: Always + # For existing Prometheus Installs, create a Service which generates Endpoints for each of the network-costs pods. + # This Service is annotated with prometheus.io/scrape: "true" to automatically get picked up by the prometheus config. + # NOTE: Setting this option to true and leaving the above extraScrapeConfig "job_name: kubecost-networking" configured will cause the + # NOTE: pods to be scraped twice. + prometheusScrape: false + # Traffic Logging will enable logging the top 5 destinations for each source + # every 30 minutes. + trafficLogging: true + # Port will set both the containerPort and hostPort to this value. + # These must be identical due to network-costs being run on hostNetwork + port: 3001 + resources: {} + #requests: + # cpu: "50m" + # memory: "20Mi" + config: + # Configuration for traffic destinations, including specific classification + # for IPs and CIDR blocks. This configuration will act as an override to the + # automatic classification provided by network-costs. + destinations: + # In Zone contains a list of address/range that will be + # classified as in zone. + in-zone: + # Loopback + - "127.0.0.1" + # IPv4 Link Local Address Space + - "169.254.0.0/16" + # Private Address Ranges in RFC-1918 + - "10.0.0.0/8" + - "172.16.0.0/12" + - "192.168.0.0/16" + + # In Region contains a list of address/range that will be + # classified as in region. This is synonymous with cross + # zone traffic, where the regions between source and destinations + # are the same, but the zone is different. + in-region: [] + + # Cross Region contains a list of address/range that will be + # classified as non-internet egress from one region to another. + cross-region: [] + + # Direct Classification specifically maps an ip address or range + # to a region (required) and/or zone (optional). This classification + # takes priority over in-zone, in-region, and cross-region configurations. + direct-classification: [] + # - region: "us-east1" + # zone: "us-east1-c" + # ips: + # - "10.0.0.0/24" + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + affinity: {} + + ## PriorityClassName + ## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass + priorityClassName: [] + ## PodMonitor + ## Allows scraping of network metrics from a dedicated prometheus operator setup + podMonitor: + enabled: false + additionalLabels: {} + additionalLabels: {} + nodeSelector: {} + annotations: {} + +# Kubecost Deployment Configuration +# Used for HA mode in Business & Enterprise tier +kubecostDeployment: + replicas: 1 + +# Kubecost Cluster Controller for Right Sizing and Cluster Turndown +clusterController: + enabled: false + image: gcr.io/kubecost1/cluster-controller:v0.0.2 + imagePullPolicy: Always + +reporting: + # Kubecost bug report feature: Logs access/collection limited to .Release.Namespace + # Ref: http://docs.kubecost.com/bug-report + logCollection: true + # Basic frontend analytics + productAnalytics: true + # Report Javascript errors + errorReporting: true + valuesReporting: true + +serviceMonitor: + enabled: false + additionalLabels: {} + +prometheusRule: + enabled: false + additionalLabels: {} + +supportNFS: false +# initChownDataImage ensures all Kubecost filepath permissions on PV or local storage are set up correctly. +initChownDataImage: "busybox" # Supports a fully qualified Docker image, e.g. registry.hub.docker.com/library/busybox:latest +initChownData: + resources: {} + #requests: + # cpu: "50m" + # memory: "20Mi" + + +grafana: + # namespace_datasources: kubecost # override the default namespace here + # namespace_dashboards: kubecost # override the default namespace here + sidecar: + dashboards: + enabled: true + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # set sidecar ERROR_THROTTLE_SLEEP env var from default 5s to 0s -> fixes https://github.com/kubecost/cost-analyzer-helm-chart/issues/877 + error_throttle_sleep: 0 + datasources: + # dataSourceFilename: foo.yml # If you need to change the name of the datasource file + enabled: true + defaultDatasourceEnabled: false + dataSourceName: prometheus-kubecost + # label that the configmaps with datasources are marked with + label: kubecost_grafana_datasource + # set sidecar ERROR_THROTTLE_SLEEP env var from default 5s to 0s -> fixes https://github.com/kubecost/cost-analyzer-helm-chart/issues/877 + error_throttle_sleep: 0 +# For grafana to be accessible, add the path to root_url. For example, if you run kubecost at www.foo.com:9090/kubecost +# set root_url to "%(protocol)s://%(domain)s:%(http_port)s/kubecost/grafana". No change is necessary here if kubecost runs at a root URL + grafana.ini: + server: + root_url: "%(protocol)s://%(domain)s:%(http_port)s/grafana" +serviceAccount: + create: true # Set this to false if you're bringing your own service account. + annotations: {} + # name: kc-test + + +# readonly: false # disable updates to kubecost from the frontend UI and via POST request + +# These configs can also be set from the Settings page in the Kubecost product UI +# Values in this block override config changes in the Settings UI on pod restart +# +#kubecostProductConfigs: +# An optional list of cluster definitions that can be added for frontend access. The local +# cluster is *always* included by default, so this list is for non-local clusters. +# Ref: https://github.com/kubecost/docs/blob/master/multi-cluster.md +# clusters: +# - name: "Cluster A" +# address: http://cluster-a.kubecost.com:9090 +# # Optional authentication credentials - only basic auth is currently supported. +# auth: +# type: basic +# # Secret name should be a secret formatted based on: https://github.com/kubecost/docs/blob/master/ingress-examples.md +# secretName: cluster-a-auth +# # Or pass auth directly as base64 encoded user:pass +# data: YWRtaW46YWRtaW4= +# # Or user and pass directly +# user: admin +# pass: admin +# - name: "Cluster B" +# address: http://cluster-b.kubecost.com:9090 +# defaultModelPricing: # default monthly resource prices, used predominately for on-prem clusters +# CPU: 28.0 +# spotCPU: 4.86 +# RAM: 3.09 +# spotRAM: 0.65 +# GPU: 693.50 +# spotGPU: 225.0 +# storage: 0.04 +# zoneNetworkEgress: 0.01 +# regionNetworkEgress: 0.01 +# internetNetworkEgress: 0.12 +# enabled: true +# # The cluster profile represents a predefined set of parameters to use when calculating savings. +# # Possible values are: [ development, production, high-availability ] +# clusterProfile: production +# customPricesEnabled: false # This makes the default view custom prices-- generally used for on-premises clusters +# spotLabel: lifecycle +# spotLabelValue: Ec2Spot +# gpuLabel: gpu +# gpuLabelValue: true +# awsServiceKeyName: ACCESSKEYID +# awsServiceKeyPassword: fakepassword # Only use if your values.yaml are stored encrypted. Otherwise provide an existing secret via serviceKeySecretName +# awsSpotDataRegion: us-east-1 +# awsSpotDataBucket: spot-data-feed-s3-bucket +# awsSpotDataPrefix: dev +# athenaProjectID: "530337586277" # The AWS AccountID where the Athena CUR is. Generally your masterpayer account +# athenaBucketName: "s3://aws-athena-query-results-530337586277-us-east-1" +# athenaRegion: us-east-1 +# athenaDatabase: athenacurcfn_athena_test1 +# athenaTable: "athena_test1" +# masterPayerARN: "" +# projectID: "123456789" # Also known as AccountID on AWS -- the current account/project that this instance of Kubecost is deployed on. +# gcpSecretName: gcp-secret # Name of a secret representing the gcp service key +# bigQueryBillingDataDataset: billing_data.gcp_billing_export_v1_01AC9F_74CF1D_5565A2 +# labelMappingConfigs: # names of k8s labels used to designate different allocation concepts +# enabled: true +# owner_label: "owner" +# team_label: "team" +# department_label: "dept" +# product_label: "product" +# environment_label: "env" +# namespace_external_label: "kubernetes_namespace" # external labels are used to map external cloud costs to kubernetes concepts +# cluster_external_label: "kubernetes_cluster" +# controller_external_label: "kubernetes_controller" +# product_external_label: "kubernetes_label_app" +# service_external_label: "kubernetes_service" +# deployment_external_label: "kubernetes_deployment" +# team_external_label: "kubernetes_label_team" +# environment_external_label: "kubernetes_label_env" +# department_external_label: "kubernetes_label_department" +# statefulset_external_label: "kubernetes_statefulset" +# daemonset_external_label: "kubernetes_daemonset" +# pod_external_label: "kubernetes_pod" +# grafanaURL: "" +# clusterName: "" # used for display in Kubecost UI +# currencyCode: "USD" # offical support for USD, CAD, EUR, and CHF +# azureBillingRegion: US # Represents 2-letter region code, e.g. West Europe = NL, Canada = CA. ref: https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes +# azureSubscriptionID: 0bd50fdf-c923-4e1e-850c-196dd3dcc5d3 +# azureClientID: f2ef6f7d-71fb-47c8-b766-8d63a19db017 +# azureTenantID: 72faf3ff-7a3f-4597-b0d9-7b0b201bb23a +# azureClientPassword: fake key # Only use if your values.yaml are stored encrypted. Otherwise provide an existing secret via serviceKeySecretName +# azureStorageAccount: "kubecoststore" # Name of Azure Storage account where cost report is being saved +# azureStorageAccessKey: "" # Azure Storage account access key found in Azure Storage portal for account where cost report is being saved +# azureStorageContainer: "test" # Name of daily month-to-date cost report for Azure +# azureStorageSecretName: "azure-storage-config" # Name of Kubernetes Secret where Azure Storage Configuration is stored +# azureStorageCreateSecret: true # Create secret for Azure Storage config from values in this file +# discount: "" # percentage discount applied to compute +# negotiatedDiscount: "" # custom negotiated cloud provider discount +# defaultIdle: false +# serviceKeySecretName: "" # Use an existing AWS or Azure secret with format as in aws-service-key-secret.yaml or azure-service-key-secret.yaml. Leave blank if using createServiceKeySecret +# createServiceKeySecret: true # Creates a secret representing your cloud service key based on data in values.yaml. If you are storing unencrypted values, add a secret manually +# sharedNamespaces: "" # namespaces with shared workloads, example value: "kube-system\,ingress-nginx\,kubecost\,monitoring" +# shareTenancyCosts: true # enable or disable sharing costs such as cluster management fees (defaults to "true" on Settings page) +# productKey: # apply business or enterprise product license +# key: "" +# enabled: false +# secretname: productkeysecret # create a secret out of a file named productkey.json of format { "key": "kc-b1325234" } +# cloudIntegrationSecret: "cloud-integration" diff --git a/index.yaml b/index.yaml index 4a222499f..6cf8d95a0 100755 --- a/index.yaml +++ b/index.yaml @@ -446,6 +446,24 @@ entries: - assets/streamsets/control-agent-2.0.100.tgz version: 2.0.100 cost-analyzer: + - annotations: + artifacthub.io/links: | + - name: Homepage + url: https://www.kubecost.com + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Kubecost + catalog.cattle.io/release-name: kubecost + apiVersion: v2 + appVersion: 1.83.2 + created: "2021-08-26T13:33:52.685132+01:00" + description: A Helm chart that sets up Kubecost, Prometheus, and Grafana to monitor + cloud costs. + digest: 10d605184b7cd7887d10e11232d3219d818c8034f0afa2a7e39755fa059f0421 + icon: https://partner-charts.rancher.io/assets/logos/kubecost.png + name: cost-analyzer + urls: + - assets/kubecost/cost-analyzer-1.83.201.tgz + version: 1.83.201 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/release-name: kubecost