<?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: Mridul Tiwari</title>
    <description>The latest articles on DEV Community by Mridul Tiwari (@mridul_it_is).</description>
    <link>https://dev.to/mridul_it_is</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%2F818449%2F187be899-c6f1-4ca9-92f8-8e8753b10d54.png</url>
      <title>DEV Community: Mridul Tiwari</title>
      <link>https://dev.to/mridul_it_is</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mridul_it_is"/>
    <language>en</language>
    <item>
      <title>Patch night wasn’t one incident — it was three failure modes in a row</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sun, 27 Sep 2026 03:13:28 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/patch-night-wasnt-one-incident-it-was-three-failure-modes-in-a-row-e2e</link>
      <guid>https://dev.to/mridul_it_is/patch-night-wasnt-one-incident-it-was-three-failure-modes-in-a-row-e2e</guid>
      <description>&lt;p&gt;Tuesday’s plan looked boring on paper: run the SSM patch runbooks across a bunch of Auto Scaling Groups, bake AMIs, promote launch templates, go home. By midnight I was still on a call with Jenkins console output in one terminal and &lt;code&gt;aws autoscaling describe-auto-scaling-groups&lt;/code&gt; in the other. Nobody had paged us for a single catastrophic outage. What we had was worse in a different way — a pile of medium failures that kept teaching the same lesson: &lt;strong&gt;the platform replaces your box faster than you can trust what’s on disk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We’re on several AWS accounts in &lt;code&gt;ap-south-1&lt;/code&gt;, with a mix of ASG-backed app tiers, central Logstash, non-prod EKS behind private ALBs, and Jenkins still in the middle of deploy paths. The week of 19–26 Sep was a patching wave plus finishing non-prod EKS ingress cutover, logging gaps on refreshed EC2, and the usual Jenkins/Argo/dashboard tickets. Storm-on-EKS had already been written up the week before; this one was the “everything else” shift.&lt;/p&gt;

&lt;p&gt;I’ll focus on three threads that actually changed how I work: &lt;strong&gt;patch automation that lied&lt;/strong&gt;, &lt;strong&gt;Filebeat that looked like Logstash&lt;/strong&gt;, and &lt;strong&gt;an ALB that went healthy only after we remembered how traffic really flows&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the runbook finishes but the AMI doesn’t
&lt;/h2&gt;

&lt;p&gt;We drove bulk patching through SSM documents — &lt;code&gt;Patching-ASG&lt;/code&gt;, &lt;code&gt;NewRunbook&lt;/code&gt;, &lt;code&gt;Ami-Patch&lt;/code&gt; — with shared params: package excludes (java, elasticsearch, tomcat, nginx, agents, and friends), IMDSv2 metadata, no overwriting the document default &lt;code&gt;TargetAmiName&lt;/code&gt;, dedupe by ASG. On paper that’s the right shape. In practice, a large batch of assisted runs &lt;strong&gt;faltered&lt;/strong&gt;: wrong params, retries, timeouts, and &lt;strong&gt;duplicate AMIs&lt;/strong&gt; for the same intent. AMIs &lt;em&gt;existed&lt;/em&gt;, but I stopped trusting “green” in the SSM console as “safe to put in the launch template.”&lt;/p&gt;

&lt;p&gt;My triage order became mechanical: does the AMI exist? Are there dupes for the same ASG intent? If we’re launching replacements, is it &lt;code&gt;InsufficientInstanceCapacity&lt;/code&gt; on Graviton in one AZ — where our retry policy was &lt;strong&gt;same subnet, same instance type&lt;/strong&gt;, no family hop? Is the worker even in SSM? When automation output looked suspect, &lt;strong&gt;manual no-reboot / standard create-image from a known-good instance&lt;/strong&gt; was slower but honest. Automation was still worth it for param gathering and dedupe logic; &lt;strong&gt;validate before LT promotion&lt;/strong&gt; was the gate we’d been skipping in spirit.&lt;/p&gt;

&lt;p&gt;Two failures stuck in my notes. On a central Logstash ASG we hit &lt;code&gt;InvalidAMIID.NotFound&lt;/code&gt;: the launch template (or source AMI) was deregistered while the instance kept running. Automation can’t &lt;code&gt;RunInstances&lt;/code&gt; until you register a fresh AMI from the live node — the running box is the source of truth, and when the running instance’s LT id/version had drifted from what the ASG thought it was using, &lt;code&gt;SourceAmiId&lt;/code&gt; &lt;strong&gt;had to come from the running instance AMI&lt;/strong&gt;, not a stale LT pointer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz1aqwyakgn7mvmsn3fev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz1aqwyakgn7mvmsn3fev.png" alt=" " width="338" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other was uglier: &lt;code&gt;NewRunbook&lt;/code&gt; timed out on an Elasticsearch master patch worker at &lt;code&gt;verifySsmInstall&lt;/code&gt; after 20 minutes. Cloud-init on &lt;strong&gt;aarch64&lt;/strong&gt; tried to install SSM via a path that blew up with &lt;code&gt;Unsupported architecture aarch64&lt;/code&gt;. The worker never registered; we had an orphaned EC2 until someone terminated it manually. That’s a recurring risk I’m now paranoid about: &lt;strong&gt;arm64 first-boot SSM install paths that don’t match the AMI family.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With patch AMIs unreliable, we fell back to &lt;strong&gt;in-place patching on ASG members&lt;/strong&gt; — &lt;code&gt;yum update&lt;/code&gt;, reboot for kernel. First time through, I learned this is not “SSH and yum” in a vacuum.&lt;/p&gt;

&lt;p&gt;I patched what I thought was a “safe” instance — termination protection in my head, “this one shouldn’t be replaced.” The ASG &lt;strong&gt;still replaced&lt;/strong&gt; it. Long patch window or a bad reboot fails the health check; the group launches from the launch template. Those replacements are &lt;strong&gt;not&lt;/strong&gt; clones of the old disk. Fresh boot, often &lt;strong&gt;missing&lt;/strong&gt; agents, log paths, local tuning, manual fixes from three incidents ago. We turned one patching task into config drift repair on top of Jenkins already being on fire.&lt;/p&gt;

&lt;p&gt;The pattern we landed on: &lt;strong&gt;ASG Standby&lt;/strong&gt;. One member at a time — move to Standby (out of rotation, still running), patch, reboot, validate, back to InService. It doesn’t make the ASG magic, but it cuts the odds that traffic and health checks drive a replace cycle on the box you’re mid-flight on. You still coordinate desired capacity and which AZ you’re touching.&lt;/p&gt;

&lt;p&gt;Then the kernel trap. &lt;code&gt;yum&lt;/code&gt; installed a new kernel; we rebooted; &lt;code&gt;uname -r&lt;/code&gt; still showed the &lt;strong&gt;old&lt;/strong&gt; kernel. On RHEL-family AMIs that often means the boot loader default never moved — &lt;code&gt;grub2-set-default&lt;/code&gt;, read &lt;code&gt;/etc/default/grub&lt;/code&gt;, &lt;code&gt;grub2-mkconfig&lt;/code&gt;, fix the right &lt;strong&gt;BOOT&lt;/strong&gt; entry and cmdline, reboot &lt;strong&gt;again&lt;/strong&gt;, verify. “Patched and rebooted” is not “running the new kernel.” First time through that was trial and error; I didn’t capture exact timings, but it burned a chunk of the window.&lt;/p&gt;

&lt;p&gt;Meanwhile Jenkins wasn’t a sidebar. On two consecutive patch nights (~mid-week), frontend build agents, deploy paths, and related CI failures ate &lt;strong&gt;3–4 hours each night&lt;/strong&gt; before patching could finish. Patch work, ASG churn, config repair, and CI recovery were &lt;strong&gt;coupled&lt;/strong&gt;. I’d call patch night done only after agents were healthy — lesson learned the expensive way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;harvester.running: 0&lt;/code&gt; and why I stopped blaming Logstash first
&lt;/h2&gt;

&lt;p&gt;Separate thread, same week: “Filebeat not sending” after an ASG instance refresh. My instinct — and I’ve seen teams do this — is to stare at Logstash or OpenSearch. The metrics told a different story: &lt;code&gt;harvester.running: 0&lt;/code&gt;, &lt;code&gt;registrar.states: 0&lt;/code&gt;. Filebeat wasn’t reading files. Output to Logstash is irrelevant until harvesters run.&lt;/p&gt;

&lt;p&gt;We walked paths and permissions. Generic template inputs didn’t match where the app actually wrote logs — path mismatch. Directories at &lt;strong&gt;750&lt;/strong&gt; and files at &lt;strong&gt;640&lt;/strong&gt; bite when the filebeat user isn’t the app user. Fix was &lt;strong&gt;manual config correction after debugging&lt;/strong&gt;; shipping came back when paths aligned. Not primarily a Logstash outage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8nu6y4a0grsd0gcuglxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8nu6y4a0grsd0gcuglxv.png" alt=" " width="338" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logstash did throw noise if you went looking: &lt;code&gt;InvalidFrameProtocolException&lt;/code&gt; for Beats protocol &lt;strong&gt;10&lt;/strong&gt; and &lt;strong&gt;13&lt;/strong&gt; on port 5044. Bytes looked like HTTP CRLF. Plain &lt;code&gt;beats { port =&amp;gt; 5044 }&lt;/code&gt; on Logstash; Filebeat &lt;code&gt;output.logstash&lt;/code&gt; without SSL. Likely something doing &lt;strong&gt;HTTP health checks on the Beats port&lt;/strong&gt; or random TCP to 5044 — fix on the LB side is &lt;strong&gt;TCP health check&lt;/strong&gt;, not HTTP on 5044. I keep that diagnostic order now: &lt;strong&gt;harvesters → paths/perms → then&lt;/strong&gt; protocol errors on the collector.&lt;/p&gt;

&lt;p&gt;Fleet-wise, Ansible had security-group gaps — filebeat role missing on some boxes, Promtail still on others. That’s a separate fix from the one-off path correction, but it explains why refresh keeps biting the same org.&lt;/p&gt;

&lt;p&gt;On EKS we were also splitting Alloy streams for application-namespace container logs — lines starting with &lt;code&gt;[TOMCAT]&lt;/code&gt; to &lt;code&gt;*-tomcat-logs&lt;/code&gt;, everything else to &lt;code&gt;*-app-logs&lt;/code&gt;. Different layer, same theme: &lt;strong&gt;the pipeline is only as good as the contract at the edge&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Private ALB by security group, and the 8080 rule we almost forgot
&lt;/h2&gt;

&lt;p&gt;Non-prod EKS ingress finished a move from &lt;strong&gt;CIDR-based private ALB&lt;/strong&gt; to &lt;strong&gt;security-group inbound&lt;/strong&gt; (&lt;code&gt;alb-private-sg&lt;/code&gt; values). We removed legacy CIDR ingress objects and dropped &lt;code&gt;alb-private.yaml&lt;/code&gt; from Argo valueFiles; Argo CD’s own ingress rode the same cutover. Shipped live with &lt;strong&gt;tcp/8080&lt;/strong&gt; from the ALB security group onto cluster and node security groups. &lt;strong&gt;No major outage&lt;/strong&gt; was reported — which still doesn’t mean it was free.&lt;/p&gt;

&lt;p&gt;The gotcha we’d seen on older shared ALBs came back: custom ALB SG on the ingress &lt;strong&gt;without&lt;/strong&gt; the LBC-managed “traffic” SG means targets sit &lt;strong&gt;unhealthy / timeout&lt;/strong&gt; until you explicitly allow &lt;strong&gt;tcp/8080 from the ALB SG onto cluster and node SGs&lt;/strong&gt;. Same pattern as before; easy to forget when the manifest “looks” right in Git.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffa6x75yuhjrg5itscoxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffa6x75yuhjrg5itscoxd.png" alt=" " width="338" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploy model shifted too: stopped Argo Rollouts canary for GitOps-managed apps in favor of &lt;strong&gt;RollingUpdate Deployment&lt;/strong&gt; with &lt;code&gt;maxUnavailable: 0&lt;/code&gt; where we configured it — less ceremony, more predictable rollouts for that environment.&lt;/p&gt;

&lt;p&gt;Smaller ALB puzzle on the same listener: one app’s host + &lt;code&gt;/prometheus&lt;/code&gt; returned a fixed &lt;strong&gt;503&lt;/strong&gt; “Backend action does not exist” while another app on the &lt;strong&gt;same&lt;/strong&gt; ALB forwarded &lt;code&gt;/prometheus&lt;/code&gt; fine. Missing or wrong listener rule for the first app’s metrics path — not a pod problem, a rule problem.&lt;/p&gt;

&lt;p&gt;Storm CI got Jenkins docker build + topology deploy aligned with other container workloads; one image tag deployable to multiple topologies with entrypoint &lt;code&gt;sleep infinity&lt;/code&gt; and jar submit on a separate path. Housekeeping that week included infra pod timezone audit (UTC vs IST) and readonly digging on why a gateway deployment scaled one pod at a time — HPA/PDB/scheduling, not glamorous but real.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I’d do again (and what I’m watching)
&lt;/h2&gt;

&lt;p&gt;This wasn’t a single root-cause postmortem; it was &lt;strong&gt;platform whack-a-mole&lt;/strong&gt; with a few sharp takeaways tied to what we actually touched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Patching:&lt;/strong&gt; Gate automation output — dupes, timeouts, arm64 SSM workers — before LT promotion. In-place on ASGs: &lt;strong&gt;Standby → patch → reboot → verify&lt;/strong&gt; &lt;code&gt;uname -r&lt;/code&gt; &lt;strong&gt;and grub default → InService&lt;/strong&gt;. Expect LT replacements to &lt;strong&gt;lack pet config&lt;/strong&gt;; don’t rely on disk state — Ansible, agents, or pull-based config has to be the default. Treat &lt;strong&gt;Jenkins health as a dependency&lt;/strong&gt; on patch night, not a parallel ticket you’ll “get to.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logs:&lt;/strong&gt; If harvesters are zero, fix Filebeat before Logstash. HTTP on 5044 is a distraction with a real fix elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EKS ingress:&lt;/strong&gt; SG-based private ALB is fine if you remember the &lt;strong&gt;ALB SG → node/cluster SG on 8080&lt;/strong&gt; contract every time.&lt;/p&gt;

&lt;p&gt;OpenSearch dedicated masters at ~97–98% OS RAM on ~16 GiB nodes with ~26–70% JVM heap looked alarming until we reconciled fixed ~10 GiB heap with OS “used” not equaling heap pressure — data nodes looked healthier on OS % because of larger RAM and mapped buffers. Critical Elasticsearch data-tier patch/reboot was &lt;strong&gt;prep and read-only SOP&lt;/strong&gt; on our shift, not execution — I’m glad that stayed someone else’s careful window.&lt;/p&gt;

&lt;p&gt;Governance housekeeping: script to copy EC2 instance governance tags to attached EBS volumes (dry-run vs &lt;code&gt;--apply&lt;/code&gt;), tested on one instance before fleet. Prometheus got a new EKS scrape job on non-prod with the same Jenkins encrypt-secret pattern as other EKS jobs.&lt;/p&gt;

&lt;p&gt;If I’d publish one table from the week for my own notebook, it would be symptoms vs layer: duplicate or missing patch AMI → &lt;strong&gt;automation/LT&lt;/strong&gt;; fresh ASG instance missing agents/logs → &lt;strong&gt;replace churn + config drift&lt;/strong&gt;; logs “not sending” with zero harvesters → &lt;strong&gt;Filebeat paths/perms&lt;/strong&gt;; ALB targets timeout → &lt;strong&gt;SG rules on 8080&lt;/strong&gt;, not the app. Nothing here is a new framework — it’s the kind of week where three boring layers stack up and the job is to &lt;strong&gt;not mistake the symptom’s loudest service for the broken contract&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next patch wave, I’m validating AMIs before promotion, running Standby on in-place work, and checking Jenkins agents before I call the night done. The rest can stay in tickets — but those three habits would have saved us half the hours we didn’t get back.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>ai</category>
    </item>
    <item>
      <title>No official Storm Helm chart — how we put Apache Storm on EKS anyway</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sat, 19 Sep 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/no-official-storm-helm-chart-how-we-put-apache-storm-on-eks-anyway-33pj</link>
      <guid>https://dev.to/mridul_it_is/no-official-storm-helm-chart-how-we-put-apache-storm-on-eks-anyway-33pj</guid>
      <description>&lt;p&gt;The Argo CD app for Storm had been red for two days, but the symptom that actually sent me down the rabbit hole was quieter than a crash loop: init containers on the Supervisor pods, stuck forever, printing the same line over and over — &lt;em&gt;waiting for nimbus …:6627&lt;/em&gt;. No Nimbus, no workers, no UI. Just a cluster that looked almost deployed and wasn't.&lt;/p&gt;

&lt;p&gt;We were trying to do something the organization had never done before: run Apache Storm on Kubernetes. Not a lift-and-shift of an existing pattern — there was no pattern. Storm still lived on traditional EC2/ASG elsewhere. The ask was to move it onto the same non-prod EKS cluster we were already standing up for the other application platform: Terraform, Karpenter, Argo GitOps, the whole stack. Streaming workloads sitting with everything else instead of a separate pet fleet.&lt;/p&gt;

&lt;p&gt;That part made sense strategically. Operationally, it was a blank page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why there was no paved road
&lt;/h2&gt;

&lt;p&gt;Apache Storm does not ship a maintained official Helm chart. The project does not publish a credible "migrate Storm to Kubernetes" guide. Community options exist — G-Research's &lt;code&gt;gresearch/storm&lt;/code&gt; chart with a Bitnami ZooKeeper subchart is the one people point at — but nothing we could treat as a supported product. We evaluated it and still built a thin local chart instead, same as other custom overlays in the repo: own the templates, own the values, no opaque upstream dependency.&lt;/p&gt;

&lt;p&gt;That decision felt right and scary in equal measure. We were the first team anywhere in the org — any account, any region — putting Storm on Kubernetes. No internal reference architecture, no runbook, no "copy what prod did." Every choice about storage, networking, image choice, and GitOps layout was experimental. Before we committed, we wrote down what we were afraid of. That list turned out to be more accurate than our initial rollout plan.&lt;/p&gt;

&lt;p&gt;We planned a phased rollout on purpose. Phase one: ZooKeeper and Nimbus only — prove the control plane and that PVCs actually bind. Phase two: Supervisors and Storm UI as stateless Deployments. Phase three: a LogViewer sidecar on supervisor pods, not a separate Deployment. Phase four: private ECR images instead of Docker Hub upstream. Phase five: Storm UI on the shared private ALB ingress pattern the rest of other already used.&lt;/p&gt;

&lt;p&gt;One shared Storm namespace on the non-prod cluster, not one cluster per environment. Karpenter-provisioned ARM64 nodes. A StorageClass for &lt;code&gt;gp3&lt;/code&gt; embedded in the Storm chart itself rather than a separate Argo Application — tradeoff being that chart prune would remove the class, but we avoided yet another GitOps app for a single consumer.&lt;/p&gt;

&lt;p&gt;The architecture looked reasonable on paper:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ZooKeeper&lt;/td&gt;
&lt;td&gt;StatefulSet&lt;/td&gt;
&lt;td&gt;PVC (data + datalog)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nimbus&lt;/td&gt;
&lt;td&gt;StatefulSet&lt;/td&gt;
&lt;td&gt;PVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supervisor&lt;/td&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;emptyDir; pod IP as &lt;code&gt;storm.local.hostname&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storm UI&lt;/td&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;emptyDir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LogViewer&lt;/td&gt;
&lt;td&gt;sidecar on Supervisor&lt;/td&gt;
&lt;td&gt;shared emptyDir &lt;code&gt;/logs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Reasonable, and completely untested in our environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cascade that wasn't obvious at first
&lt;/h2&gt;

&lt;p&gt;When things broke, they did not break loudly. Failure chain number one was storage, and it propagated silently.&lt;/p&gt;

&lt;p&gt;Our chart requested a StorageClass named &lt;code&gt;gp3&lt;/code&gt;. The EBS CSI driver on the cluster was healthy. The StorageClass did not exist. The cluster only had legacy in-tree &lt;code&gt;gp2&lt;/code&gt;. We had flagged this exact fear before rollout — "we feared silent PVC Pending forever" — and we were right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0o3q8iv31s4jbp29e2eq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0o3q8iv31s4jbp29e2eq.png" alt=" " width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PVCs for ZooKeeper and Nimbus sat in &lt;code&gt;Pending&lt;/code&gt;. Without bound volumes, those StatefulSet pods never scheduled. Without Nimbus listening on &lt;code&gt;:6627&lt;/code&gt;, everything downstream waited. Supervisor and UI init containers blocked on the nimbus health check. Argo marked the app Degraded. The StatefulSets showed OutOfSync because pods never became ready. From the outside it looked like a Storm problem. It was a storage class problem three layers down.&lt;/p&gt;

&lt;p&gt;That was the first lesson in how StatefulSet failures hide: init containers do not scream "your StorageClass is wrong." They scream "upstream isn't ready yet," which sends you chasing Nimbus when Nimbus was never going to start.&lt;/p&gt;

&lt;p&gt;We fixed the missing class — embedded &lt;code&gt;gp3&lt;/code&gt; via EBS CSI in the chart — and the control plane could finally land. Then failure chain number two hit immediately, and this one was louder.&lt;/p&gt;

&lt;p&gt;Nimbus crashed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/docker-entrypoint.sh: exec: nimbus: not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Storm UI did the same for &lt;code&gt;ui&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7u6ojzru2n2i0qps69j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7u6ojzru2n2i0qps69j3.png" alt=" " width="545" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We had copied Helm examples that pass bare args like &lt;code&gt;nimbus&lt;/code&gt; or &lt;code&gt;ui&lt;/code&gt;, which works for upstream Docker Hub images. Our private ECR images use a &lt;a href="http://docker-entrypoint.sh" rel="noopener noreferrer"&gt;&lt;code&gt;docker-entrypoint.sh&lt;/code&gt;&lt;/a&gt; that execs the first argument as a command. They need &lt;code&gt;storm nimbus&lt;/code&gt; and &lt;code&gt;storm ui&lt;/code&gt;. Supervisors and the LogViewer sidecar already used the &lt;code&gt;storm …&lt;/code&gt; form; Nimbus and UI did not. Official image docs do not apply when you own the entrypoint. We should have tested container startup before wiring the full chart, not after PVCs finally bound.&lt;/p&gt;

&lt;p&gt;Fix was a one-line args change per deployment. The archaeology cost more time than the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Argo fighting StatefulSets, and the ALB that couldn't find a port
&lt;/h2&gt;

&lt;p&gt;With pods actually running, we got failure chain number three: perpetual Argo sync drift on StatefulSet &lt;code&gt;volumeClaimTemplates&lt;/code&gt;. Kubernetes injects &lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;volumeMode&lt;/code&gt;, and &lt;code&gt;status&lt;/code&gt; after create. Our chart templates did not emit the full schema Argo expected, so the app sat OutOfSync even when the cluster was fine. This is a known footgun with GitOps and StatefulSets. We fixed it two ways: corrected the chart templates to emit the full volumeClaimTemplate schema, and added &lt;code&gt;ignoreDifferences&lt;/code&gt; jq paths with &lt;code&gt;RespectIgnoreDifferences&lt;/code&gt; for the immutable VCT fields Argo will never reconcile away.&lt;/p&gt;

&lt;p&gt;That one felt familiar if you've run StatefulSets under Argo before. The ingress problem did not.&lt;/p&gt;

&lt;p&gt;Failure chain number four was AWS Load Balancer Controller weirdness exposing Storm UI. We wanted the same private ALB pattern as other other apps. LBC returned effectively: TargetGroup port is empty. We had Instance target type with a ClusterIP service — a combination that does not work the way we had it wired. Ingress backends need numeric ports with &lt;code&gt;target-type: ip&lt;/code&gt;, not named ports with Instance mode. We switched to &lt;code&gt;target-type: ip&lt;/code&gt; and backend port &lt;code&gt;8080&lt;/code&gt; as a number, not a named service port. Storm UI came up behind the shared ALB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0o1x28056ltq7tbcy7qm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0o1x28056ltq7tbcy7qm.png" alt=" " width="545" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Separately, we were migrating inbound access on that ALB from CIDR allowlists to security-group-based inbound. That affects every app on the load balancer, not just Storm. We added a parallel SG-based ALB config file so CIDR and SG ingresses could coexist during cutover testing rather than replacing the inbound model on a shared ALB before every consumer was validated.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we validated along the way
&lt;/h2&gt;

&lt;p&gt;Not everything we worried about broke, but everything we worried about deserved an explicit check.&lt;/p&gt;

&lt;p&gt;Stateful workloads on Karpenter made us nervous — ZK and Nimbus expect stable identity and disk; Karpenter nodes are ephemeral by design. For non-prod we accepted single-replica ZooKeeper with no quorum. HA in prod is still an open question.&lt;/p&gt;

&lt;p&gt;ARM64 was non-negotiable on our Karpenter pool. Private ECR images are single-arch. If they had been amd64-only, we'd have seen scheduling failures or runtime crashes on Graviton. We verified arch before calling the rollout done.&lt;/p&gt;

&lt;p&gt;Supervisor and LogViewer logs live on &lt;code&gt;emptyDir&lt;/code&gt;. Pod restart means lost worker logs. Fine for non-prod exploration; scary for prod debugging. We noted it and moved on — durable log shipping is still TBD.&lt;/p&gt;

&lt;p&gt;Topology lifecycle is also TBD. The chart runs the cluster; it does not submit topologies. How jar submit, worker scaling, and upgrades interact with Deployments versus traditional supervisor hosts — we haven't answered that yet. We kept topologies out of scope on purpose so we could fail fast on PVCs and images without dragging application deployment into the first week.&lt;/p&gt;

&lt;p&gt;By the end of the week, all four failure chains were closed. Argo showed the Storm app healthy. We had the first Apache Storm cluster running on EKS in the organization: custom Helm, GitOps-managed, on Karpenter ARM nodes. ZooKeeper and Nimbus StatefulSets bound PVCs. Private images ran once we corrected entrypoints. Storm UI sat behind the same private ALB pattern as the rest of other.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently, and what I'd tell the next team
&lt;/h2&gt;

&lt;p&gt;If I were starting this again, I'd run a pre-flight checklist before the first &lt;code&gt;argocd app sync&lt;/code&gt;, not after init containers had been waiting for forty-eight hours:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;StorageClass exists on the target cluster&lt;/strong&gt; — &lt;code&gt;gp3&lt;/code&gt; via CSI is not the same as in-tree &lt;code&gt;gp2&lt;/code&gt;. PVC Pending cascades silently through init containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container entrypoint behavior&lt;/strong&gt; — &lt;code&gt;docker run&lt;/code&gt; with the exact args your Helm chart will pass, especially for private images. Do not assume &lt;code&gt;args: [nimbus]&lt;/code&gt; from upstream examples.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Argo + StatefulSet volumeClaimTemplates&lt;/strong&gt; — emit the full schema or configure &lt;code&gt;ignoreDifferences&lt;/code&gt; upfront. You will hit VCT drift; budget for it in the chart, not as a week-two surprise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AWS LBC + ClusterIP&lt;/strong&gt; — &lt;code&gt;target-type: ip&lt;/code&gt; and numeric backend ports. Named ports plus Instance mode gave us an empty TargetGroup port and a day of ingress debugging.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The bigger takeaway is about first-in-org workloads. No reference deployment means every assumption — ARM, storage, HA, logs, ingress models on shared infrastructure — has to be validated on the actual cluster. Writing down the fear inventory before we committed did not prevent the failures. It did prevent us from treating them as mysteries. We knew storage was a risk, entrypoints were a risk, Argo StatefulSet sync was a risk, ALB quirks were a risk. When each one fired, we recognized it instead of spiraling.&lt;/p&gt;

&lt;p&gt;We still went forward for good reasons. Platform direction is Kubernetes; maintaining a separate Storm EC2 fleet alongside a new EKS cluster doubles operational surface — patching, AMIs, security groups, deploy pipelines. Non-prod first bounded blast radius. We reused GitOps muscle we already had with other apps, Alloy, Jenkins ingress. Phased delivery let us prove the control plane before workers and UI. Someone had to be first; better on non-prod with eyes open than a surprise prod migration later.&lt;/p&gt;

&lt;p&gt;Prod cutover still has open questions: ZooKeeper HA with a three-node quorum on EKS, a topology submit pipeline from CI, supervisor horizontal scale and slot planning, durable log shipping, whether to adopt the community chart or keep the local one, DNS cutover from legacy Storm UI, and migrating the shared ALB fully to SG-based inbound after all apps are tested. None of those blocked non-prod stand-up. They are the next chapter.&lt;/p&gt;

&lt;p&gt;Storm on Kubernetes is DIY. There is no official Helm chart and no migration guide. Budget time for chart authorship and image entrypoint archaeology. And when init containers say they're waiting for Nimbus, check whether Nimbus ever had a chance to start — the bug might be three layers below Storm itself.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>argocd</category>
    </item>
    <item>
      <title>We tagged EKS workers like app servers — and Prometheus started scraping telegraf on nodes that never had it</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sat, 12 Sep 2026 05:25:01 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/we-tagged-eks-workers-like-app-servers-and-prometheus-started-scraping-telegraf-on-nodes-that-2n59</link>
      <guid>https://dev.to/mridul_it_is/we-tagged-eks-workers-like-app-servers-and-prometheus-started-scraping-telegraf-on-nodes-that-2n59</guid>
      <description>&lt;p&gt;The Telegraf Down alerts started piling up on a Thursday morning, and at first glance it looked bad. Nine targets, all critical, all under the same rule name. My first instinct was a fleet-wide agent failure — something in the monitoring stack had broken overnight and we were about to page half the platform team for a problem that didn't exist.&lt;/p&gt;

&lt;p&gt;It wasn't that. It was worse in a quieter way: one alert name, at least three unrelated root causes, and one of them was our own governance work from three days earlier finally catching up with us.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tagging work nobody thought would touch monitoring
&lt;/h2&gt;

&lt;p&gt;On September 8 we were in the middle of an org-wide AWS governance push — standard tags across prod VPCs for cost allocation, ownership, compliance, inventory. Same schema everywhere: &lt;code&gt;Application&lt;/code&gt;, &lt;code&gt;Component&lt;/code&gt;, &lt;code&gt;businessunit&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;, &lt;code&gt;techteam&lt;/code&gt;, &lt;code&gt;Role&lt;/code&gt;, &lt;code&gt;Criticality&lt;/code&gt;, and the rest. Multiple VPCs in &lt;code&gt;ap-south-1&lt;/code&gt;, each with its own change ticket, but the rules were consistent.&lt;/p&gt;

&lt;p&gt;We were careful about it. Add-only on instances and ASGs — never overwrite existing &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;service&lt;/code&gt;, &lt;code&gt;backup&lt;/code&gt;, or legacy tags. For &lt;code&gt;Component&lt;/code&gt;, &lt;code&gt;businessunit&lt;/code&gt;, and &lt;code&gt;techteam&lt;/code&gt;, if an instance already had a value, we kept it; VPC-wide defaults only filled gaps. VPC-level tags went on first (&lt;code&gt;Tech Owner&lt;/code&gt;, ticket reference), then bulk instance tagging.&lt;/p&gt;

&lt;p&gt;In one prod application VPC, that all went according to plan for the traditional stuff. Tomcat/Spring ASGs already had &lt;code&gt;techteam&lt;/code&gt; set; we added &lt;code&gt;environment=prod&lt;/code&gt; and the common governance keys without touching what was there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1t5dw3x1iex1wc25tbjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1t5dw3x1iex1wc25tbjw.png" alt=" " width="596" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The EKS application nodegroup ASG was different. Before September 8 it only carried EKS-managed tags — &lt;code&gt;eks:cluster-name&lt;/code&gt;, &lt;code&gt;eks:nodegroup-name&lt;/code&gt;, &lt;code&gt;k8s.io/cluster/*&lt;/code&gt;. No &lt;code&gt;techteam&lt;/code&gt;, no &lt;code&gt;environment&lt;/code&gt;, no &lt;code&gt;Application&lt;/code&gt;. The ASG-level script added &lt;code&gt;environment=prod&lt;/code&gt; and the governance keys. &lt;code&gt;techteam&lt;/code&gt; wasn't set at ASG level because our rule said use existing values only, and there wasn't one.&lt;/p&gt;

&lt;p&gt;The running worker instances ended up with &lt;code&gt;techteam&lt;/code&gt;, &lt;code&gt;Application&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;, and &lt;code&gt;businessunit&lt;/code&gt; anyway — likely from EKS nodegroup or launch template tagging tied to the same governance work, not from us replacing an old value. From a compliance perspective, that looked fine. From a monitoring perspective, we had just told Prometheus these were prod platform hosts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the alert fired three days later
&lt;/h2&gt;

&lt;p&gt;Central Prometheus discovers host telegraf via EC2 service discovery. The job filters on &lt;code&gt;tag:environment=prod&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;code&gt;tag:techteam&lt;/code&gt; matching a regex of several platform team values. Scrape port &lt;code&gt;:9273&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;EKS worker nodes are EC2 instances. Once they picked up &lt;code&gt;environment=prod&lt;/code&gt; plus a matching &lt;code&gt;techteam&lt;/code&gt;, they entered the scrape pool. But Kubernetes workers don't run host telegraf on &lt;code&gt;:9273&lt;/code&gt;. Metrics on those nodes come from in-cluster DaemonSets or cAdvisor — not a host agent listening on the standard port.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1qlgsdtxaguoqiw69gg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1qlgsdtxaguoqiw69gg.png" alt=" " width="385" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Five EKS worker targets went permanently &lt;code&gt;up=0&lt;/code&gt;. Telegraf Down, critical. It looked like a sudden outage. It was a discovery side effect from September 8 governance work, surfacing in bulk once alert volume crossed whatever threshold made it impossible to ignore.&lt;/p&gt;

&lt;p&gt;That was the story I wanted to be true — one cause, one fix, done by lunch. I started grouping targets by hostname and role before touching anything, which turned out to be the only reason we didn't make things worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  One alert, three root causes
&lt;/h2&gt;

&lt;p&gt;Prometheus showed roughly nine telegraf targets down, plus one kafka exporter and one redis exporter. Same alert family, completely different problems underneath.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EKS workers (5 hosts)&lt;/strong&gt; — tagging side effect. These nodes were never supposed to be in the EC2 SD scrape pool. They matched the tag filter after governance tagging. No telegraf process on &lt;code&gt;:9273&lt;/code&gt; because that's not how we monitor Kubernetes workers. False positive, unfixed at the time we captured this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New AL2023 ASG instances (2 hosts)&lt;/strong&gt; — real telegraf misconfiguration, unrelated to EKS. Launched a few days before the alert spike. Telegraf RPM was installed, but the config was broken: &lt;code&gt;prometheus_client&lt;/code&gt; output was commented out, so the agent logged "no outputs found" and had nothing to expose on the scrape port. Ansible-pull had never run on those boxes to template &lt;code&gt;telegraf.conf&lt;/code&gt;. Fixes for AL2023 telegraf existed in the ansible repo; they just hadn't been applied to new ASG instances because there was no ansible-pull cron on those hosts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kafka broker (&lt;/strong&gt;&lt;code&gt;:9308&lt;/code&gt;&lt;strong&gt;)&lt;/strong&gt; — long-standing debt, not a telegraf problem. The kafka exporter service had been disabled for months. Telegraf on &lt;code&gt;:9278&lt;/code&gt; on the same host was actually fine. The alert rule conflated exporter health with agent health, or we were looking at the wrong port when we first opened the target list.&lt;/p&gt;

&lt;p&gt;On top of those three, we also had a redis host with both telegraf and redis exporter down, and a dev/test host that probably shouldn't have been in the prod scrape config at all. Different owners, different fixes — all wearing the same alert costume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxxdbn9dmr5ni68naywx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxxdbn9dmr5ni68naywx.png" alt=" " width="489" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I spent a while on the kafka broker before I noticed telegraf was healthy and the exporter was the dead component. Classic trap: one alert name makes you assume one failure mode. The AL2023 hosts took longer because the RPM was &lt;em&gt;there&lt;/em&gt; — &lt;code&gt;systemctl status telegraf&lt;/code&gt; looked plausible until you read the config and saw the commented output block. EKS was the fastest to classify once I checked tags and confirmed no listener on &lt;code&gt;:9273&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix we wanted vs. the fixes we didn't want
&lt;/h2&gt;

&lt;p&gt;For the EKS issue, the least-change path was a Prometheus relabel drop on the telegraf EC2 SD job: drop targets where &lt;code&gt;eks:cluster-name&lt;/code&gt; exists (or an equivalent EKS tag). Roughly four lines, config reload. No governance rollback, no new DaemonSet, no alert silence.&lt;/p&gt;

&lt;p&gt;We explicitly ruled out a few alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove tags from the nodegroup&lt;/strong&gt; — rolls back compliance work for a monitoring problem. Wrong lever.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install host telegraf as a DaemonSet on EKS&lt;/strong&gt; — large ops burden unless we actually need host-level metrics on workers, which we don't for this scrape job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Silence the alert&lt;/strong&gt; — hides real failures on the AL2023 hosts and the kafka/redis issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the AL2023 hosts, the real fix is ansible-pull (or equivalent) running the telegraf role so &lt;code&gt;prometheus_client&lt;/code&gt; output gets templated correctly. That's ops work on two boxes, not a Prometheus change.&lt;/p&gt;

&lt;p&gt;For kafka, re-enable the exporter after verifying cluster health — separate ticket, separate owner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn85l504xq4xhfdnkndtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn85l504xq4xhfdnkndtu.png" alt=" " width="461" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the time we captured this, most of those fixes were still pending: Prometheus relabel for EKS nodes, ansible-pull on the AL2023 ASGs, kafka exporter re-enablement, and SSH access to diagnose the redis host.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd check before the next bulk VPC tag
&lt;/h2&gt;

&lt;p&gt;Governance tags and monitoring discovery share the same key space. We use &lt;code&gt;environment&lt;/code&gt; and &lt;code&gt;techteam&lt;/code&gt; for cost and compliance; Prometheus EC2 SD uses the same keys to decide what to scrape. Those two systems don't talk to each other until an alert fires.&lt;/p&gt;

&lt;p&gt;Before bulk tagging a VPC, I'd pull the EC2 SD jobs that filter on those tag keys and ask: will EKS nodes enter this pool? Will patch-automation orphans? Dev instances that happen to have &lt;code&gt;environment=prod&lt;/code&gt; from a template copy? Tagging makes an instance &lt;em&gt;visible&lt;/em&gt; to discovery; it doesn't install the agent discovery expects.&lt;/p&gt;

&lt;p&gt;EKS workers are not app EC2. Tagging them like traditional Tomcat boxes makes Prometheus expect host telegraf on &lt;code&gt;:9273&lt;/code&gt;. The nodes did nothing wrong. The tags were correct for governance. The scrape config was written for a different kind of machine.&lt;/p&gt;

&lt;p&gt;And when nine targets go red under one rule name, classify by host role before you fix anything. We almost treated a compliance side effect, a config drift on new AMIs, and months-old exporter debt as a single incident. They're three. The alert didn't know that. We had to.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>ai</category>
    </item>
    <item>
      <title>Standing up a greenfield EKS cluster — and every mistake we stepped on</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sat, 05 Sep 2026 04:25:11 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/standing-up-a-greenfield-eks-cluster-and-every-mistake-we-stepped-on-40h9</link>
      <guid>https://dev.to/mridul_it_is/standing-up-a-greenfield-eks-cluster-and-every-mistake-we-stepped-on-40h9</guid>
      <description>&lt;p&gt;The Argo CD UI showed &lt;code&gt;SyncFailed&lt;/code&gt; on &lt;code&gt;karpenter-node-infra&lt;/code&gt; before we'd deployed a single application pod. &lt;code&gt;EC2NodeClass&lt;/code&gt; and &lt;code&gt;NodePool&lt;/code&gt; didn't exist in the cluster — not because the manifests were wrong, but because the CRDs had never been installed. We'd already burned an afternoon on Terraform provider pins and ARM AMI mismatches. This was supposed to be the easy part: GitOps bootstrap, Karpenter online, move on.&lt;/p&gt;

&lt;p&gt;It wasn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we were building
&lt;/h2&gt;

&lt;p&gt;We weren't cloning a legacy self-managed K8s 1.21 ASG stack. This was a greenfield non-prod EKS cluster in an existing VPC — private API only, VPN/office CIDRs on the cluster security group, subnets tagged for cluster shared ownership, internal ELB, and &lt;code&gt;karpenter.sh/discovery&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The compute model had two layers on purpose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1&lt;/strong&gt; — a bootstrap managed node group: on-demand ARM64, AL2023, &lt;code&gt;t4g.xlarge&lt;/code&gt;-class instances, min 1 / max 3, tainted &lt;code&gt;CriticalAddonsOnly=true:NoSchedule&lt;/code&gt;. It runs Karpenter controller, Argo CD, EKS addons, and optionally Cluster Autoscaler scoped only to that ASG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2&lt;/strong&gt; — Karpenter NodePool for application workloads, with a separate EC2NodeClass and IAM role.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsim2v58mqjx97rteb6m9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsim2v58mqjx97rteb6m9.png" alt=" " width="389" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We chose Karpenter over Cluster Autoscaler for app scaling, EKS Pod Identity (not IRSA) for Karpenter/LBC/CA auth, Terragrunt for backend/provider DRY, &lt;code&gt;terraform-aws-modules/eks&lt;/code&gt; ~20.36, and a dedicated GitOps branch. Target Kubernetes version: &lt;strong&gt;1.36&lt;/strong&gt; on create — destroy/recreate, not an upgrade ladder on an empty cluster.&lt;/p&gt;

&lt;p&gt;That all sounded clean on paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform got mean before the cluster existed
&lt;/h2&gt;

&lt;p&gt;The first &lt;code&gt;terraform plan&lt;/code&gt; failure was the AWS provider. We'd drifted to provider 6.x; EKS module 20.x still references launch template fields that 6.x removed. Plan blew up with errors about fields that no longer exist. Fix was blunt: pin &lt;code&gt;hashicorp/aws &amp;gt;= 5.40, &amp;lt; 6.0&lt;/code&gt; alongside the module version and document the upper bound next time we bump either one.&lt;/p&gt;

&lt;p&gt;Then architecture assumptions collided with reality. We started with spot on the bootstrap pool; requirement clarified to &lt;strong&gt;100% on-demand&lt;/strong&gt;. Fine — but we'd already baked spot into early config. More annoying: we paired an &lt;strong&gt;ARM64 AMI&lt;/strong&gt; with &lt;strong&gt;x86 instance types&lt;/strong&gt;. AMI architecture has to match the instance family. Obvious in hindsight, expensive when you're staring at nodes that never join correctly.&lt;/p&gt;

&lt;p&gt;The managed node group apply failed when AWS still had &lt;code&gt;desired=0&lt;/code&gt; while we set &lt;code&gt;min_size=1&lt;/code&gt;. The EKS module ignores &lt;code&gt;desired_size&lt;/code&gt; after create — so on first create you have to set min/desired/max together, or manually bump desired ≥ min once before apply. I didn't know that until apply failed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvpn3lpgagj2jaw66z79z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvpn3lpgagj2jaw66z79z.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Disk was another silent lie. Module defaults said &lt;code&gt;disk_size=50&lt;/code&gt;, but instances came up around &lt;strong&gt;20 GiB&lt;/strong&gt;. The module default doesn't always win against the launch template path we were on. We needed explicit &lt;code&gt;block_device_mappings&lt;/code&gt; on the bootstrap launch template — 50 GiB gp3 root — to get what we thought we'd already configured.&lt;/p&gt;

&lt;p&gt;IAM role &lt;code&gt;name_prefix&lt;/code&gt; exceeded &lt;strong&gt;38 characters&lt;/strong&gt;. Set a short explicit &lt;code&gt;iam_role_name&lt;/code&gt; on the node group instead of letting Terraform generate something too long.&lt;/p&gt;

&lt;p&gt;We pinned the AL2023 ARM AMI via data source to &lt;code&gt;cluster_version&lt;/code&gt;, not "latest surprise AMI." Addons in order: pod-identity-agent before compute, then coredns, vpc-cni, kube-proxy, ebs-csi. Karpenter got its node role, instance profile, access entry, and controller Pod Identity association in Terraform — which almost caused a duplicate IAM role later when GitOps still pointed at IRSA from a reference cluster. More on that.&lt;/p&gt;

&lt;p&gt;One dead end I won't repeat: &lt;code&gt;CONTAINER_RUNTIME=docker&lt;/code&gt; on AL2023 / K8s 1.32+. Invalid. Dockershim is gone. &lt;strong&gt;containerd via nodeadm&lt;/strong&gt; is the correct path on AL2023.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitOps: where reference configs go to die
&lt;/h2&gt;

&lt;p&gt;We copied a reference GitOps branch without scrubbing it. Wrong cluster names, IRSA ARNs, Karpenter version mismatched to our K8s version. I almost created a &lt;strong&gt;duplicate Karpenter controller IAM role&lt;/strong&gt; — Terraform already had Pod Identity wired up, but Helm values still carried IRSA annotations from the old cluster.&lt;/p&gt;

&lt;p&gt;Argo CD itself went on the bootstrap nodes with tolerations for &lt;code&gt;CriticalAddonsOnly&lt;/code&gt;. Helm install first, then a Git deploy key secret — pods don't have &lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt;, so SSH agent forwarding wasn't an option.&lt;/p&gt;

&lt;p&gt;Bootstrap order we settled on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Argo CD on bootstrap nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git deploy key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;karpenter-crds&lt;/code&gt; app (sync wave -1) — CRDs from chart &lt;code&gt;crds/&lt;/code&gt; dir, ServerSideApply&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Karpenter controller (&lt;code&gt;skipCrds: true&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;karpenter-node-infra&lt;/code&gt; — EC2NodeClass + NodePool manifests&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That order exists because of a Helm behavior that's easy to miss: &lt;code&gt;helm template&lt;/code&gt; &lt;strong&gt;skips the chart&lt;/strong&gt; &lt;code&gt;crds/&lt;/code&gt; &lt;strong&gt;directory&lt;/strong&gt;. The controller chart never installed NodePool/EC2NodeClass CRDs. Argo kept reporting SyncFailed until we split CRDs into their own Application.&lt;/p&gt;

&lt;p&gt;We made it worse before we made it better. &lt;strong&gt;Two Argo apps owned the same CRDs&lt;/strong&gt;, and we had &lt;strong&gt;argo-cd self-sync&lt;/strong&gt; enabled. Sync deadlock. CRD ownership has to be exactly one Argo app; the controller must use &lt;code&gt;skipCrds: true&lt;/code&gt;. And the Application for &lt;code&gt;argo-cd&lt;/code&gt; itself should &lt;strong&gt;not&lt;/strong&gt; auto-sync — that's another path to deadlock.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;valueFiles: ../../helm-values/...&lt;/code&gt; failed with parent path escape — Argo blocked it, charts rendered empty. Fix: multi-source with &lt;code&gt;ref: values&lt;/code&gt;, or keep values under paths Argo allows inside the chart tree.&lt;/p&gt;

&lt;p&gt;Bootstrap node sizing bit us too. &lt;code&gt;t4g.large&lt;/code&gt; was too small for Argo + Karpenter + all system addons. We bumped to &lt;strong&gt;xlarge&lt;/strong&gt; and stopped fighting eviction loops on the control plane of our control plane.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Karpenter vs Cluster Autoscaler confusion
&lt;/h2&gt;

&lt;p&gt;Mid-build someone asked why Cluster Autoscaler wasn't adding nodes for pending app pods. Because &lt;strong&gt;app capacity is Karpenter's job&lt;/strong&gt;, not CA's. We scoped CA to the bootstrap ASG only — optional, and only for that tainted pool. Pending app workloads need a healthy NodePool, EC2NodeClass, and Karpenter controller — not CA scale-out.&lt;/p&gt;

&lt;p&gt;That question was a signal we'd documented the two-layer model in Terraform but not clearly enough in runbooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version path we shouldn't have taken
&lt;/h2&gt;

&lt;p&gt;On an empty cluster we walked 1.31 → 1.32 → 1.34 → 1.36 instead of targeting &lt;strong&gt;1.36 upfront&lt;/strong&gt; and destroy/recreating once. Greenfield means you pick the version before first apply, not ladder upgrades on nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The repo-server red herring
&lt;/h2&gt;

&lt;p&gt;After a bootstrap node recycle, Argo showed &lt;code&gt;ComparisonError&lt;/code&gt; and repo-server connection refused. I spent time suspecting chart bugs. Stale comparison state. Once bootstrap pods were healthy again, &lt;strong&gt;refresh&lt;/strong&gt; cleared it — not a chart fix, not a Git problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually worked
&lt;/h2&gt;

&lt;p&gt;When we stopped fighting copied config and pinned the boring stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Terraform: provider &lt;code&gt;&amp;lt; 6.0&lt;/code&gt;, explicit gp3 50 GiB on launch template, min/desired/max aligned on first NG create, Pod Identity for Karpenter/LBC/CA, short IAM role names, AMI arch matched to Graviton instance types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitOps: skeleton branch scrubbed for cluster name, discovery tag, Pod Identity vs IRSA, Karpenter version for K8s 1.36. Single CRD owner app with ServerSideApply. Controller with &lt;code&gt;skipCrds: true&lt;/code&gt;. No auto-sync on argo-cd self-management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime: xlarge bootstrap nodes, on-demand only, containerd via nodeadm on AL2023.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;End state: private control plane, Pod Identity auth, GitOps-ready Karpenter scaling, system controllers isolated from app workloads on a repeatable greenfield pattern.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fglbsqxeny84xwjaevsdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fglbsqxeny84xwjaevsdq.png" alt=" " width="389" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently next time
&lt;/h2&gt;

&lt;p&gt;I'd treat the pre-apply checklist as blocking, not advisory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Confirm on-demand vs spot, ARM vs x86, target K8s version &lt;strong&gt;before&lt;/strong&gt; first &lt;code&gt;terraform apply&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Size bootstrap for Argo + Karpenter + all addons — start at xlarge.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the EKS module &lt;code&gt;desired_size&lt;/code&gt; ignore behavior and set all three sizing knobs together on create.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pin AWS provider upper bound whenever we pin EKS module version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitOps from a skeleton, never a fork — scrub names, discovery tags, Pod Identity vs IRSA, Karpenter/K8s version alignment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CRD ownership: one Argo app, controller skips CRDs, argo-cd app doesn't auto-sync.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;valueFiles&lt;/code&gt;: stay inside allowed paths or use multi-source values refs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cluster came up fine in the end. The story isn't "EKS is hard" — it's that greenfield gives you freedom to skip legacy baggage and still step on every sharp edge if you copy someone else's YAML without reading it. We learned more from the SyncFailed CRDs and the provider 6.x plan failure than from the architecture diagram. That's probably how it should be.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>terraform</category>
    </item>
    <item>
      <title>When Kafka Hits 100% Disk and the Volume Won't Grow</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sat, 29 Aug 2026 06:44:43 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/when-kafka-hits-100-disk-and-the-volume-wont-grow-4017</link>
      <guid>https://dev.to/mridul_it_is/when-kafka-hits-100-disk-and-the-volume-wont-grow-4017</guid>
      <description>&lt;p&gt;The alert didn't come from consumer lag. It came from disk — two of three brokers on our production Kafka cluster reporting &lt;code&gt;/data&lt;/code&gt; at 100%, with about 20K free on an 850G EBS volume. That's not "we should look at this tomorrow" territory. That's "something is about to stop accepting writes" territory.&lt;/p&gt;

&lt;p&gt;We couldn't expand the volume. Not "we'd prefer not to" — the EBS volume literally wasn't modifiable at that moment. So the usual playbook — bump the disk, watch the graph flatten — was off the table. Whatever we did had to reclaim space from inside Kafka itself, without casually deleting segments on prod.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we were looking at
&lt;/h2&gt;

&lt;p&gt;This is a three-broker cluster in production. The pain was concentrated on a high-volume log topic: 40 partitions, replication factor 2, fed by Kubernetes log shippers. Three consumer groups were attached. On paper, consumption looked fine — lag was around 262, which is nothing you'd page on.&lt;/p&gt;

&lt;p&gt;Two brokers were pinned at 100%. The third still had headroom, which told us this wasn't a uniform cluster-wide misconfiguration; it was a retention and placement problem playing out unevenly across replicas.&lt;/p&gt;

&lt;p&gt;The topic config, when we pulled it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;retention.ms=172800000        # 48 hours
retention.bytes=-1            # no byte cap
segment.bytes=536870912       # 512MB segments
compression.type=producer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forty-eight hours of retention with no byte limit on a topic that ingests K8s logs at scale. That's the kind of config you set once during bootstrap and never revisit until &lt;code&gt;/data&lt;/code&gt; screams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with the obvious — and ruling things out
&lt;/h2&gt;

&lt;p&gt;First instinct: consumer lag. Maybe Logstash fell behind and segments aren't getting cleaned up because consumers haven't committed offsets far enough?&lt;/p&gt;

&lt;p&gt;We checked. Lag was ~262. Consumers were keeping up. That dead end mattered — it kept us from burning time scaling consumers as the primary fix. (More on Logstash later; it was a follow-up, not the root cause.)&lt;/p&gt;

&lt;p&gt;Next: how big is this topic actually?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; /data/kafka-logs/&amp;lt;topic&amp;gt;-&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Roughly 30G per partition. Forty partitions, RF=2 — the math adds up fast. Even with compression (&lt;code&gt;producer&lt;/code&gt;), you're holding two days of high-volume log traffic with no ceiling on total bytes. The disk didn't fill because consumers were slow. It filled because retention policy said "keep everything for 48 hours, however big that gets."&lt;/p&gt;

&lt;p&gt;I also briefly entertained a storage hack: attach a third EBS volume and use &lt;code&gt;growpart&lt;/code&gt; to extend the existing 850G disk. That doesn't work the way I wanted it to — you can't just bolt on block storage and grow an existing filesystem across unrelated volumes. Ruled out before anyone got too excited about it.&lt;/p&gt;

&lt;p&gt;At this point the picture was clear: &lt;strong&gt;time-based retention with no byte cap on a firehose topic&lt;/strong&gt;. Segments age out on the clock, not on disk pressure. Low lag doesn't help if you're still obligated to retain 48 hours of data regardless of volume.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why two brokers and not three
&lt;/h2&gt;

&lt;p&gt;With RF=2 on 40 partitions across three brokers, replica distribution isn't perfectly even. Leader election and partition assignment meant two brokers ended up holding more of the heavy replicas. The third broker had room — which is almost worse, because it makes the incident look like a broker problem when it's really a topic policy problem showing up asymmetrically.&lt;/p&gt;

&lt;p&gt;Running diagnostics locally had its own friction. One broker had bootstrap connection quirks when I tried to run &lt;code&gt;kafka-configs&lt;/code&gt; from my laptop — enough to slow me down, not enough to change the diagnosis. I didn't capture the exact error string, but it was the kind of thing where you SSH to the broker and run the command there instead of fighting client config for twenty minutes during an incident.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix we could actually do in prod
&lt;/h2&gt;

&lt;p&gt;Manual log deletion on a prod cluster is a last resort. You can orphan consumers, confuse leaders, and create a very exciting afternoon for everyone. We needed Kafka's delete policy to do the work — which meant changing retention so old segments become eligible for cleanup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv4jb9yqbkyuvty9elzb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv4jb9yqbkyuvty9elzb2.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The prod-safe path:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tighten&lt;/strong&gt; &lt;code&gt;retention.ms&lt;/code&gt; — we targeted 24h instead of 48h. Halving the time window doesn't instantly free 850G, but it changes which segments are eligible for deletion on the next cleanup cycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Set&lt;/strong&gt; &lt;code&gt;retention.bytes&lt;/code&gt; — this was the important half. Per-broker byte limits give the delete policy something to act on when time alone isn't enough. With &lt;code&gt;-1&lt;/code&gt;, Kafka had no reason to drop data early regardless of disk pressure.&lt;/p&gt;

&lt;p&gt;Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kafka-configs &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; &amp;lt;broker&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--entity-type&lt;/span&gt; topics &lt;span class="nt"&gt;--entity-name&lt;/span&gt; &amp;lt;log-topic&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alter&lt;/span&gt; &lt;span class="nt"&gt;--add-config&lt;/span&gt; retention.ms&lt;span class="o"&gt;=&lt;/span&gt;86400000,retention.bytes&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;per-broker-cap&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact byte cap needs to fit your partition count and RF — you're budgeting across replicas, not pretending one broker owns the whole topic. I don't have the final number we landed on in my notes, but the principle was: set a cap that forces segment deletion before &lt;code&gt;/data&lt;/code&gt; hits 100% again, with headroom for normal variance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Pause or scale down producers if needed&lt;/strong&gt; — before flipping retention on a full disk, you sometimes need to stop the inbound firehose briefly. K8s log shippers don't care about your incident; they'll keep writing. Reducing producer pressure before the config change gives the delete policy room to catch up instead of fighting new segments while old ones are still technically retained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Watch segments actually disappear&lt;/strong&gt; — this isn't instant. Cleanup runs on a schedule. We monitored &lt;code&gt;/data&lt;/code&gt; free space and confirmed segments aging past the new retention window were getting removed. No manual &lt;code&gt;rm -rf&lt;/code&gt; in the log directories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logstash — real problem, wrong root cause
&lt;/h2&gt;

&lt;p&gt;Only 2 of 7 Logstash instances were consuming this topic. That's worth fixing. Under-provisioned consumption can cause lag, can cause operational blind spots, and is generally sloppy.&lt;/p&gt;

&lt;p&gt;But lag was 262. The disk was full because retention said "keep 48 hours, unlimited size." Scaling Logstash would improve throughput and resilience; it would not have emptied an 850G volume holding two days of unrestricted log data. We flagged it as follow-up work, not incident mitigation.&lt;/p&gt;

&lt;p&gt;That's a distinction I want to keep sharp: &lt;strong&gt;healthy-looking lag masked an unhealthy retention policy&lt;/strong&gt;. I've seen teams chase consumer scaling during disk incidents before. Sometimes that's right. Here it would've been a distraction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;I'd have caught this before &lt;code&gt;/data&lt;/code&gt; hit 100%. Disk usage per broker and retention config on high-volume topics belong in the same dashboard. Lag alone is a lie of omission when &lt;code&gt;retention.bytes=-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If I couldn't resize the volume during the incident, I'd still open the ticket to make it resizable — storage headroom isn't a substitute for correct retention, but running prod Kafka with no expansion path is its own risk.&lt;/p&gt;

&lt;p&gt;Next time I'd also verify Logstash consumer coverage during topic onboarding, not during a disk emergency. Two of seven is a config drift problem waiting to happen.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Takeaways from this one:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Low consumer lag does not mean disk is healthy. Check &lt;code&gt;retention.ms&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;retention.bytes&lt;/code&gt; when &lt;code&gt;/data&lt;/code&gt; fills on log-heavy topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;K8s log shippers feeding Kafka can fill brokers even when every consumer group looks caught up — the firehose doesn't care about your lag graph.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you can't expand the volume, your only safe lever is retention policy. Set byte caps before you need them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>kafka</category>
      <category>ebs</category>
      <category>aws</category>
    </item>
    <item>
      <title>Why our liveness probe timed out even though /healthCheck never touched Redis</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sat, 22 Aug 2026 04:42:07 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/why-our-liveness-probe-timed-out-even-though-healthcheck-never-touched-redis-404j</link>
      <guid>https://dev.to/mridul_it_is/why-our-liveness-probe-timed-out-even-though-healthcheck-never-touched-redis-404j</guid>
      <description>&lt;p&gt;The alert looked like a dependency outage. Readiness and liveness on our Java service were failing in bursts — &lt;code&gt;context deadline exceeded (Client.Timeout exceeded while awaiting headers)&lt;/code&gt; — and around the same window, application logs were full of cache and Redis errors. My first instinct was to trace the health handler and ask whether we'd accidentally started pinging Redis on every probe.&lt;/p&gt;

&lt;p&gt;We hadn't. The handler was a static 200 OK. When it actually ran, it logged ~0 ms. That mismatch — probes dying while the health code looked fine — is what sent us down the wrong path for a few hours, and what eventually made the real cause obvious.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi257w1lmt49ccwh9owz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi257w1lmt49ccwh9owz.png" alt=" " width="394" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What we were running
&lt;/h2&gt;

&lt;p&gt;The service is a Spring Boot app behind an ingress and an AWS target group. Kubernetes runs liveness and readiness as HTTP GETs against the same path: &lt;code&gt;/healthCheck&lt;/code&gt;. Period 10 seconds, &lt;code&gt;timeoutSeconds: 1&lt;/code&gt;. The load balancer runs its own health check on the same path and port every 10 seconds.&lt;/p&gt;

&lt;p&gt;That endpoint is deliberately dumb. It does not call Redis, a database, or anything downstream. Passing the probe only proves the HTTP server can accept a request and return a response. We treat dependency health elsewhere; this path is supposed to be cheap.&lt;/p&gt;

&lt;p&gt;Under normal traffic, that design works. During an HPA scale event, it did not.&lt;/p&gt;

&lt;h2&gt;
  
  
  When things started failing
&lt;/h2&gt;

&lt;p&gt;Failures weren't steady. They clustered when the deployment scaled or pods churned — new replicas coming up, old ones draining, traffic shifting. Fresh pods looked fine. Older ones in the middle of the fleet would fail probes, then sometimes recover after load redistributed. Less often we saw &lt;code&gt;connection refused&lt;/code&gt; on pods that were starting or terminating; that part felt like noise until we separated it from the timeout failures.&lt;/p&gt;

&lt;p&gt;The timeout failures were the scary ones. Kubernetes marked pods not ready or restarted them. From outside, it looked like the service was unhealthy. From inside, when we grepped logs for the health handler itself, we kept finding fast 200s — but only on the requests that actually reached the handler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkrmrwa4mjb86zvl4jb21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkrmrwa4mjb86zvl4jb21.png" alt=" " width="247" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That distinction mattered. We weren't looking at a slow health check. We were looking at health checks that sometimes never got a thread in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chasing Redis (and missing the point)
&lt;/h2&gt;

&lt;p&gt;The timeline overlap with Redis/cache errors made this harder than it should have been. Business API paths were logging codec and connectivity issues. Latency on those endpoints spiked. It was reasonable to wonder if &lt;code&gt;/healthCheck&lt;/code&gt; had grown a dependency check we didn't know about, or if Spring's health aggregation had been turned on for something we thought was isolated.&lt;/p&gt;

&lt;p&gt;We walked the handler and confirmed: static response, no downstream calls. Optional jar/source review would have been redundant — runtime logs already showed 0 ms when the handler executed. So the cache errors were real, but they weren't &lt;em&gt;in&lt;/em&gt; the probe path. They were on API traffic that shared infrastructure with the probe path.&lt;/p&gt;

&lt;p&gt;That was our first dead end as a root cause, though not as a contributing factor. Fixing Redis wouldn't fix probe timeouts by making &lt;code&gt;/healthCheck&lt;/code&gt; faster — there was nothing left to speed up in the handler itself. But Redis slowness could still make everything worse if it blocked the threads that were supposed to serve probes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thread pool saturation
&lt;/h2&gt;

&lt;p&gt;Tomcat serves &lt;code&gt;/healthCheck&lt;/code&gt; and every API route from the same worker thread pool. We had the pool capped around 200 threads. Under load, especially during scale events when traffic hadn't yet spread evenly, worker threads filled up with slow API work. Redis trouble on those paths added latency and kept threads busy longer.&lt;/p&gt;

&lt;p&gt;Probes don't wait politely. Kubelet hits liveness and readiness every 10 seconds with a 1-second timeout. The target group adds another &lt;code&gt;/healthCheck&lt;/code&gt; every 10 seconds per instance. Those requests land in the same queue as everything else. If all 200 threads are tied up waiting on cache calls or slow downstream logic, a probe sits in the accept queue until the client gives up waiting for headers.&lt;/p&gt;

&lt;p&gt;Hence the error text: not a connection failure to Redis, not a 500 from the health handler — &lt;code&gt;Client.Timeout exceeded while awaiting headers&lt;/code&gt;. The TCP connection might succeed; the response never starts in time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhabwamdwwabjai3sfgff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhabwamdwwabjai3sfgff.png" alt=" " width="323" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we framed it that way, the intermittent pattern made sense. New pods after scale-up had empty pools and a smaller share of traffic until the service settled. They passed probes immediately. Older pods holding more connections and hotter thread utilization failed first. Pods we terminated showed &lt;code&gt;connection refused&lt;/code&gt; because the process was already gone — expected, and a different failure mode from starvation.&lt;/p&gt;

&lt;p&gt;We didn't capture exact queue depths or a precise latency number in the notes from that shift. What we had was correlation: HPA events, probe failures, high thread occupancy, and cache errors on API paths — not on the health handler when it ran.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjzsov1yv0vq10x5qn3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcjzsov1yv0vq10x5qn3t.png" alt=" " width="395" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "raise the timeout" wasn't the whole story
&lt;/h2&gt;

&lt;p&gt;Raising &lt;code&gt;timeoutSeconds&lt;/code&gt; above 1 would give probes more time to wait for a free thread. That's a valid mitigation and probably stops the bleeding on liveness kills. But it treats the symptom. A 3-second probe timeout on a handler that executes in 0 ms is a signal that something else is wrong with capacity or isolation.&lt;/p&gt;

&lt;p&gt;We weighed a few changes together:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increase probe timeout.&lt;/strong&gt; Low risk, quick to deploy. Buys headroom when the pool is briefly saturated. Doesn't fix API slowness or reduce thread contention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate probe traffic from application traffic.&lt;/strong&gt; A dedicated connector or a minimal probe path served on a different thread pool (or even a sidecar/admin port) means kubelet and the load balancer aren't competing with &lt;code&gt;/api/...&lt;/code&gt; for the same 200 workers. This is more work but addresses the architectural coupling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix the cache codec errors on API paths.&lt;/strong&gt; Indirect but real. Errors that slow business requests keep threads pinned longer, which increases the odds that a probe waits past 1 second. The health endpoint wasn't broken; the pool was over-subscribed because of problems elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop triple-stacking the same path.&lt;/strong&gt; Liveness, readiness, and the target group all hammer &lt;code&gt;/healthCheck&lt;/code&gt; on the same port. Each alone is light; combined with API load on one pool, they're another source of contention. Readiness might warrant a slightly richer check; liveness should stay as dumb as possible — but not necessarily on the same threads as heavy traffic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ved4kspvslcr87g67p1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ved4kspvslcr87g67p1.png" alt=" " width="301" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We didn't treat "make &lt;code&gt;/healthCheck&lt;/code&gt; ping Redis so failures are honest" as a fix. That would have made probes fail for the wrong reason and conflated "app process up" with "cache reachable," which is exactly what we'd almost done when we misread the Redis log correlation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed
&lt;/h2&gt;

&lt;p&gt;The immediate config change was increasing probe &lt;code&gt;timeoutSeconds&lt;/code&gt; so transient saturation during scale events didn't restart pods. In parallel — because the evidence pointed at thread occupancy, not handler logic — we prioritized the cache errors on API routes that were holding threads and traced whether Tomcat's max threads and accept queue were appropriate for peak + probe overhead.&lt;/p&gt;

&lt;p&gt;Longer term, the design direction was clear: isolate probe handling from the main servlet traffic, and avoid using one static endpoint for liveness, readiness, and external health checks without explicit headroom in the pool.&lt;/p&gt;

&lt;p&gt;After deploy, the pattern we watched for was the same one that fooled us initially: new pods staying green while the fleet scales. That's not proof the problem is gone. It only means those instances haven't hit saturation yet. Validation was watching older replicas through the next HPA event and confirming probes stayed green while API latency and thread utilization stayed within bounds — and that when cache errors appeared, they didn't precede another wave of probe timeouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd check first next time
&lt;/h2&gt;

&lt;p&gt;If the health handler is trivial and logs show 0 ms when it runs, but Kubernetes reports probe timeouts, I wouldn't start with dependency connectivity. I'd look at thread pool utilization, probe timeout vs period, and who else hits that path — kubelet twice (liveness + readiness), plus the load balancer — on the same connector as production API traffic.&lt;/p&gt;

&lt;p&gt;Probe timeout is not the same as dependency failure. A 1-second timeout on a 0 ms handler is telling you the request didn't get served in time, not that the handler logic failed. &lt;code&gt;connection refused&lt;/code&gt; on shutting-down pods is a separate signal from &lt;code&gt;awaiting headers&lt;/code&gt; on live ones.&lt;/p&gt;

&lt;p&gt;The lesson from this incident isn't "monitor more." It's narrower: &lt;strong&gt;a healthy&lt;/strong&gt; &lt;code&gt;/healthCheck&lt;/code&gt; &lt;strong&gt;implementation can still fail probes when the HTTP server is saturated&lt;/strong&gt;, and log lines about Redis on other endpoints can send you on a long detour if you assume every failure mode must flow through the health handler itself.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>java</category>
    </item>
    <item>
      <title>One Helm template change broke every Argo app — fixing nil `ingressInt` safely</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sun, 16 Aug 2026 13:30:07 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/one-helm-template-change-broke-every-argo-app-fixing-nil-ingressint-safely-dk8</link>
      <guid>https://dev.to/mridul_it_is/one-helm-template-change-broke-every-argo-app-fixing-nil-ingressint-safely-dk8</guid>
      <description>&lt;p&gt;The Slack thread started the way these things usually do: three people pasting the same Argo CD error within a few minutes of each other. Sync failed. Not one app — several. All on the same shared EKS platform, all pulling from the same application Helm chart we'd been using for ages.&lt;/p&gt;

&lt;p&gt;I opened Argo first on the app I knew had deployed recently, then on two others that hadn't changed in weeks. Same failure. That ruled out my first instinct — a bad image tag or a typo in one team's values file. Whatever broke was upstream of individual app config.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0uelcmcm76pgi3xebatp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0uelcmcm76pgi3xebatp.png" alt=" " width="503" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A shared chart, a feature merge, and a new template
&lt;/h2&gt;

&lt;p&gt;Our platform pattern is familiar if you've run Kubernetes at any scale: dozens of services, one common chart, per-app and per-env values overlays. Argo CD watches the repo and syncs each Application to its cluster. Most apps define &lt;code&gt;ingress&lt;/code&gt; for their primary routing. A subset also define &lt;code&gt;ingressExt&lt;/code&gt; for a public-facing ALB. Nobody had needed an internal-only ingress type until recently.&lt;/p&gt;

&lt;p&gt;A feature PR had landed that added support for internal ALBs — &lt;code&gt;ingressInt&lt;/code&gt; — plus matching templates &lt;code&gt;ingress-int.yaml&lt;/code&gt; and &lt;code&gt;ingress-ext.yaml&lt;/code&gt; in the shared chart. The author needed internal ingress for one service, so they added an &lt;code&gt;ingressInt&lt;/code&gt; block to that app's values file and merged. CI was green. The chart rendered fine in whatever path the PR exercised.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5v5c3hz1f0bh8tj1jro2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5v5c3hz1f0bh8tj1jro2.png" alt=" " width="503" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then Argo tried to sync everyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrowing it down
&lt;/h2&gt;

&lt;p&gt;Argo's UI isn't always generous with Helm errors, but the sync logs usually cough up the render failure. The message we kept seeing was the Helm classic:&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="na"&gt;Error: template: .../ingress-int.yaml:...&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;executing "..." at &amp;lt;.Values.ingressInt.enabled&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nil pointer evaluating interface {}.enabled&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That line tells you almost everything. The template touched &lt;code&gt;.Values.ingressInt.enabled&lt;/code&gt;. For the app that got the new values block, &lt;code&gt;ingressInt&lt;/code&gt; exists and has an &lt;code&gt;enabled&lt;/code&gt; field. For every other consumer of the chart, &lt;code&gt;ingressInt&lt;/code&gt; was never defined. In Go-template land, &lt;code&gt;.Values.ingressInt&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, and dereferencing &lt;code&gt;.enabled&lt;/code&gt; on nil is a hard stop — Helm never gets as far as creating or updating resources.&lt;/p&gt;

&lt;p&gt;I pulled the diff from the feature merge. Two new template files, and at the top of &lt;code&gt;ingress-int.yaml&lt;/code&gt;:&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="nv"&gt;- if .Values.ingressInt.enabled -&lt;/span&gt;&lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No default in the chart's root &lt;code&gt;values.yaml&lt;/code&gt;. No guard checking whether &lt;code&gt;ingressInt&lt;/code&gt; exists before reading &lt;code&gt;.enabled&lt;/code&gt;. The template runs for every app on every &lt;code&gt;helm template&lt;/code&gt; / &lt;code&gt;helm upgrade&lt;/code&gt; — the &lt;code&gt;if&lt;/code&gt; only skips the &lt;em&gt;body&lt;/em&gt; of the template; the condition itself still evaluates &lt;code&gt;.Values.ingressInt.enabled&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;That matched the blast radius. Apps with the new key: fine. Apps with only &lt;code&gt;ingress&lt;/code&gt; and maybe &lt;code&gt;ingressExt&lt;/code&gt;: broken. Apps that hadn't been touched in months: broken. Argo doesn't isolate chart render failures per consumer when they share a chart version — one bad optional key poisons the whole sync surface.&lt;/p&gt;

&lt;p&gt;We briefly wondered whether we should patch values files app by app. There are a lot of them — dev, staging, prod overlays, team forks. Adding &lt;code&gt;ingressInt: { enabled: false }&lt;/code&gt; everywhere would work, but it's the kind of churn that hides in a giant PR and still leaves you one missing file away from the next outage. The regression had already been introduced by adding &lt;code&gt;ingressInt&lt;/code&gt; to a single app's values while the template assumed every app would have the key. Repeating that pattern at scale felt wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: chart defaults and nil-safe guards
&lt;/h2&gt;

&lt;p&gt;We wanted a chart-only fix — no hunting through dozens of per-env values files, no coordination with every team to add a stub block. Two changes, applied together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, add defaults in the chart's &lt;code&gt;values.yaml&lt;/code&gt; so &lt;code&gt;ingressInt&lt;/code&gt; and &lt;code&gt;ingressExt&lt;/code&gt; always exist, even when an app never mentions them:&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="na"&gt;ingressInt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;

&lt;span class="na"&gt;ingressExt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apps that need internal or external ALBs keep overriding these in their own values. Everyone else inherits disabled defaults and never thinks about the keys again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, harden the templates so a missing or partial values merge can't take down render again. The condition in &lt;code&gt;ingress-int.yaml&lt;/code&gt; became:&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="nv"&gt;- if and .Values.ingressInt .Values.ingressInt.enabled -&lt;/span&gt;&lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same pattern in &lt;code&gt;ingress-ext.yaml&lt;/code&gt; for consistency — same class of bug, same class of fix. The &lt;code&gt;and&lt;/code&gt; short-circuits: if &lt;code&gt;ingressInt&lt;/code&gt; is nil or absent after a bad merge, the template skips cleanly instead of panicking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9cugdkso0detdp0b8rox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9cugdkso0detdp0b8rox.png" alt=" " width="509" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We reverted the one-off &lt;code&gt;ingressInt&lt;/code&gt; block from the single app's values file. With chart defaults in place, that app could set &lt;code&gt;ingressInt.enabled: true&lt;/code&gt; and its hosts/annotations when they actually needed internal ingress, without carrying a special snowflake block that implied the key was app-local rather than chart-wide.&lt;/p&gt;

&lt;p&gt;After merging the chart fix, Argo syncs recovered across the board without touching individual Application manifests or env-specific values. The app that originally needed internal ingress still opts in through overrides; the rest of the fleet never knew anything happened except that sync went red and then green again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works (and what we'd do differently)
&lt;/h2&gt;

&lt;p&gt;Helm merges values layers: chart defaults, then parent charts, then user-supplied &lt;code&gt;-f&lt;/code&gt; files and &lt;code&gt;--set&lt;/code&gt;. If the chart doesn't define a key, and no values file defines it either, &lt;code&gt;.Values.ingressInt&lt;/code&gt; is nil in the template context. Optional features can't assume every consumer opted in — especially on a shared chart where most apps will never use the feature.&lt;/p&gt;

&lt;p&gt;Defaults alone would probably have fixed this specific incident, because &lt;code&gt;ingressInt.enabled&lt;/code&gt; would resolve to &lt;code&gt;false&lt;/code&gt; everywhere. We kept the nil guard anyway. Defaults can be overridden away, subcharts can omit keys, and someone will eventually add a third ingress variant the same way. The guard costs one line and buys immunity to the exact error we saw.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmfk9hnqkzfx91rp7czge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmfk9hnqkzfx91rp7czge.png" alt=" " width="503" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process miss was visible in the PR itself: the feature was validated on one app that had &lt;code&gt;ingressInt&lt;/code&gt; in values, while the template executed for all apps on the chart. A render check that only runs &lt;code&gt;helm template&lt;/code&gt; with the happy-path values file wouldn't catch it. Next time, for optional blocks on a shared chart, I'd want CI to render against a minimal values fixture — just enough to deploy a generic app, with no &lt;code&gt;ingressInt&lt;/code&gt; — alongside the feature app's overlay. If minimal render passes, you've got both defaults and guards covered, or at least you'll see the nil pointer before merge.&lt;/p&gt;

&lt;p&gt;One template change broke every Argo app on the platform. Fixing it took chart-level defaults and a nil-safe condition, not a values-file scavenger hunt across the org. That's the pattern I'd reuse: when you add optional &lt;code&gt;.Values&lt;/code&gt; blocks to a shared Helm chart, ship chart defaults &lt;em&gt;and&lt;/em&gt; nil-safe template guards — not every consumer will define the key, and Argo will sync all of them on the same chart version whether you planned for that or not.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>argocd</category>
      <category>eks</category>
    </item>
    <item>
      <title>When TLS 1.3-only broke everything behind Akamai</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sun, 05 Jul 2026 06:59:46 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/when-tls-13-only-broke-everything-behind-akamai-j3e</link>
      <guid>https://dev.to/mridul_it_is/when-tls-13-only-broke-everything-behind-akamai-j3e</guid>
      <description>&lt;p&gt;The alert wasn't subtle. Requests just stopped hitting our backend nginx box. Internal traffic from our own domains kept flowing, but anything coming in through Akamai-hosted domains — routed via the External LB — went dead. Several frontends all depended on that backend, so they went down together.&lt;/p&gt;

&lt;p&gt;We run nginx in front of a shared backend that multiple application frontends talk to. Under normal conditions, Akamai terminates at the edge, traffic crosses the External LB, and nginx forwards to the app tier. Internal paths bypass that edge path entirely, which is why the split behavior was our first real clue: the nginx box wasn't universally broken. Something in the Akamai → External LB path was failing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chasing the wrong certificate
&lt;/h2&gt;

&lt;p&gt;We started from the frontend boxes and ran curls against the backend path. The failures looked like they were getting cut off at Akamai — not nginx, not the app. That pointed outward, not inward.&lt;/p&gt;

&lt;p&gt;We opened a ticket with Akamai. Their read was an SSL certificate problem. That didn't sit right. We hadn't rotated certs, renewed anything, or touched the cert chain on our side. If nothing on the certificate had changed, why would Akamai suddenly start rejecting handshakes?&lt;/p&gt;

&lt;p&gt;We kept digging anyway. The Akamai angle was real — requests really were dying at their edge — but "certificate issue" felt like a symptom label, not the mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  The policy mismatch
&lt;/h2&gt;

&lt;p&gt;While we were going back and forth, someone pulled up the External LB TLS security policy. That was the turn.&lt;/p&gt;

&lt;p&gt;The LB had been set to TLS 1.3 only. At Akamai, the property was on their default supported policy — the one that negotiates down through 1.2 → 1.1 → 1.0, not a strict 1.3-only handshake.&lt;/p&gt;

&lt;p&gt;TLS 1.3-only on the load balancer means the server side of the handshake insists on 1.3. Akamai's side, configured for broader compatibility, wasn't going to meet it there. The handshake never completed. From the outside it looked like Akamai was cutting requests off — and in a sense it was, because the TLS negotiation failed before anything useful got through. Easy to misread as "SSL cert broken" when the real failure mode is protocol policy mismatch.&lt;/p&gt;

&lt;p&gt;We hadn't changed certificates. We had changed (or inherited) a TLS policy that didn't match what Akamai could speak on that property.&lt;br&gt;
What fixed it&lt;/p&gt;

&lt;p&gt;We rolled the External LB TLS security policy back to one that supports both TLS 1.2 and TLS 1.3. After that change, traffic from Akamai-hosted domains started reaching nginx again, and the dependent frontends came back.&lt;/p&gt;

&lt;p&gt;No nginx reload drama, no cert redeploy — just aligning the LB's minimum/maximum protocol behavior with what the Akamai property actually negotiates.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm keeping in my head
&lt;/h2&gt;

&lt;p&gt;The split between internal (working) and Akamai (broken) saved us from burning time on nginx config. But "Akamai says certificate" plus "we didn't touch certs" should have pushed us to TLS policy sooner.&lt;/p&gt;

&lt;p&gt;The operational bit I care about: any time we change TLS policy on the External LB, we need to coordinate with whoever owns the Akamai property config. Edge and origin have to agree on what handshake they're willing to do. A 1.3-only LB in front of an Akamai property still on broad compatibility isn't a subtle drift — it's a hard cutoff.&lt;/p&gt;

&lt;p&gt;I'm marking this one complete, but the runbook note is the part that matters for the next person: check LB TLS policy against Akamai's supported cipher/protocol set before you assume the cert is bad.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sitereliabilityengineering</category>
      <category>infrastructure</category>
      <category>tls</category>
    </item>
    <item>
      <title>What is the BEST Programming Language to Start with?</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sun, 27 Feb 2022 15:41:27 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/what-is-the-best-programming-language-to-start-with-27ai</link>
      <guid>https://dev.to/mridul_it_is/what-is-the-best-programming-language-to-start-with-27ai</guid>
      <description>&lt;p&gt;One of the most popular question that every student asks before they begin their journey of programming is which programming language to choose from OR should i say&lt;/p&gt;

&lt;h2&gt;
  
  
  WHAT IS THE BEST LANGUAGE TO START WITH ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwzoposqbuoo1vprolhp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwzoposqbuoo1vprolhp.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A very cliche answer to this curiousity ridden question is "Every Language is Best, its just a matter of your personal choice"&lt;br&gt;
This would have been a good reply to someone who has learn few languages and is on the journey of making one or more, his best. But this isn't a good answer for someone who didn't even started their journey and are looking for something that is worth their time &lt;br&gt;
So, Here is a collection of all information you need to &lt;strong&gt;CHOOSE&lt;/strong&gt; which language to start from.&lt;/p&gt;

&lt;h2&gt;
  
  
  WHAT ARE THE AVAILABLE OPTIONS?
&lt;/h2&gt;

&lt;p&gt;If you are like me than you must have researched your days off to find out what are the different programming languages one can choose from ?&lt;br&gt;
And you might have come across a few like-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;PYTHON&lt;/li&gt;
&lt;li&gt;C&lt;/li&gt;
&lt;li&gt;JAVA&lt;/li&gt;
&lt;li&gt;R&lt;/li&gt;
&lt;li&gt;REACT&lt;/li&gt;
&lt;li&gt;JAVASCRIPT,etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have heard the names of any one of those than good you might have some knowledge of what we are going to discuss here&lt;br&gt;
But if you are hearing this for the first time than don't worry we are going to discuss some of them in this article only.&lt;/p&gt;

&lt;h2&gt;
  
  
  SOME SUBSTITUTES
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d3ovbe6px8r9x3vf7sv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d3ovbe6px8r9x3vf7sv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now there are two more languages that are not considered programming languages but more of sturcture and styling languages i.e. &lt;br&gt;
&lt;strong&gt;HTML AND CSS&lt;/strong&gt;.&lt;br&gt;
They are the two languages that i recommend you should at least learn for a while if you have never programmed anything because these are very basic languages which can give you a jist of what the other languages might have in store for you and these languages will give you perfect mindset to deal and learn programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shortening the List.
&lt;/h2&gt;

&lt;p&gt;Out of the above mentioned 7 programming languages there are 4 or lets say 3 languages most people are confused about that includes&lt;/p&gt;

&lt;h1&gt;
  
  
  1. C++
&lt;/h1&gt;

&lt;h1&gt;
  
  
  2. Python
&lt;/h1&gt;

&lt;h1&gt;
  
  
  3. JAVA
&lt;/h1&gt;

&lt;h1&gt;
  
  
  4. C
&lt;/h1&gt;

&lt;p&gt;And Now we are going to judge these languages based on some criterias to clear the confusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the Criterias of Judging?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;EASE to Understand&lt;/li&gt;
&lt;li&gt;Learning Curve&lt;/li&gt;
&lt;li&gt;Interface&lt;/li&gt;
&lt;li&gt;User Experience&lt;/li&gt;
&lt;li&gt;Any help website of youtube channels&lt;/li&gt;
&lt;li&gt;How much time it would take to learn?&lt;/li&gt;
&lt;li&gt;What are its real world use?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  C
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fit9ppupqvpoiys849dvy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fit9ppupqvpoiys849dvy.png" alt=" " width="312" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C is one of those language that i think is taught to first years in most of the colleges.And same was happened to me.Being a person who only knew Python by then it was not at all jarring for me to learn this language.&lt;br&gt;
So, the best advice i can give for this language is &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You have to be open Minded and let things sink in first"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;-Ease to Understand :* * * * (4/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As i mentioned earlier to learn C,One just have to let it sink in you mind for a little bit.By that i mean , Give it some time to let yourself understand its syntaxes and rules ,etc.&lt;br&gt;
In the mean time do some basic questions like Pattern Printing ,searching ,sorting and level up steadily.&lt;br&gt;
&lt;strong&gt;-Learning Curve: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Interface wise i would always recommend use an online compiler for C or a mobile app cause the other IDLE i tried for C for turbo C++ which was terrible but i give it benefit of doubt that it was meant to be used as programming IDLE for developers but for habitual Coding stuff&lt;br&gt;
&lt;strong&gt;-Interface: * * * (3/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;C is a great User Experience being it so easy  to understand and learn&lt;br&gt;
&lt;strong&gt;-User Experience : * * * *(4/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Helping guide for C are very fabulous and there are a lot of it:&lt;br&gt;
 &lt;a href="https://www.tutorialspoint.com/cprogramming/index.htm" rel="noopener noreferrer"&gt;Tutorial Point,&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.geeksforgeeks.org/why-learning-c-programming-is-a-must/" rel="noopener noreferrer"&gt;Geeks for Geeks,&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.freecodecamp.org/news/the-c-beginners-handbook/" rel="noopener noreferrer"&gt;Free Code Camp,&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.w3schools.com/c/index.php" rel="noopener noreferrer"&gt;W3school&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-Help Guide: * * * * (4/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It would take aprroximately a week or two for you to learn it if you go about only doing it for those weeks.Meaning its not much Time counsuming.&lt;br&gt;
&lt;strong&gt;-Time To Learn: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the Real world use of C i would highlight what the internet has to say for it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Real-World Applications of C. Use of the C programming language is not limited to the development of operating systems and applications. It is also used in GUI development, IDE development, etc."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;-Real World Experience: * * * (3/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  C++
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ovzf5tzg7xdwwru4wru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ovzf5tzg7xdwwru4wru.png" alt=" " width="474" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My very first experience with C++ came about a couple of days earlier and i am not kidding once you do C its insanely easy to do C++. There are only syntax changes for the most parts.You will be done with all basic stuff in a day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ease of Understanding: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As of the Learning Curve its exactly like C so if you did C earlier than this will be a piece of cake but even if you take it as your first language than also it would take you anylonger to understand than if you had take C.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learning Curve: * * (2/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will deduct a star for interface though cause although i gave C benefit of doubt that Turbo C++ was not meant to be for C.It was catered for C++ and it was not good Experience .I would recommend VS code for sure, here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Interface: * * (2/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you Use VS code as your text editor than the user experience with this language is very good.Some things are to be nit-picked but still all in all a satisfying user experience.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User Experience: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There have been a lot of Helping Media for C++ mainly because most students use it for CP(competitive Programming).So, you will not find lack of resources for C++&lt;br&gt;
some of which include:&lt;br&gt;
&lt;a href="https://www.w3schools.com/CPP/default.asp" rel="noopener noreferrer"&gt;W3school&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tutorialspoint.com/cplusplus/index.htm" rel="noopener noreferrer"&gt;Tutorialpoint&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/tagged/c%2B%2B" rel="noopener noreferrer"&gt;StackOverflow&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.geeksforgeeks.org/cpp-tutorial/" rel="noopener noreferrer"&gt;GFG&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=8jLOx1hD3_o" rel="noopener noreferrer"&gt;freecodecamp&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Helping Guide: * * * * (4/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As said earlier it won't take any more time than C did, if you are a beginner and this is your first language,But if this comes to not be your first language than it would take even lesser time for you to learn.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time to Learn: * * (2/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its Real World Use is insanely big.&lt;br&gt;
And i will quote what the internet has to say about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;" &lt;br&gt;
&lt;strong&gt;C++ Application in Real World&lt;/strong&gt;&lt;br&gt;
GUI Applications.&lt;br&gt;
Operating Systems.&lt;br&gt;
Web Browsers.&lt;br&gt;
Database Management System.&lt;br&gt;
Libraries.&lt;br&gt;
Cloud Computing and Distributed Applications."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real Word Use: * * * * (4/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JAVA
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvpr37o18fhwbuaata3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvpr37o18fhwbuaata3k.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Java is the language that i have been doing for quite some time now. So, I can give my very recent experience.&lt;/p&gt;

&lt;p&gt;As for the Ease of Understanding , i will say it looks and feels overwhelming at some times but if you give it time to sink it will become quite easy to grasp once you get over the fact that its imense and so does its code looks like.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ease of Understanding: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learning Curve is kinda Steep, You might not like but JAVA does have everything for you to figure out yourself but it also gives you very deep understanding of what make something work like it does.There is no hidden library or soemthing everything had to be mentioned by user only.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learning Curve: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recommend using Intellij IDEA as the IDE for Java, as it has additional features with it and shortcuts for long code structures to make your work load small.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Interface: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From A User's Point of view it gives almost all control to the User.So it will do exactly what you tell it to do and will not do some parts on its own.So you have Full Control Over the language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User Experience: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Java too there is no lack of Helping sites, IT being such vast language you meight never find an error which is not faced by someone else as well.&lt;br&gt;
Some of Helping Guide include:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.javatpoint.com/java-tutorial" rel="noopener noreferrer"&gt;javapoint&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.geeksforgeeks.org/java/" rel="noopener noreferrer"&gt;GFG&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.w3schools.com/java/" rel="noopener noreferrer"&gt;W3school&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ" rel="noopener noreferrer"&gt;Kunal Kushwaha's DSA playlist&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Helping Guide: * * * * (4/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Java will take some time for you to learn and more of practice is needed in it.Its kinda Steep Learning Curve contribute to its Learning time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time to Learn: * * * (3/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Java too has a lot of Real world Use and Here also i will quote what the internet has to say for it: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;" &lt;strong&gt;Applications&lt;/strong&gt;&lt;br&gt;
1) Desktop GUI Applications.&lt;br&gt;
2) Web Applications.&lt;br&gt;
3) Mobile Applications.&lt;br&gt;
4) Enterprise Applications.&lt;br&gt;
5) Scientific Applications.&lt;br&gt;
6) Web Servers &amp;amp; Applications Servers.&lt;br&gt;
7) Embedded Systems.&lt;br&gt;
8) Server Apps In Financial Industry."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real Word Use: * * * * (4/5 stars)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  PYTHON
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs4rq0x1uw9yb00rtypy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs4rq0x1uw9yb00rtypy.png" alt=" " width="601" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python is the very first language i learned so  i can tell from my experience that its fairly easy to Understand So,&lt;br&gt;
**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EASE to Understand: * * * * * (5/5 stars)
**&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;like all languages you have to learn it from very base level but for a beginner or a student as per say it does a lot of work for you as you don't have to tell what each variable's type is.(i.e. you don't have to write int a =10; again and again. you can just write a=10; and the python interpreter will take a as int).So,&lt;br&gt;
&lt;strong&gt;- LEARNING CURVE: * (1/5 starts)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Coming to the interface of python its interface depend on the type of IDLE that you use for eg-&lt;br&gt;
If you work on the default IDLE of python provided by its installer setup than its failry OK&lt;br&gt;
But if you use JUPITER NOTEBOOK than its interface is very good with features like line number and inout output bok right below the code space&lt;br&gt;
PYCHARM is also a pyhton IDLE that you can download its specifically made for Python and works fairly better than any other IDLE of Python.&lt;br&gt;
&lt;strong&gt;- INTERFACE: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python's User Experience also depend on the type of Idle that you use like if you use Pycharm than its pretty good User interface with most of the required windows open on the screen with its own terminal and folder space&lt;br&gt;
But the default IDLE of python is Not user friendly as nothing is mentioned on the IDLE to help the absolute beginners while you can use "help()" function to get help about anything from IDLE.&lt;br&gt;
&lt;strong&gt;- USER Experience: * * * * (4/5 Stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Python there very few websites to learn from some of which are&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=pkYVOmU3MgA" rel="noopener noreferrer"&gt;Free Code Camp&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://www.geeksforgeeks.org/python-data-structures-and-algorithms/" rel="noopener noreferrer"&gt;Geeks For Geeks (GFG)&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://www.udacity.com/course/data-structures-and-algorithms-in-python--ud513" rel="noopener noreferrer"&gt;Udacity (free Course)&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;- Learning Websites: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python was fairly easy and fast to learn than any other language. Most of My understanding of python comes from Expreimenting with different projects and using differnet libraries to build one or the other thing so i think&lt;br&gt;
&lt;strong&gt;- Time to Learn: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As for what python is used for I would like to quote something coursera said about python &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Python is commonly used for developing websites and software, task automation, data analysis, and data visualization. Since it's relatively easy to learn, Python has been adopted by many non-programmers such as accountants and scientists, for a variety of everyday tasks, like organizing finances" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But with that we must also know that if a beginner try to start from Python as their first language then you will be able to learn fast but there will be a lot of concepts that will never be understood by you cause in order to make python so easy it has hidden a lot of the basic key features from Storage class to Inheritance (OOPS), Method Overloading etc. which are very useful concepts. So you might learn fast but you will also miss alot of basics which may deter your foundation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- REAL World USE: * * (2/5 stars)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F599cbn1f0qf4xf32ed7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F599cbn1f0qf4xf32ed7o.png" alt=" " width="799" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, The Conclusion is -&lt;br&gt;
If you wanna learn from Absolute Basic then Go for : &lt;strong&gt;HTML and CSS&lt;/strong&gt;&lt;br&gt;
If you don't have any programming language experience : &lt;strong&gt;Python&lt;/strong&gt;&lt;br&gt;
If you have some experience but wanna know it all : &lt;strong&gt;JAVA&lt;/strong&gt;&lt;br&gt;
If you wanna do some big Projects that have C/C++ : &lt;strong&gt;C &amp;amp; C++(both)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All in all Give any language you choose some time and in the mean time do some questions and projects you wanna build etc. Soon you will become so Used to it that it will become like a second nature to you.&lt;/p&gt;

&lt;p&gt;And at last i wanna add that this is all my personal experiences and opinions.Don't go around changing your path just cause some Guy on internet said so. This Article and all other materials available on online platforms is meant to Help you on your journey.&lt;br&gt;
And please make sure to keep it that way.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>cpp</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How should I start with programming? "Its all just a dabble"</title>
      <dc:creator>Mridul Tiwari</dc:creator>
      <pubDate>Sun, 20 Feb 2022 05:57:10 +0000</pubDate>
      <link>https://dev.to/mridul_it_is/how-should-i-start-with-programming-its-all-just-a-dabble-5hng</link>
      <guid>https://dev.to/mridul_it_is/how-should-i-start-with-programming-its-all-just-a-dabble-5hng</guid>
      <description>&lt;p&gt;If anything I want you to conclude from this Blog, It is this quote right here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If he was lost for a moment, he would dive straight back into its honey. ~ Laurence Olivier ".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My very blunt Experience
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Of how it feels to begin on the journey of learning programming as not just a curriculum but my career.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  BEGINNING
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0z6lrmoaie6mstovr485.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0z6lrmoaie6mstovr485.jpg" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think it was around April or May of the last Year i.e. 2021. When I was studying for my exams of JEE taking a year drop and all my school friends were in some Colleges pursuing their degrees. I was bored enough and I got a hunch to do something to improve my soft skills. And pretty soon I realized I can't do it alone. I need some sort of a partner to do this. All in All, I and my friends started a small podcast to talk about teenage stuff namely WTeenF.&lt;/p&gt;

&lt;h2&gt;
  
  
  FIRST ENCOUNTER
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F76bm33ntkcr1wg0534s9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F76bm33ntkcr1wg0534s9.jpg" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we started building websites or I should say they began building website designs for the podcast and this made me interested in learning what in the world are they doing cause as long as I remember I never learnt anything in HTML that let me make such beautiful websites I was flabbergasted by it. So I researched my day off and found it was CSS behind all that and this led me ways to find out where can I learn CSS from. Then I came across &lt;a href="https://www.geeksforgeeks.org/" rel="noopener noreferrer"&gt;GFG(Geeks for Geeks)&lt;/a&gt; it gave me all the written stuff to understand what was programmers using in CSS. &lt;br&gt;
&lt;strong&gt;&lt;em&gt;And Yes I said programmers as I didn't consider myself anything back then than just a normal kid, not a programmer for sure.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
 But I am not that much of learning from text kinda guy so I searched two more days off and for various influencers that are doing God's job of making all that text summarized or let's just say explain it to us such as &lt;a href="//www.freecodecamp.org"&gt;freecodecamp&lt;/a&gt; and &lt;a href="//www.w3schools.com"&gt;w3schools&lt;/a&gt; are some of my favourite sites and youtube channel as in the case of former one to learn the codebase of CSS. Their teaching method of learning via programming side by side made me fall in love with the subject at hand and I still love any course they put up there. Obviously, I was excited enough then and kept doing these things and started building different projects some of which are already available for everyone to try and just some beginner-friendly stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experience with Git
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fepeza73rpqggoqiqu2nl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fepeza73rpqggoqiqu2nl.jpg" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;
That journey kicked off then and I soon learnt &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;. And for those of you who don't know what Git is don't worry I will quote what the internet has to say about it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Git is software for tracking changes in any set of files, usually used for coordinating work among programmers collaboratively developing source code during software development."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In layman language, it is software to run open-source projects on your device and push your enhancements or fixes to that open source project, which will be available to everybody.&lt;br&gt;
It is by the way was a totally reversed experience from the previous ones for me. As I couldn't learn Git via any youtube video and Just by chance after searching a lot about it and finding things on my recommended page I found a Course on Git on Udacity and here is its link:&lt;br&gt;
&lt;a href="https://www.udacity.com/course/version-control-with-git--ud123" rel="noopener noreferrer"&gt;https://www.udacity.com/course/version-control-with-git--ud123&lt;/a&gt;&lt;br&gt;
And finally learnt what GitHub is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What life might throw at you
&lt;/h2&gt;

&lt;p&gt;By this time I had already entered my college first semester and then I found a creator namely &lt;a href="https://www.youtube.com/c/KunalKushwaha" rel="noopener noreferrer"&gt;"KUNAL KUSHWAHA"&lt;/a&gt;. This man is really doing some amazing work and I started learning java from him. And for the record, it was not an easy hill for me because my laptop couldn't support any languages Compiler or IDLE nor a  text editor other than Sublime Text. So all of my java course was practised on an online compiler namely replit.&lt;/p&gt;

&lt;h2&gt;
  
  
  CONCLUSION
&lt;/h2&gt;

&lt;p&gt;So this was my journey to the point where I am now and what I can say from all this is, Actually the only thing that has been stopping me from doing anything is the fear of not knowing what it is for me in this in my future. But whenever I dive straight into it I have found myself learning and progressing fairly well... &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"With that BEST OF LUCK to all of you people in your journey as well".&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
