<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Krishna Garg</title>
    <description>The latest articles on DEV Community by Krishna Garg (@gargkrishna730).</description>
    <link>https://dev.to/gargkrishna730</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1903020%2F88be8c43-0b9a-47a6-82f6-c50a4183e398.png</url>
      <title>DEV Community: Krishna Garg</title>
      <link>https://dev.to/gargkrishna730</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gargkrishna730"/>
    <language>en</language>
    <item>
      <title>Your Kubernetes cluster is paying a cross-AZ tax. ZoneTax shows you exactly which pod.</title>
      <dc:creator>Krishna Garg</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:19:05 +0000</pubDate>
      <link>https://dev.to/gargkrishna730/your-kubernetes-cluster-is-paying-a-cross-az-tax-zonetax-shows-you-exactly-which-pod-35ie</link>
      <guid>https://dev.to/gargkrishna730/your-kubernetes-cluster-is-paying-a-cross-az-tax-zonetax-shows-you-exactly-which-pod-35ie</guid>
      <description>&lt;p&gt;Your Kubernetes cluster is probably paying a tax you cannot see.&lt;/p&gt;

&lt;p&gt;On AWS, traffic between availability zones costs about $0.01/GB in &lt;strong&gt;each direction&lt;/strong&gt; — so a GB crossing a zone boundary costs you $0.02. Nothing in your cluster tells you it is happening. It arrives days later on the bill as "EC2-Other / DataTransfer-Regional-Bytes", with no hint of which pod caused it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gargkrishna730/zonetax" rel="noopener noreferrer"&gt;ZoneTax&lt;/a&gt; makes that visible in real time, and attributes every dollar to the workload generating it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detects&lt;/strong&gt; cross-AZ traffic live, via an in-cluster DaemonSet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prices it&lt;/strong&gt; the way AWS actually bills, counting both directions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shows you who is paying it&lt;/strong&gt; — an interactive map of which namespaces and workloads talk across zones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exports Prometheus metrics&lt;/strong&gt; so you can alert with the tooling you already run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ships a CLI&lt;/strong&gt; for &lt;code&gt;zonetax top&lt;/code&gt; and &lt;code&gt;zonetax report&lt;/code&gt; without opening a dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install it in two minutes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add zonetax https://gargkrishna730.github.io/zonetax
helm &lt;span class="nb"&gt;install &lt;/span&gt;zonetax zonetax/zonetax &lt;span class="nt"&gt;-n&lt;/span&gt; zonetax &lt;span class="nt"&gt;--create-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with plain manifests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/gargkrishna730/zonetax/releases/latest/download/install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open the dashboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; zonetax port-forward svc/zonetax-collector 8080:8080
&lt;span class="c"&gt;# http://localhost:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloud and region are auto-detected from your node labels. There is nothing to configure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it found on a real cluster
&lt;/h2&gt;

&lt;p&gt;Within minutes of installing on a 3-AZ EKS cluster, one route stood out: &lt;strong&gt;97% of all cross-AZ spend&lt;/strong&gt; came from a single telemetry collector writing ~4.4 GB/hour into its database in another zone.&lt;/p&gt;

&lt;p&gt;The database was pinned to its zone by an EBS volume. The collector was stateless and had simply landed wherever the scheduler put it. The two had never been co-located because nothing had ever made the cost visible.&lt;/p&gt;

&lt;p&gt;One &lt;code&gt;nodeSelector&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cross-AZ GB/hour&lt;/th&gt;
&lt;th&gt;Cost/day&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Before&lt;/td&gt;
&lt;td&gt;4.83&lt;/td&gt;
&lt;td&gt;$2.32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;td&gt;$0.03&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Roughly &lt;strong&gt;$70/month from a one-line change&lt;/strong&gt;, on a cluster nobody thought had a network cost problem. The route disappeared from the map within one scrape interval.&lt;/p&gt;

&lt;p&gt;Two patterns worth checking in your own cluster:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Central logging or metrics backends.&lt;/strong&gt; Collectors that write a lot are the usual culprit — check where they sit relative to their storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful workloads whose volume pins them to one zone&lt;/strong&gt; while their clients spread across all of them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Accuracy
&lt;/h2&gt;

&lt;p&gt;This is a cost tool, so the number has to be trustworthy. Measured on a real 3-AZ cluster by sending a known 1 GiB between pods:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Reported&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Upload across zones&lt;/td&gt;
&lt;td&gt;1.0834 GB&lt;/td&gt;
&lt;td&gt;+0.90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Download (reply direction)&lt;/td&gt;
&lt;td&gt;1.0780 GB&lt;/td&gt;
&lt;td&gt;+0.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Through a ClusterIP Service&lt;/td&gt;
&lt;td&gt;1.0816 GB&lt;/td&gt;
&lt;td&gt;+0.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same-zone control&lt;/td&gt;
&lt;td&gt;no cross-AZ entry&lt;/td&gt;
&lt;td&gt;correct&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The small positive error is TCP/IP header overhead — conntrack counts bytes on the wire, which is exactly what AWS bills.&lt;/p&gt;

&lt;p&gt;ZoneTax attributes &lt;strong&gt;pod-to-pod&lt;/strong&gt; traffic. Anything with an endpoint outside the cluster (managed databases, S3, load balancers, internet egress) is reported separately as unattributed rather than guessed at, so you always know what is and is not being counted.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent (DaemonSet, every node)
  └─ samples /proc/net/nf_conntrack
  └─ resolves IP → pod → node → availability zone
  └─ exposes raw byte counters

collector (one pod)
  └─ scrapes agents, applies a versioned AWS pricing table
  └─ serves the REST API, the dashboard and /metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zones come from the standard &lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt; node labels, so there are no cloud credentials and no IMDS calls. The agent reads a local kernel file and generates no network traffic of its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alerting
&lt;/h2&gt;

&lt;p&gt;ZoneTax exports costed Prometheus metrics, so you alert with Prometheus and Alertmanager rather than yet another notifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CrossAZSpendHigh&lt;/span&gt;
  &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zonetax_cross_az_cost_usd &amp;gt; 1 and zonetax_coverage_complete == &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;zonetax_coverage_complete&lt;/code&gt; gauge is worth knowing about: it is &lt;code&gt;1&lt;/code&gt; only when every node in the cluster is actually being measured. Gate your alerts on it and a missing agent can never look like a drop in spend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running cost
&lt;/h2&gt;

&lt;p&gt;The agent requests 50m CPU / 64Mi memory per node; the collector 100m / 128Mi. The agent reads a local kernel file and sends nothing over the network. In practice it costs far less than the first misplaced pod it finds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Apache 2.0, multi-arch images (amd64 + arm64), AWS/EKS:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/gargkrishna730/zonetax" rel="noopener noreferrer"&gt;github.com/gargkrishna730/zonetax&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you run a multi-AZ cluster, install it and look at the top route. I would genuinely like to know what you find.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>devops</category>
      <category>finops</category>
    </item>
  </channel>
</rss>
