Added kubecost templates

This commit is contained in:
=
2026-04-18 08:22:20 +00:00
parent e33a2a51f3
commit 5e0b597cf4
2 changed files with 391 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
{{- if .Values.hooks.clusterID.enabled }}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "kubecost.fullname" . }}-hook
namespace: {{ $.Release.Namespace }}
labels:
app: {{ template "kubecost.name" . }}-kubecost
{{ include "kubecost.labels" . | indent 4 }}
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-delete
helm.sh/hook-weight: "-5"
helm.sh/hook-delete-policy: before-hook-creation
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "kubecost.fullname" . }}-hook
labels:
app: {{ template "kubecost.name" . }}
{{ include "kubecost.labels" . | indent 4 }}
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade,post-delete
helm.sh/hook-weight: "-4"
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
rules:
# The following namespaces and configmaps permissions are needed to
# grab the kube-system namespace uid and write it out to a configmap.
- apiGroups: [""]
resources:
- namespaces
verbs: ["get"]
- apiGroups: [""]
resources:
- configmaps
verbs: ["get", "create", "patch", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "kubecost.fullname" . }}-hook
labels:
app: {{ template "kubecost.name" . }}
{{ include "kubecost.labels" . | indent 4 }}
annotations:
helm.sh/hook: pre-install,pre-upgrade,post-install,post-upgrade,post-delete
helm.sh/hook-weight: "-3"
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "kubecost.fullname" . }}-hook
subjects:
- kind: ServiceAccount
name: {{ template "kubecost.fullname" . }}-hook
namespace: {{ $.Release.Namespace }}
{{- if index .Values "cost-analyzer" "global" "prometheus" "enabled" }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-edit-prom-cluster-id
namespace: {{ .Release.Namespace }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "3"
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
spec:
template:
metadata:
name: {{ .Release.Name }}-edit-prom-cluster-id
spec:
serviceAccountName: {{ template "kubecost.fullname" . }}-hook
{{- if .Values.hooks.clusterID.priorityClassName }}
priorityClassName: "{{ .Values.hooks.clusterID.priorityClassName }}"
{{- end }}
containers:
- name: kubectl
image: {{ .Values.hooks.clusterID.kubectlImage | quote }}
imagePullPolicy: IfNotPresent
command:
- sh
- "-c"
- |
/bin/bash <<'EOF'
set -o nounset
set -o errexit
set -o pipefail
CLUSTERID=$(kubectl get namespace kube-system -o jsonpath="{.metadata.uid}")
kubectl get configmap/{{ template "kubecost.prometheus-server-cm-name" . }} -oyaml > /tmp/override.yaml
sed -e 's/\$CLUSTER_ID/"'$CLUSTERID'"/g' /tmp/override.yaml > /tmp/final.yaml
kubectl apply -f /tmp/final.yaml
echo "Done replacing \$CLUSTER_ID with $CLUSTERID"
EOF
restartPolicy: OnFailure
{{- end }}
{{- if index .Values "cost-analyzer" "prometheus" "server" "clusterIDConfigmap" }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-cluster-id-configmap
namespace: {{ .Release.Namespace }}
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-weight: "3"
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
spec:
template:
metadata:
name: {{ .Release.Name }}-cluster-id-configmap
spec:
serviceAccountName: {{ template "kubecost.fullname" . }}-hook
{{- if .Values.hooks.clusterID.priorityClassName }}
priorityClassName: "{{ .Values.hooks.clusterID.priorityClassName }}"
{{- end }}
containers:
- name: kubectl
image: {{ .Values.hooks.clusterID.kubectlImage | quote }}
imagePullPolicy: IfNotPresent
command:
- sh
- "-c"
- kubectl create configmap {{ index .Values "cost-analyzer" "prometheus" "server" "clusterIDConfigmap" }} -n {{ .Release.Namespace }} -oyaml --dry-run --save-config --from-literal=CLUSTER_ID=$(kubectl get namespace kube-system -o jsonpath="{.metadata.uid}") | kubectl apply -f -
restartPolicy: OnFailure
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-cleanup-cluster-id-configmap
namespace: {{ .Release.Namespace }}
annotations:
helm.sh/hook: post-delete
helm.sh/hook-weight: "3"
helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
spec:
template:
metadata:
name: {{ .Release.Name }}-cleanup-cluster-id-configmap
spec:
serviceAccountName: {{ template "kubecost.fullname" . }}-hook
{{- if .Values.hooks.clusterID.priorityClassName }}
priorityClassName: "{{ .Values.hooks.clusterID.priorityClassName }}"
{{- end }}
containers:
- name: kubectl
image: {{ .Values.hooks.clusterID.kubectlImage | quote }}
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- kubectl delete configmap {{ index .Values "cost-analyzer" "prometheus" "server" "clusterIDConfigmap" }} -n {{ .Release.Namespace }} --ignore-not-found
restartPolicy: OnFailure
{{- end }}
{{- end }}

View File

@@ -0,0 +1,235 @@
# Default values for kubecost parent chart (wraps kubecost cost-analyzer chart).
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
hooks:
# Modifies the prometheus configmap to set the prometheus cluster_id
# external label to the cluster's kube-system ns uid.
# Creates configmap to pass kube-system ns uid as envvar to kubecost.
clusterID:
enabled: true
kubectlImage: "bitnamilegacy/kubectl:1.30.5"
priorityClassName: ""
cost-analyzer:
enabled: true
global:
prometheus:
# If false, Prometheus will not be installed -- only actively supported on paid Kubecost plans
enabled: true
thanos:
enabled: false
grafana:
# If false, Grafana will not be installed
enabled: true
notifications:
alertmanager:
# If true, allow kubecost to write to alertmanager
enabled: true
podSecurityPolicy:
enabled: false
# Define persistence volume for cost-analyzer, more information at https://github.com/kubecost/docs/blob/master/storage.md
persistentVolume:
# Upgrades from original default 0.2Gi may break if automatic disk resize is not supported
# https://github.com/kubecost/cost-analyzer-helm-chart/issues/507
size: 32Gi
# Note that setting this to false means configurations will be wiped out on pod restart.
enabled: true
# storageClass: "-"
prometheus:
kubeStateMetrics:
enabled: false
kube-state-metrics:
disabled: true
nodeExporter:
enabled: false
serviceAccounts:
nodeExporter:
create: false
extraScrapeConfigs: |
- job_name: kubecost
honor_labels: true
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
dns_sd_configs:
- names:
- {{ .Release.Name }}-cost-analyzer
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: {{ .Release.Name }}-network-costs
server:
image:
tag: v2.55.0
# 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: kubecost-cluster-info-configmap
extraFlags:
- web.enable-admin-api
- web.enable-lifecycle
- storage.tsdb.wal-compression
resources:
limits:
cpu: 1000m
memory: 2500Mi
requests:
cpu: 300m
memory: 1500Mi
global:
scrape_interval: 1m
scrape_timeout: 10s
evaluation_interval: 1m
external_labels:
cluster_id: $CLUSTER_ID
persistentVolume:
size: 32Gi
enabled: true
extraArgs:
log.level: info
log.format: json
storage.tsdb.min-block-duration: 2h
storage.tsdb.max-block-duration: 2h
query.max-concurrency: 1
query.max-samples: 100000000
enableAdminApi: true
service:
gRPC:
enabled: true
sidecarContainers:
- name: thanos-sidecar
image: quay.io/thanos/thanos:v0.36.1
args:
- sidecar
- --log.level=debug
- --tsdb.path=/data/
- --prometheus.url=http://127.0.0.1:9090
- --reloader.config-file=/etc/config/prometheus.yml
# 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/config
- name: storage-volume
mountPath: /data
subPath: ""
alertmanager:
enabled: true
image:
repository: quay.io/prometheus/alertmanager
tag: v0.27.0
resources:
limits:
cpu: 50m
memory: 100Mi
requests:
cpu: 10m
memory: 50Mi
persistentVolume:
enabled: true
pushgateway:
enabled: false
persistentVolume:
enabled: false
serverFiles:
alerts:
groups:
- name: Kubecost
rules:
- alert: kubecostDown
expr: up{job="kubecost"} == 0
annotations:
message: 'Kubecost metrics endpoint is not being scraped successfully.'
for: 10m
labels:
severity: warning
- alert: kubecostMetricsUnavailable
expr: sum(sum_over_time(node_cpu_hourly_cost[5m])) == 0
annotations:
message: 'Kubecost metrics are not available in Prometheus.'
for: 10m
labels:
severity: warning
- alert: kubecostRecordingRulesNotEvaluated
expr: avg_over_time(kubecost_cluster_memory_working_set_bytes[5m]) == 0
annotations:
message: 'Kubecost recording rules are not being successfully evaluated.'
for: 10m
labels:
severity: warning
grafana:
sidecar:
image:
repository: docker.io/kiwigrid/k8s-sidecar
tag: 1.28.0
dashboards:
enabled: true
label: kubecost_grafana_dashboard
datasources:
enabled: true
defaultDatasourceEnabled: false
label: kubecost_grafana_datasource
# Enable grafana ingress with below annotations to use Konvoy traefik auth
# ingress:
# enabled: true
# annotations:
# kubernetes.io/ingress.class: kommander-traefik
# ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
# traefik.ingress.kubernetes.io/router.tls: "true"
# traefik.ingress.kubernetes.io/router.middlewares: "${workspaceNamespace}-stripprefixes@kubernetescrd,${workspaceNamespace}-forwardauth@kubernetescrd"
# hosts: [""]
# path: "/dkp/kubecost/grafana"
# Configure grafana.ini server.root_url properly if ingress is enabled
# grafana.ini:
# server:
# protocol: http
# enable_gzip: true
# root_url: "%(protocol)s://%(domain)s:%(http_port)s/dkp/kubecost/grafana"
# auth.proxy:
# enabled: true
# header_name: X-Forwarded-User
# auto-sign-up: true
# auth.basic:
# enabled: false
# users:
# auto_assign_org_role: Admin
thanos:
store:
enabled: false
query:
enabled: false
sidecar:
enabled: false
bucket:
enabled: false
compact:
enabled: false