<?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: Silpa Nallagopula</title>
    <description>The latest articles on DEV Community by Silpa Nallagopula (@silpa_nallagopula_4d02cde).</description>
    <link>https://dev.to/silpa_nallagopula_4d02cde</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%2F4059535%2F29700658-0d94-4ee6-b214-f7137a5d82b0.png</url>
      <title>DEV Community: Silpa Nallagopula</title>
      <link>https://dev.to/silpa_nallagopula_4d02cde</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/silpa_nallagopula_4d02cde"/>
    <language>en</language>
    <item>
      <title>PostgreSQL 14 ends on Nov 12. The upgrade won't break your Java service. The next password reset will.</title>
      <dc:creator>Silpa Nallagopula</dc:creator>
      <pubDate>Fri, 06 Nov 2026 16:02:20 +0000</pubDate>
      <link>https://dev.to/silpa_nallagopula_4d02cde/postgresql-14-ends-on-nov-12-the-upgrade-wont-break-your-java-service-the-next-password-reset-14fb</link>
      <guid>https://dev.to/silpa_nallagopula_4d02cde/postgresql-14-ends-on-nov-12-the-upgrade-wont-break-your-java-service-the-next-password-reset-14fb</guid>
      <description>&lt;p&gt;PostgreSQL 14 gets its final release on November 12. After that, no more fixes. Most teams I talk to have the upgrade on a list somewhere, and most of them are worried about the data: pg_upgrade, extensions, downtime.&lt;/p&gt;

&lt;p&gt;The thing I'd worry about is smaller and later. It's a login failure that doesn't happen on upgrade day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in 14
&lt;/h2&gt;

&lt;p&gt;PostgreSQL 14 changed the default of &lt;code&gt;password_encryption&lt;/code&gt; from &lt;code&gt;md5&lt;/code&gt; to &lt;code&gt;scram-sha-256&lt;/code&gt;. Every new password is stored as a SCRAM verifier unless you change that setting.&lt;/p&gt;

&lt;p&gt;Here's the part that makes it sneaky. &lt;code&gt;pg_upgrade&lt;/code&gt; keeps the MD5 hashes you already have. So you upgrade a 12 or 13 server to 14 (or straight to 18), your apps reconnect, everything is green, and you close the ticket.&lt;/p&gt;

&lt;p&gt;Then, weeks later, someone rotates the app's database password. The new one is stored as SCRAM. A Java service that has been fine for years starts failing with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.postgresql.util.PSQLException: The authentication type 10 is not supported.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type 10 is SCRAM. The driver doesn't speak it. Moving with dump and restore doesn't avoid it: &lt;code&gt;pg_dumpall --globals-only&lt;/code&gt; carries the MD5 hashes over as they are, so you're in the same position. It only fails on day one if you create the roles by hand on the new server, because then every password is set again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which pgjdbc versions can log in
&lt;/h2&gt;

&lt;p&gt;pgjdbc added SCRAM-SHA-256 in 42.2.0, only in the Java 8+ build. But 42.2.0 shipped with a known issue: the SCRAM client classes weren't packaged, so it didn't actually work. 42.2.1 fixed that a week later.&lt;/p&gt;

&lt;p&gt;So the floor is &lt;strong&gt;42.2.1, and not a &lt;code&gt;.jre6&lt;/code&gt; or &lt;code&gt;.jre7&lt;/code&gt; build&lt;/strong&gt;. Those older-Java builds never got SCRAM at any version. That catches people: a &lt;code&gt;42.2.x.jre7&lt;/code&gt; jar looks newer than &lt;code&gt;42.2.1&lt;/code&gt;, and it still can't log in.&lt;/p&gt;

&lt;p&gt;The same change hits other clients. The floors I check against, each taken from the client's own changelog or source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go: &lt;code&gt;lib/pq&lt;/code&gt; 1.1.0, &lt;code&gt;pgx&lt;/code&gt; 3.4.0&lt;/li&gt;
&lt;li&gt;Node: &lt;code&gt;pg&lt;/code&gt; 7.9.0&lt;/li&gt;
&lt;li&gt;.NET: Npgsql 3.2.7&lt;/li&gt;
&lt;li&gt;Anything built on libpq: libpq 10&lt;/li&gt;
&lt;li&gt;PgBouncer: 1.11, or 1.14 if it looks passwords up with &lt;code&gt;auth_query&lt;/code&gt; or keeps SCRAM secrets in &lt;code&gt;auth_file&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to check before you upgrade (all read-only)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Find the PostgreSQL 14 servers in your cluster.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'postgres[^ ]*:14'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an operator (CloudNativePG, Crunchy, Zalando) runs the database, check the image in its cluster resource as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. See how each login role's password is stored today.&lt;/strong&gt; As a superuser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;password_encryption&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;rolname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;rolpassword&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'md5%'&lt;/span&gt;           &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'md5'&lt;/span&gt;
            &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;rolpassword&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'SCRAM-SHA-256%'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'scram'&lt;/span&gt;
            &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'none'&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;stored_as&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_authid&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;rolcanlogin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every &lt;code&gt;md5&lt;/code&gt; row is a password that will turn into SCRAM the next time someone resets it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Find the driver each Java service actually ships.&lt;/strong&gt; Not the version in a pom from two years ago, the jar in the running image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;ns&amp;gt; &amp;lt;pod&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'find / -name "postgresql-*.jar" 2&amp;gt;/dev/null'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything below 42.2.1, or with &lt;code&gt;.jre6&lt;/code&gt;/&lt;code&gt;.jre7&lt;/code&gt; in the name, gets bumped before the upgrade, not after the first failed rotation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this one is worth an hour this week
&lt;/h2&gt;

&lt;p&gt;The end-of-life date is a deadline you can see. This failure is one you can't: the upgrade passes, the dashboards stay green, and it surfaces on whatever day a password rotates. Usually not a day anyone connects with the upgrade.&lt;/p&gt;

&lt;p&gt;Checking takes three queries. Finding it during an incident takes a lot longer.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>kubernetes</category>
      <category>java</category>
      <category>devops</category>
    </item>
    <item>
      <title>I read the Kubernetes changelogs from 1.32 to 1.37 properly</title>
      <dc:creator>Silpa Nallagopula</dc:creator>
      <pubDate>Tue, 15 Sep 2026 13:04:57 +0000</pubDate>
      <link>https://dev.to/silpa_nallagopula_4d02cde/i-read-the-kubernetes-changelogs-from-132-to-137-properly-4821</link>
      <guid>https://dev.to/silpa_nallagopula_4d02cde/i-read-the-kubernetes-changelogs-from-132-to-137-properly-4821</guid>
      <description>&lt;p&gt;I've been building an upgrade-readiness tool for about a year, and for most of that time I worked from the changelogs the way everyone does: find the version, skim "Urgent Upgrade Notes", move on. Then a cluster I care about hit something on 1.33 that I hadn't seen coming, and I decided to stop skimming.&lt;/p&gt;

&lt;p&gt;So I cloned kubernetes/kubernetes and wrote a script that pulls out, per release, the sections that carry obligations: Urgent Upgrade Notes, Action Required, Deprecations, API Changes, Known Issues. Patch releases included, because they sneak things in. That's 36 files going back to 1.2. Then I sat down with 1.32 through 1.37 and read them. All of it. It took most of a weekend and I don't recommend it as a weekend.&lt;/p&gt;

&lt;p&gt;The numbers&lt;br&gt;
152 bullets that require someone to do something. Of those, roughly 73 I can verify by looking at the cluster: objects, CRDs, ConfigMaps, node info. The other 79 or so I can't, because they're about kubelet flags, node-level config, scrape configs, or client-side kubeconfigs. For the 1.33 → 1.34 hop specifically, 7 of the 10 urgent items are in that second bucket. I'll come back to why that matters.&lt;/p&gt;

&lt;p&gt;Things I didn't know&lt;br&gt;
The changelog is wrong about locked feature gates, at least twice. When a gate gets locked to its new default, any cluster that had it set the other way changes behaviour on upgrade. The notes mention some of these. The actual source of truth is the LockToDefault field in kube_features.go, so I diffed that between tags instead of trusting the prose. 73 gates locked across 1.32–1.35. And two dates are wrong: MaxUnavailableStatefulSet is listed under 1.35 but locks in 1.37, and StatefulSetAutoDeletePVC is listed under 1.32 but locks in 1.33. I only caught them because the source diff and the notes didn't agree. If your rules come from the release notes, you have the same two errors I had.&lt;/p&gt;

&lt;p&gt;1.30 has no Urgent Upgrade Notes. None. I re-checked because I assumed my extractor had broken. It hadn't. There just aren't any. A tool that reports something for every hop is making it up for this one.&lt;/p&gt;

&lt;p&gt;The scariest bullets in 1.34 sit under the least scary heading. They're under a line that literally says "(No, really, you MUST read this)": apiserver metric-label renames, the kubelet --cloud-config flag removed, static-pod admission changed. But in the rendered file, the heading above that block is just "v1.34.0". I scrolled past it the first time. So did the LLM I was testing that week, which is a story for another post.&lt;/p&gt;

&lt;p&gt;Old changelogs are formatted differently in ways that break naive parsing. The 1.7–1.15 era puts everything under a narrative H1, and 1.7 bold-wraps its headings. Nobody cares about this unless you write the extractor, and then you care a lot.&lt;/p&gt;

&lt;p&gt;The add-ons move when Kubernetes moves. A 1.36 target drags CoreDNS and kube-proxy along, and Istio, Karpenter, cert-manager if you run them, each with their own notes. Istio's upgradeNotes cover maybe half of what actually breaks; the rest is in the Removed/Deprecated lists and in flags whose defaults flip. Istio also drops compatibility profiles without a release note. The 1.21 profile vanished at 1.25. I only noticed because I was diffing the registration code.&lt;/p&gt;

&lt;p&gt;What I did with it&lt;br&gt;
Rules. Hand-written, one per bullet, per version, with the upstream sentence quoted verbatim and a kubectl command to verify it. About 600 across Kubernetes and seven add-ons now, plus 146 locked-gate rules generated from the source diff rather than the changelog. They run in a small Go CLI that needs a kubeconfig context and never writes anything:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kube-upgrade-check --context my-cluster --target 1.36 -o json&lt;/code&gt;&lt;br&gt;
Every rule comes back as APPLIES with the objects named, CLEARED, or NOT DETECTABLE with the manual check spelled out. That last outcome exists because of the 79. I'd rather the tool say "I can't see your kubelet flags, go run this" than pretend it looked.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Repo: github.com/runtimez-com/kube-upgrade-check&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
My first pass missed 31 items I only found on the second read, so I'm fairly sure there are more. If your last upgrade broke on something that isn't in there, the changelog line in an issue is enough.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From Kubernetes PR to Deployment Verdict: Approve, Warn, or Block</title>
      <dc:creator>Silpa Nallagopula</dc:creator>
      <pubDate>Mon, 03 Aug 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/silpa_nallagopula_4d02cde/from-kubernetes-pr-to-deployment-verdict-approve-warn-or-block-52lk</link>
      <guid>https://dev.to/silpa_nallagopula_4d02cde/from-kubernetes-pr-to-deployment-verdict-approve-warn-or-block-52lk</guid>
      <description>&lt;p&gt;A small change in a Helm values file can look completely harmless during review.&lt;/p&gt;

&lt;p&gt;The YAML is valid.&lt;br&gt;&lt;br&gt;
The Helm chart renders successfully.&lt;br&gt;&lt;br&gt;
The CI pipeline is green.&lt;br&gt;&lt;br&gt;
The pull request gets approved.&lt;/p&gt;

&lt;p&gt;But after deployment, the application starts failing, pods are restarted, or availability is reduced.&lt;/p&gt;

&lt;p&gt;The problem is that most CI checks focus on whether the Kubernetes configuration is technically valid. They do not always explain what the change will do to the workloads already running in the cluster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why normal CI checks are not enough
&lt;/h2&gt;

&lt;p&gt;Schema validation is useful. Policy checks are useful. Linting is useful.&lt;/p&gt;

&lt;p&gt;But passing those checks does not automatically mean that a change is safe to deploy.&lt;/p&gt;

&lt;p&gt;A pull request may contain changes such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing replicas from three to one&lt;/li&gt;
&lt;li&gt;Removing a memory limit&lt;/li&gt;
&lt;li&gt;Changing a readiness probe&lt;/li&gt;
&lt;li&gt;Removing a PodDisruptionBudget&lt;/li&gt;
&lt;li&gt;Using a floating image tag&lt;/li&gt;
&lt;li&gt;Modifying a NetworkPolicy&lt;/li&gt;
&lt;li&gt;Changing scheduling or topology constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of these changes may be valid Kubernetes configuration.&lt;/p&gt;

&lt;p&gt;The operational risk depends on the application, the current cluster state, the traffic pattern, and the workloads affected by the change.&lt;/p&gt;
&lt;h2&gt;
  
  
  A simple example
&lt;/h2&gt;

&lt;p&gt;Consider this change:&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;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;changed to:&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;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is nothing syntactically wrong with the new value.&lt;/p&gt;

&lt;p&gt;The Helm chart will render, and Kubernetes will accept the deployment.&lt;/p&gt;

&lt;p&gt;But the operational impact could be significant.&lt;/p&gt;

&lt;p&gt;With only one replica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A restart may temporarily make the service unavailable&lt;/li&gt;
&lt;li&gt;A node drain could interrupt the application&lt;/li&gt;
&lt;li&gt;A rolling deployment may have less capacity&lt;/li&gt;
&lt;li&gt;A single pod failure could affect all users of the service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A reviewer should not have to discover all of this by manually reading the YAML and trying to understand the possible impact.&lt;/p&gt;

&lt;p&gt;The pull request should clearly explain that availability is being reduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  From validation to a deployment verdict
&lt;/h2&gt;

&lt;p&gt;Instead of returning only a list of configuration changes, a PR-time check should provide a clear deployment verdict.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approve
&lt;/h3&gt;

&lt;p&gt;The change does not introduce a meaningful reliability, security, cost, or availability risk.&lt;/p&gt;

&lt;p&gt;For example, updating a harmless label or increasing a safe resource limit may be approved automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approve with warning
&lt;/h3&gt;

&lt;p&gt;The change is likely safe, but the reviewer should be aware of a possible impact.&lt;/p&gt;

&lt;p&gt;For example, increasing memory limits may increase cost, even if it does not create an immediate reliability problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Require approval
&lt;/h3&gt;

&lt;p&gt;The change introduces meaningful operational risk and should be reviewed by the appropriate owner.&lt;/p&gt;

&lt;p&gt;Examples may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing replicas&lt;/li&gt;
&lt;li&gt;Modifying resource limits&lt;/li&gt;
&lt;li&gt;Changing probes&lt;/li&gt;
&lt;li&gt;Removing a PodDisruptionBudget&lt;/li&gt;
&lt;li&gt;Changing network access rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Block
&lt;/h3&gt;

&lt;p&gt;The change violates a critical reliability, security, or organizational policy.&lt;/p&gt;

&lt;p&gt;Examples may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing required resource limits&lt;/li&gt;
&lt;li&gt;Introducing a known critical vulnerability&lt;/li&gt;
&lt;li&gt;Using a prohibited image tag&lt;/li&gt;
&lt;li&gt;Breaking a mandatory availability requirement&lt;/li&gt;
&lt;li&gt;Blocking an active service connection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the reviewer should see
&lt;/h2&gt;

&lt;p&gt;A useful PR-time verdict should explain more than whether a rule passed or failed.&lt;/p&gt;

&lt;p&gt;The reviewer should be able to understand:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What materially changed&lt;/li&gt;
&lt;li&gt;Why the change matters&lt;/li&gt;
&lt;li&gt;Which workloads or services are affected&lt;/li&gt;
&lt;li&gt;What the possible blast radius is&lt;/li&gt;
&lt;li&gt;Whether the change requires additional approval&lt;/li&gt;
&lt;li&gt;Whether the change can be rolled back safely&lt;/li&gt;
&lt;li&gt;What action should be taken before deployment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is not to replace engineering judgment.&lt;/p&gt;

&lt;p&gt;The goal is to give reviewers enough context to make a better decision before the change reaches production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The larger idea
&lt;/h2&gt;

&lt;p&gt;Kubernetes deployment safety is not only a YAML-validation problem.&lt;/p&gt;

&lt;p&gt;It is a decision problem.&lt;/p&gt;

&lt;p&gt;Teams need to know whether a change should be approved, approved with a warning, reviewed by an owner, or blocked before it reaches the cluster.&lt;/p&gt;

&lt;p&gt;That decision should be based on the operational effect of the change, not only whether the configuration is valid.&lt;/p&gt;

&lt;p&gt;Originally published on the Runtimez blog:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://runtimez.io/blog/pr-time-kubernetes-verdict" rel="noopener noreferrer"&gt;https://runtimez.io/blog/pr-time-kubernetes-verdict&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
      <category>platformengineering</category>
    </item>
  </channel>
</rss>
