<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Metrics on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/metrics/</link><description>Recent content in Metrics on Backend Engineering Strategy Tools</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 01 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://backend-engineering-strategy-tools.github.io/site/tags/metrics/index.xml" rel="self" type="application/rss+xml"/><item><title>Grafana</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/observability/grafana/</link><pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/observability/grafana/</guid><description>&lt;p&gt;Prometheus shows you the spike. It tells you memory climbed at 14:32, error rate crossed 5% at 14:35, and latency hit 2 seconds at 14:37. But raw PromQL results are numbers in a table. You cannot see the shape of an incident in a table. You cannot hand a table to a product manager and explain what happened.&lt;/p&gt;
&lt;p&gt;So you use Grafana. It connects to Prometheus (and Loki, and a dozen other data sources) and turns those numbers into dashboards. You see the spike, the timeline, the correlation between services — all on one screen.&lt;/p&gt;
&lt;h2 id="data-sources"&gt;Data sources
&lt;/h2&gt;&lt;p&gt;Grafana is a visualisation layer, not a storage layer. It queries data sources and renders the results. In a Kubernetes observability stack, the typical setup:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Data source&lt;/th&gt;
 &lt;th&gt;What it provides&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Prometheus&lt;/td&gt;
 &lt;td&gt;Metrics — CPU, memory, request rates, error rates, latency&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Loki&lt;/td&gt;
 &lt;td&gt;Logs — searchable, filterable, correlated with metrics by time&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Jaeger / Tempo&lt;/td&gt;
 &lt;td&gt;Traces — individual request journeys across services&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Adding a data source is a few fields in the UI or a ConfigMap if you manage Grafana as code.&lt;/p&gt;
&lt;h2 id="dashboards"&gt;Dashboards
&lt;/h2&gt;&lt;p&gt;A dashboard is a collection of panels. Each panel runs a query against a data source and renders the result as a graph, gauge, stat, table, or heatmap.&lt;/p&gt;
&lt;p&gt;The fastest way to get useful dashboards is &lt;a class="link" href="https://grafana.com/grafana/dashboards/" target="_blank" rel="noopener"
 &gt;grafana.com/grafana/dashboards&lt;/a&gt; — a library of community dashboards for almost every common component. Import by ID:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1860&lt;/strong&gt; — Node Exporter Full (host metrics: CPU, memory, disk, network)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;6417&lt;/strong&gt; — Kubernetes cluster overview&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;7362&lt;/strong&gt; — MySQL overview&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;9628&lt;/strong&gt; — Postgres overview&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Import these on day one and you have coverage before writing a single PromQL query.&lt;/p&gt;
&lt;h2 id="variables"&gt;Variables
&lt;/h2&gt;&lt;p&gt;Dashboard variables make panels reusable across namespaces, clusters, or services. A variable populated from a Prometheus label query:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;label_values(kube_pod_info{namespace=~&amp;#34;.+&amp;#34;}, namespace)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now every panel can use &lt;code&gt;$namespace&lt;/code&gt; in its query, and a dropdown at the top of the dashboard filters the whole view.&lt;/p&gt;
&lt;h2 id="alerting"&gt;Alerting
&lt;/h2&gt;&lt;p&gt;Grafana has its own alert engine that evaluates queries on a schedule and routes alerts through contact points (Slack, PagerDuty, email). For Kubernetes setups already using Alertmanager, it is usually cleaner to define alert rules in Prometheus and use Grafana purely for visualisation — one place for alert rules, not two.&lt;/p&gt;
&lt;h2 id="managing-grafana-as-code"&gt;Managing Grafana as code
&lt;/h2&gt;&lt;p&gt;Dashboards built in the UI are fragile — they live in a database and disappear if you rebuild the stack. Two better approaches:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grafana provisioning&lt;/strong&gt; — mount dashboard JSON files via ConfigMap. Grafana loads them on startup and they survive restarts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grafonnet / Jsonnet&lt;/strong&gt; — generate dashboard JSON programmatically. Verbose but version-controllable and reviewable in pull requests.&lt;/p&gt;
&lt;h2 id="the-observability-trio"&gt;The observability trio
&lt;/h2&gt;&lt;p&gt;Grafana is the front end for the full observability stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prometheus&lt;/strong&gt; — something is wrong, here are the numbers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loki&lt;/strong&gt; — here are the log lines from that time window&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jaeger&lt;/strong&gt; — here is the exact request that failed and where it slowed down&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each answers a different question. Grafana is where you look at all three in one place.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/docs/grafana/latest/" target="_blank" rel="noopener"
 &gt;Grafana documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://grafana.com/grafana/dashboards/" target="_blank" rel="noopener"
 &gt;Grafana dashboard library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack" target="_blank" rel="noopener"
 &gt;kube-prometheus-stack&lt;/a&gt; — installs Prometheus + Grafana together&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Prometheus</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/observability/prometheus/</link><pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/observability/prometheus/</guid><description>&lt;p&gt;Something is wrong. Pods are restarting, latency is climbing, and a request that usually takes 50ms is now taking 2 seconds. You know something happened — users are complaining — but you have no numbers, no history, and no way to know when it started or which service caused it.&lt;/p&gt;
&lt;p&gt;The instinct is to grep the logs. And with one service on one server, that works. But once you have 20 services running across 40 pods, grepping logs to understand system behaviour does not scale. You are looking at individual events trying to infer aggregate trends — the wrong tool for the question. Logs tell you what happened in one place at one moment. Metrics tell you how the system is behaving across all of it, over time.&lt;/p&gt;
&lt;p&gt;So you use Prometheus. It scrapes metrics from every pod, node, and cluster component on a regular interval and stores them as time series. Now you have the spike, the exact minute it started, and a number attached to every symptom.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works
&lt;/h2&gt;&lt;p&gt;Prometheus is pull-based: it reaches out to your services and scrapes a &lt;code&gt;/metrics&lt;/code&gt; endpoint on a schedule. Services expose metrics in a simple text format; Prometheus stores them and makes them queryable.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# EXPOSE from your app
http://my-service:8080/metrics

# Prometheus scrapes this every 15s and stores:
http_requests_total{method=&amp;#34;POST&amp;#34;, status=&amp;#34;500&amp;#34;} 42
http_request_duration_seconds{quantile=&amp;#34;0.99&amp;#34;} 1.847
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Most infrastructure components (Kubernetes itself, NGINX, Postgres, Redis, JVM) either expose Prometheus metrics natively or have an exporter that does it for them.&lt;/p&gt;
&lt;h2 id="in-kubernetes--kube-prometheus-stack"&gt;In Kubernetes — kube-prometheus-stack
&lt;/h2&gt;&lt;p&gt;Running Prometheus in Kubernetes manually is fiddly. The fastest path to a working Prometheus + Grafana + Alertmanager stack is the &lt;code&gt;kube-prometheus-stack&lt;/code&gt; Helm chart — it installs the Prometheus Operator, Grafana, Alertmanager, node exporters, and a set of default dashboards and alert rules in one go. Add &lt;a class="link" href="../loki/" &gt;Loki&lt;/a&gt; on top for logs.&lt;/p&gt;
&lt;h3 id="crd-workaround"&gt;CRD workaround
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;kube-prometheus-stack&lt;/code&gt; ships with a large set of CRDs. When managed through ArgoCD, applying CRDs and the chart in the same sync can cause ordering failures. The standard workaround is &lt;code&gt;skipCrds: true&lt;/code&gt; in the ArgoCD Application, with CRDs applied via a separate kustomize source in the same Application:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;repoURL&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kube-prometheus-stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;targetRevision&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;82.14.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;helm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;releaseName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kube-prometheus-stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;valueFiles&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;$values/cluster/development/overlay/monitoring/helm/kube-prometheus-stack.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;skipCrds&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This keeps the CRDs in Git and lets ArgoCD manage them, while avoiding the race condition on first install.&lt;/p&gt;
&lt;h3 id="servicemonitor"&gt;ServiceMonitor
&lt;/h3&gt;&lt;p&gt;The &lt;strong&gt;Prometheus Operator&lt;/strong&gt; (installed by the stack) manages scrape config via CRDs. The key one is &lt;code&gt;ServiceMonitor&lt;/code&gt; — it tells Prometheus which services to scrape without editing Prometheus config directly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;monitoring.coreos.com/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ServiceMonitor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;matchLabels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;endpoints&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;metrics&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Deploy this alongside your app and Prometheus picks it up automatically.&lt;/p&gt;
&lt;h2 id="promql"&gt;PromQL
&lt;/h2&gt;&lt;p&gt;Prometheus Query Language lets you slice and aggregate metrics. A few patterns worth knowing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-promql" data-lang="promql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Request rate over last 5 minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rate&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;http_requests_total[&lt;span style="color:#e6db74"&gt;5m&lt;/span&gt;]&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 99th percentile latency&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;histogram_quantile&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0.99&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;rate&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;http_request_duration_seconds_bucket[&lt;span style="color:#e6db74"&gt;5m&lt;/span&gt;]&lt;span style="color:#f92672"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Error ratio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rate&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;http_requests_total{status&lt;span style="color:#f92672"&gt;=~&lt;/span&gt;&amp;#34;&lt;span style="color:#e6db74"&gt;5..&lt;/span&gt;&amp;#34;}[&lt;span style="color:#e6db74"&gt;5m&lt;/span&gt;]&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;rate&lt;/span&gt;&lt;span style="color:#f92672"&gt;(&lt;/span&gt;http_requests_total[&lt;span style="color:#e6db74"&gt;5m&lt;/span&gt;]&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Memory usage per pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;container_memory_working_set_bytes{namespace&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;#34;&lt;span style="color:#e6db74"&gt;production&lt;/span&gt;&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="alerting"&gt;Alerting
&lt;/h2&gt;&lt;p&gt;Prometheus evaluates alert rules continuously and fires them to Alertmanager, which handles routing, grouping, and silencing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- &lt;span style="color:#f92672"&gt;alert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HighErrorRate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;expr&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;rate(http_requests_total{status=~&amp;#34;5..&amp;#34;}[5m]) &amp;gt; 0.05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;for&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;severity&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;critical&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;annotations&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;summary&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Error rate above 5% for {{ $labels.service }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;for: 5m&lt;/code&gt; means the condition must hold for 5 minutes before firing — avoids noisy alerts on brief spikes.&lt;/p&gt;
&lt;h2 id="metrics-server"&gt;Metrics Server
&lt;/h2&gt;&lt;p&gt;Metrics Server is a separate, lightweight component that provides the real-time resource metrics (&lt;code&gt;kubectl top pods&lt;/code&gt;, &lt;code&gt;kubectl top nodes&lt;/code&gt;) that HPA uses to make scaling decisions. It is not Prometheus — it does not store history and is not queryable. It exists purely to feed the Kubernetes control plane.&lt;/p&gt;
&lt;p&gt;Install via ArgoCD:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;metrics-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;argo-cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;project&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;repoURL&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://kubernetes-sigs.github.io/metrics-server&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;metrics-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;targetRevision&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3.13.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;helm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;releaseName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;metrics-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;destination&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://kubernetes.default.svc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kube-system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;syncPolicy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;automated&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selfHeal&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;prune&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;syncOptions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;CreateNamespace=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Install this early — HPA does nothing without it, and &lt;code&gt;kubectl top&lt;/code&gt; is the first thing you reach for when something looks wrong.&lt;/p&gt;
&lt;h2 id="what-prometheus-is-not"&gt;What Prometheus is not
&lt;/h2&gt;&lt;p&gt;Prometheus stores metrics — numbers over time. It does not store logs (see &lt;a class="link" href="../loki/" &gt;Loki&lt;/a&gt;) and it does not trace individual requests across services (see &lt;a class="link" href="../jaeger/" &gt;Jaeger&lt;/a&gt;). Metrics tell you &lt;em&gt;that&lt;/em&gt; something is wrong and &lt;em&gt;when&lt;/em&gt; it started. The other two tell you &lt;em&gt;what&lt;/em&gt; happened and &lt;em&gt;where&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://prometheus.io/docs/" target="_blank" rel="noopener"
 &gt;Prometheus documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack" target="_blank" rel="noopener"
 &gt;kube-prometheus-stack Helm chart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://promlabs.com/promql-cheat-sheet/" target="_blank" rel="noopener"
 &gt;PromQL cheat sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>